Explore the Visualforce App Container
Learning Objectives
After completing this unit, youโll be able to:
- Describe three differences between Visualforce pages running in Salesforce Classic compared to the same pages running in Lightning Experience.
- Describe two common code patterns that need updating to work in Lightning Experience.
- List two changes to Visualforce page default values when running in Lightning Experience.
Exploring the Visualforce App Container
The largest difference between Visualforce in Lightning Experience and Visualforce in Salesforce Classic is the environment it runs in. In Salesforce Classic, Visualforce โownsโ the page, the request, the environment. Visualforce is the application container. But in Lightning Experience, Visualforce runs inside an iframe thatโs wrapped inside the larger Lightning Experience container.
This change to the execution context has a number of effects on the way Visualforce pages can affect the overall Salesforce application. Weโll talk about these changes in this unit, but save the full details of a few of them for their own units.
The Outer Lightning Experience Container
Letโs start with the outer container, the Lightning Experience application. The Lightning Experience container is a โsingle-page application,โ or SPA, which is accessed at the /lightning URL. The /lightning page loads, its code starts up, and that application code takes over the environment.
The process by which a single-page application loads its resourcesโusually a static HTML shell and a lot of JavaScriptโis both interesting and complex. If youโve worked with JavaScript frameworks like AngularJS or React, youโre reasonably familiar with the basics of how Lightning Experience, in the form of /lightning, starts up. And to be honest, the full details donโt matter. You donโt have any control over it, and the implementation continues to evolve.
Hereโs whatโs important to know: Lightning Experience, or /lightning, is in charge of the request. Your Visualforce page is not. Your page needs to work within constraints that Lightning Experience imposes upon it. Lightning Experience is the parent context, and your Visualforce page is the child context. Children need to obey their parents.
Some of these constraints, such as the size of the frame in which your Visualforce page is displayed, are imposed directly by Lightning Experience. Theyโre easier to understand and work with, and weโll talk about them in a minute.
Other constraints are implicit, and enforced not by Lightning Experience but by the browser running it. These are mostly security and JavaScript execution constraints. Most pages arenโt impacted by these security constraints, and those that are usually fail early and with clear error messages. JavaScript errors are harder to discover and diagnose, but there are some general rules weโll cover in a bit.
The Visualforce iframe
When your Visualforce page runs in Lightning Experience, itโs displayed inside an HTML iframe. An iframe creates an embedded browsing context thatโs effectively a separate browser โwindowโ from the main Lightning Experience browsing context. The iframe creates a boundary between the Visualforce page and its parent, the Lightning Experience application.
The advantage of running Visualforce pages inside an iframe is that, for pages that donโt need to access or change the top-level browsing context, running inside the iframe looks almost exactly like running as a page in Salesforce Classic. This is why you donโt need to modify all of your Visualforce pages to adapt to the wildly different behind-the-scenes request environment of Lightning Experience. Itโs an important part of the โjust worksโ strategy for supporting Visualforce.
Of course, the flip side is that pages that do need to access the top-level browsing context, well, thereโs some things that need to change. Weโll cover some specifics in the next section.
If your page is communicating with services besides Salesforce, the iframe boundary might also result in you needing to update your organizationโs CORS settings, remote site settings, clickjack settings, or content security policy. Since these depend on security policies and settings outside of Salesforce, we canโt provide a recipe for specific changes. We simply call it to your attention here.
Impact of the New Container
The effects of the new Visualforce containerโembedding the Visualforce page into an iframe within the Lightning Experience appโcan be broadly divided into two categories, which weโll call security and scope.
Again, we want to emphasize: many, or even most Visualforce pages wonโt be affected by these issues. But for those that are, weโre thinking โforewarned is forearmed.โ Youโll find the source of the problem faster if weโve already talked about it together.
Security Impact
Elements of security that might be affected include the following.
- Session maintenance and renewal
- Authentication
- Cross-domain requests
- Embedding restrictions
We discussed a few of these briefly already, the items dealing with cross-domain requests. That is, when the content in the full browser window comes from requests to different servers and services, thereโs the potential for any of those requests to balk at being displayed in a context that itโs not prepared for. Your mission, should the need arise, is to prepare those services to handle requests intended to be put together within the Lightning Experience context. As we said before, the details vary, so we canโt provide specific answers here.
One thing we do want to mention specifically is session maintenance. A โsessionโ for our purposes here is basically some kind of token that your browser re-uses from request to request so that you donโt need to enter your username and password for every request. You often need to access the current session using the global variable $Api.Session_ID .
Hereโs the thing to keep in mind. $Api.Session_ID returns different values depending on the domain of the request. This is because the session ID varies during a session whenever you cross a hostname boundary, such as .salesforce.com to .force.com. Normally Salesforce transparently handles session hand-off between domains, but if youโre passing the session ID around yourself, be aware that you might need to re-access $Api.Session_ID from the right domain to ensure a valid session ID.
Lightning Experience and Visualforce pages are not only held in different browser contexts, theyโre also served from different domains. So, even though itโs all showing in one browser window, the session ID inside the Visualforce iframe will be different than the session ID outside the iframe, in another part of Lightning Experience. Salesforce and Lightning Experience handle this transparently in normal use. But if youโre passing around the session ID like hors d'oeuvre at a party (not usually a good idea), you might need to review how youโre handling it.
Scope Impact
When we talk about scope weโre mainly talking about the following kinds of things.
- DOM access and modification
- JavaScript scope, visibility, and access
- JavaScript global variables such as window.location
If this list sounds complicated or confusing, donโt worry, we can boil it down to something simple and easy to remember: Donโt touch someone elseโs stuff. Specifically, your JavaScript code (and stylesheet rules, for that matter) can affect elementsโDOM nodes, JavaScript variables, and so onโin your pageโs browsing context, but it canโt access elements in any other browsing context, like the parent Lightning Experience context. Donโt touch other contextsโ stuff!
Practically speaking, the most common code pattern where youโd want to do this kind of thing is to manipulate window.location to navigate to another page. This is such a common thing to do, weโve written up details on this specific issue...well, by the time youโre done with this module, youโll be sick of hearing about it, we promise.
One last note. If youโre an experienced JavaScript developer, youโre probably already thinking you know how to deal with โI donโt have access to the parent browsing contextโ issues, by using contentWindow, window.parent, or the like. Please donโt. Youโll likely run afoul of the same-origin policy (Visualforce and Lightning Experience are served from different domains, remember?). Even if you donโt, youโre probably replacing obvious, blocking bugs with subtle, intermittent bugs. Where do you want to spend your time: Doing things right, or the debugger?
Doing things right means calling APIs weโve made available in your Visualforce pages, primarily for navigation. If you really need to affect things across frame boundaries, use window.postMessage to send a message to receiving code in the other frame.
Visualforce Defaults and Environment Changes in Lightning Experience
When your Visualforce pages run in Lightning Experience a number of low-level changes happen behind the scenes. These changes enable most pages to โjust workโ in the Lightning Experience container, and sometimes you can just be happy theyโre there. But youโll still want to know theyโre happening, especially when youโre working on advanced application flows, or troubleshooting a tricky problem.
Some of these changes are simple, and obvious once you think about them. For example, Visualforce pages that run in Lightning Experience always have the standard Salesforce Classic header and sidebar suppressed. Other changes arenโt as visible, but have just as large an impact.
showHeader and sidebar Attributes Are Always false
These attributes affect the Salesforce Classic header and sidebar on Visualforce pages. The Salesforce Classic header and sidebar are always suppressed when pages run in Lightning Experience, in favor of Lightning Experience navigation elements. There are no corresponding attributes to affect the Lightning Experience header or sidebar because they canโt be suppressed.
If your page is shared between Salesforce Classic and Lightning Experience, you can still set these attributes to the values youโd like to use when the page runs in Salesforce Classic.
The sforce.one JavaScript Utility Object
Although sforce.one sounds like a droid working in the Salesforce cantina, * itโs actually a utility object that provides a number of useful functions you can use in your own JavaScript code.
sforce.one is automatically injected into your page when it runs in Lightning Experience or the Salesforce app. Youโll see it in your JavaScript debugger console and web developer resources list. Thereโs nothing you need to do to add it, and thereโs no way to suppress it, either. (Sadly, thereโs no way to get sforce.one in your Visualforce pages in Salesforce Classic.)
sforce.one is primarily used to fire navigation events. The full details are in an upcoming unit, Managing Navigationย .
____________________
* There is no Salesforce cantina. Alas.
Resources
- Modify Session Security Settings
- Visualforce Developer Guide
- Mozilla Development Network: HTML Inline Frame Element (<iframe>)
- Mozilla Development Network: Using Content Security Policy
