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