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 ¶ms.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