The browser process brings up the Service Manager ASAP - as soon as the IO thread is start - but this isn't actually soon enough for some parts of the system to be fully servicified.
We should instead bring up Mojo IPC and the Service Manager as early as possible.
Finally started poking at this. It does actually happen relatively early or at least it does in the case of content (as opposed to chrome which does a lot of init override a bunch of BrowserMainParts) but it could be earlier
From looking at this: one option may be to pull IO thread construction and some parts of content::ServiceManagerContext out of browser main loop and then perhaps short-circuit the threads creation of browser main loop? Otherwise it's probably a huge undertaking to unwind the chrome parts that run there (profile creation as well as keyed services). I guess I'm not sure what the intended threading model we're aiming for. I expect we'll have a "Chrome browser" service which does a lot of the current init but will it be given a DB/cache/process launcher thread/task-runner or will it own those as part of its service?
The reason I thought of this approach is inspried by a sample snippet from a trace:
https://screenshot.googleplex.com/yoB1JY3D3Nz
profile init and a whole gob of our code is run as part of this message loop/browser parts construct and it looks non-trivial to break that apart or move profile init elsewhere.
That said, even this approach is tricky because it seems like we have a hard dependency on initializing finch super early, even earlier than this because it has to init stuff which affects IO thread construction. There's some "fun" comments here: https://cs.chromium.org/chromium/src/chrome/browser/chrome_browser_main.cc?q=chrome_browser_main.cc&sq=package:chromium&dr&l=1159
Feedback/suggestions welcome if you have more concrete ideas
Agree with Yaron, the InitializeMojo() is called right after the CreateThread(), and the IO thread is the last thread to be created in CreateThread(). If you see the screenshot of the trace event, you will find "service_manager::mojom::Service" event is only 3 milliseconds after "IOThread::InitAsync" event: https://screenshot.googleplex.com/w65RV7dnW7n.
Is the goal of the bug is to move the initialization of the ServiceManager as early as possible, perhaps out of the browser process main loop, as long as creating ONE thread and give it a task_runner, and it doesn't need to be the IO thread? Do you have an example which parts of the system can't be fully servicified?
Dig into this issue, the ServiceManager in the browser process is created on BrowerThread::IO thread, which needs the BrowserProcessImpl to be initialized first. Currently the BrowserProcessImpl is initialized in PreCreateThreads(), so it needs to be bring up earlier. Besides, we also need to move the initialization of the delegate of the BrowerThread::IO thread (IOThread or SystemNetworkContextManager which will replace IOThread) early. So we want to which component is waiting for the ServiceManager to be initialized to make it be servicified? Is there any example? This is important because if the required component need to be initialized before BrowserProcessImpl to be created, we may need another way to start an independent ServiceManager, like the way BackgroundSeriveManager does. "Independent" means it doesn't use the browser's BrowserThread::IO thread, but an arbitrary thread.
Ken: could you please provide more background?
Sure, I can try to clarify a few things:
We do want the Service Manager to continue running on BrowserThread::IO. Service Manager doesn't actually want to know about "browser threads" though, so ServiceManagerContext could just create the thread itself (with an IO MessageLoop) and use it for Service Manager initialization.
Later in BrowserMainLoop you could extract the thread from ServiceManagerContext and assign BrowserThread::IO to be that thread. This may require some light refactoring of BrowserThread and ServiceManagerContext code.
The ultimate goal here is not just to bring up SM earlier, but to be able to bring up SM without anything else. From there we can work on individual services also having their own dependencies minimized.
An example use case of this is to be able to run e.g. the network and download services (neither of which are ready yet) without the rest of the browser, for lightweight downloads on Android.
Thanks Ken for the background!
My initial thoughts are to extra the creation of the BrowserThread::IO from the startup tasks, and it could be created right after the BrowserThread::UI being created. Then initialize the ServiceManagerContext.
Anyway, I agree, we can do a refactoring to make it possible to reassign the thread that ServiceManagerContext uses, similar to the |background_thread_| in the BackgroundServiceManager. Since ServiceManagerContext needs to add service manifests to the BuiltinManifestProvider, we need to initialize ui::ResourceBundle first, i.e., calls the line 1027 to 1065 line before creating a ServiceManagerContext: https://cs.chromium.org/chromium/src/chrome/browser/chrome_browser_main.cc?rcl=988b5be8b4540f2868547e2e08e6046bd693f84f&l=1027.
Drive-by question: Do we have any design docs or whiteboard sketches of what we want browser startup to look like in the long term?
I ask because whenever I look at it I have a hard time figuring out the responsibilities between service manager, content and chrome. Diving through all the delegates is tricky.
Steven, I know you did the "foo parts" refactor many years ago -- do you have any drawings / docs from that era?
Here's a summary of the rules that were executed:
- OnlyMergeApprovedChange: Rule Failed -- Revision d5be60ba310d4acc439c440d3dc45c410ca75111 was merged to refs/branch-heads/3578 branch with no merge approval from a TPM!
Please explain why this change was merged to the branch!
- AcknowledgeMerge: Notification Required --
Comment 1 by roc...@chromium.org
, Jun 5 2017