Mojo Hugz Chrome

1,323 views
Skip to first unread message

Ben Goodger (Google)

unread,
Nov 13, 2015, 2:03:07 PM11/13/15
to chromi...@chromium.org

Hi everyone,


On the Mandoline team we’ve been looking at rebuilding aspects of the Chromium content layer clean room, as Mojo services. One of the most mature of these services and an area where we’ve had a lot of recent momentum is Mus, the Mandoline UI Service. One way to think about it as a display server that can be run “somewhere” (its own process, thread, or on a specific thread as the needs of the platform dictate) that provides an API for rendering, windowing and input event dispatching.


We’ve seen an opportunity to wire this up to Chrome in the shorter term, to facilitate extracting Ash (the ChromeOS window system) from the Chrome browser process. This will have some good performance isolation benefits compared to the current design. We’re calling this effort “mus+ash” (say “moustache”) This is what several of us on the Mandoline team are working on right now.


Some details on Mandoline. It’s based on the bare Mojo shell, called mojo_runner, in which “pure Mojo” applications are run (e.g. .mojo files). For mus+ash, the architecture looks a bit like this:


  1. mojo_runner process starts, implements shell

  2. mojo_runner starts ash_main.mojo, which acts as sort of an “init” process for the ash environment, spawning other process, e.g. mus, the window manager, and other system UI. These processes are all .mojo apps

  3. Now we need to figure out how to run Chrome. In doing this I do not want to have to make Chrome be a pure .mojo app. I want to modify the existing chrome.exe, bonus points if it can just be a runtime flag, not a heavyweight build flag (e.g. USE_AURA).


To solve #3, I taught mojo shell how to launch native exes that happen to live alongside the mojo_runner. This is a bit of a hack but whatevs. The flow is the same for mojo apps you just say ConnectToApplication(“exe:foo”) and foo.exe will be run if it’s next to mojo_runner. The important thing to note here is that mojo_runner launches foo.exe, and shares a platform handle with it that the shell expects it to bind to a ChildController, as would happen for a .mojo app. The ChildController interface is an implementation detail of the runner, and provides a conduit for the shell to send an InterfaceRequest<Application>.


Long story short, I’ve been able to teach the runner how to launch Chrome. In Chrome startup it checks to see if the mojo-platform-channel-handle is passed on the command line, which is only passed when Chrome is run by the runner. In this mode, Chrome binds an Application request and can then connect to the “pure” Mojo services running in the shell around it.


More recently I’ve been working on teaching the renderer processes, which are (necessarily right now) started by Chrome, not the runner, how to connect to the shell. The solution for this is to have content’s ChildProcessLauncher create a platform channel pair and hand one end to the renderer and the other end to the shell.


So with this done I now have this interesting situation where from the shell’s perspective, chrome.exe sort of is just another Mojo app, and chrome.exe has a shell it can use to connect to other Mojo apps. This works really well for mus+ash as it allows us to build the new services as pure Mojo apps.


But I got to thinking - I think you could potentially scale this model further and use it as a mechanism to extract more things from the Chrome process(s) into “pure” Mojo apps.


BTW, there’s nothing that says that the Mojo runner process has to:

  • be a separate exe (the lib could just be statically linked with Chrome)

  • be a separate process (could just be either the main thread of chrome, or even a background thread in chrome)

… so I think it’s possible to implement this architecture on non-ChromeOS platforms where we are sensitive about chrome.exe being the sole entrypoint to running the browser.


A few future componentization target ideas of varying degrees of difficulty, in addition to the mus+ash project I described above:

  • Convert the extension processes to be Mojo applications using the JS content handler. The extension API would be implemented as a JS client library loaded into these processes, the implementation of which would speak via Mojo to Chrome. Chrome would delete a lot of extension-to-feature binding poop in favor of Mojo interfaces for those features. BTW, “pure” mojo applications will be deployed via CRX/updated by Omaha/using the same semantics as extensions and Chrome itself.

  • Slowly teach the renderer how to be a Mojo ContentHandler. Refactor enough of the interfaces to be able to run the Mojo PDF ContentHandler without all the Blink scaffolding. I think this is probably a lot of work but would be super nice.

  • Probably many other ideas I have only started thinking about this this week.


The nice thing about these three project ideas is that they’re not changing the fundamental process model of Chrome - no new processes or even necessarily threads (maybe other than that needed for the Mojo Shell), but they are rationalizing a lot of things and cleaning up the code quite a bit IMO.


An unfortunate side note is that because the runner and many of its services are only built with GN, some of this is only possible if either all that code is converted to be built with GYP (UGH), or we complete the GN conversion. Time to rip the bandaid methinks!


Anyway I am calling this whole thing "Mojo Hugz Chrome" because it wraps the Chrome process with minimal changes other than that warm fuzzy feeling of being surrounded by goodness. This is a lot to digest so LMK what you think!


-Ben


Ben Goodger (Google)

unread,
Nov 13, 2015, 2:23:49 PM11/13/15
to chromi...@chromium.org
BTW it may be informative to compare this to the ApplicationManager that's currently instantiated in content. The main difference is that this ApplicationManager can't load "pure" Mojo applications (.mojo files), only those loadable via a custom implementation of ApplicationLoader (or maybe via some other dance I didn't notice). This is because even though the ApplicationManager is shared with mojo_runner, mojo_runner also provides its own child process launching/hosting code that is not present in content.

-Ben
Reply all
Reply to author
Forward
0 new messages