• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Chromium Embedded Framework Authors.
2 // Portions copyright 2012 The Chromium Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 
6 #include "libcef/common/chrome/chrome_main_delegate_cef.h"
7 
8 #include <tuple>
9 
10 #include "libcef/browser/chrome/chrome_browser_context.h"
11 #include "libcef/browser/chrome/chrome_content_browser_client_cef.h"
12 #include "libcef/common/cef_switches.h"
13 #include "libcef/common/command_line_impl.h"
14 #include "libcef/common/crash_reporting.h"
15 #include "libcef/common/resource_util.h"
16 #include "libcef/renderer/chrome/chrome_content_renderer_client_cef.h"
17 
18 #include "base/command_line.h"
19 #include "base/lazy_instance.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "components/embedder_support/switches.h"
22 #include "content/public/common/content_switches.h"
23 #include "sandbox/policy/switches.h"
24 #include "third_party/blink/public/common/switches.h"
25 #include "ui/base/ui_base_switches.h"
26 
27 #if BUILDFLAG(IS_MAC)
28 #include "libcef/common/util_mac.h"
29 #endif
30 
31 namespace {
32 
33 base::LazyInstance<ChromeContentRendererClientCef>::DestructorAtExit
34     g_chrome_content_renderer_client = LAZY_INSTANCE_INITIALIZER;
35 
36 }  // namespace
37 
ChromeMainDelegateCef(CefMainRunnerHandler * runner,CefSettings * settings,CefRefPtr<CefApp> application)38 ChromeMainDelegateCef::ChromeMainDelegateCef(CefMainRunnerHandler* runner,
39                                              CefSettings* settings,
40                                              CefRefPtr<CefApp> application)
41     : ChromeMainDelegate(base::TimeTicks::Now()),
42       runner_(runner),
43       settings_(settings),
44       application_(application) {
45 #if BUILDFLAG(IS_LINUX)
46   resource_util::OverrideAssetPath();
47 #endif
48 }
49 
50 ChromeMainDelegateCef::~ChromeMainDelegateCef() = default;
51 
BasicStartupComplete(int * exit_code)52 bool ChromeMainDelegateCef::BasicStartupComplete(int* exit_code) {
53   // Returns false if startup should proceed.
54   bool result = ChromeMainDelegate::BasicStartupComplete(exit_code);
55   if (result)
56     return true;
57 
58   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
59 
60 #if BUILDFLAG(IS_POSIX)
61   // Read the crash configuration file. Platforms using Breakpad also add a
62   // command-line switch. On Windows this is done from chrome_elf.
63   crash_reporting::BasicStartupComplete(command_line);
64 #endif
65 
66   const std::string& process_type =
67       command_line->GetSwitchValueASCII(switches::kProcessType);
68   if (process_type.empty()) {
69     // In the browser process. Populate the global command-line object.
70     // TODO(chrome-runtime): Copy more settings from AlloyMainDelegate and test.
71     if (settings_->command_line_args_disabled) {
72       // Remove any existing command-line arguments.
73       base::CommandLine::StringVector argv;
74       argv.push_back(command_line->GetProgram().value());
75       command_line->InitFromArgv(argv);
76 
77       const base::CommandLine::SwitchMap& map = command_line->GetSwitches();
78       const_cast<base::CommandLine::SwitchMap*>(&map)->clear();
79     }
80 
81     bool no_sandbox = settings_->no_sandbox ? true : false;
82 
83     if (no_sandbox) {
84       command_line->AppendSwitch(sandbox::policy::switches::kNoSandbox);
85     }
86 
87     if (settings_->user_agent.length > 0) {
88       command_line->AppendSwitchASCII(
89           embedder_support::kUserAgent,
90           CefString(&settings_->user_agent).ToString());
91     } else if (settings_->user_agent_product.length > 0) {
92       command_line->AppendSwitchASCII(
93           switches::kUserAgentProductAndVersion,
94           CefString(&settings_->user_agent_product).ToString());
95     }
96 
97     if (settings_->locale.length > 0) {
98       command_line->AppendSwitchASCII(switches::kLang,
99                                       CefString(&settings_->locale).ToString());
100     } else if (!command_line->HasSwitch(switches::kLang)) {
101       command_line->AppendSwitchASCII(switches::kLang, "en-US");
102     }
103 
104     if (settings_->javascript_flags.length > 0) {
105       command_line->AppendSwitchASCII(
106           blink::switches::kJavaScriptFlags,
107           CefString(&settings_->javascript_flags).ToString());
108     }
109 
110     if (settings_->remote_debugging_port >= 1024 &&
111         settings_->remote_debugging_port <= 65535) {
112       command_line->AppendSwitchASCII(
113           switches::kRemoteDebuggingPort,
114           base::NumberToString(settings_->remote_debugging_port));
115     }
116 
117     if (settings_->uncaught_exception_stack_size > 0) {
118       command_line->AppendSwitchASCII(
119           switches::kUncaughtExceptionStackSize,
120           base::NumberToString(settings_->uncaught_exception_stack_size));
121     }
122   }
123 
124   if (application_) {
125     // Give the application a chance to view/modify the command line.
126     CefRefPtr<CefCommandLineImpl> commandLinePtr(
127         new CefCommandLineImpl(command_line, false, false));
128     application_->OnBeforeCommandLineProcessing(process_type,
129                                                 commandLinePtr.get());
130     std::ignore = commandLinePtr->Detach(nullptr);
131   }
132 
133 #if BUILDFLAG(IS_MAC)
134   util_mac::BasicStartupComplete();
135 #endif
136 
137   return false;
138 }
139 
PreSandboxStartup()140 void ChromeMainDelegateCef::PreSandboxStartup() {
141   const base::CommandLine* command_line =
142       base::CommandLine::ForCurrentProcess();
143   const std::string& process_type =
144       command_line->GetSwitchValueASCII(switches::kProcessType);
145 
146 #if BUILDFLAG(IS_MAC)
147   if (process_type.empty()) {
148     util_mac::PreSandboxStartup();
149   }
150 #endif  // BUILDFLAG(IS_MAC)
151 
152   // Since this may be configured via CefSettings we override the value on
153   // all platforms. We can't use the default implementation on macOS because
154   // chrome::GetDefaultUserDataDirectory expects to find the Chromium version
155   // number in the app bundle path.
156   resource_util::OverrideUserDataDir(settings_, command_line);
157 
158   ChromeMainDelegate::PreSandboxStartup();
159 
160   // Initialize crash reporting state for this process/module.
161   // chrome::DIR_CRASH_DUMPS must be configured before calling this function.
162   crash_reporting::PreSandboxStartup(*command_line, process_type);
163 }
164 
PreBrowserMain()165 void ChromeMainDelegateCef::PreBrowserMain() {
166   // The parent ChromeMainDelegate implementation creates the NSApplication
167   // instance on macOS, and we intentionally don't want to do that here.
168   // TODO(macos): Do we need l10n_util::OverrideLocaleWithCocoaLocale()?
169   runner_->PreBrowserMain();
170 }
171 
172 absl::variant<int, content::MainFunctionParams>
RunProcess(const std::string & process_type,content::MainFunctionParams main_function_params)173 ChromeMainDelegateCef::RunProcess(
174     const std::string& process_type,
175     content::MainFunctionParams main_function_params) {
176   if (process_type.empty()) {
177     return runner_->RunMainProcess(std::move(main_function_params));
178   }
179 
180   return ChromeMainDelegate::RunProcess(process_type,
181                                         std::move(main_function_params));
182 }
183 
184 #if BUILDFLAG(IS_LINUX)
ZygoteForked()185 void ChromeMainDelegateCef::ZygoteForked() {
186   ChromeMainDelegate::ZygoteForked();
187 
188   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
189   const std::string& process_type =
190       command_line->GetSwitchValueASCII(switches::kProcessType);
191 
192   // Initialize crash reporting state for the newly forked process.
193   crash_reporting::ZygoteForked(command_line, process_type);
194 }
195 #endif  // BUILDFLAG(IS_LINUX)
196 
CreateContentClient()197 content::ContentClient* ChromeMainDelegateCef::CreateContentClient() {
198   return &chrome_content_client_cef_;
199 }
200 
201 content::ContentBrowserClient*
CreateContentBrowserClient()202 ChromeMainDelegateCef::CreateContentBrowserClient() {
203   // Match the logic in the parent ChromeMainDelegate implementation, but create
204   // our own object type.
205   chrome_content_browser_client_ =
206       std::make_unique<ChromeContentBrowserClientCef>();
207   return chrome_content_browser_client_.get();
208 }
209 
210 content::ContentRendererClient*
CreateContentRendererClient()211 ChromeMainDelegateCef::CreateContentRendererClient() {
212   return g_chrome_content_renderer_client.Pointer();
213 }
214 
GetGlobalRequestContext()215 CefRefPtr<CefRequestContext> ChromeMainDelegateCef::GetGlobalRequestContext() {
216   auto browser_client = content_browser_client();
217   if (browser_client)
218     return browser_client->request_context();
219   return nullptr;
220 }
221 
CreateNewBrowserContext(const CefRequestContextSettings & settings,base::OnceClosure initialized_cb)222 CefBrowserContext* ChromeMainDelegateCef::CreateNewBrowserContext(
223     const CefRequestContextSettings& settings,
224     base::OnceClosure initialized_cb) {
225   auto context = new ChromeBrowserContext(settings);
226   context->InitializeAsync(std::move(initialized_cb));
227   return context;
228 }
229 
230 scoped_refptr<base::SingleThreadTaskRunner>
GetBackgroundTaskRunner()231 ChromeMainDelegateCef::GetBackgroundTaskRunner() {
232   auto browser_client = content_browser_client();
233   if (browser_client)
234     return browser_client->background_task_runner();
235   return nullptr;
236 }
237 
238 scoped_refptr<base::SingleThreadTaskRunner>
GetUserVisibleTaskRunner()239 ChromeMainDelegateCef::GetUserVisibleTaskRunner() {
240   auto browser_client = content_browser_client();
241   if (browser_client)
242     return browser_client->user_visible_task_runner();
243   return nullptr;
244 }
245 
246 scoped_refptr<base::SingleThreadTaskRunner>
GetUserBlockingTaskRunner()247 ChromeMainDelegateCef::GetUserBlockingTaskRunner() {
248   auto browser_client = content_browser_client();
249   if (browser_client)
250     return browser_client->user_blocking_task_runner();
251   return nullptr;
252 }
253 
254 scoped_refptr<base::SingleThreadTaskRunner>
GetRenderTaskRunner()255 ChromeMainDelegateCef::GetRenderTaskRunner() {
256   auto renderer_client = content_renderer_client();
257   if (renderer_client)
258     return renderer_client->render_task_runner();
259   return nullptr;
260 }
261 
262 scoped_refptr<base::SingleThreadTaskRunner>
GetWebWorkerTaskRunner()263 ChromeMainDelegateCef::GetWebWorkerTaskRunner() {
264   auto renderer_client = content_renderer_client();
265   if (renderer_client)
266     return renderer_client->GetCurrentTaskRunner();
267   return nullptr;
268 }
269 
content_browser_client() const270 ChromeContentBrowserClientCef* ChromeMainDelegateCef::content_browser_client()
271     const {
272   return static_cast<ChromeContentBrowserClientCef*>(
273       chrome_content_browser_client_.get());
274 }
275 
content_renderer_client() const276 ChromeContentRendererClientCef* ChromeMainDelegateCef::content_renderer_client()
277     const {
278   if (!g_chrome_content_renderer_client.IsCreated())
279     return nullptr;
280   return g_chrome_content_renderer_client.Pointer();
281 }