Cameron,

The way the builtin protocols (HTTP/FTP/Websockets/etc) handle this is that
the protocol handler code checks whether we're in a child process or not
when a channel is created, and we hand out different things depending on
that.  In the parent, we hand out a "good old HTTP channel" (nsHttpChannel)
just as we've always done in single-process Firefox.  In the child we hand
out a stub channel (HttpChannelChild) that looks and smells like an
nsIHttpChannel, but actually uses IPDL (our C++ cross-platform messaging
language) to essentially shunt all the real work to the parent.  When
AsyncOpen is called on the child, the stub channel winds up telling the
parent to create a regular "real" http channel, which does the actual work
of creating/sending an HTTP request, and as the reply come back, sending
the data to the child, which dispatches OnStart/OnData/OnStopRequest
messages as they arrive from the parent.

One key ingredient here is to make sure all cross-process communication is
asynchronous whenever possible (and that should be 95%+ of the time).  You
want to avoid blocking the child process waiting for synchronous
cross-process communication (and you're not allowed to block the parent
waiting to the child to respond).  You also generally want to have the
parent channel send all the relevant data to the child that it will need to
service all nsI[Foo]Channel requests, as opposed to doing a "remote object"
style approach (where you'd send a message off to the parent process to ask
the "real" channel for the answer).  This is both because 1) that would be
painfully slow, and 2) the parent and child objects may not be in the same
state. For instance, if client code calls channel.isPending() on a child
channel that hasn't dispatched OnStopRequest yet, the answer should be
'true'.  But if you ask the parent channel, it may have already hit
OnStopRequest and sent that data for that to the child (where it's waiting
to be dispatched).  So for instance, HTTP channels ship the entire set of
HTTP response headers to the child as part of receiving OnStartRequest from
the parent, so that they can service any GetResponseHeader() calls without
asking the parent.

>From talking to folks who know JS better than I do, it sounds like the
mechanism you'll want to use for all your cross-process communication is
the Message Manager:


https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Message_Manager

https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Message_Manager/Message_manager_overview

http://mxr.mozilla.org/mozilla-central/source/dom/base/nsIMessageManager.idl?force=1#15

One difference between C++/IPDL and JS/MM  is that IPDL has the builtin
concept of an IPDL "channel": it's like a pipe you set up.  Each C++ necko
channel in e10s sets up its own IPDL 'channel' (which is really just a
unique ID under the covers).  So when, for instance, an OnDataAvailable
message gets sent from the parent to the child, we automatically know which
necko channel it belongs to (from the IPDL channel it arrives on).  The
Message Manager's messages are more like DOM events--there's no notion of a
channel that they belong to, so you'll need to include as part of the
message some kind of ID that you map back to the necko channel that it's
for (I'd say use the URI, but that wouldn't work if you've got multiple
channels open to the same URI.  So you'll probably assign each channel a
GUID and keep a hashtable on both the parent and child that lets you map
from GUID->channel.

I'm happy to help some more off-list with examples of how our current
protocols handle various things as you have questions.  Hopefully this will
get you started, along with this inspirational gopher:// video:

   https://www.youtube.com/watch?v=WaSUyYSQie8

:)

Jason

On Mon, Jan 4, 2016 at 4:03 PM, Cameron Kaiser <[email protected]> wrote:

> On 1/4/16 12:09 PM, Dave Townsend wrote:
>
>> On Mon, Jan 4, 2016 at 12:03 PM, Cameron Kaiser <[email protected]>
>> wrote:
>>
>>> What's different about nsIProtocolHandler in e10s? OverbiteFF works in 45
>>> aurora without e10s on, but fails to recognize the protocol it defines
>>> with
>>> e10s enabled. There's no explanation of this in the browser console and
>>> seemingly no error. Do I have to do extra work to register the protocol
>>> handler component, or is there some other problem? A cursory search of
>>> MDN
>>> was no help.
>>>
>>> Assuming you are registering the protocol handler in chrome.manifest
>> it will only be registered in the parent process but you will probably
>> need to register it in the child process too and make it do something
>> sensible in each case. You'll have to do that with JS in a frame or
>> process script.
>>
>
> That makes sense, except I'm not sure how to split it apart. Are there any
> examples of what such a parent-child protocol handler should look like in a
> basic sense? The p-c goop in netwerk/protocol/ is not really amenable to
> determining this, not least of which being written in C++.
>
>
> Cameron Kaiser
> _______________________________________________
> dev-platform mailing list
> [email protected]
> https://lists.mozilla.org/listinfo/dev-platform
>



-- 

Jason
_______________________________________________
dev-platform mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-platform

Reply via email to