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