On 2014-08-11, 6:03 PM, Jonas Sicking wrote:
Very exited to see this happening.

Implementation issues aside, I have two comments:

* This is something that we really need on FirefoxOS. I hope that the
implementation strategy will work there too?

Yes, the majority of the code is going to be shared between desktop/Android (where <xul:browser> is used for rendering content) and Firefox OS (where mozbrowser iframes are used for rendering content.)

* A use-case that we came upon pretty quickly when we were looking at
using prerendering in FirefoxOS is that we might not know the exact
URL that the user is likely to navigate to, but we have a pretty good
guess about what template page it's going to be.

Consider for example bugzilla. After the user has done a search query,
they are likely to click on one of the bug links. Each bug has a
different URL, but all bugs share much of the page UI.

It would be really awesome if bugzilla could ask to prerender a URL
like "https://bugzilla.mozilla.org/show_bug.cgi?justLoadTemplate=true";.
Then when the user clicks a bugzilla URL like
"https://bugzilla.mozilla.org/show_bug.cgi?id=123456";, we would enable
webpage logic to somehow force the prerendered page to be used, even
though the URLs don't match.

One way to do this would be to enable some way for the current page to
talk to the prerendered page. The current page could then tell the
prerendered page "the user just clicked bug 123456", at which point
the prerendered page could use replaceState to change its URL to
"https://bugzilla.mozilla.org/show_bug.cgi?id=123456";, at which point
we would see that the URLs matched.

Another solution would be to enable the prerendered page to say "i'm
able to act as a prerender page for any URLs that match pattern
https://bugzilla.mozilla.org/show_bug.cgi?id=*";.

Would be great if someone could bring up this use case with the
prerender editors and make sure it gets covered and that a specced
solution is defined.

So I've been thinking about this use case. Here are a number of thoughts that I have so far:

* The page which asks the UA to prerender the document is responsible for telling the UA which URL patterns the prerendered page should handle. As you note above, you typically want to render a different page (e.g., https://bugzilla.mozilla.org/show_bug.cgi?justLoadTemplate=true) which knows how to handle the dynamic fetching of the resources it needs when it's taken out of prerendering mode. But the controlling page also knows what URLs on that page may be loaded into this prerendered document. So far I've been thinking of an API like this:

  var prerenderedDoc = new PrerenderedDocument(
    // url to the document being loaded
    "https://bugzilla.mozilla.org/show_bug.cgi?justLoadTemplate=true";,
    // url scope for what it can handle
    "https://bugzilla.mozilla.org/show_bug.cgi?id=";);

* The two pages need to talk to each other. For that purpose, I think we should add a postMessage API to PrerenderedDocument which will allow the controlling document to either use it for single direction communication, or post a MessagePort to the prerendered page for bidirectional communication.

* The prerendered page needs to know when it's taken out of prerendering mode. This is already possible through the visibilitychange event. However the page also needs to know what URL ended up being loaded in the controlling document. Because the prerendered page may get activated as a result of a user initiated navigation, we cannot rely on the controlling document having an opportunity to notify the prerendered page. One option would be to extend the event object for visibilitychange with a URL argument that is the URL that ends up being loaded inside the page.

* The target page's URL actually needs to change in order to avoid surprises as you navigate pages. I'm going back and forth between expecting the prerendered page to call replaceState correctly, or specifying that replaceState will get called after the visibilitychange event gets dispatched. I haven't yet made up my mind on which approach is the better one...

* Once we have the PrerenderedDocument interface, we can extend it with a number of useful events, such as "load" which tells you when the prerendered document's load event has been dispatched, and "prerenderabort" to notify the controlling document if prerendering was aborted (as a result of a call to let's say window.alert).

* The existing prerendering implementation in IE and Chrome is opportunistic, i.e., the UA will be able to ignore the <link rel=prerender> based on a number of heuristics (for example I think Chrome prerenders at most one document at a time.) I think this is a nice model to make sure that the UA has the option of avoiding prerendering for memory consumption/responsive reasons, but I am not yet sure if we need to introduce this notion on PrerenderedDocument...

* In order to simplify the implementation, there will be no direct DOM access between the two pages even if they are loaded from the same origin. This will help the UA to "kill" the prerendered page more easily once it makes an API call which is blacklisted for example. All communications need to happen by message passing.

These are still rough ideas, but any feedback is much appreciated. I'm planning to propose something along these lines once the details have been fleshed out more.

Cheers,
Ehsan

On Mon, Aug 11, 2014 at 11:47 AM, Roshan Vidyashankar
<roshan...@gmail.com> wrote:
Summary: The Prerendering API allows the rendering engine to start loading and 
rendering a web page without any visible UI until the page needs to be 
displayed to the user. It's a gecko API that consumers can choose to use. For 
now, we're not talking about exposing this to web pages yet, or even using it 
in any of our products, we're just working on the implementation.

Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=730101

Link to standard: At some point we are going to be contributing to a spec but 
there are a number of unknown things which we're hoping to find out through the 
implementation - like what APIs need to be blacklisted in prerendering (audio, 
window.open etc). Chrome and IE have shipped their own implementations of 
prerendering.

Platform coverage: All

Estimated or target release: Unknown

Preference behind which this will be implemented: dom.prerendering.enabled

Implementation Plan
There are two big parts to the implementation.

1. How do we handle the prerendering itself in a way that works both for 
desktop and b2g

For this, we're thinking about adding a boolean flag to nsDocShell which together with mIsActive will 
constitute a tri-state: "active", "inactive" and "prerendered".  As far as the 
outside code is concerned, prerendered docshells are treated as inactive ones for the most part.  This means 
that we'd basically need to not modify nsDocShell::GetIsActive, and audit all of its callers and find the 
potential consumers who would want to treat prerendered and inactive differently (I don't expect there to be 
any such consumers actually but we'll see).  We'd use the prerendered state to reflect the correct status 
reflected through the page visibility API.  The prerendered docshell masquerading as inactive will also mean 
that it won't get a rendering on b2g for example because that's how we hide mozbrowser iframes there.

In order for gaia and XUL based consumers to be able to control the prerendering, I think 
we'd need to use the nsIFrameLoader swapping facilities that we currently have for the 
<xul:browser> swapDocShells method and extend those to make them usable with the 
mozbrowser frameLoader as well.  That way we can expose the prerendering API through both 
mozbrowser and <xul:browser> while sharing hopefully most of the code between these 
different consumers, and we'd get the ability to swap the frame loaders when we need to 
actually render a prerendered document.

2. What do we do with the APIs that have undesirable side-effects in 
prerendered pages (audio, window.open etc).

We first need to decide what we're going to do when a page calls into an API which has undesired 
side effects (and that is a blurry line -- I hope as part of this we come up with an actual list of 
what those actions are!).  Chrome basically aborts the execution of scripts on the page and throws 
out the prerendered content as soon as any such APIs are called.  IE's documentation claims that 
they "pause" a web page execution when that happens, but according to my testing, that 
behavior is really border-line non-deterministic.  I think we basically have two options: either 
abort the execution of the script or throw an exception.  The former breaks run-to-completion, 
which sucks.  The latter is a bit better I think but then we need to detect when JS execution is 
"done" so that we can start to discard the prerendered content.  I don't know if the 
latter is easily doable.

We are also thinking about adding a WebIDL annotation (let's call it 
[UnsafeForPrerendering] that we can add to stuff in the IDL and have it call 
into a BindingUtils helper which does either of the above.
_______________________________________________
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform
_______________________________________________
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform


_______________________________________________
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform

Reply via email to