• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 The Chromium Embedded Framework Authors.
2 // Portions copyright (c) 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/renderer/alloy/alloy_content_renderer_client.h"
7 
8 #include <utility>
9 
10 #include "base/compiler_specific.h"
11 
12 // Enable deprecation warnings on Windows. See http://crbug.com/585142.
13 #if BUILDFLAG(IS_WIN)
14 #if defined(__clang__)
15 #pragma GCC diagnostic push
16 #pragma GCC diagnostic error "-Wdeprecated-declarations"
17 #else
18 #pragma warning(push)
19 #pragma warning(default : 4996)
20 #endif
21 #endif
22 
23 #include "libcef/browser/alloy/alloy_content_browser_client.h"
24 #include "libcef/browser/context.h"
25 #include "libcef/common/alloy/alloy_content_client.h"
26 #include "libcef/common/app_manager.h"
27 #include "libcef/common/cef_switches.h"
28 #include "libcef/common/extensions/extensions_client.h"
29 #include "libcef/common/extensions/extensions_util.h"
30 #include "libcef/common/request_impl.h"
31 #include "libcef/features/runtime_checks.h"
32 #include "libcef/renderer/alloy/alloy_render_thread_observer.h"
33 #include "libcef/renderer/alloy/url_loader_throttle_provider_impl.h"
34 #include "libcef/renderer/browser_impl.h"
35 #include "libcef/renderer/extensions/extensions_renderer_client.h"
36 #include "libcef/renderer/extensions/print_render_frame_helper_delegate.h"
37 #include "libcef/renderer/render_frame_observer.h"
38 #include "libcef/renderer/render_manager.h"
39 #include "libcef/renderer/thread_util.h"
40 
41 #include "base/command_line.h"
42 #include "base/memory/ptr_util.h"
43 #include "base/metrics/user_metrics_action.h"
44 #include "base/path_service.h"
45 #include "base/stl_util.h"
46 #include "base/strings/utf_string_conversions.h"
47 #include "base/task/post_task.h"
48 #include "build/build_config.h"
49 #include "chrome/common/chrome_switches.h"
50 #include "chrome/common/pdf_util.h"
51 #include "chrome/common/url_constants.h"
52 #include "chrome/renderer/browser_exposed_renderer_interfaces.h"
53 #include "chrome/renderer/chrome_content_renderer_client.h"
54 #include "chrome/renderer/extensions/chrome_extensions_renderer_client.h"
55 #include "chrome/renderer/loadtimes_extension_bindings.h"
56 #include "chrome/renderer/pepper/chrome_pdf_print_client.h"
57 #include "chrome/renderer/pepper/pepper_helper.h"
58 #include "chrome/renderer/plugins/chrome_plugin_placeholder.h"
59 #include "components/content_settings/core/common/content_settings_types.h"
60 #include "components/nacl/common/nacl_constants.h"
61 #include "components/pdf/common/internal_plugin_helpers.h"
62 #include "components/pdf/renderer/internal_plugin_renderer_helpers.h"
63 #include "components/pdf/renderer/pdf_find_in_page.h"
64 #include "components/printing/renderer/print_render_frame_helper.h"
65 #include "components/spellcheck/renderer/spellcheck.h"
66 #include "components/spellcheck/renderer/spellcheck_provider.h"
67 #include "components/visitedlink/renderer/visitedlink_reader.h"
68 #include "components/web_cache/renderer/web_cache_impl.h"
69 #include "content/public/browser/browser_task_traits.h"
70 #include "content/public/browser/browser_thread.h"
71 #include "content/public/browser/render_process_host.h"
72 #include "content/public/child/child_thread.h"
73 #include "content/public/common/content_constants.h"
74 #include "content/public/common/content_paths.h"
75 #include "content/public/common/content_switches.h"
76 #include "content/public/common/url_constants.h"
77 #include "content/public/renderer/render_view.h"
78 #include "content/public/renderer/render_view_visitor.h"
79 #include "extensions/common/switches.h"
80 #include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.h"
81 #include "extensions/renderer/renderer_extension_registry.h"
82 #include "ipc/ipc_sync_channel.h"
83 #include "media/base/media.h"
84 #include "mojo/public/cpp/bindings/binder_map.h"
85 #include "mojo/public/cpp/bindings/generic_pending_receiver.h"
86 #include "pdf/pdf_features.h"
87 #include "printing/print_settings.h"
88 #include "services/network/public/cpp/is_potentially_trustworthy.h"
89 #include "services/service_manager/public/cpp/connector.h"
90 #include "services/service_manager/public/cpp/interface_provider.h"
91 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
92 #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
93 #include "third_party/blink/public/platform/scheduler/web_renderer_process_type.h"
94 #include "third_party/blink/public/platform/url_conversion.h"
95 #include "third_party/blink/public/platform/web_runtime_features.h"
96 #include "third_party/blink/public/platform/web_string.h"
97 #include "third_party/blink/public/platform/web_url.h"
98 #include "third_party/blink/public/web/web_console_message.h"
99 #include "third_party/blink/public/web/web_element.h"
100 #include "third_party/blink/public/web/web_frame.h"
101 #include "third_party/blink/public/web/web_local_frame.h"
102 #include "third_party/blink/public/web/web_security_policy.h"
103 #include "third_party/blink/public/web/web_view.h"
104 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
105 #include "ui/base/l10n/l10n_util.h"
106 
107 #if BUILDFLAG(IS_MAC)
108 #include "base/mac/mac_util.h"
109 #include "base/strings/sys_string_conversions.h"
110 #endif
111 
AlloyContentRendererClient()112 AlloyContentRendererClient::AlloyContentRendererClient()
113     : main_entry_time_(base::TimeTicks::Now()),
114       render_manager_(new CefRenderManager) {
115   if (extensions::ExtensionsEnabled()) {
116     extensions_client_.reset(new extensions::CefExtensionsClient);
117     extensions::ExtensionsClient::Set(extensions_client_.get());
118     extensions_renderer_client_.reset(
119         new extensions::CefExtensionsRendererClient);
120     extensions::ExtensionsRendererClient::Set(
121         extensions_renderer_client_.get());
122   }
123 }
124 
~AlloyContentRendererClient()125 AlloyContentRendererClient::~AlloyContentRendererClient() {}
126 
127 // static
Get()128 AlloyContentRendererClient* AlloyContentRendererClient::Get() {
129   REQUIRE_ALLOY_RUNTIME();
130   return static_cast<AlloyContentRendererClient*>(
131       CefAppManager::Get()->GetContentClient()->renderer());
132 }
133 
134 scoped_refptr<base::SingleThreadTaskRunner>
GetCurrentTaskRunner()135 AlloyContentRendererClient::GetCurrentTaskRunner() {
136   // Check if currently on the render thread.
137   if (CEF_CURRENTLY_ON_RT())
138     return render_task_runner_;
139   return nullptr;
140 }
141 
RunSingleProcessCleanup()142 void AlloyContentRendererClient::RunSingleProcessCleanup() {
143   DCHECK(content::RenderProcessHost::run_renderer_in_process());
144 
145   // Make sure the render thread was actually started.
146   if (!render_task_runner_.get())
147     return;
148 
149   if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
150     RunSingleProcessCleanupOnUIThread();
151   } else {
152     base::PostTask(
153         FROM_HERE, {content::BrowserThread::UI},
154         base::BindOnce(
155             &AlloyContentRendererClient::RunSingleProcessCleanupOnUIThread,
156             base::Unretained(this)));
157   }
158 
159   // Wait for the render thread cleanup to complete. Spin instead of using
160   // base::WaitableEvent because calling Wait() is not allowed on the UI
161   // thread.
162   bool complete = false;
163   do {
164     {
165       base::AutoLock lock_scope(single_process_cleanup_lock_);
166       complete = single_process_cleanup_complete_;
167     }
168     if (!complete)
169       base::PlatformThread::YieldCurrentThread();
170   } while (!complete);
171 }
172 
PostIOThreadCreated(base::SingleThreadTaskRunner *)173 void AlloyContentRendererClient::PostIOThreadCreated(
174     base::SingleThreadTaskRunner*) {
175   // TODO(cef): Enable these once the implementation supports it.
176   blink::WebRuntimeFeatures::EnableNotifications(false);
177   blink::WebRuntimeFeatures::EnablePushMessaging(false);
178   blink::RuntimeEnabledFeatures::SetBadgingEnabled(false);
179 }
180 
RenderThreadStarted()181 void AlloyContentRendererClient::RenderThreadStarted() {
182   const base::CommandLine* command_line =
183       base::CommandLine::ForCurrentProcess();
184 
185   render_task_runner_ = base::ThreadTaskRunnerHandle::Get();
186   observer_ = std::make_unique<AlloyRenderThreadObserver>();
187   web_cache_impl_ = std::make_unique<web_cache::WebCacheImpl>();
188   visited_link_slave_ = std::make_unique<visitedlink::VisitedLinkReader>();
189 
190   content::RenderThread* thread = content::RenderThread::Get();
191 
192   const bool is_extension = CefRenderManager::IsExtensionProcess();
193 
194   thread->SetRendererProcessType(
195       is_extension
196           ? blink::scheduler::WebRendererProcessType::kExtensionRenderer
197           : blink::scheduler::WebRendererProcessType::kRenderer);
198 
199   if (is_extension) {
200     // The process name was set to "Renderer" in RendererMain(). Update it to
201     // "Extension Renderer" to highlight that it's hosting an extension.
202     base::trace_event::TraceLog::GetInstance()->set_process_name(
203         "Extension Renderer");
204   }
205 
206   thread->AddObserver(observer_.get());
207 
208   if (!command_line->HasSwitch(switches::kDisableSpellChecking)) {
209     spellcheck_ = std::make_unique<SpellCheck>(this);
210   }
211 
212   if (content::RenderProcessHost::run_renderer_in_process()) {
213     // When running in single-process mode register as a destruction observer
214     // on the render thread's MessageLoop.
215     base::CurrentThread::Get()->AddDestructionObserver(this);
216   }
217 
218 #if BUILDFLAG(IS_MAC)
219   {
220     base::ScopedCFTypeRef<CFStringRef> key(
221         base::SysUTF8ToCFStringRef("NSScrollViewRubberbanding"));
222     base::ScopedCFTypeRef<CFStringRef> value;
223 
224     // If the command-line switch is specified then set the value that will be
225     // checked in RenderThreadImpl::Init(). Otherwise, remove the application-
226     // level value.
227     if (command_line->HasSwitch(switches::kDisableScrollBounce))
228       value.reset(base::SysUTF8ToCFStringRef("false"));
229 
230     CFPreferencesSetAppValue(key, value, kCFPreferencesCurrentApplication);
231     CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
232   }
233 #endif  // BUILDFLAG(IS_MAC)
234 
235   if (extensions::PdfExtensionEnabled()) {
236     pdf_print_client_.reset(new ChromePDFPrintClient());
237     pdf::PepperPDFHost::SetPrintClient(pdf_print_client_.get());
238   }
239 
240   if (extensions::ExtensionsEnabled())
241     extensions_renderer_client_->RenderThreadStarted();
242 }
243 
ExposeInterfacesToBrowser(mojo::BinderMap * binders)244 void AlloyContentRendererClient::ExposeInterfacesToBrowser(
245     mojo::BinderMap* binders) {
246   auto task_runner = base::SequencedTaskRunnerHandle::Get();
247 
248   binders->Add(base::BindRepeating(&web_cache::WebCacheImpl::BindReceiver,
249                                    base::Unretained(web_cache_impl_.get())),
250                task_runner);
251 
252   binders->Add(visited_link_slave_->GetBindCallback(), task_runner);
253 
254   if (spellcheck_) {
255     binders->Add(
256         base::BindRepeating(
257             [](SpellCheck* spellcheck,
258                mojo::PendingReceiver<spellcheck::mojom::SpellChecker>
259                    receiver) { spellcheck->BindReceiver(std::move(receiver)); },
260             base::Unretained(spellcheck_.get())),
261         task_runner);
262   }
263 
264   render_manager_->ExposeInterfacesToBrowser(binders);
265 }
266 
RenderThreadConnected()267 void AlloyContentRendererClient::RenderThreadConnected() {
268   // Register extensions last because it will trigger WebKit initialization.
269   content::RenderThread* thread = content::RenderThread::Get();
270   thread->RegisterExtension(extensions_v8::LoadTimesExtension::Get());
271 
272   render_manager_->RenderThreadConnected();
273 }
274 
RenderFrameCreated(content::RenderFrame * render_frame)275 void AlloyContentRendererClient::RenderFrameCreated(
276     content::RenderFrame* render_frame) {
277   auto render_frame_observer = new CefRenderFrameObserver(render_frame);
278 
279   new PepperHelper(render_frame);
280 
281   if (extensions::ExtensionsEnabled()) {
282     extensions_renderer_client_->RenderFrameCreated(
283         render_frame, render_frame_observer->registry());
284 
285     render_frame_observer->associated_interfaces()->AddInterface(
286         base::BindRepeating(
287             &extensions::MimeHandlerViewContainerManager::BindReceiver,
288             render_frame->GetRoutingID()));
289   }
290 
291   const base::CommandLine* command_line =
292       base::CommandLine::ForCurrentProcess();
293   if (!command_line->HasSwitch(switches::kDisableSpellChecking)) {
294     new SpellCheckProvider(render_frame, spellcheck_.get(), this);
295   }
296 
297   bool browser_created;
298   absl::optional<bool> is_windowless;
299   render_manager_->RenderFrameCreated(render_frame, render_frame_observer,
300                                       browser_created, is_windowless);
301   if (browser_created) {
302     OnBrowserCreated(render_frame->GetRenderView(), is_windowless);
303   }
304 
305   if (is_windowless.has_value()) {
306     new printing::PrintRenderFrameHelper(
307         render_frame,
308         base::WrapUnique(
309             new extensions::CefPrintRenderFrameHelperDelegate(*is_windowless)));
310   }
311 
312   if (base::FeatureList::IsEnabled(chrome_pdf::features::kPdfUnseasoned)) {
313     render_frame_observer->associated_interfaces()->AddInterface(
314         base::BindRepeating(&pdf::PdfFindInPageFactory::BindReceiver,
315                             render_frame->GetRoutingID()));
316   }
317 }
318 
WebViewCreated(blink::WebView * web_view)319 void AlloyContentRendererClient::WebViewCreated(blink::WebView* web_view) {
320   bool browser_created;
321   absl::optional<bool> is_windowless;
322   render_manager_->WebViewCreated(web_view, browser_created, is_windowless);
323   if (browser_created) {
324     auto render_view = content::RenderView::FromWebView(web_view);
325     CHECK(render_view);
326     OnBrowserCreated(render_view, is_windowless);
327   }
328 }
329 
IsPluginHandledExternally(content::RenderFrame * render_frame,const blink::WebElement & plugin_element,const GURL & original_url,const std::string & mime_type)330 bool AlloyContentRendererClient::IsPluginHandledExternally(
331     content::RenderFrame* render_frame,
332     const blink::WebElement& plugin_element,
333     const GURL& original_url,
334     const std::string& mime_type) {
335   if (!extensions::ExtensionsEnabled())
336     return false;
337 
338   DCHECK(plugin_element.HasHTMLTagName("object") ||
339          plugin_element.HasHTMLTagName("embed"));
340   // Blink will next try to load a WebPlugin which would end up in
341   // OverrideCreatePlugin, sending another IPC only to find out the plugin is
342   // not supported. Here it suffices to return false but there should perhaps be
343   // a more unified approach to avoid sending the IPC twice.
344   chrome::mojom::PluginInfoPtr plugin_info = chrome::mojom::PluginInfo::New();
345   ChromeContentRendererClient::GetPluginInfoHost()->GetPluginInfo(
346       render_frame->GetRoutingID(), original_url,
347       render_frame->GetWebFrame()->Top()->GetSecurityOrigin(), mime_type,
348       &plugin_info);
349   // TODO(ekaramad): Not continuing here due to a disallowed status should take
350   // us to CreatePlugin. See if more in depths investigation of |status| is
351   // necessary here (see https://crbug.com/965747). For now, returning false
352   // should take us to CreatePlugin after HTMLPlugInElement which is called
353   // through HTMLPlugInElement::LoadPlugin code path.
354   if (plugin_info->status != chrome::mojom::PluginStatus::kAllowed &&
355       plugin_info->status !=
356           chrome::mojom::PluginStatus::kPlayImportantContent) {
357     // We could get here when a MimeHandlerView is loaded inside a <webview>
358     // which is using permissions API (see WebViewPluginTests).
359     ChromeExtensionsRendererClient::DidBlockMimeHandlerViewForDisallowedPlugin(
360         plugin_element);
361     return false;
362   }
363   if (plugin_info->actual_mime_type == pdf::kInternalPluginMimeType &&
364       pdf::IsInternalPluginExternallyHandled()) {
365     // Only actually treat the internal PDF plugin as externally handled if
366     // used within an origin allowed to create the internal PDF plugin;
367     // otherwise, let Blink try to create the in-process PDF plugin.
368     if (IsPdfInternalPluginAllowedOrigin(
369             render_frame->GetWebFrame()->GetSecurityOrigin())) {
370       return true;
371     }
372   }
373   return ChromeExtensionsRendererClient::MaybeCreateMimeHandlerView(
374       plugin_element, original_url, plugin_info->actual_mime_type,
375       plugin_info->plugin);
376 }
377 
OverrideCreatePlugin(content::RenderFrame * render_frame,const blink::WebPluginParams & params,blink::WebPlugin ** plugin)378 bool AlloyContentRendererClient::OverrideCreatePlugin(
379     content::RenderFrame* render_frame,
380     const blink::WebPluginParams& params,
381     blink::WebPlugin** plugin) {
382   std::string orig_mime_type = params.mime_type.Utf8();
383   if (extensions::ExtensionsEnabled() &&
384       !extensions_renderer_client_->OverrideCreatePlugin(render_frame,
385                                                          params)) {
386     return false;
387   }
388 
389   GURL url(params.url);
390   chrome::mojom::PluginInfoPtr plugin_info = chrome::mojom::PluginInfo::New();
391   ChromeContentRendererClient::GetPluginInfoHost()->GetPluginInfo(
392       render_frame->GetRoutingID(), url,
393       render_frame->GetWebFrame()->Top()->GetSecurityOrigin(), orig_mime_type,
394       &plugin_info);
395   *plugin = ChromeContentRendererClient::CreatePlugin(render_frame, params,
396                                                       *plugin_info);
397   return true;
398 }
399 
WillSendRequest(blink::WebLocalFrame * frame,ui::PageTransition transition_type,const blink::WebURL & url,const net::SiteForCookies & site_for_cookies,const url::Origin * initiator_origin,GURL * new_url)400 void AlloyContentRendererClient::WillSendRequest(
401     blink::WebLocalFrame* frame,
402     ui::PageTransition transition_type,
403     const blink::WebURL& url,
404     const net::SiteForCookies& site_for_cookies,
405     const url::Origin* initiator_origin,
406     GURL* new_url) {
407   if (extensions::ExtensionsEnabled()) {
408     extensions_renderer_client_->WillSendRequest(frame, transition_type, url,
409                                                  site_for_cookies,
410                                                  initiator_origin, new_url);
411     if (!new_url->is_empty())
412       return;
413   }
414 }
415 
VisitedLinkHash(const char * canonical_url,size_t length)416 uint64_t AlloyContentRendererClient::VisitedLinkHash(const char* canonical_url,
417                                                      size_t length) {
418   return visited_link_slave_->ComputeURLFingerprint(canonical_url, length);
419 }
420 
IsLinkVisited(uint64_t link_hash)421 bool AlloyContentRendererClient::IsLinkVisited(uint64_t link_hash) {
422   return visited_link_slave_->IsVisited(link_hash);
423 }
424 
IsOriginIsolatedPepperPlugin(const base::FilePath & plugin_path)425 bool AlloyContentRendererClient::IsOriginIsolatedPepperPlugin(
426     const base::FilePath& plugin_path) {
427   // Isolate all the plugins (including the PDF plugin).
428   return true;
429 }
430 
AddSupportedKeySystems(std::vector<std::unique_ptr<::media::KeySystemProperties>> * key_systems)431 void AlloyContentRendererClient::AddSupportedKeySystems(
432     std::vector<std::unique_ptr<::media::KeySystemProperties>>* key_systems) {
433   key_systems_provider_.AddSupportedKeySystems(key_systems);
434 }
435 
IsKeySystemsUpdateNeeded()436 bool AlloyContentRendererClient::IsKeySystemsUpdateNeeded() {
437   return key_systems_provider_.IsKeySystemsUpdateNeeded();
438 }
439 
RunScriptsAtDocumentStart(content::RenderFrame * render_frame)440 void AlloyContentRendererClient::RunScriptsAtDocumentStart(
441     content::RenderFrame* render_frame) {
442   if (extensions::ExtensionsEnabled())
443     extensions_renderer_client_->RunScriptsAtDocumentStart(render_frame);
444 }
445 
RunScriptsAtDocumentEnd(content::RenderFrame * render_frame)446 void AlloyContentRendererClient::RunScriptsAtDocumentEnd(
447     content::RenderFrame* render_frame) {
448   if (extensions::ExtensionsEnabled())
449     extensions_renderer_client_->RunScriptsAtDocumentEnd(render_frame);
450 }
451 
RunScriptsAtDocumentIdle(content::RenderFrame * render_frame)452 void AlloyContentRendererClient::RunScriptsAtDocumentIdle(
453     content::RenderFrame* render_frame) {
454   if (extensions::ExtensionsEnabled())
455     extensions_renderer_client_->RunScriptsAtDocumentIdle(render_frame);
456 }
457 
DevToolsAgentAttached()458 void AlloyContentRendererClient::DevToolsAgentAttached() {
459   // WebWorkers may be creating agents on a different thread.
460   if (!render_task_runner_->BelongsToCurrentThread()) {
461     render_task_runner_->PostTask(
462         FROM_HERE,
463         base::BindOnce(&AlloyContentRendererClient::DevToolsAgentAttached,
464                        base::Unretained(this)));
465     return;
466   }
467 
468   render_manager_->DevToolsAgentAttached();
469 }
470 
DevToolsAgentDetached()471 void AlloyContentRendererClient::DevToolsAgentDetached() {
472   // WebWorkers may be creating agents on a different thread.
473   if (!render_task_runner_->BelongsToCurrentThread()) {
474     render_task_runner_->PostTask(
475         FROM_HERE,
476         base::BindOnce(&AlloyContentRendererClient::DevToolsAgentDetached,
477                        base::Unretained(this)));
478     return;
479   }
480 
481   render_manager_->DevToolsAgentDetached();
482 }
483 
484 std::unique_ptr<blink::URLLoaderThrottleProvider>
CreateURLLoaderThrottleProvider(blink::URLLoaderThrottleProviderType provider_type)485 AlloyContentRendererClient::CreateURLLoaderThrottleProvider(
486     blink::URLLoaderThrottleProviderType provider_type) {
487   return std::make_unique<CefURLLoaderThrottleProviderImpl>(provider_type);
488 }
489 
GetInterface(const std::string & interface_name,mojo::ScopedMessagePipeHandle interface_pipe)490 void AlloyContentRendererClient::GetInterface(
491     const std::string& interface_name,
492     mojo::ScopedMessagePipeHandle interface_pipe) {
493   // TODO(crbug.com/977637): Get rid of the use of this implementation of
494   // |service_manager::LocalInterfaceProvider|. This was done only to avoid
495   // churning spellcheck code while eliminating the "chrome" and
496   // "chrome_renderer" services. Spellcheck is (and should remain) the only
497   // consumer of this implementation.
498   content::RenderThread::Get()->BindHostReceiver(
499       mojo::GenericPendingReceiver(interface_name, std::move(interface_pipe)));
500 }
501 
WillDestroyCurrentMessageLoop()502 void AlloyContentRendererClient::WillDestroyCurrentMessageLoop() {
503   base::AutoLock lock_scope(single_process_cleanup_lock_);
504   single_process_cleanup_complete_ = true;
505 }
506 
OnBrowserCreated(content::RenderView * render_view,absl::optional<bool> is_windowless)507 void AlloyContentRendererClient::OnBrowserCreated(
508     content::RenderView* render_view,
509     absl::optional<bool> is_windowless) {
510 #if BUILDFLAG(IS_MAC)
511   const bool windowless = is_windowless.has_value() && *is_windowless;
512 
513   // FIXME: It would be better if this API would be a callback from the
514   // WebKit layer, or if it would be exposed as an WebView instance method; the
515   // current implementation uses a static variable, and WebKit needs to be
516   // patched in order to make it work for each WebView instance
517   render_view->GetWebView()->SetUseExternalPopupMenusThisInstance(!windowless);
518 #endif
519 }
520 
RunSingleProcessCleanupOnUIThread()521 void AlloyContentRendererClient::RunSingleProcessCleanupOnUIThread() {
522   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
523 
524   // Clean up the single existing RenderProcessHost.
525   content::RenderProcessHost* host = nullptr;
526   content::RenderProcessHost::iterator iterator(
527       content::RenderProcessHost::AllHostsIterator());
528   if (!iterator.IsAtEnd()) {
529     host = iterator.GetCurrentValue();
530     host->Cleanup();
531     iterator.Advance();
532     DCHECK(iterator.IsAtEnd());
533   }
534   DCHECK(host);
535 
536   // Clear the run_renderer_in_process() flag to avoid a DCHECK in the
537   // RenderProcessHost destructor.
538   content::RenderProcessHost::SetRunRendererInProcess(false);
539 
540   // Deletion of the RenderProcessHost object will stop the render thread and
541   // result in a call to WillDestroyCurrentMessageLoop.
542   // Cleanup() will cause deletion to be posted as a task on the UI thread but
543   // this task will only execute when running in multi-threaded message loop
544   // mode (because otherwise the UI message loop has already stopped). Therefore
545   // we need to explicitly delete the object when not running in this mode.
546   if (!CefContext::Get()->settings().multi_threaded_message_loop)
547     delete host;
548 }
549 
550 // Enable deprecation warnings on Windows. See http://crbug.com/585142.
551 #if BUILDFLAG(IS_WIN)
552 #if defined(__clang__)
553 #pragma GCC diagnostic pop
554 #else
555 #pragma warning(pop)
556 #endif
557 #endif
558