How Chrome Code Touches Content
Without some sort of additional compatibility layer, any chrome code
which touches content without using the message manager
<https://developer.mozilla.org/en/The_message_manager> will break when
content processes are turned on. There are many possible ways to access
content, but the following are the most common.
.contentWindow/.contentDocument
The most direct, but least common way to touch content is by accessing
it directly through the <browser> element .contentWindow and
.contentDocument properties. This gives you direct access to the DOM
window and document objects within the browser.
DOM events .originalTarget
DOM events currently propagate from content down through the XUL
document which contains the <browser>. A lot of chrome code adds event
listeners to the <browser> or even to the top-level XUL window and
watches for events such as mouse click events (for example, to show the
browser content menu). The event handlers uses the event.originalTarget
property to determine which window the event was targeted at, and to
collect information in order to process the event.
With content processes, DOM events originating from content do not
propagate to chrome. They only propagate to the message manager scripts
which run in content. Event handlers installed on chrome elements will
never fire for content events.
Web Progress Listeners
The nsIWebProgress object associated with a browser exists in the
content process, and is accessed via the message manager. Chrome code
which currently uses nsIWebProgressListener to respond to navigation and
load in content must run in the content process. The <browser> no longer
has a .webProgress property.
Docshells
The docshell hierarchy for content exists in the content process. The
<browser> no longer has a .docShell property.
Network Events
The networking API (nsIChannel etc.) exists in both processes, but all
actual networking runs in the chrome process. In the content process,
all network requests are forwarded asynchronously to the chrome process.
In extension code (especially download helpers and adblockers) it is a
somewhat common practice to install global network listeners using
observer topics such as http-on-modify-request, and associate these
channels with their window with the load group and interface requestor.
Because the window exists in the content process and networking events
are all delivered asynchronously, this observer code will need to move
to the content process. I will post more details about how we plan to
make this easier shortly.
Other
There are undoubtedly other ways in which extensions can touch content.
We need additional data.
Data Gathering
We have been gathering data about the Firefox code and about extensions
in order to get a better sense for how many extensions may break, and
what sort of mitigations we can put in place.
Firstly, Felipe Gomes has been working with the Firefox frontend code,
disabling the nonessential features and porting a small subset to the
message manager so that it can be run. He got a first version working
back in December
<http://felipe.wordpress.com/2010/12/16/first-steps-into-an-e10s-firefox/>,
and is currently working on a longer-term code that we can actually
check into the tree.
I have been looking through the source code for the most popular addons
and have collected observations about the top 25 or so in this
spreadsheet
<https://spreadsheets.google.com/spreadsheet/ccc?key=0Ag3-54eJ7D8OdDZ1U09kVEl1UnZ4QU1wVU9yS2dBcGc&hl=en_US>.
This attempts to capture my best guess about whether the addon touches
content, the ways in which it touches content, and how much of the code
will need to be refactored. It also looks at whether any of the
compatibility shims (described below) might help avoid extensive rewriting.
The next step of data gathering, starting now, will expand on our manual
examination of code and attempt to do automatic examinations. We will
attempt to dynamically instrument Firefox to determine all the places
where chrome JS touches "content objects" (objects that will only exist
in the content process). We will also work on a static analysis which
will read source code of extensions and give clues about the places in
which chrome code touches content. These projects are both complicated
tasks, because it is not always easy to determine the runtime context
for a piece of code, or whether a particular event listener is intended
to watch for chrome or content events. We will continue to refine these
tools.
Potential Mitigations
Although we would like all extensions to migrate to either use the
Jetpack SDK or use the message manager, it is clear that getting addon
authors to port to either of these solutions will involve some
significant code refactoring and will not be a quick process. In order
to make it possible to release this feature quickly, we are considering
the following strategies to help lessen the impact of switching to
content processes.
Disabling Content Processes for Unported Extensions
If a user has an extension which is not yet compatible with content
processes, we can simply choose not to turn on content processes for
that user. Because the message manager works equally well in
single-process or multi-process mode, this is a decision we can make at
startup time. This will probably involve a flag in install.rdf or
chrome.manifest which indicates that an extension is not yet ready. If
we can get 75%, or 80%, or 90% of users running with content processes,
that will be an overall win.
The disavantage of this plan is that we must continue to test both
codepaths for a period of time. It is not a permanent solution, and we
would hope to phase out single-process mode after enough extensions are
compatible.
Automatic Rewriting of Simple Extensions
It may be possible to automatically or semi-automatically rewrite some
extensions so that they are compatible. This plan is still in its
infancy, and depends on the success of the static analysis data
gathering mentioned above. This may take the form of rewriting an
extension to use the message manager directly, or to use the Jetpack SDK.
This is much more likely to work for simple addons which use standard
code patterns. It is unlikely to work for big and complex addons.
CPOW Wrappers
The final strategy being discussed is to implement a cross-process
wrapper which mirrors JavaScript (the DOM, primarily) from the content
process to be accessed by chrome script. This would allow
<browser>.contentDocument and <browser>.contentWindow to be available
even when content processes are active.
CPOWs are limited: they are a one-way wrapper, which means that chrome
can access content properties, but cannot expose objects or functions
callable by content. Since CPOWs are a synchronous wrapper, one of the
primary benefits of content processes (improved responsiveness) may be
lost when CPOWs are used.
In order for CPOWs to be really useful, it may also be necessary to
implement DOM event propagation when chrome code has registered an event
listener. We are still investigation whether this is practical for
performance reasons.
We really don't know yet how useful CPOWs will be, and probably won't
know until we can install some extensions and see what breaks.
Other Work
In the meantime, while the frontend work and measurement efforts
continue, other parts of the Electrolysis work will resume as soon as we
have a desktop browser which is basically functional. We are going to
have to do some serious work for accessibility and developer tools in
order to prepare for content processes, as well as some work in graphics
and plugins which is already pretty well understood.
--BDS
Anthony Hughes
Quality Engineer
Mozilla Corporation
.contentWindow/.contentDocument
DOM events .originalTarget
Web Progress Listeners
Docshells
Network Events
Other
Data Gathering
Potential Mitigations
CPOW Wrappers
Other Work
--BDS
_______________________________________________
dev-planning mailing list
dev-pl...@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-planning
> CPOW Wrappers
>
> The final strategy being discussed is to implement a cross-process
> wrapper which mirrors JavaScript (the DOM, primarily) from the content
> process to be accessed by chrome script. This would allow
> <browser>.contentDocument and <browser>.contentWindow to be available
> even when content processes are active.
>
> CPOWs are limited: they are a one-way wrapper, which means that chrome
> can access content properties, but cannot expose objects or functions
> callable by content. Since CPOWs are a synchronous wrapper, one of the
> primary benefits of content processes (improved responsiveness) may be
> lost when CPOWs are used.
>
> In order for CPOWs to be really useful, it may also be necessary to
> implement DOM event propagation when chrome code has registered an event
> listener. We are still investigation whether this is practical for
> performance reasons.
>
> We really don't know yet how useful CPOWs will be, and probably won't
> know until we can install some extensions and see what breaks.
If we end up using CPOWs, can we find a way to _not_ enable them in
Firefox Mobile? We dropped the idea of using CPOWs when we first
started doing e10s. At the time, CPOWs killed any chrome
responsiveness gains a separate process gave mobile.
--BDS
--BDS
As I understand content scripts:
https://developer.mozilla.org/en/The_message_manager#Content_scripts
they support a kind of client/server split of extensions. There must be
a lot of additional rules about content scripts implicit in this design
but not explicit in the documentation. We need guidance on what goes
into each side of this split.
...
> I have been looking through the source code for the most popular addons
> and have collected observations about the top 25 or so in this
> spreadsheet
> <https://spreadsheets.google.com/spreadsheet/ccc?key=0Ag3-54eJ7D8OdDZ1U09kVEl1UnZ4QU1wVU9yS2dBcGc&hl=en_US>.
Hmm, the Firebug entry says "bad" under status ;-).
FWIW our goal on the Firebug project as been to have our UI entirely
separate from the data-collection code by the time the multiprocess tabs
land. We've made a lot of progress on understanding what needs to be
done. We're pretty far along on the Script panel. I believe Firebug
could be client/server within on the current process model by the end of
the year, depending of course on not having surprises.
jjb
I'm not sure what other kind of guidance I can provide at this point.
I'm happy to answer specific questions (in mozilla.dev.platform) as they
come up.
> Hmm, the Firebug entry says "bad" under status ;-).
That just means that Firebug will need to be refactored in order to work
properly. It's the same sort of large problem that the builtin developer
tools have. I understand you have things like a JS debugging protocol
which will make this simpler.
--BDS
The most basic guidance is this: content scripts can access the web
DOM, but can't access the chrome UI
More samples and dcos here:
https://wiki.mozilla.org/Mobile/Fennec/Extensions/Electrolysis
> I have been looking through the source code for the most popular addons
> and have collected observations about the top 25 or so in this
> spreadsheet
> <https://spreadsheets.google.com/spreadsheet/ccc?key=0Ag3-54eJ7D8OdDZ1U09kVEl1UnZ4QU1wVU9yS2dBcGc&hl=en_US>.
> This attempts to capture my best guess about whether the addon touches
> content, the ways in which it touches content, and how much of the code
> will need to be refactored. It also looks at whether any of the
> compatibility shims (described below) might help avoid extensive rewriting.
Flashblock author here. Please add event propagation to the row. We use
a custom event to communicate between our XBL running in untrusted
content and our whitelist code running in chrome. For example:
Flashblock.checkWhitelist(e.target.ownerDocument.location)
> The next step of data gathering, starting now, will expand on our manual
> examination of code and attempt to do automatic examinations. We will
> attempt to dynamically instrument Firefox to determine all the places
> where chrome JS touches "content objects" (objects that will only exist
> in the content process). We will also work on a static analysis which
> will read source code of extensions and give clues about the places in
> which chrome code touches content. These projects are both complicated
> tasks, because it is not always easy to determine the runtime context
> for a piece of code, or whether a particular event listener is intended
> to watch for chrome or content events. We will continue to refine these
> tools.
Putting on my xSidebar hat on (I run an extension porting service that
helps SeaMonkey users by porting Firefox extensions to SeaMonkey). My
observation is that the majority of extensions want to overlay
contentAreaContextMenu and then check various properties of
nsContextMenu/gContextMenu to hide/unhide their menu items. e.g.
gContextMenu.target, onImage, onLink, isTextSelected. Something
equivalent needs to be implemented post process separation for
extensions to hook into.
Phil
--
Philip Chee <phi...@aleytys.pc.my>, <phili...@gmail.com>
http://flashblock.mozdev.org/ http://xsidebar.mozdev.org
Guard us from the she-wolf and the wolf, and guard us from the thief,
oh Night, and so be good for us to pass.
[ ]JUMP! -- One hundred thousand lemmings can't be wrong.
* TagZilla 0.066.6
Can we easily enough start emitting some kinds of warnings in console
when the known non-content-process-proof methods are used, with pointer
to some doc that explains the problems and replacements? That way,
extension (and UI) devs would at least get pointers when debugging.
Also, we can get the AMO team to add tests and warnings into their
add-on checks that get run on every upload.
I wonder what kind of transition interfaces people have so they can
start building future-proof code right now - I guess they can't actually
use the message manager to communicate to content right now when content
processes are not activated, so they can't just switch to the new way of
doing things right away but need to implement both ways, right? (Of
course, they might be able to use the Add-ons SDK for some things, but
probably not everything.)
Robert Kaiser
--
Note that any statements of mine - no matter how passionate - are never
meant to be offensive but very often as food for thought or possible
arguments that we as a community should think about. And most of the
time, I even appreciate irony and fun! :)
Thanks for that data point, btw - we are thinking about timeframes when
we need good support for content processes in crash-stats, so this is
good to know for me when working on Q3 priorities. I guess it doesn't
need to be at the top of the list yet, then.
--BDS
Ah, that's cool, then.
> Flashblock author here. Please add event propagation to the row. We use
> a custom event to communicate between our XBL running in untrusted
> content and our whitelist code running in chrome. For example:
>
> Flashblock.checkWhitelist(e.target.ownerDocument.location)
Having created a similar flash-blocking (and showing) add-on for
Fennec, you'll have no trouble handling this in a child content
script.
> Putting on my xSidebar hat on (I run an extension porting service that
> helps SeaMonkey users by porting Firefox extensions to SeaMonkey). My
> observation is that the majority of extensions want to overlay
> contentAreaContextMenu and then check various properties of
> nsContextMenu/gContextMenu to hide/unhide their menu items. e.g.
> gContextMenu.target, onImage, onLink, isTextSelected. Something
> equivalent needs to be implemented post process separation for
> extensions to hook into.
Indeed. Firefox will need this support for it's own menu items. Fennec
handles this by sending a message from child process to the parent
process, with the details of the contextmenu target. The same can
happen for Firefox.