1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "extensions/renderer/dispatcher.h"
6 
7 #include <stddef.h>
8 
9 #include <algorithm>
10 #include <memory>
11 #include <utility>
12 
13 #include "base/bind.h"
14 #include "base/callback.h"
15 #include "base/callback_helpers.h"
16 #include "base/debug/alias.h"
17 #include "base/feature_list.h"
18 #include "base/lazy_instance.h"
19 #include "base/memory/ptr_util.h"
20 #include "base/metrics/histogram_macros.h"
21 #include "base/stl_util.h"
22 #include "base/strings/string_piece.h"
23 #include "base/strings/string_util.h"
24 #include "base/strings/utf_string_conversions.h"
25 #include "base/time/time.h"
26 #include "base/values.h"
27 #include "build/build_config.h"
28 #include "content/public/common/content_features.h"
29 #include "content/public/common/content_switches.h"
30 #include "content/public/renderer/render_frame.h"
31 #include "content/public/renderer/render_thread.h"
32 #include "content/public/renderer/v8_value_converter.h"
33 #include "extensions/common/api/messaging/message.h"
34 #include "extensions/common/constants.h"
35 #include "extensions/common/cors_util.h"
36 #include "extensions/common/extension.h"
37 #include "extensions/common/extension_api.h"
38 #include "extensions/common/extension_messages.h"
39 #include "extensions/common/extension_urls.h"
40 #include "extensions/common/extensions_client.h"
41 #include "extensions/common/features/behavior_feature.h"
42 #include "extensions/common/features/feature.h"
43 #include "extensions/common/features/feature_channel.h"
44 #include "extensions/common/features/feature_provider.h"
45 #include "extensions/common/manifest.h"
46 #include "extensions/common/manifest_constants.h"
47 #include "extensions/common/manifest_handlers/background_info.h"
48 #include "extensions/common/manifest_handlers/options_page_info.h"
49 #include "extensions/common/message_bundle.h"
50 #include "extensions/common/permissions/permission_set.h"
51 #include "extensions/common/permissions/permissions_data.h"
52 #include "extensions/common/switches.h"
53 #include "extensions/common/view_type.h"
54 #include "extensions/grit/extensions_renderer_resources.h"
55 #include "extensions/renderer/api/automation/automation_internal_custom_bindings.h"
56 #include "extensions/renderer/api_activity_logger.h"
57 #include "extensions/renderer/api_definitions_natives.h"
58 #include "extensions/renderer/app_window_custom_bindings.h"
59 #include "extensions/renderer/blob_native_handler.h"
60 #include "extensions/renderer/content_watcher.h"
61 #include "extensions/renderer/context_menus_custom_bindings.h"
62 #include "extensions/renderer/dispatcher_delegate.h"
63 #include "extensions/renderer/display_source_custom_bindings.h"
64 #include "extensions/renderer/dom_activity_logger.h"
65 #include "extensions/renderer/extension_frame_helper.h"
66 #include "extensions/renderer/extension_interaction_provider.h"
67 #include "extensions/renderer/extensions_renderer_client.h"
68 #include "extensions/renderer/file_system_natives.h"
69 #include "extensions/renderer/guest_view/guest_view_internal_custom_bindings.h"
70 #include "extensions/renderer/id_generator_custom_bindings.h"
71 #include "extensions/renderer/ipc_message_sender.h"
72 #include "extensions/renderer/logging_native_handler.h"
73 #include "extensions/renderer/messaging_bindings.h"
74 #include "extensions/renderer/messaging_util.h"
75 #include "extensions/renderer/module_system.h"
76 #include "extensions/renderer/native_extension_bindings_system.h"
77 #include "extensions/renderer/native_renderer_messaging_service.h"
78 #include "extensions/renderer/process_info_native_handler.h"
79 #include "extensions/renderer/render_frame_observer_natives.h"
80 #include "extensions/renderer/renderer_extension_registry.h"
81 #include "extensions/renderer/runtime_custom_bindings.h"
82 #include "extensions/renderer/safe_builtins.h"
83 #include "extensions/renderer/script_context.h"
84 #include "extensions/renderer/script_context_set.h"
85 #include "extensions/renderer/script_injection.h"
86 #include "extensions/renderer/script_injection_manager.h"
87 #include "extensions/renderer/set_icon_natives.h"
88 #include "extensions/renderer/static_v8_external_one_byte_string_resource.h"
89 #include "extensions/renderer/test_features_native_handler.h"
90 #include "extensions/renderer/test_native_handler.h"
91 #include "extensions/renderer/user_gestures_native_handler.h"
92 #include "extensions/renderer/utils_native_handler.h"
93 #include "extensions/renderer/v8_context_native_handler.h"
94 #include "extensions/renderer/v8_helpers.h"
95 #include "extensions/renderer/wake_event_page.h"
96 #include "extensions/renderer/worker_script_context_set.h"
97 #include "extensions/renderer/worker_thread_dispatcher.h"
98 #include "extensions/renderer/worker_thread_util.h"
99 #include "gin/converter.h"
100 #include "mojo/public/js/grit/mojo_bindings_resources.h"
101 #include "services/network/public/mojom/cors.mojom.h"
102 #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
103 #include "third_party/blink/public/mojom/frame/user_activation_notification_type.mojom.h"
104 #include "third_party/blink/public/platform/web_string.h"
105 #include "third_party/blink/public/platform/web_url_request.h"
106 #include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h"
107 #include "third_party/blink/public/web/web_custom_element.h"
108 #include "third_party/blink/public/web/web_document.h"
109 #include "third_party/blink/public/web/web_frame.h"
110 #include "third_party/blink/public/web/web_local_frame.h"
111 #include "third_party/blink/public/web/web_script_controller.h"
112 #include "third_party/blink/public/web/web_security_policy.h"
113 #include "third_party/blink/public/web/web_settings.h"
114 #include "third_party/blink/public/web/web_view.h"
115 #include "ui/base/layout.h"
116 #include "ui/base/resource/resource_bundle.h"
117 #include "v8/include/v8.h"
118 
119 using blink::WebDocument;
120 using blink::WebSecurityPolicy;
121 using blink::WebString;
122 using blink::WebView;
123 using content::RenderThread;
124 
125 namespace extensions {
126 
127 // Constant to define the default profile id for the renderer to 0.
128 // Since each renderer is associated with a single context, we don't need
129 // separate ids for the profile.
130 const int kRendererProfileId = 0;
131 
132 namespace {
133 
134 static const char kOnSuspendEvent[] = "runtime.onSuspend";
135 static const char kOnSuspendCanceledEvent[] = "runtime.onSuspendCanceled";
136 
CrashOnException(const v8::TryCatch & trycatch)137 void CrashOnException(const v8::TryCatch& trycatch) {
138   NOTREACHED();
139 }
140 
141 // Calls a method |method_name| in a module |module_name| belonging to the
142 // module system from |context|. Intended as a callback target from
143 // ScriptContextSet::ForEach.
CallModuleMethod(const std::string & module_name,const std::string & method_name,const base::ListValue * args,ScriptContext * context)144 void CallModuleMethod(const std::string& module_name,
145                       const std::string& method_name,
146                       const base::ListValue* args,
147                       ScriptContext* context) {
148   v8::HandleScope handle_scope(context->isolate());
149   v8::Context::Scope context_scope(context->v8_context());
150 
151   std::unique_ptr<content::V8ValueConverter> converter =
152       content::V8ValueConverter::Create();
153 
154   std::vector<v8::Local<v8::Value>> arguments;
155   for (const auto& arg : *args) {
156     arguments.push_back(converter->ToV8Value(&arg, context->v8_context()));
157   }
158 
159   context->module_system()->CallModuleMethodSafe(
160       module_name, method_name, &arguments);
161 }
162 
163 // This handles the "chrome." root API object in script contexts.
164 class ChromeNativeHandler : public ObjectBackedNativeHandler {
165  public:
ChromeNativeHandler(ScriptContext * context)166   explicit ChromeNativeHandler(ScriptContext* context)
167       : ObjectBackedNativeHandler(context) {}
168 
169   // ObjectBackedNativeHandler:
AddRoutes()170   void AddRoutes() override {
171     RouteHandlerFunction("GetChrome",
172                          base::BindRepeating(&ChromeNativeHandler::GetChrome,
173                                              base::Unretained(this)));
174   }
175 
GetChrome(const v8::FunctionCallbackInfo<v8::Value> & args)176   void GetChrome(const v8::FunctionCallbackInfo<v8::Value>& args) {
177     // Check for the chrome property. If one doesn't exist, create one.
178     v8::Local<v8::String> chrome_string(
179         v8::String::NewFromUtf8(context()->isolate(), "chrome",
180                                 v8::NewStringType::kInternalized)
181             .ToLocalChecked());
182     v8::Local<v8::Object> global(context()->v8_context()->Global());
183     // TODO(crbug.com/913942): Possibly replace ToLocalChecked here with
184     // actual error handling.
185     v8::Local<v8::Value> chrome(
186         global->Get(context()->v8_context(), chrome_string).ToLocalChecked());
187     if (chrome->IsUndefined()) {
188       chrome = v8::Object::New(context()->isolate());
189       global->Set(context()->v8_context(), chrome_string, chrome).ToChecked();
190     }
191     args.GetReturnValue().Set(chrome);
192   }
193 };
194 
195 class HandleScopeHelper {
196  public:
HandleScopeHelper(ScriptContext * script_context)197   HandleScopeHelper(ScriptContext* script_context)
198       : handle_scope_(script_context->isolate()),
199         context_scope_(script_context->v8_context()) {}
200 
201  private:
202   v8::HandleScope handle_scope_;
203   v8::Context::Scope context_scope_;
204 
205   DISALLOW_COPY_AND_ASSIGN(HandleScopeHelper);
206 };
207 
208 base::LazyInstance<WorkerScriptContextSet>::DestructorAtExit
209     g_worker_script_context_set = LAZY_INSTANCE_INITIALIZER;
210 
211 }  // namespace
212 
PendingServiceWorker(blink::WebServiceWorkerContextProxy * context_proxy)213 Dispatcher::PendingServiceWorker::PendingServiceWorker(
214     blink::WebServiceWorkerContextProxy* context_proxy)
215     : task_runner(base::ThreadTaskRunnerHandle::Get()),
216       context_proxy(context_proxy) {
217   DCHECK(context_proxy);
218 }
219 
220 Dispatcher::PendingServiceWorker::~PendingServiceWorker() = default;
221 
222 // Note that we can't use Blink public APIs in the constructor becase Blink
223 // is not initialized at the point we create Dispatcher.
Dispatcher(std::unique_ptr<DispatcherDelegate> delegate)224 Dispatcher::Dispatcher(std::unique_ptr<DispatcherDelegate> delegate)
225     : delegate_(std::move(delegate)),
226       content_watcher_(new ContentWatcher()),
227       source_map_(&ui::ResourceBundle::GetSharedInstance()),
228       v8_schema_registry_(new V8SchemaRegistry),
229       user_script_set_manager_observer_(this),
230       activity_logging_enabled_(false),
231       receiver_(this) {
232   bindings_system_ = CreateBindingsSystem(
233       IPCMessageSender::CreateMainThreadIPCMessageSender());
234 
235   script_context_set_.reset(new ScriptContextSet(&active_extension_ids_));
236   user_script_set_manager_.reset(new UserScriptSetManager());
237   script_injection_manager_.reset(
238       new ScriptInjectionManager(user_script_set_manager_.get()));
239   user_script_set_manager_observer_.Add(user_script_set_manager_.get());
240   PopulateSourceMap();
241   WakeEventPage::Get()->Init(RenderThread::Get());
242   // Ideally this should be done after checking
243   // ExtensionAPIEnabledInExtensionServiceWorkers(), but the Dispatcher is
244   // created so early that sending an IPC from browser/ process to synchronize
245   // this enabled-ness is too late.
246   WorkerThreadDispatcher::Get()->Init(RenderThread::Get());
247 
248   // Register WebSecurityPolicy whitelists for the chrome-extension:// scheme.
249   WebString extension_scheme(WebString::FromASCII(kExtensionScheme));
250 
251   // Extension resources are HTTP-like and safe to expose to the fetch API. The
252   // rules for the fetch API are consistent with XHR.
253   WebSecurityPolicy::RegisterURLSchemeAsSupportingFetchAPI(extension_scheme);
254 
255   // Extension resources, when loaded as the top-level document, should bypass
256   // Blink's strict first-party origin checks.
257   WebSecurityPolicy::RegisterURLSchemeAsFirstPartyWhenTopLevel(
258       extension_scheme);
259 
260   // Disallow running javascript URLs on the chrome-extension scheme.
261   WebSecurityPolicy::RegisterURLSchemeAsNotAllowingJavascriptURLs(
262       extension_scheme);
263 
264   // Initialize host permissions for any extensions that were activated before
265   // WebKit was initialized.
266   for (const std::string& extension_id : active_extension_ids_) {
267     const Extension* extension =
268         RendererExtensionRegistry::Get()->GetByID(extension_id);
269     CHECK(extension);
270     InitOriginPermissions(extension);
271   }
272 
273   EnableCustomElementWhiteList();
274 }
275 
~Dispatcher()276 Dispatcher::~Dispatcher() {
277 }
278 
279 // static
GetWorkerScriptContextSet()280 WorkerScriptContextSet* Dispatcher::GetWorkerScriptContextSet() {
281   return &(g_worker_script_context_set.Get());
282 }
283 
OnRenderThreadStarted(content::RenderThread * thread)284 void Dispatcher::OnRenderThreadStarted(content::RenderThread* thread) {
285   thread->RegisterExtension(extensions::SafeBuiltins::CreateV8Extension());
286 }
287 
OnRenderFrameCreated(content::RenderFrame * render_frame)288 void Dispatcher::OnRenderFrameCreated(content::RenderFrame* render_frame) {
289   script_injection_manager_->OnRenderFrameCreated(render_frame);
290   content_watcher_->OnRenderFrameCreated(render_frame);
291 }
292 
IsExtensionActive(const std::string & extension_id) const293 bool Dispatcher::IsExtensionActive(const std::string& extension_id) const {
294   bool is_active =
295       active_extension_ids_.find(extension_id) != active_extension_ids_.end();
296   if (is_active)
297     CHECK(RendererExtensionRegistry::Get()->Contains(extension_id));
298   return is_active;
299 }
300 
DidCreateScriptContext(blink::WebLocalFrame * frame,const v8::Local<v8::Context> & v8_context,int32_t world_id)301 void Dispatcher::DidCreateScriptContext(
302     blink::WebLocalFrame* frame,
303     const v8::Local<v8::Context>& v8_context,
304     int32_t world_id) {
305   const base::TimeTicks start_time = base::TimeTicks::Now();
306 
307   ScriptContext* context =
308       script_context_set_->Register(frame, v8_context, world_id);
309 
310   // Initialize origin permissions for content scripts, which can't be
311   // initialized in |ActivateExtension|.
312   if (context->context_type() == Feature::CONTENT_SCRIPT_CONTEXT)
313     InitOriginPermissions(context->extension());
314 
315   context->SetModuleSystem(
316       std::make_unique<ModuleSystem>(context, &source_map_));
317 
318   ModuleSystem* module_system = context->module_system();
319 
320   // Enable natives in startup.
321   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system);
322 
323   RegisterNativeHandlers(module_system, context, bindings_system_.get(),
324                          v8_schema_registry_.get());
325 
326   bindings_system_->DidCreateScriptContext(context);
327 
328   // Inject custom JS into the platform app context.
329   if (IsWithinPlatformApp()) {
330     module_system->Require("platformApp");
331   }
332 
333   RequireGuestViewModules(context);
334 
335   const base::TimeDelta elapsed = base::TimeTicks::Now() - start_time;
336   switch (context->context_type()) {
337     case Feature::UNSPECIFIED_CONTEXT:
338       UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_Unspecified",
339                           elapsed);
340       break;
341     case Feature::BLESSED_EXTENSION_CONTEXT:
342       // For service workers this is handled in
343       // WillEvaluateServiceWorkerOnWorkerThread().
344       DCHECK(!context->IsForServiceWorker());
345       UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_Blessed", elapsed);
346       break;
347     case Feature::UNBLESSED_EXTENSION_CONTEXT:
348       UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_Unblessed",
349                           elapsed);
350       break;
351     case Feature::CONTENT_SCRIPT_CONTEXT:
352       UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_ContentScript",
353                           elapsed);
354       break;
355     case Feature::WEB_PAGE_CONTEXT:
356       UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_WebPage", elapsed);
357       break;
358     case Feature::BLESSED_WEB_PAGE_CONTEXT:
359       UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_BlessedWebPage",
360                           elapsed);
361       break;
362     case Feature::WEBUI_CONTEXT:
363       UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_WebUI", elapsed);
364       break;
365     case Feature::WEBUI_UNTRUSTED_CONTEXT:
366       // Extension APIs in untrusted WebUIs are temporary so don't bother
367       // recording metrics for them.
368       break;
369     case Feature::LOCK_SCREEN_EXTENSION_CONTEXT:
370       UMA_HISTOGRAM_TIMES(
371           "Extensions.DidCreateScriptContext_LockScreenExtension", elapsed);
372       break;
373   }
374 
375   VLOG(1) << "Num tracked contexts: " << script_context_set_->size();
376 }
377 
DidInitializeServiceWorkerContextOnWorkerThread(blink::WebServiceWorkerContextProxy * context_proxy,const GURL & service_worker_scope,const GURL & script_url)378 void Dispatcher::DidInitializeServiceWorkerContextOnWorkerThread(
379     blink::WebServiceWorkerContextProxy* context_proxy,
380     const GURL& service_worker_scope,
381     const GURL& script_url) {
382   if (!script_url.SchemeIs(kExtensionScheme))
383     return;
384 
385   {
386     base::AutoLock lock(service_workers_paused_for_on_loaded_message_lock_);
387     ExtensionId extension_id =
388         RendererExtensionRegistry::Get()->GetExtensionOrAppIDByURL(script_url);
389     // If the extension is already loaded we don't have to suspend the service
390     // worker. The service worker will continue in
391     // Dispatcher::WillEvaluateServiceWorkerOnWorkerThread().
392     if (RendererExtensionRegistry::Get()->GetByID(extension_id))
393       return;
394 
395     // Suspend the service worker until loaded message of the extension comes.
396     // The service worker will be resumed in Dispatcher::OnLoaded().
397     context_proxy->PauseEvaluation();
398     service_workers_paused_for_on_loaded_message_.emplace(
399         extension_id, std::make_unique<PendingServiceWorker>(context_proxy));
400   }
401 }
402 
WillEvaluateServiceWorkerOnWorkerThread(blink::WebServiceWorkerContextProxy * context_proxy,v8::Local<v8::Context> v8_context,int64_t service_worker_version_id,const GURL & service_worker_scope,const GURL & script_url)403 void Dispatcher::WillEvaluateServiceWorkerOnWorkerThread(
404     blink::WebServiceWorkerContextProxy* context_proxy,
405     v8::Local<v8::Context> v8_context,
406     int64_t service_worker_version_id,
407     const GURL& service_worker_scope,
408     const GURL& script_url) {
409   const base::TimeTicks start_time = base::TimeTicks::Now();
410 
411   // TODO(crbug/961821): We may want to give service workers not registered
412   // by extensions minimal bindings, the same as other webpage-like contexts.
413   if (!script_url.SchemeIs(kExtensionScheme)) {
414     // Early-out if this isn't a chrome-extension:// scheme, because looking up
415     // the extension registry is unnecessary if it's not. Checking this will
416     // also skip over hosted apps, which is the desired behavior - hosted app
417     // service workers are not our concern.
418     return;
419   }
420 
421   const Extension* extension =
422       RendererExtensionRegistry::Get()->GetExtensionOrAppByURL(script_url);
423 
424   if (!extension) {
425     // TODO(kalman): This is no good. Instead we need to either:
426     //
427     // - Hold onto the v8::Context and create the ScriptContext and install
428     //   our bindings when this extension is loaded.
429     // - Deal with there being an extension ID (script_url.host()) but no
430     //   extension associated with it, then document that getBackgroundClient
431     //   may fail if the extension hasn't loaded yet.
432     //
433     // The former is safer, but is unfriendly to caching (e.g. session restore).
434     // It seems to contradict the service worker idiom.
435     //
436     // The latter is friendly to caching, but running extension code without an
437     // installed extension makes me nervous, and means that we won't be able to
438     // expose arbitrary (i.e. capability-checked) extension APIs to service
439     // workers. We will probably need to relax some assertions - we just need
440     // to find them.
441     //
442     // Perhaps this could be solved with our own event on the service worker
443     // saying that an extension is ready, and documenting that extension APIs
444     // won't work before that event has fired?
445     return;
446   }
447 
448   // Only the script specific in the manifest's background data gets bindings.
449   //
450   // TODO(crbug/961821): We may want to give other service workers registered
451   // by extensions minimal bindings, just as we might want to give them to
452   // service workers that aren't registered by extensions.
453   ScriptContext* context = new ScriptContext(
454       v8_context, nullptr, extension, Feature::BLESSED_EXTENSION_CONTEXT,
455       extension, Feature::BLESSED_EXTENSION_CONTEXT);
456   context->set_url(script_url);
457   context->set_service_worker_scope(service_worker_scope);
458   context->set_service_worker_version_id(service_worker_version_id);
459 
460   if (ExtensionsRendererClient::Get()
461           ->ExtensionAPIEnabledForServiceWorkerScript(service_worker_scope,
462                                                       script_url)) {
463     WorkerThreadDispatcher* worker_dispatcher = WorkerThreadDispatcher::Get();
464     std::unique_ptr<IPCMessageSender> ipc_sender =
465         IPCMessageSender::CreateWorkerThreadIPCMessageSender(
466             worker_dispatcher, service_worker_version_id);
467     ActivationSequence worker_activation_sequence =
468         *RendererExtensionRegistry::Get()->GetWorkerActivationSequence(
469             extension->id());
470     worker_dispatcher->AddWorkerData(
471         service_worker_version_id, worker_activation_sequence, context,
472         CreateBindingsSystem(std::move(ipc_sender)));
473     worker_thread_util::SetWorkerContextProxy(context_proxy);
474 
475     // TODO(lazyboy): Make sure accessing |source_map_| in worker thread is
476     // safe.
477     context->SetModuleSystem(
478         std::make_unique<ModuleSystem>(context, &source_map_));
479 
480     ModuleSystem* module_system = context->module_system();
481     // Enable natives in startup.
482     ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system);
483     NativeExtensionBindingsSystem* worker_bindings_system =
484         WorkerThreadDispatcher::GetBindingsSystem();
485     RegisterNativeHandlers(module_system, context, worker_bindings_system,
486                            WorkerThreadDispatcher::GetV8SchemaRegistry());
487 
488     worker_bindings_system->DidCreateScriptContext(context);
489 
490     // TODO(lazyboy): Get rid of RequireGuestViewModules() as this doesn't seem
491     // necessary for Extension SW.
492     RequireGuestViewModules(context);
493 
494     worker_dispatcher->DidInitializeContext(service_worker_version_id);
495   }
496 
497   g_worker_script_context_set.Get().Insert(base::WrapUnique(context));
498 
499   v8::Isolate* isolate = context->isolate();
500 
501   // Fetch the source code for service_worker_bindings.js.
502   base::StringPiece script_resource =
503       ui::ResourceBundle::GetSharedInstance().GetRawDataResource(
504           IDR_SERVICE_WORKER_BINDINGS_JS);
505   v8::Local<v8::String> script =
506       v8::String::NewExternalOneByte(
507           isolate, new StaticV8ExternalOneByteStringResource(script_resource))
508           .ToLocalChecked();
509 
510   // Run service_worker.js to get the main function.
511   v8::Local<v8::Function> main_function;
512   {
513     v8::Local<v8::Value> result = context->RunScript(
514         v8_helpers::ToV8StringUnsafe(isolate, "service_worker"), script,
515         base::Bind(&CrashOnException));
516     CHECK(result->IsFunction());
517     main_function = result.As<v8::Function>();
518   }
519 
520   // Expose CHECK/DCHECK/NOTREACHED to the main function with a
521   // LoggingNativeHandler. Admire the neat base::Bind trick to both Invalidate
522   // and delete the native handler.
523   LoggingNativeHandler* logging = new LoggingNativeHandler(context);
524   logging->Initialize();
525   context->AddInvalidationObserver(
526       base::BindOnce(&NativeHandler::Invalidate, base::Owned(logging)));
527 
528   // Execute the main function with its dependencies passed in as arguments.
529   v8::Local<v8::Value> args[] = {
530       // The extension's background URL.
531       v8_helpers::ToV8StringUnsafe(
532           isolate, BackgroundInfo::GetBackgroundURL(extension).spec()),
533       // The wake-event-page native function.
534       WakeEventPage::Get()->GetForContext(context),
535       // The logging module.
536       logging->NewInstance(),
537   };
538   context->SafeCallFunction(main_function, base::size(args), args);
539 
540   const base::TimeDelta elapsed = base::TimeTicks::Now() - start_time;
541   UMA_HISTOGRAM_TIMES(
542       "Extensions.DidInitializeServiceWorkerContextOnWorkerThread", elapsed);
543 }
544 
WillReleaseScriptContext(blink::WebLocalFrame * frame,const v8::Local<v8::Context> & v8_context,int32_t world_id)545 void Dispatcher::WillReleaseScriptContext(
546     blink::WebLocalFrame* frame,
547     const v8::Local<v8::Context>& v8_context,
548     int32_t world_id) {
549   ScriptContext* context = script_context_set_->GetByV8Context(v8_context);
550   if (!context)
551     return;
552   bindings_system_->WillReleaseScriptContext(context);
553 
554   script_context_set_->Remove(context);
555   VLOG(1) << "Num tracked contexts: " << script_context_set_->size();
556 }
557 
DidStartServiceWorkerContextOnWorkerThread(int64_t service_worker_version_id,const GURL & service_worker_scope,const GURL & script_url)558 void Dispatcher::DidStartServiceWorkerContextOnWorkerThread(
559     int64_t service_worker_version_id,
560     const GURL& service_worker_scope,
561     const GURL& script_url) {
562   if (!ExtensionsRendererClient::Get()
563            ->ExtensionAPIEnabledForServiceWorkerScript(service_worker_scope,
564                                                        script_url))
565     return;
566 
567   DCHECK(worker_thread_util::IsWorkerThread());
568   WorkerThreadDispatcher::Get()->DidStartContext(service_worker_scope,
569                                                  service_worker_version_id);
570 }
571 
WillDestroyServiceWorkerContextOnWorkerThread(v8::Local<v8::Context> v8_context,int64_t service_worker_version_id,const GURL & service_worker_scope,const GURL & script_url)572 void Dispatcher::WillDestroyServiceWorkerContextOnWorkerThread(
573     v8::Local<v8::Context> v8_context,
574     int64_t service_worker_version_id,
575     const GURL& service_worker_scope,
576     const GURL& script_url) {
577   // Note that using ExtensionAPIEnabledForServiceWorkerScript() won't work here
578   // as RendererExtensionRegistry might have already unloaded this extension.
579   // Use the existence of ServiceWorkerData as the source of truth instead.
580   if (!WorkerThreadDispatcher::GetServiceWorkerData()) {
581     // If extension APIs in service workers aren't enabled, we just need to
582     // remove the context.
583     g_worker_script_context_set.Get().Remove(v8_context, script_url);
584   } else {
585     // TODO(lazyboy/devlin): Should this cleanup happen in a worker class, like
586     // WorkerThreadDispatcher? If so, we should move the initialization as well.
587     ScriptContext* script_context = WorkerThreadDispatcher::GetScriptContext();
588     NativeExtensionBindingsSystem* worker_bindings_system =
589         WorkerThreadDispatcher::GetBindingsSystem();
590     worker_bindings_system->WillReleaseScriptContext(script_context);
591     WorkerThreadDispatcher::Get()->DidStopContext(service_worker_scope,
592                                                   service_worker_version_id);
593     // Note: we have to remove the context (and thus perform invalidation on
594     // the native handlers) prior to removing the worker data, which destroys
595     // the associated bindings system.
596     g_worker_script_context_set.Get().Remove(v8_context, script_url);
597     WorkerThreadDispatcher::Get()->RemoveWorkerData(service_worker_version_id);
598     worker_thread_util::SetWorkerContextProxy(nullptr);
599   }
600 
601   std::string extension_id =
602       RendererExtensionRegistry::Get()->GetExtensionOrAppIDByURL(script_url);
603   {
604     base::AutoLock lock(service_workers_paused_for_on_loaded_message_lock_);
605     service_workers_paused_for_on_loaded_message_.erase(extension_id);
606   }
607 }
608 
DidCreateDocumentElement(blink::WebLocalFrame * frame)609 void Dispatcher::DidCreateDocumentElement(blink::WebLocalFrame* frame) {
610   // Note: use GetEffectiveDocumentURLForContext() and not just
611   // frame->document()->url() so that this also injects the stylesheet on
612   // about:blank frames that are hosted in the extension process. (Even though
613   // this is used to determine whether to inject a stylesheet, we don't use
614   // GetEffectiveDocumentURLForInjection() because we inject based on whether
615   // it is an extension context, rather than based on the extension's injection
616   // permissions.)
617   GURL effective_document_url =
618       ScriptContext::GetEffectiveDocumentURLForContext(
619           frame, frame->GetDocument().Url(), true /* match_about_blank */);
620 
621   const Extension* extension =
622       RendererExtensionRegistry::Get()->GetExtensionOrAppByURL(
623           effective_document_url);
624 
625   if (extension &&
626       (extension->is_extension() || extension->is_platform_app())) {
627     int resource_id = extension->is_platform_app() ? IDR_PLATFORM_APP_CSS
628                                                    : IDR_EXTENSION_FONTS_CSS;
629     std::string stylesheet =
630         ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
631             resource_id);
632     base::ReplaceFirstSubstringAfterOffset(
633         &stylesheet, 0, "$FONTFAMILY", system_font_family_);
634     base::ReplaceFirstSubstringAfterOffset(
635         &stylesheet, 0, "$FONTSIZE", system_font_size_);
636 
637     // Blink doesn't let us define an additional user agent stylesheet, so
638     // we insert the default platform app or extension stylesheet into all
639     // documents that are loaded in each app or extension.
640     frame->GetDocument().InsertStyleSheet(WebString::FromUTF8(stylesheet));
641   }
642 
643   // If this is an extension options page, and the extension has opted into
644   // using Chrome styles, then insert the Chrome extension stylesheet.
645   if (extension && extension->is_extension() &&
646       OptionsPageInfo::ShouldUseChromeStyle(extension) &&
647       effective_document_url == OptionsPageInfo::GetOptionsPage(extension)) {
648     std::string extension_css =
649         ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
650             IDR_EXTENSION_CSS);
651     frame->GetDocument().InsertStyleSheet(WebString::FromUTF8(extension_css));
652   }
653 }
654 
RunScriptsAtDocumentStart(content::RenderFrame * render_frame)655 void Dispatcher::RunScriptsAtDocumentStart(content::RenderFrame* render_frame) {
656   ExtensionFrameHelper* frame_helper = ExtensionFrameHelper::Get(render_frame);
657   if (!frame_helper)
658     return;  // The frame is invisible to extensions.
659 
660   frame_helper->RunScriptsAtDocumentStart();
661   // |frame_helper| and |render_frame| might be dead by now.
662 }
663 
RunScriptsAtDocumentEnd(content::RenderFrame * render_frame)664 void Dispatcher::RunScriptsAtDocumentEnd(content::RenderFrame* render_frame) {
665   ExtensionFrameHelper* frame_helper = ExtensionFrameHelper::Get(render_frame);
666   if (!frame_helper)
667     return;  // The frame is invisible to extensions.
668 
669   frame_helper->RunScriptsAtDocumentEnd();
670   // |frame_helper| and |render_frame| might be dead by now.
671 }
672 
RunScriptsAtDocumentIdle(content::RenderFrame * render_frame)673 void Dispatcher::RunScriptsAtDocumentIdle(content::RenderFrame* render_frame) {
674   ExtensionFrameHelper* frame_helper = ExtensionFrameHelper::Get(render_frame);
675   if (!frame_helper)
676     return;  // The frame is invisible to extensions.
677 
678   frame_helper->RunScriptsAtDocumentIdle();
679   // |frame_helper| and |render_frame| might be dead by now.
680 }
681 
OnExtensionResponse(int request_id,bool success,const base::ListValue & response,const std::string & error)682 void Dispatcher::OnExtensionResponse(int request_id,
683                                      bool success,
684                                      const base::ListValue& response,
685                                      const std::string& error) {
686   bindings_system_->HandleResponse(request_id, success, response, error);
687 }
688 
DispatchEvent(const std::string & extension_id,const std::string & event_name,const base::ListValue & event_args,const EventFilteringInfo * filtering_info) const689 void Dispatcher::DispatchEvent(const std::string& extension_id,
690                                const std::string& event_name,
691                                const base::ListValue& event_args,
692                                const EventFilteringInfo* filtering_info) const {
693   script_context_set_->ForEach(
694       extension_id, nullptr,
695       base::Bind(&NativeExtensionBindingsSystem::DispatchEventInContext,
696                  base::Unretained(bindings_system_.get()), event_name,
697                  &event_args, filtering_info));
698 }
699 
InvokeModuleSystemMethod(content::RenderFrame * render_frame,const std::string & extension_id,const std::string & module_name,const std::string & function_name,const base::ListValue & args)700 void Dispatcher::InvokeModuleSystemMethod(content::RenderFrame* render_frame,
701                                           const std::string& extension_id,
702                                           const std::string& module_name,
703                                           const std::string& function_name,
704                                           const base::ListValue& args) {
705   script_context_set_->ForEach(
706       extension_id, render_frame,
707       base::Bind(&CallModuleMethod, module_name, function_name, &args));
708 }
709 
710 // static
GetJsResources()711 std::vector<Dispatcher::JsResourceInfo> Dispatcher::GetJsResources() {
712   // Libraries.
713   std::vector<JsResourceInfo> resources = {
714       {"appView", IDR_APP_VIEW_JS},
715       {"appViewElement", IDR_APP_VIEW_ELEMENT_JS},
716       {"appViewDeny", IDR_APP_VIEW_DENY_JS},
717       {"entryIdManager", IDR_ENTRY_ID_MANAGER},
718       {"extensionOptions", IDR_EXTENSION_OPTIONS_JS},
719       {"extensionOptionsElement", IDR_EXTENSION_OPTIONS_ELEMENT_JS},
720       {"extensionOptionsAttributes", IDR_EXTENSION_OPTIONS_ATTRIBUTES_JS},
721       {"extensionOptionsConstants", IDR_EXTENSION_OPTIONS_CONSTANTS_JS},
722       {"extensionOptionsEvents", IDR_EXTENSION_OPTIONS_EVENTS_JS},
723       {"feedbackPrivate", IDR_FEEDBACK_PRIVATE_CUSTOM_BINDINGS_JS},
724       {"fileEntryBindingUtil", IDR_FILE_ENTRY_BINDING_UTIL_JS},
725       {"fileSystem", IDR_FILE_SYSTEM_CUSTOM_BINDINGS_JS},
726       {"guestView", IDR_GUEST_VIEW_JS},
727       {"guestViewAttributes", IDR_GUEST_VIEW_ATTRIBUTES_JS},
728       {"guestViewContainer", IDR_GUEST_VIEW_CONTAINER_JS},
729       {"guestViewContainerElement", IDR_GUEST_VIEW_CONTAINER_ELEMENT_JS},
730       {"guestViewDeny", IDR_GUEST_VIEW_DENY_JS},
731       {"guestViewEvents", IDR_GUEST_VIEW_EVENTS_JS},
732       {"safeMethods", IDR_SAFE_METHODS_JS},
733       {"imageUtil", IDR_IMAGE_UTIL_JS},
734       {"setIcon", IDR_SET_ICON_JS},
735       {"test", IDR_TEST_CUSTOM_BINDINGS_JS},
736       {"test_environment_specific_bindings",
737        IDR_BROWSER_TEST_ENVIRONMENT_SPECIFIC_BINDINGS_JS},
738       {"uncaught_exception_handler", IDR_UNCAUGHT_EXCEPTION_HANDLER_JS},
739       {"utils", IDR_UTILS_JS},
740       {"webRequest", IDR_WEB_REQUEST_CUSTOM_BINDINGS_JS},
741       {"webRequestEvent", IDR_WEB_REQUEST_EVENT_JS},
742       // Note: webView not webview so that this doesn't interfere with the
743       // chrome.webview API bindings.
744       {"webView", IDR_WEB_VIEW_JS},
745       {"webViewElement", IDR_WEB_VIEW_ELEMENT_JS},
746       {"extensionsWebViewElement", IDR_EXTENSIONS_WEB_VIEW_ELEMENT_JS},
747       {"webViewDeny", IDR_WEB_VIEW_DENY_JS},
748       {"webViewActionRequests", IDR_WEB_VIEW_ACTION_REQUESTS_JS},
749       {"webViewApiMethods", IDR_WEB_VIEW_API_METHODS_JS},
750       {"webViewAttributes", IDR_WEB_VIEW_ATTRIBUTES_JS},
751       {"webViewConstants", IDR_WEB_VIEW_CONSTANTS_JS},
752       {"webViewEvents", IDR_WEB_VIEW_EVENTS_JS},
753       {"webViewInternal", IDR_WEB_VIEW_INTERNAL_CUSTOM_BINDINGS_JS},
754 
755       {"keep_alive", IDR_KEEP_ALIVE_JS},
756       {"mojo_bindings", IDR_MOJO_MOJO_BINDINGS_JS},
757       {"mojo_bindings_lite", IDR_MOJO_MOJO_BINDINGS_LITE_JS},
758       {"extensions/common/mojom/keep_alive.mojom", IDR_KEEP_ALIVE_MOJOM_JS},
759 
760       // Custom bindings.
761       {"automation", IDR_AUTOMATION_CUSTOM_BINDINGS_JS},
762       {"automationEvent", IDR_AUTOMATION_EVENT_JS},
763       {"automationNode", IDR_AUTOMATION_NODE_JS},
764       {"automationTreeCache", IDR_AUTOMATION_TREE_CACHE_JS},
765       {"app.runtime", IDR_APP_RUNTIME_CUSTOM_BINDINGS_JS},
766       {"app.window", IDR_APP_WINDOW_CUSTOM_BINDINGS_JS},
767       {"declarativeWebRequest", IDR_DECLARATIVE_WEBREQUEST_CUSTOM_BINDINGS_JS},
768       {"displaySource", IDR_DISPLAY_SOURCE_CUSTOM_BINDINGS_JS},
769       {"contextMenus", IDR_CONTEXT_MENUS_CUSTOM_BINDINGS_JS},
770       {"contextMenusHandlers", IDR_CONTEXT_MENUS_HANDLERS_JS},
771       {"mimeHandlerPrivate", IDR_MIME_HANDLER_PRIVATE_CUSTOM_BINDINGS_JS},
772       {"extensions/common/api/mime_handler.mojom", IDR_MIME_HANDLER_MOJOM_JS},
773       {"mojoPrivate", IDR_MOJO_PRIVATE_CUSTOM_BINDINGS_JS},
774       {"permissions", IDR_PERMISSIONS_CUSTOM_BINDINGS_JS},
775       {"printerProvider", IDR_PRINTER_PROVIDER_CUSTOM_BINDINGS_JS},
776       {"webViewRequest", IDR_WEB_VIEW_REQUEST_CUSTOM_BINDINGS_JS},
777 
778       // Platform app sources that are not API-specific..
779       {"platformApp", IDR_PLATFORM_APP_JS},
780   };
781 
782   return resources;
783 }
784 
785 // NOTE: please use the naming convention "foo_natives" for these.
786 // static
RegisterNativeHandlers(ModuleSystem * module_system,ScriptContext * context,Dispatcher * dispatcher,NativeExtensionBindingsSystem * bindings_system,V8SchemaRegistry * v8_schema_registry)787 void Dispatcher::RegisterNativeHandlers(
788     ModuleSystem* module_system,
789     ScriptContext* context,
790     Dispatcher* dispatcher,
791     NativeExtensionBindingsSystem* bindings_system,
792     V8SchemaRegistry* v8_schema_registry) {
793   module_system->RegisterNativeHandler(
794       "chrome",
795       std::unique_ptr<NativeHandler>(new ChromeNativeHandler(context)));
796   module_system->RegisterNativeHandler(
797       "logging",
798       std::unique_ptr<NativeHandler>(new LoggingNativeHandler(context)));
799   module_system->RegisterNativeHandler("schema_registry",
800                                        v8_schema_registry->AsNativeHandler());
801   module_system->RegisterNativeHandler(
802       "test_features",
803       std::unique_ptr<NativeHandler>(new TestFeaturesNativeHandler(context)));
804   module_system->RegisterNativeHandler(
805       "test_native_handler",
806       std::unique_ptr<NativeHandler>(new TestNativeHandler(context)));
807   module_system->RegisterNativeHandler(
808       "user_gestures",
809       std::unique_ptr<NativeHandler>(new UserGesturesNativeHandler(context)));
810   module_system->RegisterNativeHandler(
811       "utils", std::unique_ptr<NativeHandler>(new UtilsNativeHandler(context)));
812   module_system->RegisterNativeHandler(
813       "v8_context",
814       std::unique_ptr<NativeHandler>(new V8ContextNativeHandler(context)));
815   module_system->RegisterNativeHandler(
816       "messaging_natives", std::make_unique<MessagingBindings>(context));
817   module_system->RegisterNativeHandler(
818       "apiDefinitions", std::unique_ptr<NativeHandler>(
819                             new ApiDefinitionsNatives(dispatcher, context)));
820   module_system->RegisterNativeHandler(
821       "setIcon", std::unique_ptr<NativeHandler>(new SetIconNatives(context)));
822   module_system->RegisterNativeHandler(
823       "activityLogger", std::make_unique<APIActivityLogger>(context));
824   module_system->RegisterNativeHandler(
825       "renderFrameObserverNatives",
826       std::unique_ptr<NativeHandler>(new RenderFrameObserverNatives(context)));
827 
828   // Natives used by multiple APIs.
829   module_system->RegisterNativeHandler(
830       "file_system_natives",
831       std::unique_ptr<NativeHandler>(new FileSystemNatives(context)));
832 
833   // Custom bindings.
834   module_system->RegisterNativeHandler(
835       "app_window_natives",
836       std::unique_ptr<NativeHandler>(new AppWindowCustomBindings(context)));
837   module_system->RegisterNativeHandler(
838       "blob_natives",
839       std::unique_ptr<NativeHandler>(new BlobNativeHandler(context)));
840   module_system->RegisterNativeHandler(
841       "context_menus",
842       std::unique_ptr<NativeHandler>(new ContextMenusCustomBindings(context)));
843   module_system->RegisterNativeHandler(
844       "guest_view_internal", std::unique_ptr<NativeHandler>(
845                                  new GuestViewInternalCustomBindings(context)));
846   module_system->RegisterNativeHandler(
847       "id_generator",
848       std::unique_ptr<NativeHandler>(new IdGeneratorCustomBindings(context)));
849   module_system->RegisterNativeHandler(
850       "runtime",
851       std::unique_ptr<NativeHandler>(new RuntimeCustomBindings(context)));
852   module_system->RegisterNativeHandler(
853       "display_source",
854       std::make_unique<DisplaySourceCustomBindings>(context, bindings_system));
855   module_system->RegisterNativeHandler(
856       "automationInternal",
857       std::make_unique<extensions::AutomationInternalCustomBindings>(
858           context, bindings_system));
859 }
860 
OnControlMessageReceived(const IPC::Message & message)861 bool Dispatcher::OnControlMessageReceived(const IPC::Message& message) {
862   if (WorkerThreadDispatcher::Get()->OnControlMessageReceived(message))
863     return true;
864 
865   bool handled = true;
866   IPC_BEGIN_MESSAGE_MAP(Dispatcher, message)
867   IPC_MESSAGE_HANDLER(ExtensionMsg_CancelSuspend, OnCancelSuspend)
868   IPC_MESSAGE_HANDLER(ExtensionMsg_DeliverMessage, OnDeliverMessage)
869   IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchOnConnect, OnDispatchOnConnect)
870   IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchOnDisconnect, OnDispatchOnDisconnect)
871   IPC_MESSAGE_HANDLER(ExtensionMsg_Loaded, OnLoaded)
872   IPC_MESSAGE_HANDLER(ExtensionMsg_MessageInvoke, OnMessageInvoke)
873   IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchEvent, OnDispatchEvent)
874   IPC_MESSAGE_HANDLER(ExtensionMsg_SetSessionInfo, OnSetSessionInfo)
875   IPC_MESSAGE_HANDLER(ExtensionMsg_SetScriptingAllowlist,
876                       OnSetScriptingAllowlist)
877   IPC_MESSAGE_HANDLER(ExtensionMsg_SetSystemFont, OnSetSystemFont)
878   IPC_MESSAGE_HANDLER(ExtensionMsg_SetWebViewPartitionID,
879                       OnSetWebViewPartitionID)
880   IPC_MESSAGE_HANDLER(ExtensionMsg_ShouldSuspend, OnShouldSuspend)
881   IPC_MESSAGE_HANDLER(ExtensionMsg_Suspend, OnSuspend)
882   IPC_MESSAGE_HANDLER(ExtensionMsg_TransferBlobs, OnTransferBlobs)
883   IPC_MESSAGE_HANDLER(ExtensionMsg_Unloaded, OnUnloaded)
884   IPC_MESSAGE_HANDLER(ExtensionMsg_UpdatePermissions, OnUpdatePermissions)
885   IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateDefaultPolicyHostRestrictions,
886                       OnUpdateDefaultPolicyHostRestrictions)
887   IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateTabSpecificPermissions,
888                       OnUpdateTabSpecificPermissions)
889   IPC_MESSAGE_HANDLER(ExtensionMsg_ClearTabSpecificPermissions,
890                       OnClearTabSpecificPermissions)
891   IPC_MESSAGE_FORWARD(ExtensionMsg_WatchPages,
892                       content_watcher_.get(),
893                       ContentWatcher::OnWatchPages)
894   IPC_MESSAGE_UNHANDLED(handled = false)
895   IPC_END_MESSAGE_MAP()
896 
897   return handled;
898 }
899 
RegisterMojoInterfaces(blink::AssociatedInterfaceRegistry * associated_interfaces)900 void Dispatcher::RegisterMojoInterfaces(
901     blink::AssociatedInterfaceRegistry* associated_interfaces) {
902   // This base::Unretained() is safe, because:
903   // 1) the Dispatcher is a RenderThreadObserver and outlives the RenderThread.
904   // 2) |asscoiated_interfaces| is owned by the RenderThread.
905   // As well the Dispatcher is owned by the
906   // ExtensionsRendererClient, which in turn is a leaky LazyInstance (and thus
907   // never deleted).
908   associated_interfaces->AddInterface(base::BindRepeating(
909       &Dispatcher::OnRendererAssociatedRequest, base::Unretained(this)));
910 }
911 
UnregisterMojoInterfaces(blink::AssociatedInterfaceRegistry * associated_interfaces)912 void Dispatcher::UnregisterMojoInterfaces(
913     blink::AssociatedInterfaceRegistry* associated_interfaces) {
914   associated_interfaces->RemoveInterface(mojom::Renderer::Name_);
915 }
916 
OnRendererAssociatedRequest(mojo::PendingAssociatedReceiver<mojom::Renderer> receiver)917 void Dispatcher::OnRendererAssociatedRequest(
918     mojo::PendingAssociatedReceiver<mojom::Renderer> receiver) {
919   receiver_.Bind(std::move(receiver));
920 }
921 
ActivateExtension(const std::string & extension_id)922 void Dispatcher::ActivateExtension(const std::string& extension_id) {
923   const Extension* extension =
924       RendererExtensionRegistry::Get()->GetByID(extension_id);
925   if (!extension) {
926     NOTREACHED();
927     // Extension was activated but was never loaded. This probably means that
928     // the renderer failed to load it (or the browser failed to tell us when it
929     // did). Failures shouldn't happen, but instead of crashing there (which
930     // executes on all renderers) be conservative and only crash in the renderer
931     // of the extension which failed to load; this one.
932     std::string& error = extension_load_errors_[extension_id];
933     char minidump[256];
934     base::debug::Alias(&minidump);
935     base::snprintf(minidump, base::size(minidump), "e::dispatcher:%s:%s",
936                    extension_id.c_str(), error.c_str());
937     LOG(FATAL) << extension_id << " was never loaded: " << error;
938   }
939 
940   // It's possible that the same extension might generate multiple activation
941   // messages, for example from an extension background page followed by an
942   // extension subframe on a regular tab.  Ensure that any given extension is
943   // only activated once.
944   if (IsExtensionActive(extension_id))
945     return;
946 
947   active_extension_ids_.insert(extension_id);
948 
949   if (activity_logging_enabled_) {
950     DOMActivityLogger::AttachToWorld(DOMActivityLogger::kMainWorldId,
951                                      extension_id);
952   }
953 
954   InitOriginPermissions(extension);
955 
956   UpdateActiveExtensions();
957 }
958 
OnCancelSuspend(const std::string & extension_id)959 void Dispatcher::OnCancelSuspend(const std::string& extension_id) {
960   DispatchEvent(extension_id, kOnSuspendCanceledEvent, base::ListValue(),
961                 nullptr);
962 }
963 
OnDeliverMessage(int worker_thread_id,const PortId & target_port_id,const Message & message)964 void Dispatcher::OnDeliverMessage(int worker_thread_id,
965                                   const PortId& target_port_id,
966                                   const Message& message) {
967   DCHECK_EQ(kMainThreadId, worker_thread_id);
968   bindings_system_->messaging_service()->DeliverMessage(
969       script_context_set_.get(), target_port_id, message,
970       NULL);  // All render frames.
971 }
972 
OnDispatchOnConnect(int worker_thread_id,const PortId & target_port_id,const std::string & channel_name,const ExtensionMsg_TabConnectionInfo & source,const ExtensionMsg_ExternalConnectionInfo & info)973 void Dispatcher::OnDispatchOnConnect(
974     int worker_thread_id,
975     const PortId& target_port_id,
976     const std::string& channel_name,
977     const ExtensionMsg_TabConnectionInfo& source,
978     const ExtensionMsg_ExternalConnectionInfo& info) {
979   DCHECK_EQ(kMainThreadId, worker_thread_id);
980   DCHECK(!target_port_id.is_opener);
981 
982   bindings_system_->messaging_service()->DispatchOnConnect(
983       script_context_set_.get(), target_port_id, channel_name, source, info,
984       NULL);  // All render frames.
985 }
986 
OnDispatchOnDisconnect(int worker_thread_id,const PortId & port_id,const std::string & error_message)987 void Dispatcher::OnDispatchOnDisconnect(int worker_thread_id,
988                                         const PortId& port_id,
989                                         const std::string& error_message) {
990   DCHECK_EQ(kMainThreadId, worker_thread_id);
991   bindings_system_->messaging_service()->DispatchOnDisconnect(
992       script_context_set_.get(), port_id, error_message,
993       NULL);  // All render frames.
994 }
995 
OnLoaded(const std::vector<ExtensionMsg_Loaded_Params> & loaded_extensions)996 void Dispatcher::OnLoaded(
997     const std::vector<ExtensionMsg_Loaded_Params>& loaded_extensions) {
998   for (const auto& param : loaded_extensions) {
999     std::string error;
1000     scoped_refptr<const Extension> extension =
1001         param.ConvertToExtension(kRendererProfileId, &error);
1002     if (!extension.get()) {
1003       NOTREACHED() << error;
1004       // Note: in tests |param.id| has been observed to be empty (see comment
1005       // just below) so this isn't all that reliable.
1006       extension_load_errors_[param.id] = error;
1007       continue;
1008     }
1009     RendererExtensionRegistry* extension_registry =
1010         RendererExtensionRegistry::Get();
1011     // TODO(kalman): This test is deliberately not a CHECK (though I wish it
1012     // could be) and uses extension->id() not params.id:
1013     // 1. For some reason params.id can be empty. I've only seen it with
1014     //    the webstore extension, in tests, and I've spent some time trying to
1015     //    figure out why - but cost/benefit won.
1016     // 2. The browser only sends this IPC to RenderProcessHosts once, but the
1017     //    Dispatcher is attached to a RenderThread. Presumably there is a
1018     //    mismatch there. In theory one would think it's possible for the
1019     //    browser to figure this out itself - but again, cost/benefit.
1020     if (!extension_registry->Insert(extension)) {
1021       // TODO(devlin): This may be fixed by crbug.com/528026. Monitor, and
1022       // consider making this a release CHECK.
1023       NOTREACHED();
1024     }
1025     if (param.worker_activation_sequence) {
1026       extension_registry->SetWorkerActivationSequence(
1027           extension, *param.worker_activation_sequence);
1028     }
1029     if (param.uses_default_policy_blocked_allowed_hosts) {
1030       extension->permissions_data()->SetUsesDefaultHostRestrictions(
1031           kRendererProfileId);
1032     } else {
1033       extension->permissions_data()->SetPolicyHostRestrictions(
1034           param.policy_blocked_hosts, param.policy_allowed_hosts);
1035     }
1036 
1037     ExtensionsRendererClient::Get()->OnExtensionLoaded(*extension);
1038 
1039     // Resume service worker if it is suspended.
1040     {
1041       base::AutoLock lock(service_workers_paused_for_on_loaded_message_lock_);
1042       auto it =
1043           service_workers_paused_for_on_loaded_message_.find(extension->id());
1044       if (it != service_workers_paused_for_on_loaded_message_.end()) {
1045         scoped_refptr<base::SingleThreadTaskRunner> task_runner =
1046             std::move(it->second->task_runner);
1047         // Using base::Unretained() should be fine as this won't get destructed.
1048         task_runner->PostTask(
1049             FROM_HERE,
1050             base::BindOnce(&Dispatcher::ResumeEvaluationOnWorkerThread,
1051                            base::Unretained(this), extension->id()));
1052       }
1053     }
1054   }
1055 
1056   // Update the available bindings for all contexts. These may have changed if
1057   // an externally_connectable extension was loaded that can connect to an
1058   // open webpage.
1059   UpdateAllBindings();
1060 }
1061 
OnMessageInvoke(const std::string & extension_id,const std::string & module_name,const std::string & function_name,const base::ListValue & args)1062 void Dispatcher::OnMessageInvoke(const std::string& extension_id,
1063                                  const std::string& module_name,
1064                                  const std::string& function_name,
1065                                  const base::ListValue& args) {
1066   InvokeModuleSystemMethod(nullptr, extension_id, module_name, function_name,
1067                            args);
1068 }
1069 
OnDispatchEvent(const ExtensionMsg_DispatchEvent_Params & params,const base::ListValue & event_args)1070 void Dispatcher::OnDispatchEvent(
1071     const ExtensionMsg_DispatchEvent_Params& params,
1072     const base::ListValue& event_args) {
1073   content::RenderFrame* background_frame =
1074       ExtensionFrameHelper::GetBackgroundPageFrame(params.extension_id);
1075 
1076   // Synthesize a user gesture if this was in response to user action; this is
1077   // necessary if the gesture was e.g. by clicking on the extension toolbar
1078   // icon, context menu entry, etc.
1079   //
1080   // This will only add an active user gesture for the background page, so any
1081   // listeners in different frames (like a popup or tab) won't be able to use
1082   // the user gesture. This is intentional, since frames other than the
1083   // background page should have their own user gestures, such as through button
1084   // clicks.
1085   if (params.is_user_gesture && background_frame) {
1086     ScriptContext* background_context =
1087         ScriptContextSet::GetMainWorldContextForFrame(background_frame);
1088     if (background_context && bindings_system_->HasEventListenerInContext(
1089                                   params.event_name, background_context)) {
1090       background_frame->GetWebFrame()->NotifyUserActivation(
1091           blink::mojom::UserActivationNotificationType::kExtensionEvent);
1092     }
1093   }
1094 
1095   DispatchEvent(params.extension_id, params.event_name, event_args,
1096                 &params.filtering_info);
1097 
1098   if (background_frame) {
1099     // Tell the browser process when an event has been dispatched with a lazy
1100     // background page active.
1101     const Extension* extension =
1102         RendererExtensionRegistry::Get()->GetByID(params.extension_id);
1103     if (extension && BackgroundInfo::HasLazyBackgroundPage(extension)) {
1104       background_frame->Send(new ExtensionHostMsg_EventAck(
1105           background_frame->GetRoutingID(), params.event_id));
1106     }
1107   }
1108 }
1109 
OnSetSessionInfo(version_info::Channel channel,FeatureSessionType session_type,bool is_lock_screen_context)1110 void Dispatcher::OnSetSessionInfo(version_info::Channel channel,
1111                                   FeatureSessionType session_type,
1112                                   bool is_lock_screen_context) {
1113   SetCurrentChannel(channel);
1114   SetCurrentFeatureSessionType(session_type);
1115   script_context_set_->set_is_lock_screen_context(is_lock_screen_context);
1116 
1117   // chrome-extension: resources should be allowed to register ServiceWorkers.
1118   blink::WebSecurityPolicy::RegisterURLSchemeAsAllowingServiceWorkers(
1119       blink::WebString::FromUTF8(extensions::kExtensionScheme));
1120 
1121   blink::WebSecurityPolicy::RegisterURLSchemeAsAllowingWasmEvalCSP(
1122       blink::WebString::FromUTF8(extensions::kExtensionScheme));
1123 }
1124 
OnSetScriptingAllowlist(const ExtensionsClient::ScriptingAllowlist & extension_ids)1125 void Dispatcher::OnSetScriptingAllowlist(
1126     const ExtensionsClient::ScriptingAllowlist& extension_ids) {
1127   ExtensionsClient::Get()->SetScriptingAllowlist(extension_ids);
1128 }
1129 
OnSetSystemFont(const std::string & font_family,const std::string & font_size)1130 void Dispatcher::OnSetSystemFont(const std::string& font_family,
1131                                  const std::string& font_size) {
1132   system_font_family_ = font_family;
1133   system_font_size_ = font_size;
1134 }
1135 
OnSetWebViewPartitionID(const std::string & partition_id)1136 void Dispatcher::OnSetWebViewPartitionID(const std::string& partition_id) {
1137   // |webview_partition_id_| cannot be changed once set.
1138   CHECK(webview_partition_id_.empty() || webview_partition_id_ == partition_id);
1139   webview_partition_id_ = partition_id;
1140 }
1141 
OnShouldSuspend(const std::string & extension_id,uint64_t sequence_id)1142 void Dispatcher::OnShouldSuspend(const std::string& extension_id,
1143                                  uint64_t sequence_id) {
1144   RenderThread::Get()->Send(
1145       new ExtensionHostMsg_ShouldSuspendAck(extension_id, sequence_id));
1146 }
1147 
OnSuspend(const std::string & extension_id)1148 void Dispatcher::OnSuspend(const std::string& extension_id) {
1149   // Dispatch the suspend event. This doesn't go through the standard event
1150   // dispatch machinery because it requires special handling. We need to let
1151   // the browser know when we are starting and stopping the event dispatch, so
1152   // that it still considers the extension idle despite any activity the suspend
1153   // event creates.
1154   DispatchEvent(extension_id, kOnSuspendEvent, base::ListValue(), nullptr);
1155   RenderThread::Get()->Send(new ExtensionHostMsg_SuspendAck(extension_id));
1156 }
1157 
OnTransferBlobs(const std::vector<std::string> & blob_uuids)1158 void Dispatcher::OnTransferBlobs(const std::vector<std::string>& blob_uuids) {
1159   RenderThread::Get()->Send(new ExtensionHostMsg_TransferBlobsAck(blob_uuids));
1160 }
1161 
OnUnloaded(const std::string & id)1162 void Dispatcher::OnUnloaded(const std::string& id) {
1163   // See comment in OnLoaded for why it would be nice, but perhaps incorrect,
1164   // to CHECK here rather than guarding.
1165   // TODO(devlin): This may be fixed by crbug.com/528026. Monitor, and
1166   // consider making this a release CHECK.
1167   if (!RendererExtensionRegistry::Get()->Remove(id)) {
1168     NOTREACHED();
1169     return;
1170   }
1171 
1172   ExtensionsRendererClient::Get()->OnExtensionUnloaded(id);
1173 
1174   bindings_system_->OnExtensionRemoved(id);
1175 
1176   active_extension_ids_.erase(id);
1177 
1178   script_injection_manager_->OnExtensionUnloaded(id);
1179 
1180   // If the extension is later reloaded with a different set of permissions,
1181   // we'd like it to get a new isolated world ID, so that it can pick up the
1182   // changed origin whitelist.
1183   ScriptInjection::RemoveIsolatedWorld(id);
1184 
1185   // Inform the bindings system that the contexts will be removed to allow time
1186   // to clear out context-specific data, and then remove the contexts
1187   // themselves.
1188   script_context_set_->ForEach(
1189       id, nullptr,
1190       base::Bind(&NativeExtensionBindingsSystem::WillReleaseScriptContext,
1191                  base::Unretained(bindings_system_.get())));
1192   script_context_set_->OnExtensionUnloaded(id);
1193 
1194   // Update the available bindings for the remaining contexts. These may have
1195   // changed if an externally_connectable extension is unloaded and a webpage
1196   // is no longer accessible.
1197   UpdateAllBindings();
1198 
1199   // Invalidates the messages map for the extension in case the extension is
1200   // reloaded with a new messages map.
1201   EraseL10nMessagesMap(id);
1202 
1203   // Update the origin access map so that any content scripts injected no longer
1204   // have dedicated allow/block lists for extra origins.
1205   WebSecurityPolicy::ClearOriginAccessListForOrigin(
1206       Extension::GetBaseURLFromExtensionId(id));
1207 
1208   // We don't do anything with existing platform-app stylesheets. They will
1209   // stay resident, but the URL pattern corresponding to the unloaded
1210   // extension's URL just won't match anything anymore.
1211 }
1212 
OnUpdateDefaultPolicyHostRestrictions(const ExtensionMsg_UpdateDefaultPolicyHostRestrictions_Params & params)1213 void Dispatcher::OnUpdateDefaultPolicyHostRestrictions(
1214     const ExtensionMsg_UpdateDefaultPolicyHostRestrictions_Params& params) {
1215   PermissionsData::SetDefaultPolicyHostRestrictions(
1216       kRendererProfileId, params.default_policy_blocked_hosts,
1217       params.default_policy_allowed_hosts);
1218   // Update blink host permission allowlist exceptions for all loaded
1219   // extensions.
1220   for (const std::string& extension_id :
1221        RendererExtensionRegistry::Get()->GetIDs()) {
1222     const Extension* extension =
1223         RendererExtensionRegistry::Get()->GetByID(extension_id);
1224     if (extension->permissions_data()->UsesDefaultPolicyHostRestrictions()) {
1225       UpdateOriginPermissions(*extension);
1226     }
1227   }
1228   UpdateAllBindings();
1229 }
1230 
OnUpdatePermissions(const ExtensionMsg_UpdatePermissions_Params & params)1231 void Dispatcher::OnUpdatePermissions(
1232     const ExtensionMsg_UpdatePermissions_Params& params) {
1233   const Extension* extension =
1234       RendererExtensionRegistry::Get()->GetByID(params.extension_id);
1235   if (!extension)
1236     return;
1237 
1238   if (params.uses_default_policy_host_restrictions) {
1239     extension->permissions_data()->SetUsesDefaultHostRestrictions(
1240         kRendererProfileId);
1241   } else {
1242     extension->permissions_data()->SetPolicyHostRestrictions(
1243         params.policy_blocked_hosts, params.policy_allowed_hosts);
1244   }
1245 
1246   std::unique_ptr<const PermissionSet> active =
1247       params.active_permissions.ToPermissionSet();
1248   std::unique_ptr<const PermissionSet> withheld =
1249       params.withheld_permissions.ToPermissionSet();
1250 
1251   extension->permissions_data()->SetPermissions(std::move(active),
1252                                                 std::move(withheld));
1253   UpdateOriginPermissions(*extension);
1254 
1255   UpdateBindingsForExtension(*extension);
1256 }
1257 
OnUpdateTabSpecificPermissions(const GURL & visible_url,const std::string & extension_id,const URLPatternSet & new_hosts,bool update_origin_whitelist,int tab_id)1258 void Dispatcher::OnUpdateTabSpecificPermissions(const GURL& visible_url,
1259                                                 const std::string& extension_id,
1260                                                 const URLPatternSet& new_hosts,
1261                                                 bool update_origin_whitelist,
1262                                                 int tab_id) {
1263   const Extension* extension =
1264       RendererExtensionRegistry::Get()->GetByID(extension_id);
1265   if (!extension)
1266     return;
1267 
1268   extension->permissions_data()->UpdateTabSpecificPermissions(
1269       tab_id, extensions::PermissionSet(extensions::APIPermissionSet(),
1270                                         extensions::ManifestPermissionSet(),
1271                                         new_hosts.Clone(), new_hosts.Clone()));
1272 
1273   if (update_origin_whitelist)
1274     UpdateOriginPermissions(*extension);
1275 }
1276 
OnClearTabSpecificPermissions(const std::vector<std::string> & extension_ids,bool update_origin_whitelist,int tab_id)1277 void Dispatcher::OnClearTabSpecificPermissions(
1278     const std::vector<std::string>& extension_ids,
1279     bool update_origin_whitelist,
1280     int tab_id) {
1281   for (const std::string& id : extension_ids) {
1282     const Extension* extension = RendererExtensionRegistry::Get()->GetByID(id);
1283     if (extension) {
1284       extension->permissions_data()->ClearTabSpecificPermissions(tab_id);
1285       if (update_origin_whitelist)
1286         UpdateOriginPermissions(*extension);
1287     }
1288   }
1289 }
1290 
SetActivityLoggingEnabled(bool enabled)1291 void Dispatcher::SetActivityLoggingEnabled(bool enabled) {
1292   activity_logging_enabled_ = enabled;
1293   if (enabled) {
1294     for (const std::string& id : active_extension_ids_)
1295       DOMActivityLogger::AttachToWorld(DOMActivityLogger::kMainWorldId, id);
1296   }
1297   script_injection_manager_->set_activity_logging_enabled(enabled);
1298   user_script_set_manager_->set_activity_logging_enabled(enabled);
1299 }
1300 
OnUserScriptsUpdated(const std::set<HostID> & changed_hosts)1301 void Dispatcher::OnUserScriptsUpdated(const std::set<HostID>& changed_hosts) {
1302   UpdateActiveExtensions();
1303 }
1304 
UpdateActiveExtensions()1305 void Dispatcher::UpdateActiveExtensions() {
1306   std::set<std::string> active_extensions = active_extension_ids_;
1307   user_script_set_manager_->GetAllActiveExtensionIds(&active_extensions);
1308   delegate_->OnActiveExtensionsUpdated(active_extensions);
1309 }
1310 
InitOriginPermissions(const Extension * extension)1311 void Dispatcher::InitOriginPermissions(const Extension* extension) {
1312   UpdateOriginPermissions(*extension);
1313 }
1314 
UpdateOriginPermissions(const Extension & extension)1315 void Dispatcher::UpdateOriginPermissions(const Extension& extension) {
1316   // Remove all old patterns associated with this extension.
1317   WebSecurityPolicy::ClearOriginAccessListForOrigin(extension.url());
1318 
1319   std::vector<network::mojom::CorsOriginPatternPtr> allow_list =
1320       CreateCorsOriginAccessAllowList(
1321           extension,
1322           PermissionsData::EffectiveHostPermissionsMode::kIncludeTabSpecific);
1323   ExtensionsClient::Get()->AddOriginAccessPermissions(
1324       extension, IsExtensionActive(extension.id()), &allow_list);
1325   for (const auto& entry : allow_list) {
1326     WebSecurityPolicy::AddOriginAccessAllowListEntry(
1327         extension.url(), WebString::FromUTF8(entry->protocol),
1328         WebString::FromUTF8(entry->domain), entry->port,
1329         entry->domain_match_mode, entry->port_match_mode, entry->priority);
1330   }
1331 
1332   for (const auto& entry : CreateCorsOriginAccessBlockList(extension)) {
1333     WebSecurityPolicy::AddOriginAccessBlockListEntry(
1334         extension.url(), WebString::FromUTF8(entry->protocol),
1335         WebString::FromUTF8(entry->domain), entry->port,
1336         entry->domain_match_mode, entry->port_match_mode, entry->priority);
1337   }
1338 }
1339 
EnableCustomElementWhiteList()1340 void Dispatcher::EnableCustomElementWhiteList() {
1341   blink::WebCustomElement::AddEmbedderCustomElementName("appview");
1342   blink::WebCustomElement::AddEmbedderCustomElementName("extensionoptions");
1343   blink::WebCustomElement::AddEmbedderCustomElementName("webview");
1344 }
1345 
UpdateAllBindings()1346 void Dispatcher::UpdateAllBindings() {
1347   bindings_system_->UpdateBindings(ExtensionId() /* all contexts */,
1348                                    false /* permissions_changed */,
1349                                    script_context_set_iterator());
1350   // TODO(crbug.com/986416): Can "externally_connectable" affect Service Worker
1351   // ScriptContext-s in some way? We'd need to process that here if that is the
1352   // case.
1353 }
1354 
UpdateBindingsForExtension(const Extension & extension)1355 void Dispatcher::UpdateBindingsForExtension(const Extension& extension) {
1356   bindings_system_->UpdateBindings(extension.id(),
1357                                    true /* permissions_changed */,
1358                                    script_context_set_iterator());
1359 
1360   // Update Service Worker bindings too, if applicable.
1361   if (!BackgroundInfo::IsServiceWorkerBased(&extension))
1362     return;
1363 
1364   const bool updated =
1365       WorkerThreadDispatcher::Get()->UpdateBindingsForWorkers(extension.id());
1366   // TODO(lazyboy): When can this fail?
1367   DCHECK(updated) << "Some or all workers failed to update bindings.";
1368 }
1369 
1370 // NOTE: please use the naming convention "foo_natives" for these.
RegisterNativeHandlers(ModuleSystem * module_system,ScriptContext * context,NativeExtensionBindingsSystem * bindings_system,V8SchemaRegistry * v8_schema_registry)1371 void Dispatcher::RegisterNativeHandlers(
1372     ModuleSystem* module_system,
1373     ScriptContext* context,
1374     NativeExtensionBindingsSystem* bindings_system,
1375     V8SchemaRegistry* v8_schema_registry) {
1376   RegisterNativeHandlers(module_system, context, this, bindings_system,
1377                          v8_schema_registry);
1378   const Extension* extension = context->extension();
1379   int manifest_version = extension ? extension->manifest_version() : 1;
1380   bool is_component_extension =
1381       extension && Manifest::IsComponentLocation(extension->location());
1382   bool send_request_disabled = messaging_util::IsSendRequestDisabled(context);
1383   module_system->RegisterNativeHandler(
1384       "process",
1385       std::unique_ptr<NativeHandler>(new ProcessInfoNativeHandler(
1386           context, context->GetExtensionID(),
1387           context->GetContextTypeDescription(),
1388           ExtensionsRendererClient::Get()->IsIncognitoProcess(),
1389           is_component_extension, manifest_version, send_request_disabled)));
1390 
1391   delegate_->RegisterNativeHandlers(this, module_system, bindings_system,
1392                                     context);
1393 }
1394 
PopulateSourceMap()1395 void Dispatcher::PopulateSourceMap() {
1396   const std::vector<JsResourceInfo> resources = GetJsResources();
1397   for (const auto& resource : resources)
1398     source_map_.RegisterSource(resource.name, resource.id);
1399   delegate_->PopulateSourceMap(&source_map_);
1400 }
1401 
IsWithinPlatformApp()1402 bool Dispatcher::IsWithinPlatformApp() {
1403   for (auto iter = active_extension_ids_.begin();
1404        iter != active_extension_ids_.end(); ++iter) {
1405     const Extension* extension =
1406         RendererExtensionRegistry::Get()->GetByID(*iter);
1407     if (extension && extension->is_platform_app())
1408       return true;
1409   }
1410   return false;
1411 }
1412 
RequireGuestViewModules(ScriptContext * context)1413 void Dispatcher::RequireGuestViewModules(ScriptContext* context) {
1414   ModuleSystem* module_system = context->module_system();
1415   bool requires_guest_view_module = false;
1416 
1417   // This determines whether to register error-providing custom elements for the
1418   // GuestView types that are not available. We only do this in contexts where
1419   // it is possible to gain access to a given GuestView element by declaring the
1420   // necessary permission in a manifest file. We don't want to define
1421   // error-providing elements in other extension contexts as the names could
1422   // collide with names used in the extension. Also, WebUIs may be whitelisted
1423   // to use GuestViews, but we don't define the error-providing elements in this
1424   // case.
1425   const bool is_platform_app =
1426       context->context_type() == Feature::BLESSED_EXTENSION_CONTEXT &&
1427       !context->IsForServiceWorker() && context->extension() &&
1428       context->extension()->is_platform_app();
1429   const bool app_view_permission_exists = is_platform_app;
1430   // The webview permission is also available to internal whitelisted
1431   // extensions, but not to extensions in general.
1432   const bool web_view_permission_exists = is_platform_app;
1433 
1434   // TODO(fsamuel): Eagerly calling Require on context startup is expensive.
1435   // It would be better if there were a light way of detecting when a webview
1436   // or appview is created and only then set up the infrastructure.
1437 
1438   // Require AppView.
1439   if (context->GetAvailability("appViewEmbedderInternal").is_available()) {
1440     requires_guest_view_module = true;
1441     module_system->Require("appViewElement");
1442   } else if (app_view_permission_exists) {
1443     module_system->Require("appViewDeny");
1444   }
1445 
1446   // Require ExtensionOptions.
1447   if (context->GetAvailability("extensionOptionsInternal").is_available()) {
1448     requires_guest_view_module = true;
1449     module_system->Require("extensionOptionsElement");
1450   }
1451 
1452   // Require WebView.
1453   if (context->GetAvailability("webViewInternal").is_available()) {
1454     requires_guest_view_module = true;
1455     // The embedder of the extensions layer may define its own implementation
1456     // of WebView.
1457     delegate_->RequireWebViewModules(context);
1458   } else if (web_view_permission_exists) {
1459     module_system->Require("webViewDeny");
1460   }
1461 
1462   if (requires_guest_view_module) {
1463     // If a frame has guest view custom elements defined, we need to make sure
1464     // the custom elements are also defined in subframes. The subframes will
1465     // need a scripting context which we will need to forcefully create if
1466     // the subframe doesn't otherwise have any scripts.
1467     context->web_frame()
1468         ->View()
1469         ->GetSettings()
1470         ->SetForceMainWorldInitialization(true);
1471   }
1472 }
1473 
CreateBindingsSystem(std::unique_ptr<IPCMessageSender> ipc_sender)1474 std::unique_ptr<NativeExtensionBindingsSystem> Dispatcher::CreateBindingsSystem(
1475     std::unique_ptr<IPCMessageSender> ipc_sender) {
1476   auto bindings_system =
1477       std::make_unique<NativeExtensionBindingsSystem>(std::move(ipc_sender));
1478   delegate_->InitializeBindingsSystem(this, bindings_system.get());
1479   return bindings_system;
1480 }
1481 
ResumeEvaluationOnWorkerThread(const ExtensionId & extension_id)1482 void Dispatcher::ResumeEvaluationOnWorkerThread(
1483     const ExtensionId& extension_id) {
1484   base::AutoLock lock(service_workers_paused_for_on_loaded_message_lock_);
1485   auto it = service_workers_paused_for_on_loaded_message_.find(extension_id);
1486   if (it != service_workers_paused_for_on_loaded_message_.end()) {
1487     blink::WebServiceWorkerContextProxy* context_proxy =
1488         it->second->context_proxy;
1489     context_proxy->ResumeEvaluation();
1490     service_workers_paused_for_on_loaded_message_.erase(it);
1491   }
1492 }
1493 
1494 }  // namespace extensions
1495