Custom visual authors and users - we'd like you help to find the last bugs in a new feature for custom visuals - sandboxing. We've seen a lot of great visuals be created by our community, and we've seen how some of those visual interact with each other, with our own UI elements, and with our APIs. This has led to some glitches for users and visual authors. So we're planning to add sandboxing. Sandboxing will be enabled in the service on or after March 22nd 2016.
Asks and Acitons for custom visuals users/developers
What is sandboxing for custom visuals
Sandboxing provides a layer of isolation for each custom visual by hosting it in a dedicated iFrame. Your code and dependencies are injected dynamically into the iFrame. It ensures you don’t have conflicts with other visuals/elements on your page and removes access to APIs that you shouldn’t be using in your custom visuals.
When will Sandboxing be enabled for custom visuals?
We expect it to enabled sandboxing on or around March 22nd 2016. We’ll adjust this based on your feedback and reported issues.
What is the impact on my custom visual?
Sandboxing runs your visual’s code in a low privilege iFrame with no domain. You will not be able to assume access to Power BI styles (CSS), Power BI fonts, or undocumented Power BI APIs. We will inject all the required interfaces into the iFrame including your visual’s code. Then we will marshal data points and required settings across the iFrame boundary. Since the iFrame has no domain, you will not have access to cookies or local storage. Lastly, how you debug your custom visual will change a little, which I’ll cover below.
Here’s an example iFrame that your visual would be loaded into:
<iframe class="visual-sandbox" src="/sandbox?plugin= MyVisualName" style="width: 1177px; height: 682.04px;" sandbox="allow-scripts"></iframe>
How can I test my visual in the Sandbox?
Starting now you can test your visuals, dashboards, and reports in the sandbox by adding the following flag to the URL in the address bar.
Follow these steps:
How do I debug in the sandbox?
To debug, the easiest way is to add the following line of code to your visual’s init method or wherever you’d like a breakpoint for the browser’s debugger.
Then, when you’d like to debug your visual, launch the browser’s debugger, add your visual to the page and bind some data to it. The debugger will automatically break when init is called by Power BI allowing you to see your code. Without this, you may find it hard to identify where the code is located in the browser’s debugger since it is dynamically injected into the iFrame.
A note about unhandled exceptions
One thing that is important for you to add to your visuals is some hardening for unhandled exceptions. To keep the iframe and the host page in sync, we run synchronization code in the iFrame alongside your visual’s code. If your visual throws an unhandled exception, we attempt to catch it so our synchronization code keeps working. Even then, your code might not work in the resulting state. We’ve found that some custom visuals have unpredictable behaviors after they throw an unhandled exception. Unfortunately, since it’s your code we’re not able to fix those issues on our side. The most common symptom of this is the visual stops resizing correctly when the user resizes the visual in Power BI. If you see this happening, check if the custom visual is throwing exceptions and resolve those before submitting an issue.
Here's a list of known bugs we're tracking:
1) Sometimes the visual does not resize in the iFrame. Usually this is due to an unhandled exception in the visual, but sometmies it's the framework. We're working on a fix. Your code should trap it's exceptions to avoid one of the major causes.
2) Fonts and CSS styles. Some visuals depend on Fonts and CSS from Power BI. Not all styles are available within the sandbox. You will not have access to Power BI's fonts in the iFrame. Please adjust the code of your visual to use specific and predictable Fonts and CSS.
2) iFrame within custom visuals are blocked. This is feature is due to the sandbox security policies we set. You should updated your code not to use an iFrame.
3) Performance for loading custom visuals. The is an impact due to the sandbox for how fast cusotm visuals load. We are working on fixes to make this better and some features to make it better still.
Overall makes perfect sense... Though a couple of Qs:
Assumption is that this applies to both reports and dashbaords?
Is there any noticeable impact on performance?
Good questions. The sandbox will apply to custom visuals on both the dashboard and reports. There will be a performance impact for loading custom visuals. We will mitigate this in segments, first with a whitelist of known good extensions that I think most people will use. The whitelist will at first not be user controllable. As we iterate we'll add add user control over the whitelist in one for or another. Please test your visuals and tell us how you perceive performance, it is one of the reasons we want folks to test before we enable the sandbox for everyone.
can you confirm that is NOT possible to test in Sandbox directly from Developer Tools?
It seems that the only way to load custom visuals in an iframe is importing a PBIWIZ file...
I encountered the following issue when trying to use the ListView control in my visuals in Sandbox mode:
1. The call to ListViewFactory.createListView() does not return.
2. When debugging, I get a TypeError exception with the following message - "a.scrollbar is not a function", refering to a statement in the ListView's constructor in visuals.min.js(Which is not present in the constructor in listView.ts on github).
3. A look in visual.js reveals that the "a" object is variable called "scrollInner" which is a jQuery selection of the div.scrollbar-inner element appended to the container element given in the ListViewOptions object.
4. It can be seen in the browser's DOM inspector that the div.scrollbar-inner was indeed appended to the container element.
My guess is that jQuery.scrollbar does not function properly in Sandbox mode.
Also, I second danieleperilli's post.
As the title says, whenever I call hostServices.analyzeFilter() in Sandbox mode, it returns "undefined".
The debugger does not yield any exciting information, so I don't have much to elaborate on. I did check to see if my FilterAnalyzerOptions object is still being initialized correctly in this mode, and it still is.
Edited: Ignore previous edit...
Correct, you can only test the sandbox in reports and on dashboards in the service. We've debated whether to bring it to dev tools itself and have held off since we think it would make debugging harder and won't provide much benefit there. We could add it. Is this something you'd strongly desire?
Thank you for reporting these issues. I am on the custom visual framework team and would be more than happy to discuss these issues and understand your scenario.
The sandbox feature only brings in a minimal set of dependencies to render a visual. Some of the libraries and frameworks that are otherwise included on the regular PowerBi page are not included within the sandbox including the JQuery.Scrollbar plugin which is not part of our supported public API.
The “hostServices.analyzeFilter()” function is also not part of the public supported API. This functionality is currently protected by the sandbox. I am interested in hearing what you were using this function call for?
I realize that there has not been a lot of clearity yet regarding what PowerBi functionality is guarenteed to be long term supported in custom visuals. We are working to address those gaps so that it is very clear what functions we support, maintain, and ensure will never break.
Thanks for your reply.
I've been using both ListView and the analyzeFilter() function in two of my custom visuals, both of which are new types of slicers(A hierarchical slicer and A searchable slicer, to be exact).
The ListView issue is less critical, because I chose it out of convenience(Uniform look and feel with the original slicer, and some other useful features), and writing a control of my own that would meet my requirements will (hopefully) not be too much of a trouble.
The hostServices.analyzeFilter() function, on the other hand, is a different case. I wanted my slicers to have a functionality similar to that of the original one. More specifically, I wanted selections to-
1. Apply a filter on the page(The same way the original Slicer does, as opposed to the type of filtering done by the Treemap visual, for example). [Speaking of which, is there by any chance a way for a visual to apply a filter on the report level?]
2. To persist when the visual is reloaded(E.g, the selection should be retained after leaving the page and going back to it).
I achieved (1) by either implementing an IInteractiveBehavior and using an interactivityService(Like in the original Slicer) or by using the SelectionManager and persist the selections with hostServices.persistProperties().
In order to achieve (2), I use hostServices.analyzeFilter() on the dataView.metadata.objects's filter property, and process the returned AnalyzedFilter object's selectedIdentities property(Which is pretty much what is done in Slicer's DataConversion.convert() function). I guess manual processing of the SemanticFilter to get the selected scope identities is possible, but it seems a bit nightmarish and a lot like a functionality that should be provided to developers.
If there are Sandbox-friendly ways to achieve the above, I would really appreciate a reference.
Thanks a lot,