Move extension_messages.h to extensions/common.
[chromium-blink-merge.git] / chrome / renderer / extensions / dispatcher.cc
blobc3752b6c73cc139ce1f0e554ab720419bfe191c3
1 // Copyright (c) 2012 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.
5 #include "chrome/renderer/extensions/dispatcher.h"
7 #include "base/callback.h"
8 #include "base/command_line.h"
9 #include "base/debug/alias.h"
10 #include "base/json/json_reader.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/metrics/user_metrics_action.h"
13 #include "base/sha1.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_piece.h"
16 #include "base/strings/string_split.h"
17 #include "base/strings/string_util.h"
18 #include "chrome/common/chrome_switches.h"
19 #include "chrome/common/chrome_version_info.h"
20 #include "chrome/common/crash_keys.h"
21 #include "chrome/common/extensions/api/messaging/message.h"
22 #include "chrome/common/extensions/features/feature_channel.h"
23 #include "chrome/common/extensions/manifest_handlers/externally_connectable.h"
24 #include "chrome/common/extensions/message_bundle.h"
25 #include "chrome/common/url_constants.h"
26 #include "chrome/renderer/chrome_render_process_observer.h"
27 #include "chrome/renderer/extensions/api_activity_logger.h"
28 #include "chrome/renderer/extensions/api_definitions_natives.h"
29 #include "chrome/renderer/extensions/app_bindings.h"
30 #include "chrome/renderer/extensions/app_runtime_custom_bindings.h"
31 #include "chrome/renderer/extensions/app_window_custom_bindings.h"
32 #include "chrome/renderer/extensions/binding_generating_native_handler.h"
33 #include "chrome/renderer/extensions/blob_native_handler.h"
34 #include "chrome/renderer/extensions/chrome_v8_context.h"
35 #include "chrome/renderer/extensions/chrome_v8_extension.h"
36 #include "chrome/renderer/extensions/content_watcher.h"
37 #include "chrome/renderer/extensions/context_menus_custom_bindings.h"
38 #include "chrome/renderer/extensions/css_native_handler.h"
39 #include "chrome/renderer/extensions/document_custom_bindings.h"
40 #include "chrome/renderer/extensions/dom_activity_logger.h"
41 #include "chrome/renderer/extensions/event_bindings.h"
42 #include "chrome/renderer/extensions/extension_groups.h"
43 #include "chrome/renderer/extensions/extension_helper.h"
44 #include "chrome/renderer/extensions/file_browser_handler_custom_bindings.h"
45 #include "chrome/renderer/extensions/file_browser_private_custom_bindings.h"
46 #include "chrome/renderer/extensions/file_system_natives.h"
47 #include "chrome/renderer/extensions/i18n_custom_bindings.h"
48 #include "chrome/renderer/extensions/id_generator_custom_bindings.h"
49 #include "chrome/renderer/extensions/logging_native_handler.h"
50 #include "chrome/renderer/extensions/media_galleries_custom_bindings.h"
51 #include "chrome/renderer/extensions/messaging_bindings.h"
52 #include "chrome/renderer/extensions/module_system.h"
53 #include "chrome/renderer/extensions/object_backed_native_handler.h"
54 #include "chrome/renderer/extensions/page_actions_custom_bindings.h"
55 #include "chrome/renderer/extensions/page_capture_custom_bindings.h"
56 #include "chrome/renderer/extensions/pepper_request_natives.h"
57 #include "chrome/renderer/extensions/render_view_observer_natives.h"
58 #include "chrome/renderer/extensions/request_sender.h"
59 #include "chrome/renderer/extensions/runtime_custom_bindings.h"
60 #include "chrome/renderer/extensions/safe_builtins.h"
61 #include "chrome/renderer/extensions/send_request_natives.h"
62 #include "chrome/renderer/extensions/set_icon_natives.h"
63 #include "chrome/renderer/extensions/sync_file_system_custom_bindings.h"
64 #include "chrome/renderer/extensions/tab_finder.h"
65 #include "chrome/renderer/extensions/tabs_custom_bindings.h"
66 #include "chrome/renderer/extensions/user_script_slave.h"
67 #include "chrome/renderer/extensions/utils_native_handler.h"
68 #include "chrome/renderer/extensions/webstore_bindings.h"
69 #include "chrome/renderer/resource_bundle_source_map.h"
70 #include "content/public/renderer/render_thread.h"
71 #include "content/public/renderer/render_view.h"
72 #include "content/public/renderer/v8_value_converter.h"
73 #include "extensions/common/constants.h"
74 #include "extensions/common/extension.h"
75 #include "extensions/common/extension_api.h"
76 #include "extensions/common/extension_messages.h"
77 #include "extensions/common/extension_urls.h"
78 #include "extensions/common/features/feature.h"
79 #include "extensions/common/features/feature_provider.h"
80 #include "extensions/common/manifest.h"
81 #include "extensions/common/manifest_constants.h"
82 #include "extensions/common/manifest_handlers/background_info.h"
83 #include "extensions/common/manifest_handlers/sandboxed_page_info.h"
84 #include "extensions/common/permissions/permission_set.h"
85 #include "extensions/common/permissions/permissions_data.h"
86 #include "extensions/common/switches.h"
87 #include "extensions/common/view_type.h"
88 #include "grit/common_resources.h"
89 #include "grit/renderer_resources.h"
90 #include "third_party/WebKit/public/platform/WebString.h"
91 #include "third_party/WebKit/public/platform/WebURLRequest.h"
92 #include "third_party/WebKit/public/web/WebCustomElement.h"
93 #include "third_party/WebKit/public/web/WebDataSource.h"
94 #include "third_party/WebKit/public/web/WebDocument.h"
95 #include "third_party/WebKit/public/web/WebFrame.h"
96 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
97 #include "third_party/WebKit/public/web/WebScopedUserGesture.h"
98 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
99 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
100 #include "third_party/WebKit/public/web/WebView.h"
101 #include "ui/base/layout.h"
102 #include "ui/base/resource/resource_bundle.h"
103 #include "v8/include/v8.h"
105 #if defined(ENABLE_WEBRTC)
106 #include "chrome/renderer/extensions/cast_streaming_native_handler.h"
107 #endif
109 using base::UserMetricsAction;
110 using blink::WebDataSource;
111 using blink::WebDocument;
112 using blink::WebFrame;
113 using blink::WebScopedUserGesture;
114 using blink::WebSecurityPolicy;
115 using blink::WebString;
116 using blink::WebVector;
117 using blink::WebView;
118 using content::RenderThread;
119 using content::RenderView;
121 namespace extensions {
123 namespace {
125 static const int64 kInitialExtensionIdleHandlerDelayMs = 5*1000;
126 static const int64 kMaxExtensionIdleHandlerDelayMs = 5*60*1000;
127 static const char kEventDispatchFunction[] = "dispatchEvent";
128 static const char kOnSuspendEvent[] = "runtime.onSuspend";
129 static const char kOnSuspendCanceledEvent[] = "runtime.onSuspendCanceled";
131 // Returns the global value for "chrome" from |context|. If one doesn't exist
132 // creates a new object for it.
134 // Note that this isn't necessarily an object, since webpages can write, for
135 // example, "window.chrome = true".
136 v8::Handle<v8::Value> GetOrCreateChrome(ChromeV8Context* context) {
137 v8::Handle<v8::String> chrome_string(
138 v8::String::NewFromUtf8(context->isolate(), "chrome"));
139 v8::Handle<v8::Object> global(context->v8_context()->Global());
140 v8::Handle<v8::Value> chrome(global->Get(chrome_string));
141 if (chrome->IsUndefined()) {
142 chrome = v8::Object::New(context->isolate());
143 global->Set(chrome_string, chrome);
145 return chrome;
148 // Returns |value| cast to an object if possible, else an empty handle.
149 v8::Handle<v8::Object> AsObjectOrEmpty(v8::Handle<v8::Value> value) {
150 return value->IsObject() ? value.As<v8::Object>() : v8::Handle<v8::Object>();
153 class TestFeaturesNativeHandler : public ObjectBackedNativeHandler {
154 public:
155 explicit TestFeaturesNativeHandler(ChromeV8Context* context)
156 : ObjectBackedNativeHandler(context) {
157 RouteFunction("GetAPIFeatures",
158 base::Bind(&TestFeaturesNativeHandler::GetAPIFeatures,
159 base::Unretained(this)));
162 private:
163 void GetAPIFeatures(const v8::FunctionCallbackInfo<v8::Value>& args) {
164 base::Value* value = base::JSONReader::Read(
165 ResourceBundle::GetSharedInstance().GetRawDataResource(
166 IDR_EXTENSION_API_FEATURES).as_string());
167 scoped_ptr<content::V8ValueConverter> converter(
168 content::V8ValueConverter::create());
169 args.GetReturnValue().Set(
170 converter->ToV8Value(value, context()->v8_context()));
174 class UserGesturesNativeHandler : public ObjectBackedNativeHandler {
175 public:
176 explicit UserGesturesNativeHandler(ChromeV8Context* context)
177 : ObjectBackedNativeHandler(context) {
178 RouteFunction("IsProcessingUserGesture",
179 base::Bind(&UserGesturesNativeHandler::IsProcessingUserGesture,
180 base::Unretained(this)));
181 RouteFunction("RunWithUserGesture",
182 base::Bind(&UserGesturesNativeHandler::RunWithUserGesture,
183 base::Unretained(this)));
184 RouteFunction("RunWithoutUserGesture",
185 base::Bind(&UserGesturesNativeHandler::RunWithoutUserGesture,
186 base::Unretained(this)));
189 private:
190 void IsProcessingUserGesture(
191 const v8::FunctionCallbackInfo<v8::Value>& args) {
192 args.GetReturnValue().Set(v8::Boolean::New(
193 args.GetIsolate(),
194 blink::WebUserGestureIndicator::isProcessingUserGesture()));
197 void RunWithUserGesture(
198 const v8::FunctionCallbackInfo<v8::Value>& args) {
199 blink::WebScopedUserGesture user_gesture;
200 CHECK_EQ(args.Length(), 1);
201 CHECK(args[0]->IsFunction());
202 v8::Handle<v8::Value> no_args;
203 context()->CallFunction(v8::Handle<v8::Function>::Cast(args[0]),
204 0, &no_args);
207 void RunWithoutUserGesture(
208 const v8::FunctionCallbackInfo<v8::Value>& args) {
209 blink::WebUserGestureIndicator::consumeUserGesture();
210 CHECK_EQ(args.Length(), 1);
211 CHECK(args[0]->IsFunction());
212 v8::Handle<v8::Value> no_args;
213 context()->CallFunction(v8::Handle<v8::Function>::Cast(args[0]),
214 0, &no_args);
218 class V8ContextNativeHandler : public ObjectBackedNativeHandler {
219 public:
220 V8ContextNativeHandler(ChromeV8Context* context, Dispatcher* dispatcher)
221 : ObjectBackedNativeHandler(context),
222 context_(context),
223 dispatcher_(dispatcher) {
224 RouteFunction("GetAvailability",
225 base::Bind(&V8ContextNativeHandler::GetAvailability,
226 base::Unretained(this)));
227 RouteFunction("GetModuleSystem",
228 base::Bind(&V8ContextNativeHandler::GetModuleSystem,
229 base::Unretained(this)));
232 private:
233 void GetAvailability(const v8::FunctionCallbackInfo<v8::Value>& args) {
234 CHECK_EQ(args.Length(), 1);
235 v8::Isolate* isolate = args.GetIsolate();
236 std::string api_name = *v8::String::Utf8Value(args[0]->ToString());
237 Feature::Availability availability = context_->GetAvailability(api_name);
239 v8::Handle<v8::Object> ret = v8::Object::New(isolate);
240 ret->Set(v8::String::NewFromUtf8(isolate, "is_available"),
241 v8::Boolean::New(isolate, availability.is_available()));
242 ret->Set(v8::String::NewFromUtf8(isolate, "message"),
243 v8::String::NewFromUtf8(isolate, availability.message().c_str()));
244 ret->Set(v8::String::NewFromUtf8(isolate, "result"),
245 v8::Integer::New(isolate, availability.result()));
246 args.GetReturnValue().Set(ret);
249 void GetModuleSystem(const v8::FunctionCallbackInfo<v8::Value>& args) {
250 CHECK_EQ(args.Length(), 1);
251 CHECK(args[0]->IsObject());
252 v8::Handle<v8::Context> v8_context =
253 v8::Handle<v8::Object>::Cast(args[0])->CreationContext();
254 ChromeV8Context* context = dispatcher_->v8_context_set().GetByV8Context(
255 v8_context);
256 args.GetReturnValue().Set(context->module_system()->NewInstance());
259 ChromeV8Context* context_;
260 Dispatcher* dispatcher_;
263 class ChromeNativeHandler : public ObjectBackedNativeHandler {
264 public:
265 explicit ChromeNativeHandler(ChromeV8Context* context)
266 : ObjectBackedNativeHandler(context) {
267 RouteFunction("GetChrome",
268 base::Bind(&ChromeNativeHandler::GetChrome, base::Unretained(this)));
271 void GetChrome(const v8::FunctionCallbackInfo<v8::Value>& args) {
272 args.GetReturnValue().Set(GetOrCreateChrome(context()));
276 class PrintNativeHandler : public ObjectBackedNativeHandler {
277 public:
278 explicit PrintNativeHandler(ChromeV8Context* context)
279 : ObjectBackedNativeHandler(context) {
280 RouteFunction("Print",
281 base::Bind(&PrintNativeHandler::Print,
282 base::Unretained(this)));
285 void Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
286 if (args.Length() < 1)
287 return;
289 std::vector<std::string> components;
290 for (int i = 0; i < args.Length(); ++i)
291 components.push_back(*v8::String::Utf8Value(args[i]->ToString()));
293 LOG(ERROR) << JoinString(components, ',');
297 class LazyBackgroundPageNativeHandler : public ChromeV8Extension {
298 public:
299 LazyBackgroundPageNativeHandler(Dispatcher* dispatcher,
300 ChromeV8Context* context)
301 : ChromeV8Extension(dispatcher, context) {
302 RouteFunction("IncrementKeepaliveCount",
303 base::Bind(&LazyBackgroundPageNativeHandler::IncrementKeepaliveCount,
304 base::Unretained(this)));
305 RouteFunction("DecrementKeepaliveCount",
306 base::Bind(&LazyBackgroundPageNativeHandler::DecrementKeepaliveCount,
307 base::Unretained(this)));
310 void IncrementKeepaliveCount(
311 const v8::FunctionCallbackInfo<v8::Value>& args) {
312 if (!context())
313 return;
314 RenderView* render_view = context()->GetRenderView();
315 if (IsContextLazyBackgroundPage(render_view, context()->extension())) {
316 render_view->Send(new ExtensionHostMsg_IncrementLazyKeepaliveCount(
317 render_view->GetRoutingID()));
321 void DecrementKeepaliveCount(
322 const v8::FunctionCallbackInfo<v8::Value>& args) {
323 if (!context())
324 return;
325 RenderView* render_view = context()->GetRenderView();
326 if (IsContextLazyBackgroundPage(render_view, context()->extension())) {
327 render_view->Send(new ExtensionHostMsg_DecrementLazyKeepaliveCount(
328 render_view->GetRoutingID()));
332 private:
333 bool IsContextLazyBackgroundPage(RenderView* render_view,
334 const Extension* extension) {
335 if (!render_view)
336 return false;
338 ExtensionHelper* helper = ExtensionHelper::Get(render_view);
339 return (extension && BackgroundInfo::HasLazyBackgroundPage(extension) &&
340 helper->view_type() == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
344 class ProcessInfoNativeHandler : public ChromeV8Extension {
345 public:
346 ProcessInfoNativeHandler(Dispatcher* dispatcher,
347 ChromeV8Context* context,
348 const std::string& extension_id,
349 const std::string& context_type,
350 bool is_incognito_context,
351 int manifest_version,
352 bool send_request_disabled)
353 : ChromeV8Extension(dispatcher, context),
354 extension_id_(extension_id),
355 context_type_(context_type),
356 is_incognito_context_(is_incognito_context),
357 manifest_version_(manifest_version),
358 send_request_disabled_(send_request_disabled) {
359 RouteFunction("GetExtensionId",
360 base::Bind(&ProcessInfoNativeHandler::GetExtensionId,
361 base::Unretained(this)));
362 RouteFunction("GetContextType",
363 base::Bind(&ProcessInfoNativeHandler::GetContextType,
364 base::Unretained(this)));
365 RouteFunction("InIncognitoContext",
366 base::Bind(&ProcessInfoNativeHandler::InIncognitoContext,
367 base::Unretained(this)));
368 RouteFunction("GetManifestVersion",
369 base::Bind(&ProcessInfoNativeHandler::GetManifestVersion,
370 base::Unretained(this)));
371 RouteFunction("IsSendRequestDisabled",
372 base::Bind(&ProcessInfoNativeHandler::IsSendRequestDisabled,
373 base::Unretained(this)));
374 RouteFunction("HasSwitch",
375 base::Bind(&ProcessInfoNativeHandler::HasSwitch,
376 base::Unretained(this)));
379 private:
380 void GetExtensionId(const v8::FunctionCallbackInfo<v8::Value>& args) {
381 args.GetReturnValue()
382 .Set(v8::String::NewFromUtf8(args.GetIsolate(), extension_id_.c_str()));
385 void GetContextType(const v8::FunctionCallbackInfo<v8::Value>& args) {
386 args.GetReturnValue()
387 .Set(v8::String::NewFromUtf8(args.GetIsolate(), context_type_.c_str()));
390 void InIncognitoContext(const v8::FunctionCallbackInfo<v8::Value>& args) {
391 args.GetReturnValue().Set(is_incognito_context_);
394 void GetManifestVersion(const v8::FunctionCallbackInfo<v8::Value>& args) {
395 args.GetReturnValue().Set(static_cast<int32_t>(manifest_version_));
398 void IsSendRequestDisabled(const v8::FunctionCallbackInfo<v8::Value>& args) {
399 if (send_request_disabled_) {
400 args.GetReturnValue().Set(v8::String::NewFromUtf8(args.GetIsolate(),
401 "sendRequest and onRequest are obsolete."
402 " Please use sendMessage and onMessage instead."));
406 void HasSwitch(const v8::FunctionCallbackInfo<v8::Value>& args) {
407 CHECK(args.Length() == 1 && args[0]->IsString());
408 bool has_switch = CommandLine::ForCurrentProcess()->HasSwitch(
409 *v8::String::Utf8Value(args[0]));
410 args.GetReturnValue().Set(v8::Boolean::New(args.GetIsolate(), has_switch));
413 std::string extension_id_;
414 std::string context_type_;
415 bool is_incognito_context_;
416 int manifest_version_;
417 bool send_request_disabled_;
420 void InstallAppBindings(ModuleSystem* module_system,
421 v8::Handle<v8::Object> chrome) {
422 module_system->SetLazyField(chrome, "app", "app", "chromeApp");
425 void InstallWebstoreBindings(ModuleSystem* module_system,
426 v8::Handle<v8::Object> chrome) {
427 module_system->SetLazyField(chrome, "webstore", "webstore", "chromeWebstore");
430 // Calls a method |method_name| in a module |module_name| belonging to the
431 // module system from |context|. Intended as a callback target from
432 // ChromeV8ContextSet::ForEach.
433 void CallModuleMethod(const std::string& module_name,
434 const std::string& method_name,
435 const base::ListValue* args,
436 ChromeV8Context* context) {
437 v8::HandleScope handle_scope(context->isolate());
438 v8::Context::Scope context_scope(context->v8_context());
440 scoped_ptr<content::V8ValueConverter> converter(
441 content::V8ValueConverter::create());
443 std::vector<v8::Handle<v8::Value> > arguments;
444 for (base::ListValue::const_iterator it = args->begin(); it != args->end();
445 ++it) {
446 arguments.push_back(converter->ToV8Value(*it, context->v8_context()));
449 context->module_system()->CallModuleMethod(
450 module_name, method_name, &arguments);
453 } // namespace
455 Dispatcher::Dispatcher()
456 : content_watcher_(new ContentWatcher()),
457 is_webkit_initialized_(false),
458 webrequest_adblock_(false),
459 webrequest_adblock_plus_(false),
460 webrequest_other_(false),
461 source_map_(&ResourceBundle::GetSharedInstance()),
462 v8_schema_registry_(new V8SchemaRegistry) {
463 const CommandLine& command_line = *(CommandLine::ForCurrentProcess());
464 is_extension_process_ =
465 command_line.HasSwitch(extensions::switches::kExtensionProcess) ||
466 command_line.HasSwitch(::switches::kSingleProcess);
468 if (is_extension_process_) {
469 RenderThread::Get()->SetIdleNotificationDelayInMs(
470 kInitialExtensionIdleHandlerDelayMs);
473 RenderThread::Get()->RegisterExtension(SafeBuiltins::CreateV8Extension());
475 user_script_slave_.reset(new UserScriptSlave(&extensions_));
476 request_sender_.reset(new RequestSender(this));
477 PopulateSourceMap();
478 PopulateLazyBindingsMap();
481 Dispatcher::~Dispatcher() {
484 bool Dispatcher::OnControlMessageReceived(const IPC::Message& message) {
485 bool handled = true;
486 IPC_BEGIN_MESSAGE_MAP(Dispatcher, message)
487 IPC_MESSAGE_HANDLER(ExtensionMsg_SetChannel, OnSetChannel)
488 IPC_MESSAGE_HANDLER(ExtensionMsg_MessageInvoke, OnMessageInvoke)
489 IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchOnConnect, OnDispatchOnConnect)
490 IPC_MESSAGE_HANDLER(ExtensionMsg_DeliverMessage, OnDeliverMessage)
491 IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchOnDisconnect,
492 OnDispatchOnDisconnect)
493 IPC_MESSAGE_HANDLER(ExtensionMsg_SetFunctionNames, OnSetFunctionNames)
494 IPC_MESSAGE_HANDLER(ExtensionMsg_SetSystemFont, OnSetSystemFont)
495 IPC_MESSAGE_HANDLER(ExtensionMsg_Loaded, OnLoaded)
496 IPC_MESSAGE_HANDLER(ExtensionMsg_Unloaded, OnUnloaded)
497 IPC_MESSAGE_HANDLER(ExtensionMsg_SetScriptingWhitelist,
498 OnSetScriptingWhitelist)
499 IPC_MESSAGE_HANDLER(ExtensionMsg_ActivateExtension, OnActivateExtension)
500 IPC_MESSAGE_HANDLER(ExtensionMsg_UpdatePermissions, OnUpdatePermissions)
501 IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateTabSpecificPermissions,
502 OnUpdateTabSpecificPermissions)
503 IPC_MESSAGE_HANDLER(ExtensionMsg_ClearTabSpecificPermissions,
504 OnClearTabSpecificPermissions)
505 IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateUserScripts, OnUpdateUserScripts)
506 IPC_MESSAGE_HANDLER(ExtensionMsg_UsingWebRequestAPI, OnUsingWebRequestAPI)
507 IPC_MESSAGE_HANDLER(ExtensionMsg_ShouldSuspend, OnShouldSuspend)
508 IPC_MESSAGE_HANDLER(ExtensionMsg_Suspend, OnSuspend)
509 IPC_MESSAGE_HANDLER(ExtensionMsg_CancelSuspend, OnCancelSuspend)
510 IPC_MESSAGE_FORWARD(ExtensionMsg_WatchPages,
511 content_watcher_.get(), ContentWatcher::OnWatchPages)
512 IPC_MESSAGE_UNHANDLED(handled = false)
513 IPC_END_MESSAGE_MAP()
515 return handled;
518 void Dispatcher::WebKitInitialized() {
519 // For extensions, we want to ensure we call the IdleHandler every so often,
520 // even if the extension keeps up activity.
521 if (is_extension_process_) {
522 forced_idle_timer_.Start(FROM_HERE,
523 base::TimeDelta::FromMilliseconds(kMaxExtensionIdleHandlerDelayMs),
524 RenderThread::Get(), &RenderThread::IdleHandler);
527 // Initialize host permissions for any extensions that were activated before
528 // WebKit was initialized.
529 for (std::set<std::string>::iterator iter = active_extension_ids_.begin();
530 iter != active_extension_ids_.end(); ++iter) {
531 const Extension* extension = extensions_.GetByID(*iter);
532 CHECK(extension);
535 EnableCustomElementWhiteList();
537 is_webkit_initialized_ = true;
540 void Dispatcher::IdleNotification() {
541 if (is_extension_process_) {
542 // Dampen the forced delay as well if the extension stays idle for long
543 // periods of time.
544 int64 forced_delay_ms = std::max(
545 RenderThread::Get()->GetIdleNotificationDelayInMs(),
546 kMaxExtensionIdleHandlerDelayMs);
547 forced_idle_timer_.Stop();
548 forced_idle_timer_.Start(FROM_HERE,
549 base::TimeDelta::FromMilliseconds(forced_delay_ms),
550 RenderThread::Get(), &RenderThread::IdleHandler);
554 void Dispatcher::OnRenderProcessShutdown() {
555 v8_schema_registry_.reset();
558 void Dispatcher::OnSetFunctionNames(
559 const std::vector<std::string>& names) {
560 function_names_.clear();
561 for (size_t i = 0; i < names.size(); ++i)
562 function_names_.insert(names[i]);
565 void Dispatcher::OnSetSystemFont(const std::string& font_family,
566 const std::string& font_size) {
567 system_font_family_ = font_family;
568 system_font_size_ = font_size;
571 void Dispatcher::OnSetChannel(int channel) {
572 SetCurrentChannel(static_cast<chrome::VersionInfo::Channel>(channel));
575 void Dispatcher::OnMessageInvoke(const std::string& extension_id,
576 const std::string& module_name,
577 const std::string& function_name,
578 const base::ListValue& args,
579 bool user_gesture) {
580 InvokeModuleSystemMethod(
581 NULL, extension_id, module_name, function_name, args, user_gesture);
584 void Dispatcher::OnDispatchOnConnect(
585 int target_port_id,
586 const std::string& channel_name,
587 const base::DictionaryValue& source_tab,
588 const ExtensionMsg_ExternalConnectionInfo& info,
589 const std::string& tls_channel_id) {
590 DCHECK(!ContainsKey(port_to_tab_id_map_, target_port_id));
591 DCHECK_EQ(1, target_port_id % 2); // target renderer ports have odd IDs.
592 int sender_tab_id = -1;
593 source_tab.GetInteger("id", &sender_tab_id);
594 port_to_tab_id_map_[target_port_id] = sender_tab_id;
596 MessagingBindings::DispatchOnConnect(
597 v8_context_set_.GetAll(),
598 target_port_id, channel_name, source_tab,
599 info.source_id, info.target_id, info.source_url,
600 tls_channel_id,
601 NULL); // All render views.
604 void Dispatcher::OnDeliverMessage(int target_port_id,
605 const Message& message) {
606 scoped_ptr<RequestSender::ScopedTabID> scoped_tab_id;
607 std::map<int, int>::const_iterator it =
608 port_to_tab_id_map_.find(target_port_id);
609 if (it != port_to_tab_id_map_.end()) {
610 scoped_tab_id.reset(new RequestSender::ScopedTabID(request_sender(),
611 it->second));
614 MessagingBindings::DeliverMessage(
615 v8_context_set_.GetAll(),
616 target_port_id,
617 message,
618 NULL); // All render views.
621 void Dispatcher::OnDispatchOnDisconnect(int port_id,
622 const std::string& error_message) {
623 MessagingBindings::DispatchOnDisconnect(
624 v8_context_set_.GetAll(),
625 port_id, error_message,
626 NULL); // All render views.
629 void Dispatcher::OnLoaded(
630 const std::vector<ExtensionMsg_Loaded_Params>& loaded_extensions) {
631 std::vector<ExtensionMsg_Loaded_Params>::const_iterator i;
632 for (i = loaded_extensions.begin(); i != loaded_extensions.end(); ++i) {
633 std::string error;
634 scoped_refptr<const Extension> extension = i->ConvertToExtension(&error);
635 if (!extension.get()) {
636 extension_load_errors_[i->id] = error;
637 continue;
639 OnLoadedInternal(extension);
641 // Update the available bindings for all contexts. These may have changed if
642 // an externally_connectable extension was loaded that can connect to an
643 // open webpage.
644 AddOrRemoveBindings("");
647 void Dispatcher::OnLoadedInternal(scoped_refptr<const Extension> extension) {
648 extensions_.Insert(extension);
651 void Dispatcher::OnUnloaded(const std::string& id) {
652 extensions_.Remove(id);
653 active_extension_ids_.erase(id);
655 // If the extension is later reloaded with a different set of permissions,
656 // we'd like it to get a new isolated world ID, so that it can pick up the
657 // changed origin whitelist.
658 user_script_slave_->RemoveIsolatedWorld(id);
660 // Invalidate all of the contexts that were removed.
661 // TODO(kalman): add an invalidation observer interface to ChromeV8Context.
662 ChromeV8ContextSet::ContextSet removed_contexts =
663 v8_context_set_.OnExtensionUnloaded(id);
664 for (ChromeV8ContextSet::ContextSet::iterator it = removed_contexts.begin();
665 it != removed_contexts.end(); ++it) {
666 request_sender_->InvalidateSource(*it);
669 // Update the available bindings for the remaining contexts. These may have
670 // changed if an externally_connectable extension is unloaded and a webpage
671 // is no longer accessible.
672 AddOrRemoveBindings("");
674 // Invalidates the messages map for the extension in case the extension is
675 // reloaded with a new messages map.
676 EraseL10nMessagesMap(id);
678 // We don't do anything with existing platform-app stylesheets. They will
679 // stay resident, but the URL pattern corresponding to the unloaded
680 // extension's URL just won't match anything anymore.
683 void Dispatcher::OnSetScriptingWhitelist(
684 const ExtensionsClient::ScriptingWhitelist& extension_ids) {
685 ExtensionsClient::Get()->SetScriptingWhitelist(extension_ids);
688 bool Dispatcher::IsExtensionActive(
689 const std::string& extension_id) const {
690 bool is_active =
691 active_extension_ids_.find(extension_id) != active_extension_ids_.end();
692 if (is_active)
693 CHECK(extensions_.Contains(extension_id));
694 return is_active;
697 v8::Handle<v8::Object> Dispatcher::GetOrCreateObject(
698 v8::Handle<v8::Object> object,
699 const std::string& field,
700 v8::Isolate* isolate) {
701 v8::Handle<v8::String> key = v8::String::NewFromUtf8(isolate, field.c_str());
702 // If the object has a callback property, it is assumed it is an unavailable
703 // API, so it is safe to delete. This is checked before GetOrCreateObject is
704 // called.
705 if (object->HasRealNamedCallbackProperty(key)) {
706 object->Delete(key);
707 } else if (object->HasRealNamedProperty(key)) {
708 v8::Handle<v8::Value> value = object->Get(key);
709 CHECK(value->IsObject());
710 return v8::Handle<v8::Object>::Cast(value);
713 v8::Handle<v8::Object> new_object = v8::Object::New(isolate);
714 object->Set(key, new_object);
715 return new_object;
718 void Dispatcher::AddOrRemoveBindingsForContext(ChromeV8Context* context) {
719 v8::HandleScope handle_scope(context->isolate());
720 v8::Context::Scope context_scope(context->v8_context());
722 // TODO(kalman): Make the bindings registration have zero overhead then run
723 // the same code regardless of context type.
724 switch (context->context_type()) {
725 case Feature::UNSPECIFIED_CONTEXT:
726 case Feature::WEB_PAGE_CONTEXT:
727 case Feature::BLESSED_WEB_PAGE_CONTEXT: {
728 // Web page context; it's too expensive to run the full bindings code.
729 // Hard-code that the app and webstore APIs are available...
730 RegisterBinding("app", context);
731 RegisterBinding("webstore", context);
733 // ... and that the runtime API might be available if any extension can
734 // connect to it.
735 bool runtime_is_available = false;
736 for (ExtensionSet::const_iterator it = extensions_.begin();
737 it != extensions_.end(); ++it) {
738 ExternallyConnectableInfo* info =
739 static_cast<ExternallyConnectableInfo*>((*it)->GetManifestData(
740 manifest_keys::kExternallyConnectable));
741 if (info && info->matches.MatchesURL(context->GetURL())) {
742 runtime_is_available = true;
743 break;
746 if (runtime_is_available)
747 RegisterBinding("runtime", context);
748 break;
751 case Feature::BLESSED_EXTENSION_CONTEXT:
752 case Feature::UNBLESSED_EXTENSION_CONTEXT:
753 case Feature::CONTENT_SCRIPT_CONTEXT: {
754 // Extension context; iterate through all the APIs and bind the available
755 // ones.
756 FeatureProvider* api_feature_provider = FeatureProvider::GetAPIFeatures();
757 const std::vector<std::string>& apis =
758 api_feature_provider->GetAllFeatureNames();
759 for (std::vector<std::string>::const_iterator it = apis.begin();
760 it != apis.end(); ++it) {
761 const std::string& api_name = *it;
762 Feature* feature = api_feature_provider->GetFeature(api_name);
763 DCHECK(feature);
765 // Internal APIs are included via require(api_name) from internal code
766 // rather than chrome[api_name].
767 if (feature->IsInternal())
768 continue;
770 // If this API has a parent feature (and isn't marked 'noparent'),
771 // then this must be a function or event, so we should not register.
772 if (api_feature_provider->GetParent(feature) != NULL)
773 continue;
775 if (context->IsAnyFeatureAvailableToContext(*feature))
776 RegisterBinding(api_name, context);
778 break;
783 v8::Handle<v8::Object> Dispatcher::GetOrCreateBindObjectIfAvailable(
784 const std::string& api_name,
785 std::string* bind_name,
786 ChromeV8Context* context) {
787 std::vector<std::string> split;
788 base::SplitString(api_name, '.', &split);
790 v8::Handle<v8::Object> bind_object;
792 // Check if this API has an ancestor. If the API's ancestor is available and
793 // the API is not available, don't install the bindings for this API. If
794 // the API is available and its ancestor is not, delete the ancestor and
795 // install the bindings for the API. This is to prevent loading the ancestor
796 // API schema if it will not be needed.
798 // For example:
799 // If app is available and app.window is not, just install app.
800 // If app.window is available and app is not, delete app and install
801 // app.window on a new object so app does not have to be loaded.
802 FeatureProvider* api_feature_provider = FeatureProvider::GetAPIFeatures();
803 std::string ancestor_name;
804 bool only_ancestor_available = false;
806 for (size_t i = 0; i < split.size() - 1; ++i) {
807 ancestor_name += (i ? ".": "") + split[i];
808 if (api_feature_provider->GetFeature(ancestor_name) &&
809 context->GetAvailability(ancestor_name).is_available() &&
810 !context->GetAvailability(api_name).is_available()) {
811 only_ancestor_available = true;
812 break;
815 if (bind_object.IsEmpty()) {
816 bind_object = AsObjectOrEmpty(GetOrCreateChrome(context));
817 if (bind_object.IsEmpty())
818 return v8::Handle<v8::Object>();
820 bind_object = GetOrCreateObject(bind_object, split[i], context->isolate());
823 if (only_ancestor_available)
824 return v8::Handle<v8::Object>();
826 if (bind_name)
827 *bind_name = split.back();
829 return bind_object.IsEmpty() ?
830 AsObjectOrEmpty(GetOrCreateChrome(context)) : bind_object;
833 void Dispatcher::RegisterBinding(const std::string& api_name,
834 ChromeV8Context* context) {
835 std::string bind_name;
836 v8::Handle<v8::Object> bind_object =
837 GetOrCreateBindObjectIfAvailable(api_name, &bind_name, context);
839 // Empty if the bind object failed to be created, probably because the
840 // extension overrode chrome with a non-object, e.g. window.chrome = true.
841 if (bind_object.IsEmpty())
842 return;
844 v8::Local<v8::String> v8_api_name =
845 v8::String::NewFromUtf8(context->isolate(), api_name.c_str());
846 if (bind_object->HasRealNamedProperty(v8_api_name)) {
847 // The bind object may already have the property if the API has been
848 // registered before (or if the extension has put something there already,
849 // but, whatevs).
851 // In the former case, we need to re-register the bindings for the APIs
852 // which the extension now has permissions for (if any), but not touch any
853 // others so that we don't destroy state such as event listeners.
855 // TODO(kalman): Only register available APIs to make this all moot.
856 if (bind_object->HasRealNamedCallbackProperty(v8_api_name))
857 return; // lazy binding still there, nothing to do
858 if (bind_object->Get(v8_api_name)->IsObject())
859 return; // binding has already been fully installed
862 ModuleSystem* module_system = context->module_system();
863 if (lazy_bindings_map_.find(api_name) != lazy_bindings_map_.end()) {
864 InstallBindings(module_system, context->v8_context(), api_name);
865 } else if (!source_map_.Contains(api_name)) {
866 module_system->RegisterNativeHandler(
867 api_name,
868 scoped_ptr<NativeHandler>(new BindingGeneratingNativeHandler(
869 module_system,
870 api_name,
871 "binding")));
872 module_system->SetNativeLazyField(bind_object,
873 bind_name,
874 api_name,
875 "binding");
876 } else {
877 module_system->SetLazyField(bind_object,
878 bind_name,
879 api_name,
880 "binding");
884 // NOTE: please use the naming convention "foo_natives" for these.
885 void Dispatcher::RegisterNativeHandlers(ModuleSystem* module_system,
886 ChromeV8Context* context) {
887 module_system->RegisterNativeHandler("event_natives",
888 scoped_ptr<NativeHandler>(EventBindings::Create(this, context)));
889 module_system->RegisterNativeHandler("messaging_natives",
890 scoped_ptr<NativeHandler>(MessagingBindings::Get(this, context)));
891 module_system->RegisterNativeHandler("apiDefinitions",
892 scoped_ptr<NativeHandler>(new ApiDefinitionsNatives(this, context)));
893 module_system->RegisterNativeHandler("sendRequest",
894 scoped_ptr<NativeHandler>(
895 new SendRequestNatives(this, request_sender_.get(), context)));
896 module_system->RegisterNativeHandler("setIcon",
897 scoped_ptr<NativeHandler>(
898 new SetIconNatives(this, request_sender_.get(), context)));
899 module_system->RegisterNativeHandler("activityLogger",
900 scoped_ptr<NativeHandler>(new APIActivityLogger(this, context)));
901 module_system->RegisterNativeHandler("renderViewObserverNatives",
902 scoped_ptr<NativeHandler>(new RenderViewObserverNatives(this, context)));
904 // Natives used by multiple APIs.
905 module_system->RegisterNativeHandler("file_system_natives",
906 scoped_ptr<NativeHandler>(new FileSystemNatives(context)));
908 // Custom bindings.
909 module_system->RegisterNativeHandler("app",
910 scoped_ptr<NativeHandler>(new AppBindings(this, context)));
911 module_system->RegisterNativeHandler("app_runtime",
912 scoped_ptr<NativeHandler>(
913 new AppRuntimeCustomBindings(this, context)));
914 module_system->RegisterNativeHandler("app_window_natives",
915 scoped_ptr<NativeHandler>(
916 new AppWindowCustomBindings(this, context)));
917 module_system->RegisterNativeHandler("blob_natives",
918 scoped_ptr<NativeHandler>(new BlobNativeHandler(context)));
919 module_system->RegisterNativeHandler("context_menus",
920 scoped_ptr<NativeHandler>(
921 new ContextMenusCustomBindings(this, context)));
922 module_system->RegisterNativeHandler(
923 "css_natives", scoped_ptr<NativeHandler>(new CssNativeHandler(context)));
924 module_system->RegisterNativeHandler("document_natives",
925 scoped_ptr<NativeHandler>(
926 new DocumentCustomBindings(this, context)));
927 module_system->RegisterNativeHandler("sync_file_system",
928 scoped_ptr<NativeHandler>(
929 new SyncFileSystemCustomBindings(this, context)));
930 module_system->RegisterNativeHandler("file_browser_handler",
931 scoped_ptr<NativeHandler>(new FileBrowserHandlerCustomBindings(
932 this, context)));
933 module_system->RegisterNativeHandler("file_browser_private",
934 scoped_ptr<NativeHandler>(new FileBrowserPrivateCustomBindings(
935 this, context)));
936 module_system->RegisterNativeHandler("i18n",
937 scoped_ptr<NativeHandler>(
938 new I18NCustomBindings(this, context)));
939 module_system->RegisterNativeHandler(
940 "id_generator",
941 scoped_ptr<NativeHandler>(new IdGeneratorCustomBindings(this, context)));
942 module_system->RegisterNativeHandler("mediaGalleries",
943 scoped_ptr<NativeHandler>(
944 new MediaGalleriesCustomBindings(this, context)));
945 module_system->RegisterNativeHandler("page_actions",
946 scoped_ptr<NativeHandler>(
947 new PageActionsCustomBindings(this, context)));
948 module_system->RegisterNativeHandler("page_capture",
949 scoped_ptr<NativeHandler>(
950 new PageCaptureCustomBindings(this, context)));
951 module_system->RegisterNativeHandler(
952 "pepper_request_natives",
953 scoped_ptr<NativeHandler>(new PepperRequestNatives(context)));
954 module_system->RegisterNativeHandler("runtime",
955 scoped_ptr<NativeHandler>(new RuntimeCustomBindings(this, context)));
956 module_system->RegisterNativeHandler("tabs",
957 scoped_ptr<NativeHandler>(new TabsCustomBindings(this, context)));
958 module_system->RegisterNativeHandler("webstore",
959 scoped_ptr<NativeHandler>(new WebstoreBindings(this, context)));
960 #if defined(ENABLE_WEBRTC)
961 module_system->RegisterNativeHandler("cast_streaming_natives",
962 scoped_ptr<NativeHandler>(new CastStreamingNativeHandler(context)));
963 #endif
966 void Dispatcher::PopulateSourceMap() {
967 // Libraries.
968 source_map_.RegisterSource("automationNode", IDR_AUTOMATION_NODE_JS);
969 source_map_.RegisterSource("automationTree", IDR_AUTOMATION_TREE_JS);
970 source_map_.RegisterSource("entryIdManager", IDR_ENTRY_ID_MANAGER);
971 source_map_.RegisterSource(kEventBindings, IDR_EVENT_BINDINGS_JS);
972 source_map_.RegisterSource("imageUtil", IDR_IMAGE_UTIL_JS);
973 source_map_.RegisterSource("json_schema", IDR_JSON_SCHEMA_JS);
974 source_map_.RegisterSource("lastError", IDR_LAST_ERROR_JS);
975 source_map_.RegisterSource("messaging", IDR_MESSAGING_JS);
976 source_map_.RegisterSource("messaging_utils", IDR_MESSAGING_UTILS_JS);
977 source_map_.RegisterSource("pepper_request", IDR_PEPPER_REQUEST_JS);
978 source_map_.RegisterSource(kSchemaUtils, IDR_SCHEMA_UTILS_JS);
979 source_map_.RegisterSource("sendRequest", IDR_SEND_REQUEST_JS);
980 source_map_.RegisterSource("setIcon", IDR_SET_ICON_JS);
981 source_map_.RegisterSource("test", IDR_TEST_CUSTOM_BINDINGS_JS);
982 source_map_.RegisterSource("unload_event", IDR_UNLOAD_EVENT_JS);
983 source_map_.RegisterSource("utils", IDR_UTILS_JS);
985 // Custom bindings.
986 source_map_.RegisterSource("app", IDR_APP_CUSTOM_BINDINGS_JS);
987 source_map_.RegisterSource("app.runtime", IDR_APP_RUNTIME_CUSTOM_BINDINGS_JS);
988 source_map_.RegisterSource("app.window", IDR_APP_WINDOW_CUSTOM_BINDINGS_JS);
989 source_map_.RegisterSource("automation", IDR_AUTOMATION_CUSTOM_BINDINGS_JS);
990 source_map_.RegisterSource("automationNode", IDR_AUTOMATION_NODE_JS);
991 source_map_.RegisterSource("automationTree", IDR_AUTOMATION_TREE_JS);
992 source_map_.RegisterSource("browserAction",
993 IDR_BROWSER_ACTION_CUSTOM_BINDINGS_JS);
994 source_map_.RegisterSource("contextMenus",
995 IDR_CONTEXT_MENUS_CUSTOM_BINDINGS_JS);
996 source_map_.RegisterSource("declarativeContent",
997 IDR_DECLARATIVE_CONTENT_CUSTOM_BINDINGS_JS);
998 source_map_.RegisterSource("declarativeWebRequest",
999 IDR_DECLARATIVE_WEBREQUEST_CUSTOM_BINDINGS_JS);
1000 source_map_.RegisterSource("desktopCapture",
1001 IDR_DESKTOP_CAPTURE_CUSTOM_BINDINGS_JS);
1002 source_map_.RegisterSource("developerPrivate",
1003 IDR_DEVELOPER_PRIVATE_CUSTOM_BINDINGS_JS);
1004 source_map_.RegisterSource("downloads",
1005 IDR_DOWNLOADS_CUSTOM_BINDINGS_JS);
1006 source_map_.RegisterSource("extension", IDR_EXTENSION_CUSTOM_BINDINGS_JS);
1007 source_map_.RegisterSource("feedbackPrivate",
1008 IDR_FEEDBACK_PRIVATE_CUSTOM_BINDINGS_JS);
1009 source_map_.RegisterSource("fileBrowserHandler",
1010 IDR_FILE_BROWSER_HANDLER_CUSTOM_BINDINGS_JS);
1011 source_map_.RegisterSource("fileBrowserPrivate",
1012 IDR_FILE_BROWSER_PRIVATE_CUSTOM_BINDINGS_JS);
1013 source_map_.RegisterSource("fileSystem",
1014 IDR_FILE_SYSTEM_CUSTOM_BINDINGS_JS);
1015 source_map_.RegisterSource("fileSystemProvider",
1016 IDR_FILE_SYSTEM_PROVIDER_CUSTOM_BINDINGS_JS);
1017 source_map_.RegisterSource("gcm",
1018 IDR_GCM_CUSTOM_BINDINGS_JS);
1019 source_map_.RegisterSource("i18n", IDR_I18N_CUSTOM_BINDINGS_JS);
1020 source_map_.RegisterSource("identity", IDR_IDENTITY_CUSTOM_BINDINGS_JS);
1021 source_map_.RegisterSource("imageWriterPrivate",
1022 IDR_IMAGE_WRITER_PRIVATE_CUSTOM_BINDINGS_JS);
1023 source_map_.RegisterSource("input.ime", IDR_INPUT_IME_CUSTOM_BINDINGS_JS);
1024 source_map_.RegisterSource("mediaGalleries",
1025 IDR_MEDIA_GALLERIES_CUSTOM_BINDINGS_JS);
1026 source_map_.RegisterSource("notifications",
1027 IDR_NOTIFICATIONS_CUSTOM_BINDINGS_JS);
1028 source_map_.RegisterSource("omnibox", IDR_OMNIBOX_CUSTOM_BINDINGS_JS);
1029 source_map_.RegisterSource("pageActions",
1030 IDR_PAGE_ACTIONS_CUSTOM_BINDINGS_JS);
1031 source_map_.RegisterSource("pageAction", IDR_PAGE_ACTION_CUSTOM_BINDINGS_JS);
1032 source_map_.RegisterSource("pageCapture",
1033 IDR_PAGE_CAPTURE_CUSTOM_BINDINGS_JS);
1034 source_map_.RegisterSource("permissions", IDR_PERMISSIONS_CUSTOM_BINDINGS_JS);
1035 source_map_.RegisterSource("runtime", IDR_RUNTIME_CUSTOM_BINDINGS_JS);
1036 source_map_.RegisterSource("syncFileSystem",
1037 IDR_SYNC_FILE_SYSTEM_CUSTOM_BINDINGS_JS);
1038 source_map_.RegisterSource("systemIndicator",
1039 IDR_SYSTEM_INDICATOR_CUSTOM_BINDINGS_JS);
1040 source_map_.RegisterSource("tabCapture", IDR_TAB_CAPTURE_CUSTOM_BINDINGS_JS);
1041 source_map_.RegisterSource("tabs", IDR_TABS_CUSTOM_BINDINGS_JS);
1042 source_map_.RegisterSource("tts", IDR_TTS_CUSTOM_BINDINGS_JS);
1043 source_map_.RegisterSource("ttsEngine", IDR_TTS_ENGINE_CUSTOM_BINDINGS_JS);
1044 source_map_.RegisterSource("webRequest", IDR_WEB_REQUEST_CUSTOM_BINDINGS_JS);
1045 source_map_.RegisterSource("webRequestInternal",
1046 IDR_WEB_REQUEST_INTERNAL_CUSTOM_BINDINGS_JS);
1047 #if defined(ENABLE_WEBRTC)
1048 source_map_.RegisterSource("cast.streaming.rtpStream",
1049 IDR_CAST_STREAMING_RTP_STREAM_CUSTOM_BINDINGS_JS);
1050 source_map_.RegisterSource("cast.streaming.session",
1051 IDR_CAST_STREAMING_SESSION_CUSTOM_BINDINGS_JS);
1052 source_map_.RegisterSource(
1053 "cast.streaming.udpTransport",
1054 IDR_CAST_STREAMING_UDP_TRANSPORT_CUSTOM_BINDINGS_JS);
1055 #endif
1056 source_map_.RegisterSource("webstore", IDR_WEBSTORE_CUSTOM_BINDINGS_JS);
1057 source_map_.RegisterSource("windowControls", IDR_WINDOW_CONTROLS_JS);
1058 source_map_.RegisterSource("binding", IDR_BINDING_JS);
1060 // Custom types sources.
1061 source_map_.RegisterSource("ChromeSetting", IDR_CHROME_SETTING_JS);
1062 source_map_.RegisterSource("StorageArea", IDR_STORAGE_AREA_JS);
1063 source_map_.RegisterSource("ContentSetting", IDR_CONTENT_SETTING_JS);
1064 source_map_.RegisterSource("ChromeDirectSetting",
1065 IDR_CHROME_DIRECT_SETTING_JS);
1067 // Platform app sources that are not API-specific..
1068 source_map_.RegisterSource("tagWatcher", IDR_TAG_WATCHER_JS);
1069 source_map_.RegisterSource("webview", IDR_WEBVIEW_CUSTOM_BINDINGS_JS);
1070 // Note: webView not webview so that this doesn't interfere with the
1071 // chrome.webview API bindings.
1072 source_map_.RegisterSource("webView", IDR_WEB_VIEW_JS);
1073 source_map_.RegisterSource("webViewExperimental",
1074 IDR_WEB_VIEW_EXPERIMENTAL_JS);
1075 source_map_.RegisterSource("webViewRequest",
1076 IDR_WEB_VIEW_REQUEST_CUSTOM_BINDINGS_JS);
1077 source_map_.RegisterSource("denyWebView", IDR_WEB_VIEW_DENY_JS);
1078 source_map_.RegisterSource("adView", IDR_AD_VIEW_JS);
1079 source_map_.RegisterSource("denyAdView", IDR_AD_VIEW_DENY_JS);
1080 source_map_.RegisterSource("platformApp", IDR_PLATFORM_APP_JS);
1081 source_map_.RegisterSource("injectAppTitlebar", IDR_INJECT_APP_TITLEBAR_JS);
1084 void Dispatcher::PopulateLazyBindingsMap() {
1085 lazy_bindings_map_["app"] = InstallAppBindings;
1086 lazy_bindings_map_["webstore"] = InstallWebstoreBindings;
1089 void Dispatcher::InstallBindings(ModuleSystem* module_system,
1090 v8::Handle<v8::Context> v8_context,
1091 const std::string& api) {
1092 std::map<std::string, BindingInstaller>::const_iterator lazy_binding =
1093 lazy_bindings_map_.find(api);
1094 if (lazy_binding != lazy_bindings_map_.end()) {
1095 v8::Handle<v8::Object> global(v8_context->Global());
1096 v8::Handle<v8::Object> chrome =
1097 global->Get(v8::String::NewFromUtf8(v8_context->GetIsolate(), "chrome"))
1098 ->ToObject();
1099 (*lazy_binding->second)(module_system, chrome);
1100 } else {
1101 module_system->Require(api);
1105 void Dispatcher::DidCreateScriptContext(
1106 WebFrame* frame, v8::Handle<v8::Context> v8_context, int extension_group,
1107 int world_id) {
1108 #if !defined(ENABLE_EXTENSIONS)
1109 return;
1110 #endif
1112 std::string extension_id = GetExtensionID(frame, world_id);
1114 const Extension* extension = extensions_.GetByID(extension_id);
1115 if (!extension && !extension_id.empty()) {
1116 // There are conditions where despite a context being associated with an
1117 // extension, no extension actually gets found. Ignore "invalid" because
1118 // CSP blocks extension page loading by switching the extension ID to
1119 // "invalid". This isn't interesting.
1120 if (extension_id != "invalid") {
1121 LOG(ERROR) << "Extension \"" << extension_id << "\" not found";
1122 RenderThread::Get()->RecordAction(
1123 UserMetricsAction("ExtensionNotFound_ED"));
1126 extension_id = "";
1129 Feature::Context context_type = ClassifyJavaScriptContext(
1130 extension,
1131 extension_group,
1132 UserScriptSlave::GetDataSourceURLForFrame(frame),
1133 frame->document().securityOrigin());
1135 ChromeV8Context* context =
1136 new ChromeV8Context(v8_context, frame, extension, context_type);
1137 v8_context_set_.Add(context);
1139 if (extension)
1140 InitOriginPermissions(extension, context_type);
1143 scoped_ptr<ModuleSystem> module_system(new ModuleSystem(context,
1144 &source_map_));
1145 context->set_module_system(module_system.Pass());
1147 ModuleSystem* module_system = context->module_system();
1149 // Enable natives in startup.
1150 ModuleSystem::NativesEnabledScope natives_enabled_scope(
1151 module_system);
1153 RegisterNativeHandlers(module_system, context);
1155 module_system->RegisterNativeHandler("chrome",
1156 scoped_ptr<NativeHandler>(new ChromeNativeHandler(context)));
1157 module_system->RegisterNativeHandler("print",
1158 scoped_ptr<NativeHandler>(new PrintNativeHandler(context)));
1159 module_system->RegisterNativeHandler("lazy_background_page",
1160 scoped_ptr<NativeHandler>(
1161 new LazyBackgroundPageNativeHandler(this, context)));
1162 module_system->RegisterNativeHandler("logging",
1163 scoped_ptr<NativeHandler>(new LoggingNativeHandler(context)));
1164 module_system->RegisterNativeHandler("schema_registry",
1165 v8_schema_registry_->AsNativeHandler());
1166 module_system->RegisterNativeHandler("v8_context",
1167 scoped_ptr<NativeHandler>(new V8ContextNativeHandler(context, this)));
1168 module_system->RegisterNativeHandler("test_features",
1169 scoped_ptr<NativeHandler>(new TestFeaturesNativeHandler(context)));
1170 module_system->RegisterNativeHandler("user_gestures",
1171 scoped_ptr<NativeHandler>(new UserGesturesNativeHandler(context)));
1172 module_system->RegisterNativeHandler("utils",
1173 scoped_ptr<NativeHandler>(new UtilsNativeHandler(context)));
1175 int manifest_version = extension ? extension->manifest_version() : 1;
1176 bool send_request_disabled =
1177 (extension && Manifest::IsUnpackedLocation(extension->location()) &&
1178 BackgroundInfo::HasLazyBackgroundPage(extension));
1179 module_system->RegisterNativeHandler("process",
1180 scoped_ptr<NativeHandler>(new ProcessInfoNativeHandler(
1181 this, context, context->GetExtensionID(),
1182 context->GetContextTypeDescription(),
1183 ChromeRenderProcessObserver::is_incognito_process(),
1184 manifest_version, send_request_disabled)));
1186 // chrome.Event is part of the public API (although undocumented). Make it
1187 // lazily evalulate to Event from event_bindings.js. For extensions only
1188 // though, not all webpages!
1189 if (context->extension()) {
1190 v8::Handle<v8::Object> chrome = AsObjectOrEmpty(GetOrCreateChrome(context));
1191 if (!chrome.IsEmpty())
1192 module_system->SetLazyField(chrome, "Event", kEventBindings, "Event");
1195 AddOrRemoveBindingsForContext(context);
1197 bool is_within_platform_app = IsWithinPlatformApp();
1198 // Inject custom JS into the platform app context.
1199 if (is_within_platform_app) {
1200 module_system->Require("platformApp");
1203 if (context_type == Feature::BLESSED_EXTENSION_CONTEXT &&
1204 is_within_platform_app &&
1205 GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV &&
1206 CommandLine::ForCurrentProcess()->HasSwitch(
1207 ::switches::kEnableAppWindowControls)) {
1208 module_system->Require("windowControls");
1211 // We used to limit WebView to |BLESSED_EXTENSION_CONTEXT| within platform
1212 // apps. An ext/app runs in a blessed extension context, if it is the active
1213 // extension in the current process, in other words, if it is loaded in a top
1214 // frame. To support webview in a non-frame extension, we have to allow
1215 // unblessed extension context as well.
1216 // Note: setting up the WebView class here, not the chrome.webview API.
1217 // The API will be automatically set up when first used.
1218 if (context_type == Feature::BLESSED_EXTENSION_CONTEXT ||
1219 context_type == Feature::UNBLESSED_EXTENSION_CONTEXT) {
1220 if (extension->HasAPIPermission(APIPermission::kWebView)) {
1221 module_system->Require("webView");
1222 if (GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV) {
1223 module_system->Require("webViewExperimental");
1224 } else {
1225 // TODO(asargent) We need a whitelist for webview experimental.
1226 // crbug.com/264852
1227 std::string id_hash = base::SHA1HashString(extension->id());
1228 std::string hexencoded_id_hash = base::HexEncode(id_hash.c_str(),
1229 id_hash.length());
1230 if (hexencoded_id_hash == "8C3741E3AF0B93B6E8E0DDD499BB0B74839EA578" ||
1231 hexencoded_id_hash == "E703483CEF33DEC18B4B6DD84B5C776FB9182BDB" ||
1232 hexencoded_id_hash == "1A26E32DE447A17CBE5E9750CDBA78F58539B39C" ||
1233 hexencoded_id_hash == "59048028102D7B4C681DBC7BC6CD980C3DC66DA3") {
1234 module_system->Require("webViewExperimental");
1237 } else {
1238 module_system->Require("denyWebView");
1242 // Same comment as above for <adview> tag.
1243 if (context_type == Feature::BLESSED_EXTENSION_CONTEXT &&
1244 is_within_platform_app) {
1245 if (CommandLine::ForCurrentProcess()->HasSwitch(
1246 ::switches::kEnableAdview)) {
1247 if (extension->HasAPIPermission(APIPermission::kAdView)) {
1248 module_system->Require("adView");
1249 } else {
1250 module_system->Require("denyAdView");
1255 VLOG(1) << "Num tracked contexts: " << v8_context_set_.size();
1258 std::string Dispatcher::GetExtensionID(const WebFrame* frame, int world_id) {
1259 if (world_id != 0) {
1260 // Isolated worlds (content script).
1261 return user_script_slave_->GetExtensionIdForIsolatedWorld(world_id);
1264 // TODO(kalman): Delete this check.
1265 if (frame->document().securityOrigin().isUnique())
1266 return std::string();
1268 // Extension pages (chrome-extension:// URLs).
1269 GURL frame_url = UserScriptSlave::GetDataSourceURLForFrame(frame);
1270 return extensions_.GetExtensionOrAppIDByURL(frame_url);
1273 bool Dispatcher::IsWithinPlatformApp() {
1274 for (std::set<std::string>::iterator iter = active_extension_ids_.begin();
1275 iter != active_extension_ids_.end(); ++iter) {
1276 const Extension* extension = extensions_.GetByID(*iter);
1277 if (extension && extension->is_platform_app())
1278 return true;
1280 return false;
1283 void Dispatcher::WillReleaseScriptContext(
1284 WebFrame* frame, v8::Handle<v8::Context> v8_context, int world_id) {
1285 ChromeV8Context* context = v8_context_set_.GetByV8Context(v8_context);
1286 if (!context)
1287 return;
1289 // If the V8 context has an OOM exception, javascript execution has been
1290 // stopped, so dispatching an onUnload event is pointless.
1291 if (!v8_context->HasOutOfMemoryException())
1292 context->DispatchOnUnloadEvent();
1293 // TODO(kalman): add an invalidation observer interface to ChromeV8Context.
1294 request_sender_->InvalidateSource(context);
1296 v8_context_set_.Remove(context);
1297 VLOG(1) << "Num tracked contexts: " << v8_context_set_.size();
1300 void Dispatcher::DidCreateDocumentElement(blink::WebFrame* frame) {
1301 if (IsWithinPlatformApp()) {
1302 // WebKit doesn't let us define an additional user agent stylesheet, so we
1303 // insert the default platform app stylesheet into all documents that are
1304 // loaded in each app.
1305 std::string stylesheet =
1306 ResourceBundle::GetSharedInstance().
1307 GetRawDataResource(IDR_PLATFORM_APP_CSS).as_string();
1308 ReplaceFirstSubstringAfterOffset(&stylesheet, 0,
1309 "$FONTFAMILY", system_font_family_);
1310 ReplaceFirstSubstringAfterOffset(&stylesheet, 0,
1311 "$FONTSIZE", system_font_size_);
1312 frame->document().insertStyleSheet(WebString::fromUTF8(stylesheet));
1315 content_watcher_->DidCreateDocumentElement(frame);
1318 void Dispatcher::DidMatchCSS(
1319 blink::WebFrame* frame,
1320 const blink::WebVector<blink::WebString>& newly_matching_selectors,
1321 const blink::WebVector<blink::WebString>& stopped_matching_selectors) {
1322 content_watcher_->DidMatchCSS(
1323 frame, newly_matching_selectors, stopped_matching_selectors);
1327 void Dispatcher::OnActivateExtension(const std::string& extension_id) {
1328 const Extension* extension = extensions_.GetByID(extension_id);
1329 if (!extension) {
1330 // Extension was activated but was never loaded. This probably means that
1331 // the renderer failed to load it (or the browser failed to tell us when it
1332 // did). Failures shouldn't happen, but instead of crashing there (which
1333 // executes on all renderers) be conservative and only crash in the renderer
1334 // of the extension which failed to load; this one.
1335 std::string& error = extension_load_errors_[extension_id];
1336 char minidump[256];
1337 base::debug::Alias(&minidump);
1338 base::snprintf(minidump, arraysize(minidump),
1339 "e::dispatcher:%s:%s", extension_id.c_str(), error.c_str());
1340 CHECK(extension) << extension_id << " was never loaded: " << error;
1343 active_extension_ids_.insert(extension_id);
1345 // This is called when starting a new extension page, so start the idle
1346 // handler ticking.
1347 RenderThread::Get()->ScheduleIdleHandler(kInitialExtensionIdleHandlerDelayMs);
1349 UpdateActiveExtensions();
1351 if (is_webkit_initialized_) {
1352 DOMActivityLogger::AttachToWorld(DOMActivityLogger::kMainWorldId,
1353 extension_id);
1357 void Dispatcher::InitOriginPermissions(const Extension* extension,
1358 Feature::Context context_type) {
1359 // TODO(jstritar): We should try to remove this special case. Also, these
1360 // whitelist entries need to be updated when the kManagement permission
1361 // changes.
1362 if (context_type == Feature::BLESSED_EXTENSION_CONTEXT &&
1363 extension->HasAPIPermission(APIPermission::kManagement)) {
1364 WebSecurityPolicy::addOriginAccessWhitelistEntry(
1365 extension->url(),
1366 WebString::fromUTF8(content::kChromeUIScheme),
1367 WebString::fromUTF8(chrome::kChromeUIExtensionIconHost),
1368 false);
1371 AddOrRemoveOriginPermissions(
1372 UpdatedExtensionPermissionsInfo::ADDED,
1373 extension,
1374 PermissionsData::GetEffectiveHostPermissions(extension));
1377 void Dispatcher::AddOrRemoveOriginPermissions(
1378 UpdatedExtensionPermissionsInfo::Reason reason,
1379 const Extension* extension,
1380 const URLPatternSet& origins) {
1381 for (URLPatternSet::const_iterator i = origins.begin();
1382 i != origins.end(); ++i) {
1383 const char* schemes[] = {
1384 content::kHttpScheme,
1385 content::kHttpsScheme,
1386 content::kFileScheme,
1387 content::kChromeUIScheme,
1388 content::kFtpScheme,
1390 for (size_t j = 0; j < arraysize(schemes); ++j) {
1391 if (i->MatchesScheme(schemes[j])) {
1392 ((reason == UpdatedExtensionPermissionsInfo::REMOVED) ?
1393 WebSecurityPolicy::removeOriginAccessWhitelistEntry :
1394 WebSecurityPolicy::addOriginAccessWhitelistEntry)(
1395 extension->url(),
1396 WebString::fromUTF8(schemes[j]),
1397 WebString::fromUTF8(i->host()),
1398 i->match_subdomains());
1404 void Dispatcher::EnableCustomElementWhiteList() {
1405 blink::WebCustomElement::addEmbedderCustomElementName("webview");
1406 // TODO(fsamuel): Add <adview> to the whitelist once it has been converted
1407 // into a custom element.
1408 blink::WebCustomElement::addEmbedderCustomElementName("browser-plugin");
1411 void Dispatcher::AddOrRemoveBindings(const std::string& extension_id) {
1412 v8_context_set().ForEach(
1413 extension_id,
1414 NULL, // all render views
1415 base::Bind(&Dispatcher::AddOrRemoveBindingsForContext,
1416 base::Unretained(this)));
1419 void Dispatcher::OnUpdatePermissions(
1420 const ExtensionMsg_UpdatePermissions_Params& params) {
1421 int reason_id = params.reason_id;
1422 const std::string& extension_id = params.extension_id;
1423 const APIPermissionSet& apis = params.apis;
1424 const ManifestPermissionSet& manifest_permissions =
1425 params.manifest_permissions;
1426 const URLPatternSet& explicit_hosts = params.explicit_hosts;
1427 const URLPatternSet& scriptable_hosts = params.scriptable_hosts;
1429 const Extension* extension = extensions_.GetByID(extension_id);
1430 if (!extension)
1431 return;
1433 scoped_refptr<const PermissionSet> delta =
1434 new PermissionSet(apis, manifest_permissions,
1435 explicit_hosts, scriptable_hosts);
1436 scoped_refptr<const PermissionSet> old_active =
1437 extension->GetActivePermissions();
1438 UpdatedExtensionPermissionsInfo::Reason reason =
1439 static_cast<UpdatedExtensionPermissionsInfo::Reason>(reason_id);
1441 const PermissionSet* new_active = NULL;
1442 switch (reason) {
1443 case UpdatedExtensionPermissionsInfo::ADDED:
1444 new_active = PermissionSet::CreateUnion(old_active.get(), delta.get());
1445 break;
1446 case UpdatedExtensionPermissionsInfo::REMOVED:
1447 new_active =
1448 PermissionSet::CreateDifference(old_active.get(), delta.get());
1449 break;
1452 PermissionsData::SetActivePermissions(extension, new_active);
1453 AddOrRemoveOriginPermissions(reason, extension, explicit_hosts);
1454 AddOrRemoveBindings(extension->id());
1457 void Dispatcher::OnUpdateTabSpecificPermissions(
1458 int page_id,
1459 int tab_id,
1460 const std::string& extension_id,
1461 const URLPatternSet& origin_set) {
1462 RenderView* view = TabFinder::Find(tab_id);
1464 // For now, the message should only be sent to the render view that contains
1465 // the target tab. This may change. Either way, if this is the target tab it
1466 // gives us the chance to check against the page ID to avoid races.
1467 DCHECK(view);
1468 if (view && view->GetPageId() != page_id)
1469 return;
1471 const Extension* extension = extensions_.GetByID(extension_id);
1472 if (!extension)
1473 return;
1475 PermissionsData::UpdateTabSpecificPermissions(
1476 extension,
1477 tab_id,
1478 new PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
1479 origin_set, URLPatternSet()));
1482 void Dispatcher::OnClearTabSpecificPermissions(
1483 int tab_id,
1484 const std::vector<std::string>& extension_ids) {
1485 for (std::vector<std::string>::const_iterator it = extension_ids.begin();
1486 it != extension_ids.end(); ++it) {
1487 const Extension* extension = extensions_.GetByID(*it);
1488 if (extension)
1489 PermissionsData::ClearTabSpecificPermissions(extension, tab_id);
1493 void Dispatcher::OnUpdateUserScripts(
1494 base::SharedMemoryHandle scripts) {
1495 DCHECK(base::SharedMemory::IsHandleValid(scripts)) << "Bad scripts handle";
1496 user_script_slave_->UpdateScripts(scripts);
1497 UpdateActiveExtensions();
1500 void Dispatcher::UpdateActiveExtensions() {
1501 // In single-process mode, the browser process reports the active extensions.
1502 if (CommandLine::ForCurrentProcess()->HasSwitch(::switches::kSingleProcess))
1503 return;
1505 std::set<std::string> active_extensions = active_extension_ids_;
1506 user_script_slave_->GetActiveExtensions(&active_extensions);
1507 crash_keys::SetActiveExtensions(active_extensions);
1510 void Dispatcher::OnUsingWebRequestAPI(
1511 bool adblock, bool adblock_plus, bool other) {
1512 webrequest_adblock_ = adblock;
1513 webrequest_adblock_plus_ = adblock_plus;
1514 webrequest_other_ = other;
1517 void Dispatcher::OnShouldSuspend(const std::string& extension_id,
1518 int sequence_id) {
1519 RenderThread::Get()->Send(
1520 new ExtensionHostMsg_ShouldSuspendAck(extension_id, sequence_id));
1523 void Dispatcher::OnSuspend(const std::string& extension_id) {
1524 // Dispatch the suspend event. This doesn't go through the standard event
1525 // dispatch machinery because it requires special handling. We need to let
1526 // the browser know when we are starting and stopping the event dispatch, so
1527 // that it still considers the extension idle despite any activity the suspend
1528 // event creates.
1529 DispatchEvent(extension_id, kOnSuspendEvent);
1530 RenderThread::Get()->Send(new ExtensionHostMsg_SuspendAck(extension_id));
1533 void Dispatcher::OnCancelSuspend(const std::string& extension_id) {
1534 DispatchEvent(extension_id, kOnSuspendCanceledEvent);
1537 // TODO(kalman): This is checking for the wrong thing, it should be checking if
1538 // the frame's security origin is unique. The extension sandbox directive is
1539 // checked for in extensions/common/manifest_handlers/csp_info.cc.
1540 bool Dispatcher::IsSandboxedPage(const GURL& url) const {
1541 if (url.SchemeIs(kExtensionScheme)) {
1542 const Extension* extension = extensions_.GetByID(url.host());
1543 if (extension) {
1544 return SandboxedPageInfo::IsSandboxedPage(extension, url.path());
1547 return false;
1550 Feature::Context Dispatcher::ClassifyJavaScriptContext(
1551 const Extension* extension,
1552 int extension_group,
1553 const GURL& url,
1554 const blink::WebSecurityOrigin& origin) {
1555 DCHECK_GE(extension_group, 0);
1556 if (extension_group == EXTENSION_GROUP_CONTENT_SCRIPTS) {
1557 return extension ? // TODO(kalman): when does this happen?
1558 Feature::CONTENT_SCRIPT_CONTEXT : Feature::UNSPECIFIED_CONTEXT;
1561 // We have an explicit check for sandboxed pages before checking whether the
1562 // extension is active in this process because:
1563 // 1. Sandboxed pages run in the same process as regular extension pages, so
1564 // the extension is considered active.
1565 // 2. ScriptContext creation (which triggers bindings injection) happens
1566 // before the SecurityContext is updated with the sandbox flags (after
1567 // reading the CSP header), so the caller can't check if the context's
1568 // security origin is unique yet.
1569 if (IsSandboxedPage(url))
1570 return Feature::WEB_PAGE_CONTEXT;
1572 if (extension && IsExtensionActive(extension->id())) {
1573 // |extension| is active in this process, but it could be either a true
1574 // extension process or within the extent of a hosted app. In the latter
1575 // case this would usually be considered a (blessed) web page context,
1576 // unless the extension in question is a component extension, in which case
1577 // we cheat and call it blessed.
1578 return (extension->is_hosted_app() &&
1579 extension->location() != Manifest::COMPONENT) ?
1580 Feature::BLESSED_WEB_PAGE_CONTEXT : Feature::BLESSED_EXTENSION_CONTEXT;
1583 // TODO(kalman): This isUnique() check is wrong, it should be performed as
1584 // part of IsSandboxedPage().
1585 if (!origin.isUnique() && extensions_.ExtensionBindingsAllowed(url)) {
1586 if (!extension) // TODO(kalman): when does this happen?
1587 return Feature::UNSPECIFIED_CONTEXT;
1588 return extension->is_hosted_app() ?
1589 Feature::BLESSED_WEB_PAGE_CONTEXT :
1590 Feature::UNBLESSED_EXTENSION_CONTEXT;
1593 if (url.is_valid())
1594 return Feature::WEB_PAGE_CONTEXT;
1596 return Feature::UNSPECIFIED_CONTEXT;
1599 void Dispatcher::OnExtensionResponse(int request_id,
1600 bool success,
1601 const base::ListValue& response,
1602 const std::string& error) {
1603 request_sender_->HandleResponse(request_id, success, response, error);
1606 bool Dispatcher::CheckContextAccessToExtensionAPI(
1607 const std::string& function_name, ChromeV8Context* context) const {
1608 if (!context) {
1609 DLOG(ERROR) << "Not in a v8::Context";
1610 return false;
1613 if (!context->extension()) {
1614 context->isolate()->ThrowException(v8::Exception::Error(
1615 v8::String::NewFromUtf8(context->isolate(), "Not in an extension.")));
1616 return false;
1619 // Theoretically we could end up with bindings being injected into sandboxed
1620 // frames, for example content scripts. Don't let them execute API functions.
1621 blink::WebFrame* frame = context->web_frame();
1622 if (IsSandboxedPage(UserScriptSlave::GetDataSourceURLForFrame(frame))) {
1623 static const char kMessage[] =
1624 "%s cannot be used within a sandboxed frame.";
1625 std::string error_msg = base::StringPrintf(kMessage, function_name.c_str());
1626 context->isolate()->ThrowException(v8::Exception::Error(
1627 v8::String::NewFromUtf8(context->isolate(), error_msg.c_str())));
1628 return false;
1631 Feature::Availability availability = context->GetAvailability(function_name);
1632 if (!availability.is_available()) {
1633 context->isolate()->ThrowException(
1634 v8::Exception::Error(v8::String::NewFromUtf8(
1635 context->isolate(), availability.message().c_str())));
1638 return availability.is_available();
1641 void Dispatcher::DispatchEvent(const std::string& extension_id,
1642 const std::string& event_name) const {
1643 base::ListValue args;
1644 args.Set(0, new base::StringValue(event_name));
1645 args.Set(1, new base::ListValue());
1647 // Needed for Windows compilation, since kEventBindings is declared extern.
1648 const char* local_event_bindings = kEventBindings;
1649 v8_context_set_.ForEach(
1650 extension_id,
1651 NULL, // all render views
1652 base::Bind(&CallModuleMethod,
1653 local_event_bindings,
1654 kEventDispatchFunction,
1655 &args));
1658 void Dispatcher::InvokeModuleSystemMethod(
1659 content::RenderView* render_view,
1660 const std::string& extension_id,
1661 const std::string& module_name,
1662 const std::string& function_name,
1663 const base::ListValue& args,
1664 bool user_gesture) {
1665 scoped_ptr<WebScopedUserGesture> web_user_gesture;
1666 if (user_gesture)
1667 web_user_gesture.reset(new WebScopedUserGesture);
1669 v8_context_set_.ForEach(
1670 extension_id,
1671 render_view,
1672 base::Bind(&CallModuleMethod, module_name, function_name, &args));
1674 // Reset the idle handler each time there's any activity like event or message
1675 // dispatch, for which Invoke is the chokepoint.
1676 if (is_extension_process_) {
1677 RenderThread::Get()->ScheduleIdleHandler(
1678 kInitialExtensionIdleHandlerDelayMs);
1681 // Tell the browser process when an event has been dispatched with a lazy
1682 // background page active.
1683 const Extension* extension = extensions_.GetByID(extension_id);
1684 if (extension && BackgroundInfo::HasLazyBackgroundPage(extension) &&
1685 module_name == kEventBindings &&
1686 function_name == kEventDispatchFunction) {
1687 RenderView* background_view =
1688 ExtensionHelper::GetBackgroundPage(extension_id);
1689 if (background_view) {
1690 background_view->Send(new ExtensionHostMsg_EventAck(
1691 background_view->GetRoutingID()));
1696 void Dispatcher::ClearPortData(int port_id) {
1697 // Only the target port side has entries in |port_to_tab_id_map_|. If
1698 // |port_id| is a source port, std::map::erase() will just silently fail
1699 // here as a no-op.
1700 port_to_tab_id_map_.erase(port_id);
1703 } // namespace extensions