{"id":853,"date":"2019-03-28T18:03:53","date_gmt":"2019-03-28T17:03:53","guid":{"rendered":"http:\/\/blogs.igalia.com\/jaragunde\/?p=853"},"modified":"2019-07-31T08:20:20","modified_gmt":"2019-07-31T06:20:20","slug":"the-chromium-startup-process","status":"publish","type":"post","link":"https:\/\/blogs.igalia.com\/jaragunde\/2019\/03\/the-chromium-startup-process\/","title":{"rendered":"The Chromium startup process"},"content":{"rendered":"<p>I&#8217;ve been investigating the process of Chromium startup, the classes involved and the calls exchanged between them. This is a summary of my findings!<\/p>\n<p>There are several implementations of a browser living inside Chromium source code, known as \u201cshells\u201d. Chrome is the main one, of course, but there are other implementations like the content_shell, a minimal browser designed to exercise the content API; the app_shell, a minimal container for Chrome Apps, and several others.<\/p>\n<p>To investigate the difference between the different shell, we can start checking the binary entry point and find out how it evolves. This is a sequence diagram that starts from the content_shell main() function:<\/p>\n<p><a href=\"https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/app_shell-sequence.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/app_shell-sequence.png\" alt=\"content_shell and app_shell sequence diagram\" width=\"1192\" height=\"383\" class=\"alignnone size-full wp-image-856\" srcset=\"https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/app_shell-sequence.png 1192w, https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/app_shell-sequence-300x96.png 300w, https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/app_shell-sequence-768x247.png 768w, https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/app_shell-sequence-1024x329.png 1024w, https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/app_shell-sequence-500x161.png 500w\" sizes=\"auto, (max-width: 1192px) 100vw, 1192px\" \/><\/a><\/p>\n<p>It creates two objects, ShellMainDelegate and ContentMainParams, then hands control to ContentMain() as implemented in the content module.<\/p>\n<p>Chrome\u2019s main is very similar, it also spawns a couple objects and then hands control to ContentMain(), following exactly the same code path from that point onward:<\/p>\n<p><a href=\"https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/chrome-init-sequence.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/chrome-init-sequence.png\" alt=\"Chrome init sequence diagram\" width=\"743\" height=\"323\" class=\"alignnone size-full wp-image-855\" srcset=\"https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/chrome-init-sequence.png 743w, https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/chrome-init-sequence-300x130.png 300w, https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/chrome-init-sequence-500x217.png 500w\" sizes=\"auto, (max-width: 743px) 100vw, 743px\" \/><\/a><\/p>\n<p>If we took a look to the app_shell, it would be very similar, and it\u2019s probably the same for other shells, so where\u2019s the magic? What\u2019s the difference between the many shells in Chromium? The key is the implementation of that first object created in the main() function:<\/p>\n<p><a href=\"https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ContentMainDelegate.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ContentMainDelegate.png\" alt=\"ContentMainDelegate class diagram\" width=\"648\" height=\"547\" class=\"alignnone size-full wp-image-857\" srcset=\"https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ContentMainDelegate.png 648w, https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ContentMainDelegate-300x253.png 300w, https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ContentMainDelegate-355x300.png 355w\" sizes=\"auto, (max-width: 648px) 100vw, 648px\" \/><\/a><\/p>\n<p>Those *MainDelegate objects created in main() are implementations of ContentMainDelegate. This delegate will get the control in key moments of the initialization process, so the shells can customize what happens. Two important events are the calls to CreateContentBrowserClient and CreateContentRendererClient, which will enable the shells to customize the behavior of the Browser and Render processes.<\/p>\n<p><a href=\"https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ContentBrowserClient.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ContentBrowserClient.png\" alt=\"ContentBrowserClient class diagram\" width=\"1237\" height=\"747\" class=\"alignnone size-full wp-image-859\" srcset=\"https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ContentBrowserClient.png 1237w, https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ContentBrowserClient-300x181.png 300w, https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ContentBrowserClient-768x464.png 768w, https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ContentBrowserClient-1024x618.png 1024w, https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ContentBrowserClient-497x300.png 497w\" sizes=\"auto, (max-width: 1237px) 100vw, 1237px\" \/><\/a><\/p>\n<p>The diagram above shows how the ContentMainDelegate implementations provided by the different shells intantiate each their own implementation of ContentBrowserClient. This class runs in the UI thread and is able to customize the browser logic, its API is able to enable or disable certain parameters (e.g. AllowGpuLaunchRetryOnIOThread), provide delegates on certain objects (e.g. GetWebContentsViewDelegate), etc. A remarkable responsibility of ContentBrowserClient is providing an implementation of BrowserMainParts, which runs code in certain stages of the initialization.<\/p>\n<p>There is a parallel hierarchy of ContentRendererClient classes, which works analogously to what we\u2019ve just seen for ContentBrowserClient:<\/p>\n<p><a href=\"https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ContentRendererClient.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ContentRendererClient.png\" alt=\"ContentRendererClient class diagram\" width=\"720\" height=\"591\" class=\"alignnone size-full wp-image-860\" srcset=\"https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ContentRendererClient.png 720w, https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ContentRendererClient-300x246.png 300w, https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ContentRendererClient-365x300.png 365w\" sizes=\"auto, (max-width: 720px) 100vw, 720px\" \/><\/a><\/p>\n<p>The specific case of extensions::ShellContentRendererClient is interesting because it contains the details to setup the extension API:<\/p>\n<p><a href=\"https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ShellContentRendererClient.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ShellContentRendererClient.png\" alt=\"ShellContentRendererClient class diagram\" width=\"1007\" height=\"813\" class=\"alignnone size-full wp-image-861\" srcset=\"https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ShellContentRendererClient.png 1007w, https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ShellContentRendererClient-300x242.png 300w, https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ShellContentRendererClient-768x620.png 768w, https:\/\/blogs.igalia.com\/jaragunde\/files\/2019\/03\/ShellContentRendererClient-372x300.png 372w\" sizes=\"auto, (max-width: 1007px) 100vw, 1007px\" \/><\/a><\/p>\n<p>The purpose of both ExtensionsClient and ExtensionsRendererClient is to set up the extensions system. The difference lies in the knowledge of the renderer process and its concepts by ExtensionsRendererClient, only methods that make use of this knowledge should be there, otherwise they should be part of ExtensionsClient, which has a much bigger API already.<br \/>\nThe specific implementation of ShellExtensionsRendererClient is very simple but it owns an instance of extensions::Dispatcher; this is an important class that sets up extension features on demand whenever necessary.<\/p>\n<p>The investigation may continue in different directions, and I&#8217;ll try to share more report like this one. Finally, these are the source files for the diagrams and a shared document containing the same information in this report, where any comments, corrections and updates are welcome!<\/p>\n<ul>\n<li><a href=\"https:\/\/docs.google.com\/document\/d\/1LWJ4gLUk65kKSgC6wBJ0soxf5VFUC0wQwW8dP6w2jjg\/edit#\">Shared document<\/a><\/li>\n<li><a href=\"https:\/\/people.igalia.com\/jaragunde\/chromium\/Diagrams.zip\">Diagrams<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve been investigating the process of Chromium startup, the classes involved and the calls exchanged between them. This is a summary of my findings! There are several implementations of a browser living inside Chromium source code, known as \u201cshells\u201d. Chrome &hellip; <a href=\"https:\/\/blogs.igalia.com\/jaragunde\/2019\/03\/the-chromium-startup-process\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":17,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[23,24,3],"tags":[],"class_list":["post-853","post","type-post","status-publish","format-standard","hentry","category-browsers","category-chromium","category-igalia"],"_links":{"self":[{"href":"https:\/\/blogs.igalia.com\/jaragunde\/wp-json\/wp\/v2\/posts\/853","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.igalia.com\/jaragunde\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.igalia.com\/jaragunde\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.igalia.com\/jaragunde\/wp-json\/wp\/v2\/users\/17"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.igalia.com\/jaragunde\/wp-json\/wp\/v2\/comments?post=853"}],"version-history":[{"count":8,"href":"https:\/\/blogs.igalia.com\/jaragunde\/wp-json\/wp\/v2\/posts\/853\/revisions"}],"predecessor-version":[{"id":920,"href":"https:\/\/blogs.igalia.com\/jaragunde\/wp-json\/wp\/v2\/posts\/853\/revisions\/920"}],"wp:attachment":[{"href":"https:\/\/blogs.igalia.com\/jaragunde\/wp-json\/wp\/v2\/media?parent=853"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.igalia.com\/jaragunde\/wp-json\/wp\/v2\/categories?post=853"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.igalia.com\/jaragunde\/wp-json\/wp\/v2\/tags?post=853"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}