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/extension_messages.h"
23 #include "chrome/common/extensions/features/feature_channel.h"
24 #include "chrome/common/extensions/manifest_handlers/externally_connectable.h"
25 #include "chrome/common/extensions/message_bundle.h"
26 #include "chrome/common/url_constants.h"
27 #include "chrome/renderer/chrome_render_process_observer.h"
28 #include "chrome/renderer/extensions/api_activity_logger.h"
29 #include "chrome/renderer/extensions/api_definitions_natives.h"
30 #include "chrome/renderer/extensions/app_bindings.h"
31 #include "chrome/renderer/extensions/app_runtime_custom_bindings.h"
32 #include "chrome/renderer/extensions/app_window_custom_bindings.h"
33 #include "chrome/renderer/extensions/binding_generating_native_handler.h"
34 #include "chrome/renderer/extensions/blob_native_handler.h"
35 #include "chrome/renderer/extensions/chrome_v8_context.h"
36 #include "chrome/renderer/extensions/chrome_v8_extension.h"
37 #include "chrome/renderer/extensions/content_watcher.h"
38 #include "chrome/renderer/extensions/context_menus_custom_bindings.h"
39 #include "chrome/renderer/extensions/css_native_handler.h"
40 #include "chrome/renderer/extensions/document_custom_bindings.h"
41 #include "chrome/renderer/extensions/dom_activity_logger.h"
42 #include "chrome/renderer/extensions/event_bindings.h"
43 #include "chrome/renderer/extensions/extension_groups.h"
44 #include "chrome/renderer/extensions/extension_helper.h"
45 #include "chrome/renderer/extensions/file_browser_handler_custom_bindings.h"
46 #include "chrome/renderer/extensions/file_browser_private_custom_bindings.h"
47 #include "chrome/renderer/extensions/file_system_natives.h"
48 #include "chrome/renderer/extensions/i18n_custom_bindings.h"
49 #include "chrome/renderer/extensions/id_generator_custom_bindings.h"
50 #include "chrome/renderer/extensions/logging_native_handler.h"
51 #include "chrome/renderer/extensions/media_galleries_custom_bindings.h"
52 #include "chrome/renderer/extensions/messaging_bindings.h"
53 #include "chrome/renderer/extensions/module_system.h"
54 #include "chrome/renderer/extensions/object_backed_native_handler.h"
55 #include "chrome/renderer/extensions/page_actions_custom_bindings.h"
56 #include "chrome/renderer/extensions/page_capture_custom_bindings.h"
57 #include "chrome/renderer/extensions/pepper_request_natives.h"
58 #include "chrome/renderer/extensions/render_view_observer_natives.h"
59 #include "chrome/renderer/extensions/request_sender.h"
60 #include "chrome/renderer/extensions/runtime_custom_bindings.h"
61 #include "chrome/renderer/extensions/safe_builtins.h"
62 #include "chrome/renderer/extensions/send_request_natives.h"
63 #include "chrome/renderer/extensions/set_icon_natives.h"
64 #include "chrome/renderer/extensions/sync_file_system_custom_bindings.h"
65 #include "chrome/renderer/extensions/tab_finder.h"
66 #include "chrome/renderer/extensions/tabs_custom_bindings.h"
67 #include "chrome/renderer/extensions/user_script_slave.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_urls.h"
77 #include "extensions/common/features/feature.h"
78 #include "extensions/common/features/feature_provider.h"
79 #include "extensions/common/manifest.h"
80 #include "extensions/common/manifest_constants.h"
81 #include "extensions/common/manifest_handlers/background_info.h"
82 #include "extensions/common/manifest_handlers/sandboxed_page_info.h"
83 #include "extensions/common/permissions/permission_set.h"
84 #include "extensions/common/permissions/permissions_data.h"
85 #include "extensions/common/switches.h"
86 #include "extensions/common/view_type.h"
87 #include "grit/common_resources.h"
88 #include "grit/renderer_resources.h"
89 #include "third_party/WebKit/public/platform/WebString.h"
90 #include "third_party/WebKit/public/platform/WebURLRequest.h"
91 #include "third_party/WebKit/public/web/WebCustomElement.h"
92 #include "third_party/WebKit/public/web/WebDataSource.h"
93 #include "third_party/WebKit/public/web/WebDocument.h"
94 #include "third_party/WebKit/public/web/WebFrame.h"
95 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
96 #include "third_party/WebKit/public/web/WebScopedUserGesture.h"
97 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
98 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
99 #include "third_party/WebKit/public/web/WebView.h"
100 #include "ui/base/layout.h"
101 #include "ui/base/resource/resource_bundle.h"
102 #include "v8/include/v8.h"
104 #if defined(ENABLE_WEBRTC)
105 #include "chrome/renderer/extensions/cast_streaming_native_handler.h"
108 using base::UserMetricsAction
;
109 using blink::WebDataSource
;
110 using blink::WebDocument
;
111 using blink::WebFrame
;
112 using blink::WebScopedUserGesture
;
113 using blink::WebSecurityPolicy
;
114 using blink::WebString
;
115 using blink::WebVector
;
116 using blink::WebView
;
117 using content::RenderThread
;
118 using content::RenderView
;
120 namespace extensions
{
124 static const int64 kInitialExtensionIdleHandlerDelayMs
= 5*1000;
125 static const int64 kMaxExtensionIdleHandlerDelayMs
= 5*60*1000;
126 static const char kEventDispatchFunction
[] = "dispatchEvent";
127 static const char kOnSuspendEvent
[] = "runtime.onSuspend";
128 static const char kOnSuspendCanceledEvent
[] = "runtime.onSuspendCanceled";
130 // Returns the global value for "chrome" from |context|. If one doesn't exist
131 // creates a new object for it.
133 // Note that this isn't necessarily an object, since webpages can write, for
134 // example, "window.chrome = true".
135 v8::Handle
<v8::Value
> GetOrCreateChrome(ChromeV8Context
* context
) {
136 v8::Handle
<v8::String
> chrome_string(
137 v8::String::NewFromUtf8(context
->isolate(), "chrome"));
138 v8::Handle
<v8::Object
> global(context
->v8_context()->Global());
139 v8::Handle
<v8::Value
> chrome(global
->Get(chrome_string
));
140 if (chrome
->IsUndefined()) {
141 chrome
= v8::Object::New(context
->isolate());
142 global
->Set(chrome_string
, chrome
);
147 // Returns |value| cast to an object if possible, else an empty handle.
148 v8::Handle
<v8::Object
> AsObjectOrEmpty(v8::Handle
<v8::Value
> value
) {
149 return value
->IsObject() ? value
.As
<v8::Object
>() : v8::Handle
<v8::Object
>();
152 class TestFeaturesNativeHandler
: public ObjectBackedNativeHandler
{
154 explicit TestFeaturesNativeHandler(ChromeV8Context
* context
)
155 : ObjectBackedNativeHandler(context
) {
156 RouteFunction("GetAPIFeatures",
157 base::Bind(&TestFeaturesNativeHandler::GetAPIFeatures
,
158 base::Unretained(this)));
162 void GetAPIFeatures(const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
163 base::Value
* value
= base::JSONReader::Read(
164 ResourceBundle::GetSharedInstance().GetRawDataResource(
165 IDR_EXTENSION_API_FEATURES
).as_string());
166 scoped_ptr
<content::V8ValueConverter
> converter(
167 content::V8ValueConverter::create());
168 args
.GetReturnValue().Set(
169 converter
->ToV8Value(value
, context()->v8_context()));
173 class UserGesturesNativeHandler
: public ObjectBackedNativeHandler
{
175 explicit UserGesturesNativeHandler(ChromeV8Context
* context
)
176 : ObjectBackedNativeHandler(context
) {
177 RouteFunction("IsProcessingUserGesture",
178 base::Bind(&UserGesturesNativeHandler::IsProcessingUserGesture
,
179 base::Unretained(this)));
180 RouteFunction("RunWithUserGesture",
181 base::Bind(&UserGesturesNativeHandler::RunWithUserGesture
,
182 base::Unretained(this)));
183 RouteFunction("RunWithoutUserGesture",
184 base::Bind(&UserGesturesNativeHandler::RunWithoutUserGesture
,
185 base::Unretained(this)));
189 void IsProcessingUserGesture(
190 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
191 args
.GetReturnValue().Set(v8::Boolean::New(
193 blink::WebUserGestureIndicator::isProcessingUserGesture()));
196 void RunWithUserGesture(
197 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
198 blink::WebScopedUserGesture user_gesture
;
199 CHECK_EQ(args
.Length(), 1);
200 CHECK(args
[0]->IsFunction());
201 v8::Handle
<v8::Value
> no_args
;
202 context()->CallFunction(v8::Handle
<v8::Function
>::Cast(args
[0]),
206 void RunWithoutUserGesture(
207 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
208 blink::WebUserGestureIndicator::consumeUserGesture();
209 CHECK_EQ(args
.Length(), 1);
210 CHECK(args
[0]->IsFunction());
211 v8::Handle
<v8::Value
> no_args
;
212 context()->CallFunction(v8::Handle
<v8::Function
>::Cast(args
[0]),
217 class V8ContextNativeHandler
: public ObjectBackedNativeHandler
{
219 V8ContextNativeHandler(ChromeV8Context
* context
, Dispatcher
* dispatcher
)
220 : ObjectBackedNativeHandler(context
),
222 dispatcher_(dispatcher
) {
223 RouteFunction("GetAvailability",
224 base::Bind(&V8ContextNativeHandler::GetAvailability
,
225 base::Unretained(this)));
226 RouteFunction("GetModuleSystem",
227 base::Bind(&V8ContextNativeHandler::GetModuleSystem
,
228 base::Unretained(this)));
232 void GetAvailability(const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
233 CHECK_EQ(args
.Length(), 1);
234 v8::Isolate
* isolate
= args
.GetIsolate();
235 std::string api_name
= *v8::String::Utf8Value(args
[0]->ToString());
236 Feature::Availability availability
= context_
->GetAvailability(api_name
);
238 v8::Handle
<v8::Object
> ret
= v8::Object::New(isolate
);
239 ret
->Set(v8::String::NewFromUtf8(isolate
, "is_available"),
240 v8::Boolean::New(isolate
, availability
.is_available()));
241 ret
->Set(v8::String::NewFromUtf8(isolate
, "message"),
242 v8::String::NewFromUtf8(isolate
, availability
.message().c_str()));
243 ret
->Set(v8::String::NewFromUtf8(isolate
, "result"),
244 v8::Integer::New(isolate
, availability
.result()));
245 args
.GetReturnValue().Set(ret
);
248 void GetModuleSystem(const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
249 CHECK_EQ(args
.Length(), 1);
250 CHECK(args
[0]->IsObject());
251 v8::Handle
<v8::Context
> v8_context
=
252 v8::Handle
<v8::Object
>::Cast(args
[0])->CreationContext();
253 ChromeV8Context
* context
= dispatcher_
->v8_context_set().GetByV8Context(
255 args
.GetReturnValue().Set(context
->module_system()->NewInstance());
258 ChromeV8Context
* context_
;
259 Dispatcher
* dispatcher_
;
262 class ChromeNativeHandler
: public ObjectBackedNativeHandler
{
264 explicit ChromeNativeHandler(ChromeV8Context
* context
)
265 : ObjectBackedNativeHandler(context
) {
266 RouteFunction("GetChrome",
267 base::Bind(&ChromeNativeHandler::GetChrome
, base::Unretained(this)));
270 void GetChrome(const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
271 args
.GetReturnValue().Set(GetOrCreateChrome(context()));
275 class PrintNativeHandler
: public ObjectBackedNativeHandler
{
277 explicit PrintNativeHandler(ChromeV8Context
* context
)
278 : ObjectBackedNativeHandler(context
) {
279 RouteFunction("Print",
280 base::Bind(&PrintNativeHandler::Print
,
281 base::Unretained(this)));
284 void Print(const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
285 if (args
.Length() < 1)
288 std::vector
<std::string
> components
;
289 for (int i
= 0; i
< args
.Length(); ++i
)
290 components
.push_back(*v8::String::Utf8Value(args
[i
]->ToString()));
292 LOG(ERROR
) << JoinString(components
, ',');
296 class LazyBackgroundPageNativeHandler
: public ChromeV8Extension
{
298 LazyBackgroundPageNativeHandler(Dispatcher
* dispatcher
,
299 ChromeV8Context
* context
)
300 : ChromeV8Extension(dispatcher
, context
) {
301 RouteFunction("IncrementKeepaliveCount",
302 base::Bind(&LazyBackgroundPageNativeHandler::IncrementKeepaliveCount
,
303 base::Unretained(this)));
304 RouteFunction("DecrementKeepaliveCount",
305 base::Bind(&LazyBackgroundPageNativeHandler::DecrementKeepaliveCount
,
306 base::Unretained(this)));
309 void IncrementKeepaliveCount(
310 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
313 RenderView
* render_view
= context()->GetRenderView();
314 if (IsContextLazyBackgroundPage(render_view
, context()->extension())) {
315 render_view
->Send(new ExtensionHostMsg_IncrementLazyKeepaliveCount(
316 render_view
->GetRoutingID()));
320 void DecrementKeepaliveCount(
321 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
324 RenderView
* render_view
= context()->GetRenderView();
325 if (IsContextLazyBackgroundPage(render_view
, context()->extension())) {
326 render_view
->Send(new ExtensionHostMsg_DecrementLazyKeepaliveCount(
327 render_view
->GetRoutingID()));
332 bool IsContextLazyBackgroundPage(RenderView
* render_view
,
333 const Extension
* extension
) {
337 ExtensionHelper
* helper
= ExtensionHelper::Get(render_view
);
338 return (extension
&& BackgroundInfo::HasLazyBackgroundPage(extension
) &&
339 helper
->view_type() == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE
);
343 class ProcessInfoNativeHandler
: public ChromeV8Extension
{
345 ProcessInfoNativeHandler(Dispatcher
* dispatcher
,
346 ChromeV8Context
* context
,
347 const std::string
& extension_id
,
348 const std::string
& context_type
,
349 bool is_incognito_context
,
350 int manifest_version
,
351 bool send_request_disabled
)
352 : ChromeV8Extension(dispatcher
, context
),
353 extension_id_(extension_id
),
354 context_type_(context_type
),
355 is_incognito_context_(is_incognito_context
),
356 manifest_version_(manifest_version
),
357 send_request_disabled_(send_request_disabled
) {
358 RouteFunction("GetExtensionId",
359 base::Bind(&ProcessInfoNativeHandler::GetExtensionId
,
360 base::Unretained(this)));
361 RouteFunction("GetContextType",
362 base::Bind(&ProcessInfoNativeHandler::GetContextType
,
363 base::Unretained(this)));
364 RouteFunction("InIncognitoContext",
365 base::Bind(&ProcessInfoNativeHandler::InIncognitoContext
,
366 base::Unretained(this)));
367 RouteFunction("GetManifestVersion",
368 base::Bind(&ProcessInfoNativeHandler::GetManifestVersion
,
369 base::Unretained(this)));
370 RouteFunction("IsSendRequestDisabled",
371 base::Bind(&ProcessInfoNativeHandler::IsSendRequestDisabled
,
372 base::Unretained(this)));
373 RouteFunction("HasSwitch",
374 base::Bind(&ProcessInfoNativeHandler::HasSwitch
,
375 base::Unretained(this)));
379 void GetExtensionId(const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
380 args
.GetReturnValue()
381 .Set(v8::String::NewFromUtf8(args
.GetIsolate(), extension_id_
.c_str()));
384 void GetContextType(const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
385 args
.GetReturnValue()
386 .Set(v8::String::NewFromUtf8(args
.GetIsolate(), context_type_
.c_str()));
389 void InIncognitoContext(const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
390 args
.GetReturnValue().Set(is_incognito_context_
);
393 void GetManifestVersion(const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
394 args
.GetReturnValue().Set(static_cast<int32_t>(manifest_version_
));
397 void IsSendRequestDisabled(const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
398 if (send_request_disabled_
) {
399 args
.GetReturnValue().Set(v8::String::NewFromUtf8(args
.GetIsolate(),
400 "sendRequest and onRequest are obsolete."
401 " Please use sendMessage and onMessage instead."));
405 void HasSwitch(const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
406 CHECK(args
.Length() == 1 && args
[0]->IsString());
407 bool has_switch
= CommandLine::ForCurrentProcess()->HasSwitch(
408 *v8::String::Utf8Value(args
[0]));
409 args
.GetReturnValue().Set(v8::Boolean::New(args
.GetIsolate(), has_switch
));
412 std::string extension_id_
;
413 std::string context_type_
;
414 bool is_incognito_context_
;
415 int manifest_version_
;
416 bool send_request_disabled_
;
419 void InstallAppBindings(ModuleSystem
* module_system
,
420 v8::Handle
<v8::Object
> chrome
) {
421 module_system
->SetLazyField(chrome
, "app", "app", "chromeApp");
424 void InstallWebstoreBindings(ModuleSystem
* module_system
,
425 v8::Handle
<v8::Object
> chrome
) {
426 module_system
->SetLazyField(chrome
, "webstore", "webstore", "chromeWebstore");
429 // Calls a method |method_name| in a module |module_name| belonging to the
430 // module system from |context|. Intended as a callback target from
431 // ChromeV8ContextSet::ForEach.
432 void CallModuleMethod(const std::string
& module_name
,
433 const std::string
& method_name
,
434 const base::ListValue
* args
,
435 ChromeV8Context
* context
) {
436 v8::HandleScope
handle_scope(context
->isolate());
437 v8::Context::Scope
context_scope(context
->v8_context());
439 scoped_ptr
<content::V8ValueConverter
> converter(
440 content::V8ValueConverter::create());
442 std::vector
<v8::Handle
<v8::Value
> > arguments
;
443 for (base::ListValue::const_iterator it
= args
->begin(); it
!= args
->end();
445 arguments
.push_back(converter
->ToV8Value(*it
, context
->v8_context()));
448 context
->module_system()->CallModuleMethod(
449 module_name
, method_name
, &arguments
);
454 Dispatcher::Dispatcher()
455 : content_watcher_(new ContentWatcher()),
456 is_webkit_initialized_(false),
457 webrequest_adblock_(false),
458 webrequest_adblock_plus_(false),
459 webrequest_other_(false),
460 source_map_(&ResourceBundle::GetSharedInstance()),
461 v8_schema_registry_(new V8SchemaRegistry
) {
462 const CommandLine
& command_line
= *(CommandLine::ForCurrentProcess());
463 is_extension_process_
=
464 command_line
.HasSwitch(extensions::switches::kExtensionProcess
) ||
465 command_line
.HasSwitch(::switches::kSingleProcess
);
467 if (is_extension_process_
) {
468 RenderThread::Get()->SetIdleNotificationDelayInMs(
469 kInitialExtensionIdleHandlerDelayMs
);
472 RenderThread::Get()->RegisterExtension(SafeBuiltins::CreateV8Extension());
474 user_script_slave_
.reset(new UserScriptSlave(&extensions_
));
475 request_sender_
.reset(new RequestSender(this));
477 PopulateLazyBindingsMap();
480 Dispatcher::~Dispatcher() {
483 bool Dispatcher::OnControlMessageReceived(const IPC::Message
& message
) {
485 IPC_BEGIN_MESSAGE_MAP(Dispatcher
, message
)
486 IPC_MESSAGE_HANDLER(ExtensionMsg_SetChannel
, OnSetChannel
)
487 IPC_MESSAGE_HANDLER(ExtensionMsg_MessageInvoke
, OnMessageInvoke
)
488 IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchOnConnect
, OnDispatchOnConnect
)
489 IPC_MESSAGE_HANDLER(ExtensionMsg_DeliverMessage
, OnDeliverMessage
)
490 IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchOnDisconnect
,
491 OnDispatchOnDisconnect
)
492 IPC_MESSAGE_HANDLER(ExtensionMsg_SetFunctionNames
, OnSetFunctionNames
)
493 IPC_MESSAGE_HANDLER(ExtensionMsg_SetSystemFont
, OnSetSystemFont
)
494 IPC_MESSAGE_HANDLER(ExtensionMsg_Loaded
, OnLoaded
)
495 IPC_MESSAGE_HANDLER(ExtensionMsg_Unloaded
, OnUnloaded
)
496 IPC_MESSAGE_HANDLER(ExtensionMsg_SetScriptingWhitelist
,
497 OnSetScriptingWhitelist
)
498 IPC_MESSAGE_HANDLER(ExtensionMsg_ActivateExtension
, OnActivateExtension
)
499 IPC_MESSAGE_HANDLER(ExtensionMsg_UpdatePermissions
, OnUpdatePermissions
)
500 IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateTabSpecificPermissions
,
501 OnUpdateTabSpecificPermissions
)
502 IPC_MESSAGE_HANDLER(ExtensionMsg_ClearTabSpecificPermissions
,
503 OnClearTabSpecificPermissions
)
504 IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateUserScripts
, OnUpdateUserScripts
)
505 IPC_MESSAGE_HANDLER(ExtensionMsg_UsingWebRequestAPI
, OnUsingWebRequestAPI
)
506 IPC_MESSAGE_HANDLER(ExtensionMsg_ShouldSuspend
, OnShouldSuspend
)
507 IPC_MESSAGE_HANDLER(ExtensionMsg_Suspend
, OnSuspend
)
508 IPC_MESSAGE_HANDLER(ExtensionMsg_CancelSuspend
, OnCancelSuspend
)
509 IPC_MESSAGE_FORWARD(ExtensionMsg_WatchPages
,
510 content_watcher_
.get(), ContentWatcher::OnWatchPages
)
511 IPC_MESSAGE_UNHANDLED(handled
= false)
512 IPC_END_MESSAGE_MAP()
517 void Dispatcher::WebKitInitialized() {
518 // For extensions, we want to ensure we call the IdleHandler every so often,
519 // even if the extension keeps up activity.
520 if (is_extension_process_
) {
521 forced_idle_timer_
.Start(FROM_HERE
,
522 base::TimeDelta::FromMilliseconds(kMaxExtensionIdleHandlerDelayMs
),
523 RenderThread::Get(), &RenderThread::IdleHandler
);
526 // Initialize host permissions for any extensions that were activated before
527 // WebKit was initialized.
528 for (std::set
<std::string
>::iterator iter
= active_extension_ids_
.begin();
529 iter
!= active_extension_ids_
.end(); ++iter
) {
530 const Extension
* extension
= extensions_
.GetByID(*iter
);
532 InitOriginPermissions(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
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
,
580 InvokeModuleSystemMethod(
581 NULL
, extension_id
, module_name
, function_name
, args
, user_gesture
);
584 void Dispatcher::OnDispatchOnConnect(
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 MessagingBindings::DispatchOnConnect(
591 v8_context_set_
.GetAll(),
592 target_port_id
, channel_name
, source_tab
,
593 info
.source_id
, info
.target_id
, info
.source_url
,
595 NULL
); // All render views.
598 void Dispatcher::OnDeliverMessage(int target_port_id
,
599 const Message
& message
) {
600 MessagingBindings::DeliverMessage(
601 v8_context_set_
.GetAll(),
604 NULL
); // All render views.
607 void Dispatcher::OnDispatchOnDisconnect(int port_id
,
608 const std::string
& error_message
) {
609 MessagingBindings::DispatchOnDisconnect(
610 v8_context_set_
.GetAll(),
611 port_id
, error_message
,
612 NULL
); // All render views.
615 void Dispatcher::OnLoaded(
616 const std::vector
<ExtensionMsg_Loaded_Params
>& loaded_extensions
) {
617 std::vector
<ExtensionMsg_Loaded_Params
>::const_iterator i
;
618 for (i
= loaded_extensions
.begin(); i
!= loaded_extensions
.end(); ++i
) {
620 scoped_refptr
<const Extension
> extension
= i
->ConvertToExtension(&error
);
621 if (!extension
.get()) {
622 extension_load_errors_
[i
->id
] = error
;
625 OnLoadedInternal(extension
);
627 // Update the available bindings for all contexts. These may have changed if
628 // an externally_connectable extension was loaded that can connect to an
630 AddOrRemoveBindings("");
633 void Dispatcher::OnLoadedInternal(scoped_refptr
<const Extension
> extension
) {
634 extensions_
.Insert(extension
);
637 void Dispatcher::OnUnloaded(const std::string
& id
) {
638 extensions_
.Remove(id
);
639 active_extension_ids_
.erase(id
);
641 // If the extension is later reloaded with a different set of permissions,
642 // we'd like it to get a new isolated world ID, so that it can pick up the
643 // changed origin whitelist.
644 user_script_slave_
->RemoveIsolatedWorld(id
);
646 // Invalidate all of the contexts that were removed.
647 // TODO(kalman): add an invalidation observer interface to ChromeV8Context.
648 ChromeV8ContextSet::ContextSet removed_contexts
=
649 v8_context_set_
.OnExtensionUnloaded(id
);
650 for (ChromeV8ContextSet::ContextSet::iterator it
= removed_contexts
.begin();
651 it
!= removed_contexts
.end(); ++it
) {
652 request_sender_
->InvalidateSource(*it
);
655 // Update the available bindings for the remaining contexts. These may have
656 // changed if an externally_connectable extension is unloaded and a webpage
657 // is no longer accessible.
658 AddOrRemoveBindings("");
660 // Invalidates the messages map for the extension in case the extension is
661 // reloaded with a new messages map.
662 EraseL10nMessagesMap(id
);
664 // We don't do anything with existing platform-app stylesheets. They will
665 // stay resident, but the URL pattern corresponding to the unloaded
666 // extension's URL just won't match anything anymore.
669 void Dispatcher::OnSetScriptingWhitelist(
670 const ExtensionsClient::ScriptingWhitelist
& extension_ids
) {
671 ExtensionsClient::Get()->SetScriptingWhitelist(extension_ids
);
674 bool Dispatcher::IsExtensionActive(
675 const std::string
& extension_id
) const {
677 active_extension_ids_
.find(extension_id
) != active_extension_ids_
.end();
679 CHECK(extensions_
.Contains(extension_id
));
683 v8::Handle
<v8::Object
> Dispatcher::GetOrCreateObject(
684 v8::Handle
<v8::Object
> object
,
685 const std::string
& field
,
686 v8::Isolate
* isolate
) {
687 v8::Handle
<v8::String
> key
= v8::String::NewFromUtf8(isolate
, field
.c_str());
688 // If the object has a callback property, it is assumed it is an unavailable
689 // API, so it is safe to delete. This is checked before GetOrCreateObject is
691 if (object
->HasRealNamedCallbackProperty(key
)) {
693 } else if (object
->HasRealNamedProperty(key
)) {
694 v8::Handle
<v8::Value
> value
= object
->Get(key
);
695 CHECK(value
->IsObject());
696 return v8::Handle
<v8::Object
>::Cast(value
);
699 v8::Handle
<v8::Object
> new_object
= v8::Object::New(isolate
);
700 object
->Set(key
, new_object
);
704 void Dispatcher::AddOrRemoveBindingsForContext(ChromeV8Context
* context
) {
705 v8::HandleScope
handle_scope(context
->isolate());
706 v8::Context::Scope
context_scope(context
->v8_context());
708 // TODO(kalman): Make the bindings registration have zero overhead then run
709 // the same code regardless of context type.
710 switch (context
->context_type()) {
711 case Feature::UNSPECIFIED_CONTEXT
:
712 case Feature::WEB_PAGE_CONTEXT
:
713 case Feature::BLESSED_WEB_PAGE_CONTEXT
: {
714 // Web page context; it's too expensive to run the full bindings code.
715 // Hard-code that the app and webstore APIs are available...
716 RegisterBinding("app", context
);
717 RegisterBinding("webstore", context
);
719 // ... and that the runtime API might be available if any extension can
721 bool runtime_is_available
= false;
722 for (ExtensionSet::const_iterator it
= extensions_
.begin();
723 it
!= extensions_
.end(); ++it
) {
724 ExternallyConnectableInfo
* info
=
725 static_cast<ExternallyConnectableInfo
*>((*it
)->GetManifestData(
726 manifest_keys::kExternallyConnectable
));
727 if (info
&& info
->matches
.MatchesURL(context
->GetURL())) {
728 runtime_is_available
= true;
732 if (runtime_is_available
)
733 RegisterBinding("runtime", context
);
737 case Feature::BLESSED_EXTENSION_CONTEXT
:
738 case Feature::UNBLESSED_EXTENSION_CONTEXT
:
739 case Feature::CONTENT_SCRIPT_CONTEXT
: {
740 // Extension context; iterate through all the APIs and bind the available
742 FeatureProvider
* api_feature_provider
= FeatureProvider::GetAPIFeatures();
743 const std::vector
<std::string
>& apis
=
744 api_feature_provider
->GetAllFeatureNames();
745 for (std::vector
<std::string
>::const_iterator it
= apis
.begin();
746 it
!= apis
.end(); ++it
) {
747 const std::string
& api_name
= *it
;
748 Feature
* feature
= api_feature_provider
->GetFeature(api_name
);
751 // Internal APIs are included via require(api_name) from internal code
752 // rather than chrome[api_name].
753 if (feature
->IsInternal())
756 // If this API has a parent feature (and isn't marked 'noparent'),
757 // then this must be a function or event, so we should not register.
758 if (api_feature_provider
->GetParent(feature
) != NULL
)
761 if (context
->IsAnyFeatureAvailableToContext(*feature
))
762 RegisterBinding(api_name
, context
);
769 v8::Handle
<v8::Object
> Dispatcher::GetOrCreateBindObjectIfAvailable(
770 const std::string
& api_name
,
771 std::string
* bind_name
,
772 ChromeV8Context
* context
) {
773 std::vector
<std::string
> split
;
774 base::SplitString(api_name
, '.', &split
);
776 v8::Handle
<v8::Object
> bind_object
;
778 // Check if this API has an ancestor. If the API's ancestor is available and
779 // the API is not available, don't install the bindings for this API. If
780 // the API is available and its ancestor is not, delete the ancestor and
781 // install the bindings for the API. This is to prevent loading the ancestor
782 // API schema if it will not be needed.
785 // If app is available and app.window is not, just install app.
786 // If app.window is available and app is not, delete app and install
787 // app.window on a new object so app does not have to be loaded.
788 FeatureProvider
* api_feature_provider
= FeatureProvider::GetAPIFeatures();
789 std::string ancestor_name
;
790 bool only_ancestor_available
= false;
792 for (size_t i
= 0; i
< split
.size() - 1; ++i
) {
793 ancestor_name
+= (i
? ".": "") + split
[i
];
794 if (api_feature_provider
->GetFeature(ancestor_name
) &&
795 context
->GetAvailability(ancestor_name
).is_available() &&
796 !context
->GetAvailability(api_name
).is_available()) {
797 only_ancestor_available
= true;
801 if (bind_object
.IsEmpty()) {
802 bind_object
= AsObjectOrEmpty(GetOrCreateChrome(context
));
803 if (bind_object
.IsEmpty())
804 return v8::Handle
<v8::Object
>();
806 bind_object
= GetOrCreateObject(bind_object
, split
[i
], context
->isolate());
809 if (only_ancestor_available
)
810 return v8::Handle
<v8::Object
>();
813 *bind_name
= split
.back();
815 return bind_object
.IsEmpty() ?
816 AsObjectOrEmpty(GetOrCreateChrome(context
)) : bind_object
;
819 void Dispatcher::RegisterBinding(const std::string
& api_name
,
820 ChromeV8Context
* context
) {
821 std::string bind_name
;
822 v8::Handle
<v8::Object
> bind_object
=
823 GetOrCreateBindObjectIfAvailable(api_name
, &bind_name
, context
);
825 // Empty if the bind object failed to be created, probably because the
826 // extension overrode chrome with a non-object, e.g. window.chrome = true.
827 if (bind_object
.IsEmpty())
830 v8::Local
<v8::String
> v8_api_name
=
831 v8::String::NewFromUtf8(context
->isolate(), api_name
.c_str());
832 if (bind_object
->HasRealNamedProperty(v8_api_name
)) {
833 // The bind object may already have the property if the API has been
834 // registered before (or if the extension has put something there already,
837 // In the former case, we need to re-register the bindings for the APIs
838 // which the extension now has permissions for (if any), but not touch any
839 // others so that we don't destroy state such as event listeners.
841 // TODO(kalman): Only register available APIs to make this all moot.
842 if (bind_object
->HasRealNamedCallbackProperty(v8_api_name
))
843 return; // lazy binding still there, nothing to do
844 if (bind_object
->Get(v8_api_name
)->IsObject())
845 return; // binding has already been fully installed
848 ModuleSystem
* module_system
= context
->module_system();
849 if (lazy_bindings_map_
.find(api_name
) != lazy_bindings_map_
.end()) {
850 InstallBindings(module_system
, context
->v8_context(), api_name
);
851 } else if (!source_map_
.Contains(api_name
)) {
852 module_system
->RegisterNativeHandler(
854 scoped_ptr
<NativeHandler
>(new BindingGeneratingNativeHandler(
858 module_system
->SetNativeLazyField(bind_object
,
863 module_system
->SetLazyField(bind_object
,
870 // NOTE: please use the naming convention "foo_natives" for these.
871 void Dispatcher::RegisterNativeHandlers(ModuleSystem
* module_system
,
872 ChromeV8Context
* context
) {
873 module_system
->RegisterNativeHandler("event_natives",
874 scoped_ptr
<NativeHandler
>(EventBindings::Create(this, context
)));
875 module_system
->RegisterNativeHandler("messaging_natives",
876 scoped_ptr
<NativeHandler
>(MessagingBindings::Get(this, context
)));
877 module_system
->RegisterNativeHandler("apiDefinitions",
878 scoped_ptr
<NativeHandler
>(new ApiDefinitionsNatives(this, context
)));
879 module_system
->RegisterNativeHandler("sendRequest",
880 scoped_ptr
<NativeHandler
>(
881 new SendRequestNatives(this, request_sender_
.get(), context
)));
882 module_system
->RegisterNativeHandler("setIcon",
883 scoped_ptr
<NativeHandler
>(
884 new SetIconNatives(this, request_sender_
.get(), context
)));
885 module_system
->RegisterNativeHandler("activityLogger",
886 scoped_ptr
<NativeHandler
>(new APIActivityLogger(this, context
)));
887 module_system
->RegisterNativeHandler("renderViewObserverNatives",
888 scoped_ptr
<NativeHandler
>(new RenderViewObserverNatives(this, context
)));
890 // Natives used by multiple APIs.
891 module_system
->RegisterNativeHandler("file_system_natives",
892 scoped_ptr
<NativeHandler
>(new FileSystemNatives(context
)));
895 module_system
->RegisterNativeHandler("app",
896 scoped_ptr
<NativeHandler
>(new AppBindings(this, context
)));
897 module_system
->RegisterNativeHandler("app_runtime",
898 scoped_ptr
<NativeHandler
>(
899 new AppRuntimeCustomBindings(this, context
)));
900 module_system
->RegisterNativeHandler("app_window_natives",
901 scoped_ptr
<NativeHandler
>(
902 new AppWindowCustomBindings(this, context
)));
903 module_system
->RegisterNativeHandler("blob_natives",
904 scoped_ptr
<NativeHandler
>(new BlobNativeHandler(context
)));
905 module_system
->RegisterNativeHandler("context_menus",
906 scoped_ptr
<NativeHandler
>(
907 new ContextMenusCustomBindings(this, context
)));
908 module_system
->RegisterNativeHandler(
909 "css_natives", scoped_ptr
<NativeHandler
>(new CssNativeHandler(context
)));
910 module_system
->RegisterNativeHandler("document_natives",
911 scoped_ptr
<NativeHandler
>(
912 new DocumentCustomBindings(this, context
)));
913 module_system
->RegisterNativeHandler("sync_file_system",
914 scoped_ptr
<NativeHandler
>(
915 new SyncFileSystemCustomBindings(this, context
)));
916 module_system
->RegisterNativeHandler("file_browser_handler",
917 scoped_ptr
<NativeHandler
>(new FileBrowserHandlerCustomBindings(
919 module_system
->RegisterNativeHandler("file_browser_private",
920 scoped_ptr
<NativeHandler
>(new FileBrowserPrivateCustomBindings(
922 module_system
->RegisterNativeHandler("i18n",
923 scoped_ptr
<NativeHandler
>(
924 new I18NCustomBindings(this, context
)));
925 module_system
->RegisterNativeHandler(
927 scoped_ptr
<NativeHandler
>(new IdGeneratorCustomBindings(this, context
)));
928 module_system
->RegisterNativeHandler("mediaGalleries",
929 scoped_ptr
<NativeHandler
>(
930 new MediaGalleriesCustomBindings(this, context
)));
931 module_system
->RegisterNativeHandler("page_actions",
932 scoped_ptr
<NativeHandler
>(
933 new PageActionsCustomBindings(this, context
)));
934 module_system
->RegisterNativeHandler("page_capture",
935 scoped_ptr
<NativeHandler
>(
936 new PageCaptureCustomBindings(this, context
)));
937 module_system
->RegisterNativeHandler(
938 "pepper_request_natives",
939 scoped_ptr
<NativeHandler
>(new PepperRequestNatives(context
)));
940 module_system
->RegisterNativeHandler("runtime",
941 scoped_ptr
<NativeHandler
>(new RuntimeCustomBindings(this, context
)));
942 module_system
->RegisterNativeHandler("tabs",
943 scoped_ptr
<NativeHandler
>(new TabsCustomBindings(this, context
)));
944 module_system
->RegisterNativeHandler("webstore",
945 scoped_ptr
<NativeHandler
>(new WebstoreBindings(this, context
)));
946 #if defined(ENABLE_WEBRTC)
947 module_system
->RegisterNativeHandler("cast_streaming_natives",
948 scoped_ptr
<NativeHandler
>(new CastStreamingNativeHandler(context
)));
952 void Dispatcher::PopulateSourceMap() {
954 source_map_
.RegisterSource("entryIdManager", IDR_ENTRY_ID_MANAGER
);
955 source_map_
.RegisterSource(kEventBindings
, IDR_EVENT_BINDINGS_JS
);
956 source_map_
.RegisterSource("imageUtil", IDR_IMAGE_UTIL_JS
);
957 source_map_
.RegisterSource("json_schema", IDR_JSON_SCHEMA_JS
);
958 source_map_
.RegisterSource("lastError", IDR_LAST_ERROR_JS
);
959 source_map_
.RegisterSource("messaging", IDR_MESSAGING_JS
);
960 source_map_
.RegisterSource("messaging_utils", IDR_MESSAGING_UTILS_JS
);
961 source_map_
.RegisterSource("pepper_request", IDR_PEPPER_REQUEST_JS
);
962 source_map_
.RegisterSource(kSchemaUtils
, IDR_SCHEMA_UTILS_JS
);
963 source_map_
.RegisterSource("sendRequest", IDR_SEND_REQUEST_JS
);
964 source_map_
.RegisterSource("setIcon", IDR_SET_ICON_JS
);
965 source_map_
.RegisterSource("test", IDR_TEST_CUSTOM_BINDINGS_JS
);
966 source_map_
.RegisterSource("unload_event", IDR_UNLOAD_EVENT_JS
);
967 source_map_
.RegisterSource("utils", IDR_UTILS_JS
);
970 source_map_
.RegisterSource("app", IDR_APP_CUSTOM_BINDINGS_JS
);
971 source_map_
.RegisterSource("app.runtime", IDR_APP_RUNTIME_CUSTOM_BINDINGS_JS
);
972 source_map_
.RegisterSource("app.window", IDR_APP_WINDOW_CUSTOM_BINDINGS_JS
);
973 source_map_
.RegisterSource("bluetooth", IDR_BLUETOOTH_CUSTOM_BINDINGS_JS
);
974 source_map_
.RegisterSource("browserAction",
975 IDR_BROWSER_ACTION_CUSTOM_BINDINGS_JS
);
976 source_map_
.RegisterSource("contextMenus",
977 IDR_CONTEXT_MENUS_CUSTOM_BINDINGS_JS
);
978 source_map_
.RegisterSource("declarativeContent",
979 IDR_DECLARATIVE_CONTENT_CUSTOM_BINDINGS_JS
);
980 source_map_
.RegisterSource("declarativeWebRequest",
981 IDR_DECLARATIVE_WEBREQUEST_CUSTOM_BINDINGS_JS
);
982 source_map_
.RegisterSource("desktopCapture",
983 IDR_DESKTOP_CAPTURE_CUSTOM_BINDINGS_JS
);
984 source_map_
.RegisterSource("developerPrivate",
985 IDR_DEVELOPER_PRIVATE_CUSTOM_BINDINGS_JS
);
986 source_map_
.RegisterSource("downloads",
987 IDR_DOWNLOADS_CUSTOM_BINDINGS_JS
);
988 source_map_
.RegisterSource("experimental.offscreen",
989 IDR_EXPERIMENTAL_OFFSCREENTABS_CUSTOM_BINDINGS_JS
);
990 source_map_
.RegisterSource("extension", IDR_EXTENSION_CUSTOM_BINDINGS_JS
);
991 source_map_
.RegisterSource("feedbackPrivate",
992 IDR_FEEDBACK_PRIVATE_CUSTOM_BINDINGS_JS
);
993 source_map_
.RegisterSource("fileBrowserHandler",
994 IDR_FILE_BROWSER_HANDLER_CUSTOM_BINDINGS_JS
);
995 source_map_
.RegisterSource("fileBrowserPrivate",
996 IDR_FILE_BROWSER_PRIVATE_CUSTOM_BINDINGS_JS
);
997 source_map_
.RegisterSource("fileSystem",
998 IDR_FILE_SYSTEM_CUSTOM_BINDINGS_JS
);
999 source_map_
.RegisterSource("fileSystemProvider",
1000 IDR_FILE_SYSTEM_PROVIDER_CUSTOM_BINDINGS_JS
);
1001 source_map_
.RegisterSource("gcm",
1002 IDR_GCM_CUSTOM_BINDINGS_JS
);
1003 source_map_
.RegisterSource("i18n", IDR_I18N_CUSTOM_BINDINGS_JS
);
1004 source_map_
.RegisterSource("identity", IDR_IDENTITY_CUSTOM_BINDINGS_JS
);
1005 source_map_
.RegisterSource("imageWriterPrivate",
1006 IDR_IMAGE_WRITER_PRIVATE_CUSTOM_BINDINGS_JS
);
1007 source_map_
.RegisterSource("input.ime", IDR_INPUT_IME_CUSTOM_BINDINGS_JS
);
1008 source_map_
.RegisterSource("mediaGalleries",
1009 IDR_MEDIA_GALLERIES_CUSTOM_BINDINGS_JS
);
1010 source_map_
.RegisterSource("notifications",
1011 IDR_NOTIFICATIONS_CUSTOM_BINDINGS_JS
);
1012 source_map_
.RegisterSource("omnibox", IDR_OMNIBOX_CUSTOM_BINDINGS_JS
);
1013 source_map_
.RegisterSource("pageActions",
1014 IDR_PAGE_ACTIONS_CUSTOM_BINDINGS_JS
);
1015 source_map_
.RegisterSource("pageAction", IDR_PAGE_ACTION_CUSTOM_BINDINGS_JS
);
1016 source_map_
.RegisterSource("pageCapture",
1017 IDR_PAGE_CAPTURE_CUSTOM_BINDINGS_JS
);
1018 source_map_
.RegisterSource("permissions", IDR_PERMISSIONS_CUSTOM_BINDINGS_JS
);
1019 source_map_
.RegisterSource("runtime", IDR_RUNTIME_CUSTOM_BINDINGS_JS
);
1020 source_map_
.RegisterSource("syncFileSystem",
1021 IDR_SYNC_FILE_SYSTEM_CUSTOM_BINDINGS_JS
);
1022 source_map_
.RegisterSource("systemIndicator",
1023 IDR_SYSTEM_INDICATOR_CUSTOM_BINDINGS_JS
);
1024 source_map_
.RegisterSource("tabCapture", IDR_TAB_CAPTURE_CUSTOM_BINDINGS_JS
);
1025 source_map_
.RegisterSource("tabs", IDR_TABS_CUSTOM_BINDINGS_JS
);
1026 source_map_
.RegisterSource("tts", IDR_TTS_CUSTOM_BINDINGS_JS
);
1027 source_map_
.RegisterSource("ttsEngine", IDR_TTS_ENGINE_CUSTOM_BINDINGS_JS
);
1028 source_map_
.RegisterSource("webRequest", IDR_WEB_REQUEST_CUSTOM_BINDINGS_JS
);
1029 source_map_
.RegisterSource("webRequestInternal",
1030 IDR_WEB_REQUEST_INTERNAL_CUSTOM_BINDINGS_JS
);
1031 #if defined(ENABLE_WEBRTC)
1032 source_map_
.RegisterSource("cast.streaming.rtpStream",
1033 IDR_CAST_STREAMING_RTP_STREAM_CUSTOM_BINDINGS_JS
);
1034 source_map_
.RegisterSource("cast.streaming.session",
1035 IDR_CAST_STREAMING_SESSION_CUSTOM_BINDINGS_JS
);
1036 source_map_
.RegisterSource(
1037 "cast.streaming.udpTransport",
1038 IDR_CAST_STREAMING_UDP_TRANSPORT_CUSTOM_BINDINGS_JS
);
1040 source_map_
.RegisterSource("webstore", IDR_WEBSTORE_CUSTOM_BINDINGS_JS
);
1041 source_map_
.RegisterSource("windowControls", IDR_WINDOW_CONTROLS_JS
);
1042 source_map_
.RegisterSource("binding", IDR_BINDING_JS
);
1044 // Custom types sources.
1045 source_map_
.RegisterSource("ChromeSetting", IDR_CHROME_SETTING_JS
);
1046 source_map_
.RegisterSource("StorageArea", IDR_STORAGE_AREA_JS
);
1047 source_map_
.RegisterSource("ContentSetting", IDR_CONTENT_SETTING_JS
);
1048 source_map_
.RegisterSource("ChromeDirectSetting",
1049 IDR_CHROME_DIRECT_SETTING_JS
);
1051 // Platform app sources that are not API-specific..
1052 source_map_
.RegisterSource("tagWatcher", IDR_TAG_WATCHER_JS
);
1053 // Note: webView not webview so that this doesn't interfere with the
1054 // chrome.webview API bindings.
1055 source_map_
.RegisterSource("webView", IDR_WEB_VIEW_JS
);
1056 source_map_
.RegisterSource("webViewExperimental",
1057 IDR_WEB_VIEW_EXPERIMENTAL_JS
);
1058 source_map_
.RegisterSource("webViewRequest",
1059 IDR_WEB_VIEW_REQUEST_CUSTOM_BINDINGS_JS
);
1060 source_map_
.RegisterSource("denyWebView", IDR_WEB_VIEW_DENY_JS
);
1061 source_map_
.RegisterSource("adView", IDR_AD_VIEW_JS
);
1062 source_map_
.RegisterSource("denyAdView", IDR_AD_VIEW_DENY_JS
);
1063 source_map_
.RegisterSource("platformApp", IDR_PLATFORM_APP_JS
);
1064 source_map_
.RegisterSource("injectAppTitlebar", IDR_INJECT_APP_TITLEBAR_JS
);
1067 void Dispatcher::PopulateLazyBindingsMap() {
1068 lazy_bindings_map_
["app"] = InstallAppBindings
;
1069 lazy_bindings_map_
["webstore"] = InstallWebstoreBindings
;
1072 void Dispatcher::InstallBindings(ModuleSystem
* module_system
,
1073 v8::Handle
<v8::Context
> v8_context
,
1074 const std::string
& api
) {
1075 std::map
<std::string
, BindingInstaller
>::const_iterator lazy_binding
=
1076 lazy_bindings_map_
.find(api
);
1077 if (lazy_binding
!= lazy_bindings_map_
.end()) {
1078 v8::Handle
<v8::Object
> global(v8_context
->Global());
1079 v8::Handle
<v8::Object
> chrome
=
1080 global
->Get(v8::String::NewFromUtf8(v8_context
->GetIsolate(), "chrome"))
1082 (*lazy_binding
->second
)(module_system
, chrome
);
1084 module_system
->Require(api
);
1088 void Dispatcher::DidCreateScriptContext(
1089 WebFrame
* frame
, v8::Handle
<v8::Context
> v8_context
, int extension_group
,
1091 #if !defined(ENABLE_EXTENSIONS)
1095 std::string extension_id
= GetExtensionID(frame
, world_id
);
1097 const Extension
* extension
= extensions_
.GetByID(extension_id
);
1098 if (!extension
&& !extension_id
.empty()) {
1099 // There are conditions where despite a context being associated with an
1100 // extension, no extension actually gets found. Ignore "invalid" because
1101 // CSP blocks extension page loading by switching the extension ID to
1102 // "invalid". This isn't interesting.
1103 if (extension_id
!= "invalid") {
1104 LOG(ERROR
) << "Extension \"" << extension_id
<< "\" not found";
1105 RenderThread::Get()->RecordAction(
1106 UserMetricsAction("ExtensionNotFound_ED"));
1112 Feature::Context context_type
= ClassifyJavaScriptContext(
1115 UserScriptSlave::GetDataSourceURLForFrame(frame
),
1116 frame
->document().securityOrigin());
1118 ChromeV8Context
* context
=
1119 new ChromeV8Context(v8_context
, frame
, extension
, context_type
);
1120 v8_context_set_
.Add(context
);
1123 scoped_ptr
<ModuleSystem
> module_system(new ModuleSystem(context
,
1125 context
->set_module_system(module_system
.Pass());
1127 ModuleSystem
* module_system
= context
->module_system();
1129 // Enable natives in startup.
1130 ModuleSystem::NativesEnabledScope
natives_enabled_scope(
1133 RegisterNativeHandlers(module_system
, context
);
1135 module_system
->RegisterNativeHandler("chrome",
1136 scoped_ptr
<NativeHandler
>(new ChromeNativeHandler(context
)));
1137 module_system
->RegisterNativeHandler("print",
1138 scoped_ptr
<NativeHandler
>(new PrintNativeHandler(context
)));
1139 module_system
->RegisterNativeHandler("lazy_background_page",
1140 scoped_ptr
<NativeHandler
>(
1141 new LazyBackgroundPageNativeHandler(this, context
)));
1142 module_system
->RegisterNativeHandler("logging",
1143 scoped_ptr
<NativeHandler
>(new LoggingNativeHandler(context
)));
1144 module_system
->RegisterNativeHandler("schema_registry",
1145 v8_schema_registry_
->AsNativeHandler());
1146 module_system
->RegisterNativeHandler("v8_context",
1147 scoped_ptr
<NativeHandler
>(new V8ContextNativeHandler(context
, this)));
1148 module_system
->RegisterNativeHandler("test_features",
1149 scoped_ptr
<NativeHandler
>(new TestFeaturesNativeHandler(context
)));
1150 module_system
->RegisterNativeHandler("user_gestures",
1151 scoped_ptr
<NativeHandler
>(new UserGesturesNativeHandler(context
)));
1153 int manifest_version
= extension
? extension
->manifest_version() : 1;
1154 bool send_request_disabled
=
1155 (extension
&& Manifest::IsUnpackedLocation(extension
->location()) &&
1156 BackgroundInfo::HasLazyBackgroundPage(extension
));
1157 module_system
->RegisterNativeHandler("process",
1158 scoped_ptr
<NativeHandler
>(new ProcessInfoNativeHandler(
1159 this, context
, context
->GetExtensionID(),
1160 context
->GetContextTypeDescription(),
1161 ChromeRenderProcessObserver::is_incognito_process(),
1162 manifest_version
, send_request_disabled
)));
1164 // chrome.Event is part of the public API (although undocumented). Make it
1165 // lazily evalulate to Event from event_bindings.js. For extensions only
1166 // though, not all webpages!
1167 if (context
->extension()) {
1168 v8::Handle
<v8::Object
> chrome
= AsObjectOrEmpty(GetOrCreateChrome(context
));
1169 if (!chrome
.IsEmpty())
1170 module_system
->SetLazyField(chrome
, "Event", kEventBindings
, "Event");
1173 AddOrRemoveBindingsForContext(context
);
1175 bool is_within_platform_app
= IsWithinPlatformApp();
1176 // Inject custom JS into the platform app context.
1177 if (is_within_platform_app
) {
1178 module_system
->Require("platformApp");
1181 if (context_type
== Feature::BLESSED_EXTENSION_CONTEXT
&&
1182 is_within_platform_app
&&
1183 GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV
&&
1184 CommandLine::ForCurrentProcess()->HasSwitch(
1185 ::switches::kEnableAppWindowControls
)) {
1186 module_system
->Require("windowControls");
1189 // Currently only platform apps and whitelisted component extensions support
1190 // the <webview> tag, because the "denyWebView" module will affect the
1191 // performance of DOM modifications (http://crbug.com/196453).
1192 // We used to limit WebView to |BLESSED_EXTENSION_CONTEXT| within platform
1193 // apps. An ext/app runs in a blessed extension context, if it is the active
1194 // extension in the current process, in other words, if it is loaded in a top
1195 // frame. To support webview in a non-frame extension, we have to allow
1196 // unblessed extension context as well.
1197 if (context_type
== Feature::BLESSED_EXTENSION_CONTEXT
||
1198 context_type
== Feature::UNBLESSED_EXTENSION_CONTEXT
) {
1199 // Note: setting up the WebView class here, not the chrome.webview API.
1200 // The API will be automatically set up when first used.
1201 if (extension
->HasAPIPermission(APIPermission::kWebView
)) {
1202 module_system
->Require("webView");
1203 bool includeExperimental
=
1204 GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV
;
1205 if (!includeExperimental
) {
1206 // TODO(asargent) We need a whitelist for webview experimental.
1208 std::string id_hash
= base::SHA1HashString(extension
->id());
1209 std::string hexencoded_id_hash
= base::HexEncode(id_hash
.c_str(),
1211 if (hexencoded_id_hash
== "8C3741E3AF0B93B6E8E0DDD499BB0B74839EA578" ||
1212 hexencoded_id_hash
== "E703483CEF33DEC18B4B6DD84B5C776FB9182BDB" ||
1213 hexencoded_id_hash
== "1A26E32DE447A17CBE5E9750CDBA78F58539B39C" ||
1214 hexencoded_id_hash
== "59048028102D7B4C681DBC7BC6CD980C3DC66DA3")
1215 includeExperimental
= true;
1217 if (includeExperimental
)
1218 module_system
->Require("webViewExperimental");
1220 module_system
->Require("denyWebView");
1224 // Same comment as above for <adview> tag.
1225 if (context_type
== Feature::BLESSED_EXTENSION_CONTEXT
&&
1226 is_within_platform_app
) {
1227 if (CommandLine::ForCurrentProcess()->HasSwitch(
1228 ::switches::kEnableAdview
)) {
1229 if (extension
->HasAPIPermission(APIPermission::kAdView
)) {
1230 module_system
->Require("adView");
1232 module_system
->Require("denyAdView");
1237 VLOG(1) << "Num tracked contexts: " << v8_context_set_
.size();
1240 std::string
Dispatcher::GetExtensionID(const WebFrame
* frame
, int world_id
) {
1241 if (world_id
!= 0) {
1242 // Isolated worlds (content script).
1243 return user_script_slave_
->GetExtensionIdForIsolatedWorld(world_id
);
1246 // TODO(kalman): Delete this check.
1247 if (frame
->document().securityOrigin().isUnique())
1248 return std::string();
1250 // Extension pages (chrome-extension:// URLs).
1251 GURL frame_url
= UserScriptSlave::GetDataSourceURLForFrame(frame
);
1252 return extensions_
.GetExtensionOrAppIDByURL(frame_url
);
1255 bool Dispatcher::IsWithinPlatformApp() {
1256 for (std::set
<std::string
>::iterator iter
= active_extension_ids_
.begin();
1257 iter
!= active_extension_ids_
.end(); ++iter
) {
1258 const Extension
* extension
= extensions_
.GetByID(*iter
);
1259 if (extension
&& extension
->is_platform_app())
1265 void Dispatcher::WillReleaseScriptContext(
1266 WebFrame
* frame
, v8::Handle
<v8::Context
> v8_context
, int world_id
) {
1267 ChromeV8Context
* context
= v8_context_set_
.GetByV8Context(v8_context
);
1271 context
->DispatchOnUnloadEvent();
1272 // TODO(kalman): add an invalidation observer interface to ChromeV8Context.
1273 request_sender_
->InvalidateSource(context
);
1275 v8_context_set_
.Remove(context
);
1276 VLOG(1) << "Num tracked contexts: " << v8_context_set_
.size();
1279 void Dispatcher::DidCreateDocumentElement(blink::WebFrame
* frame
) {
1280 if (IsWithinPlatformApp()) {
1281 // WebKit doesn't let us define an additional user agent stylesheet, so we
1282 // insert the default platform app stylesheet into all documents that are
1283 // loaded in each app.
1284 std::string stylesheet
=
1285 ResourceBundle::GetSharedInstance().
1286 GetRawDataResource(IDR_PLATFORM_APP_CSS
).as_string();
1287 ReplaceFirstSubstringAfterOffset(&stylesheet
, 0,
1288 "$FONTFAMILY", system_font_family_
);
1289 ReplaceFirstSubstringAfterOffset(&stylesheet
, 0,
1290 "$FONTSIZE", system_font_size_
);
1291 frame
->document().insertUserStyleSheet(
1292 WebString::fromUTF8(stylesheet
), WebDocument::UserStyleAuthorLevel
);
1295 content_watcher_
->DidCreateDocumentElement(frame
);
1298 void Dispatcher::DidMatchCSS(
1299 blink::WebFrame
* frame
,
1300 const blink::WebVector
<blink::WebString
>& newly_matching_selectors
,
1301 const blink::WebVector
<blink::WebString
>& stopped_matching_selectors
) {
1302 content_watcher_
->DidMatchCSS(
1303 frame
, newly_matching_selectors
, stopped_matching_selectors
);
1307 void Dispatcher::OnActivateExtension(const std::string
& extension_id
) {
1308 const Extension
* extension
= extensions_
.GetByID(extension_id
);
1310 // Extension was activated but was never loaded. This probably means that
1311 // the renderer failed to load it (or the browser failed to tell us when it
1312 // did). Failures shouldn't happen, but instead of crashing there (which
1313 // executes on all renderers) be conservative and only crash in the renderer
1314 // of the extension which failed to load; this one.
1315 std::string
& error
= extension_load_errors_
[extension_id
];
1317 base::debug::Alias(&minidump
);
1318 base::snprintf(minidump
, arraysize(minidump
),
1319 "e::dispatcher:%s:%s", extension_id
.c_str(), error
.c_str());
1320 CHECK(extension
) << extension_id
<< " was never loaded: " << error
;
1323 active_extension_ids_
.insert(extension_id
);
1325 // This is called when starting a new extension page, so start the idle
1327 RenderThread::Get()->ScheduleIdleHandler(kInitialExtensionIdleHandlerDelayMs
);
1329 UpdateActiveExtensions();
1331 if (is_webkit_initialized_
) {
1332 InitOriginPermissions(extension
);
1333 DOMActivityLogger::AttachToWorld(DOMActivityLogger::kMainWorldId
,
1338 void Dispatcher::InitOriginPermissions(const Extension
* extension
) {
1339 // TODO(jstritar): We should try to remove this special case. Also, these
1340 // whitelist entries need to be updated when the kManagement permission
1342 if (extension
->HasAPIPermission(APIPermission::kManagement
)) {
1343 WebSecurityPolicy::addOriginAccessWhitelistEntry(
1345 WebString::fromUTF8(chrome::kChromeUIScheme
),
1346 WebString::fromUTF8(chrome::kChromeUIExtensionIconHost
),
1350 AddOrRemoveOriginPermissions(
1351 UpdatedExtensionPermissionsInfo::ADDED
,
1353 extension
->GetActivePermissions()->explicit_hosts());
1356 void Dispatcher::AddOrRemoveOriginPermissions(
1357 UpdatedExtensionPermissionsInfo::Reason reason
,
1358 const Extension
* extension
,
1359 const URLPatternSet
& origins
) {
1360 for (URLPatternSet::const_iterator i
= origins
.begin();
1361 i
!= origins
.end(); ++i
) {
1362 const char* schemes
[] = {
1363 content::kHttpScheme
,
1364 content::kHttpsScheme
,
1365 content::kFileScheme
,
1366 chrome::kChromeUIScheme
,
1368 for (size_t j
= 0; j
< arraysize(schemes
); ++j
) {
1369 if (i
->MatchesScheme(schemes
[j
])) {
1370 ((reason
== UpdatedExtensionPermissionsInfo::REMOVED
) ?
1371 WebSecurityPolicy::removeOriginAccessWhitelistEntry
:
1372 WebSecurityPolicy::addOriginAccessWhitelistEntry
)(
1374 WebString::fromUTF8(schemes
[j
]),
1375 WebString::fromUTF8(i
->host()),
1376 i
->match_subdomains());
1382 void Dispatcher::EnableCustomElementWhiteList() {
1383 blink::WebRuntimeFeatures::enableEmbedderCustomElements(true);
1384 blink::WebCustomElement::addEmbedderCustomElementName("webview");
1385 // TODO(fsamuel): Add <adview> to the whitelist once it has been converted
1386 // into a custom element.
1387 blink::WebCustomElement::addEmbedderCustomElementName("browser-plugin");
1390 void Dispatcher::AddOrRemoveBindings(const std::string
& extension_id
) {
1391 v8_context_set().ForEach(
1393 NULL
, // all render views
1394 base::Bind(&Dispatcher::AddOrRemoveBindingsForContext
,
1395 base::Unretained(this)));
1398 void Dispatcher::OnUpdatePermissions(
1399 const ExtensionMsg_UpdatePermissions_Params
& params
) {
1400 int reason_id
= params
.reason_id
;
1401 const std::string
& extension_id
= params
.extension_id
;
1402 const APIPermissionSet
& apis
= params
.apis
;
1403 const ManifestPermissionSet
& manifest_permissions
=
1404 params
.manifest_permissions
;
1405 const URLPatternSet
& explicit_hosts
= params
.explicit_hosts
;
1406 const URLPatternSet
& scriptable_hosts
= params
.scriptable_hosts
;
1408 const Extension
* extension
= extensions_
.GetByID(extension_id
);
1412 scoped_refptr
<const PermissionSet
> delta
=
1413 new PermissionSet(apis
, manifest_permissions
,
1414 explicit_hosts
, scriptable_hosts
);
1415 scoped_refptr
<const PermissionSet
> old_active
=
1416 extension
->GetActivePermissions();
1417 UpdatedExtensionPermissionsInfo::Reason reason
=
1418 static_cast<UpdatedExtensionPermissionsInfo::Reason
>(reason_id
);
1420 const PermissionSet
* new_active
= NULL
;
1422 case UpdatedExtensionPermissionsInfo::ADDED
:
1423 new_active
= PermissionSet::CreateUnion(old_active
.get(), delta
.get());
1425 case UpdatedExtensionPermissionsInfo::REMOVED
:
1427 PermissionSet::CreateDifference(old_active
.get(), delta
.get());
1431 PermissionsData::SetActivePermissions(extension
, new_active
);
1432 AddOrRemoveOriginPermissions(reason
, extension
, explicit_hosts
);
1433 AddOrRemoveBindings(extension
->id());
1436 void Dispatcher::OnUpdateTabSpecificPermissions(
1439 const std::string
& extension_id
,
1440 const URLPatternSet
& origin_set
) {
1441 RenderView
* view
= TabFinder::Find(tab_id
);
1443 // For now, the message should only be sent to the render view that contains
1444 // the target tab. This may change. Either way, if this is the target tab it
1445 // gives us the chance to check against the page ID to avoid races.
1447 if (view
&& view
->GetPageId() != page_id
)
1450 const Extension
* extension
= extensions_
.GetByID(extension_id
);
1454 PermissionsData::UpdateTabSpecificPermissions(
1457 new PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
1458 origin_set
, URLPatternSet()));
1461 void Dispatcher::OnClearTabSpecificPermissions(
1463 const std::vector
<std::string
>& extension_ids
) {
1464 for (std::vector
<std::string
>::const_iterator it
= extension_ids
.begin();
1465 it
!= extension_ids
.end(); ++it
) {
1466 const Extension
* extension
= extensions_
.GetByID(*it
);
1468 PermissionsData::ClearTabSpecificPermissions(extension
, tab_id
);
1472 void Dispatcher::OnUpdateUserScripts(
1473 base::SharedMemoryHandle scripts
) {
1474 DCHECK(base::SharedMemory::IsHandleValid(scripts
)) << "Bad scripts handle";
1475 user_script_slave_
->UpdateScripts(scripts
);
1476 UpdateActiveExtensions();
1479 void Dispatcher::UpdateActiveExtensions() {
1480 // In single-process mode, the browser process reports the active extensions.
1481 if (CommandLine::ForCurrentProcess()->HasSwitch(::switches::kSingleProcess
))
1484 std::set
<std::string
> active_extensions
= active_extension_ids_
;
1485 user_script_slave_
->GetActiveExtensions(&active_extensions
);
1486 crash_keys::SetActiveExtensions(active_extensions
);
1489 void Dispatcher::OnUsingWebRequestAPI(
1490 bool adblock
, bool adblock_plus
, bool other
) {
1491 webrequest_adblock_
= adblock
;
1492 webrequest_adblock_plus_
= adblock_plus
;
1493 webrequest_other_
= other
;
1496 void Dispatcher::OnShouldSuspend(const std::string
& extension_id
,
1498 RenderThread::Get()->Send(
1499 new ExtensionHostMsg_ShouldSuspendAck(extension_id
, sequence_id
));
1502 void Dispatcher::OnSuspend(const std::string
& extension_id
) {
1503 // Dispatch the suspend event. This doesn't go through the standard event
1504 // dispatch machinery because it requires special handling. We need to let
1505 // the browser know when we are starting and stopping the event dispatch, so
1506 // that it still considers the extension idle despite any activity the suspend
1508 DispatchEvent(extension_id
, kOnSuspendEvent
);
1509 RenderThread::Get()->Send(new ExtensionHostMsg_SuspendAck(extension_id
));
1512 void Dispatcher::OnCancelSuspend(const std::string
& extension_id
) {
1513 DispatchEvent(extension_id
, kOnSuspendCanceledEvent
);
1516 // TODO(kalman): This is checking for the wrong thing, it should be checking if
1517 // the frame's security origin is unique. The extension sandbox directive is
1518 // checked for in extensions/common/manifest_handlers/csp_info.cc.
1519 bool Dispatcher::IsSandboxedPage(const GURL
& url
) const {
1520 if (url
.SchemeIs(kExtensionScheme
)) {
1521 const Extension
* extension
= extensions_
.GetByID(url
.host());
1523 return SandboxedPageInfo::IsSandboxedPage(extension
, url
.path());
1529 Feature::Context
Dispatcher::ClassifyJavaScriptContext(
1530 const Extension
* extension
,
1531 int extension_group
,
1533 const blink::WebSecurityOrigin
& origin
) {
1534 DCHECK_GE(extension_group
, 0);
1535 if (extension_group
== EXTENSION_GROUP_CONTENT_SCRIPTS
) {
1536 return extension
? // TODO(kalman): when does this happen?
1537 Feature::CONTENT_SCRIPT_CONTEXT
: Feature::UNSPECIFIED_CONTEXT
;
1540 // We have an explicit check for sandboxed pages before checking whether the
1541 // extension is active in this process because:
1542 // 1. Sandboxed pages run in the same process as regular extension pages, so
1543 // the extension is considered active.
1544 // 2. ScriptContext creation (which triggers bindings injection) happens
1545 // before the SecurityContext is updated with the sandbox flags (after
1546 // reading the CSP header), so the caller can't check if the context's
1547 // security origin is unique yet.
1548 if (IsSandboxedPage(url
))
1549 return Feature::WEB_PAGE_CONTEXT
;
1551 if (extension
&& IsExtensionActive(extension
->id())) {
1552 // |extension| is active in this process, but it could be either a true
1553 // extension process or within the extent of a hosted app. In the latter
1554 // case this would usually be considered a (blessed) web page context,
1555 // unless the extension in question is a component extension, in which case
1556 // we cheat and call it blessed.
1557 return (extension
->is_hosted_app() &&
1558 extension
->location() != Manifest::COMPONENT
) ?
1559 Feature::BLESSED_WEB_PAGE_CONTEXT
: Feature::BLESSED_EXTENSION_CONTEXT
;
1562 // TODO(kalman): This isUnique() check is wrong, it should be performed as
1563 // part of IsSandboxedPage().
1564 if (!origin
.isUnique() && extensions_
.ExtensionBindingsAllowed(url
)) {
1565 if (!extension
) // TODO(kalman): when does this happen?
1566 return Feature::UNSPECIFIED_CONTEXT
;
1567 return extension
->is_hosted_app() ?
1568 Feature::BLESSED_WEB_PAGE_CONTEXT
:
1569 Feature::UNBLESSED_EXTENSION_CONTEXT
;
1573 return Feature::WEB_PAGE_CONTEXT
;
1575 return Feature::UNSPECIFIED_CONTEXT
;
1578 void Dispatcher::OnExtensionResponse(int request_id
,
1580 const base::ListValue
& response
,
1581 const std::string
& error
) {
1582 request_sender_
->HandleResponse(request_id
, success
, response
, error
);
1585 bool Dispatcher::CheckContextAccessToExtensionAPI(
1586 const std::string
& function_name
, ChromeV8Context
* context
) const {
1588 DLOG(ERROR
) << "Not in a v8::Context";
1592 if (!context
->extension()) {
1593 context
->isolate()->ThrowException(v8::Exception::Error(
1594 v8::String::NewFromUtf8(context
->isolate(), "Not in an extension.")));
1598 // Theoretically we could end up with bindings being injected into sandboxed
1599 // frames, for example content scripts. Don't let them execute API functions.
1600 blink::WebFrame
* frame
= context
->web_frame();
1601 if (IsSandboxedPage(UserScriptSlave::GetDataSourceURLForFrame(frame
))) {
1602 static const char kMessage
[] =
1603 "%s cannot be used within a sandboxed frame.";
1604 std::string error_msg
= base::StringPrintf(kMessage
, function_name
.c_str());
1605 context
->isolate()->ThrowException(v8::Exception::Error(
1606 v8::String::NewFromUtf8(context
->isolate(), error_msg
.c_str())));
1610 Feature::Availability availability
= context
->GetAvailability(function_name
);
1611 if (!availability
.is_available()) {
1612 context
->isolate()->ThrowException(
1613 v8::Exception::Error(v8::String::NewFromUtf8(
1614 context
->isolate(), availability
.message().c_str())));
1617 return availability
.is_available();
1620 void Dispatcher::DispatchEvent(const std::string
& extension_id
,
1621 const std::string
& event_name
) const {
1622 base::ListValue args
;
1623 args
.Set(0, new base::StringValue(event_name
));
1624 args
.Set(1, new base::ListValue());
1626 // Needed for Windows compilation, since kEventBindings is declared extern.
1627 const char* local_event_bindings
= kEventBindings
;
1628 v8_context_set_
.ForEach(
1630 NULL
, // all render views
1631 base::Bind(&CallModuleMethod
,
1632 local_event_bindings
,
1633 kEventDispatchFunction
,
1637 void Dispatcher::InvokeModuleSystemMethod(
1638 content::RenderView
* render_view
,
1639 const std::string
& extension_id
,
1640 const std::string
& module_name
,
1641 const std::string
& function_name
,
1642 const base::ListValue
& args
,
1643 bool user_gesture
) {
1644 scoped_ptr
<WebScopedUserGesture
> web_user_gesture
;
1646 web_user_gesture
.reset(new WebScopedUserGesture
);
1648 v8_context_set_
.ForEach(
1651 base::Bind(&CallModuleMethod
, module_name
, function_name
, &args
));
1653 // Reset the idle handler each time there's any activity like event or message
1654 // dispatch, for which Invoke is the chokepoint.
1655 if (is_extension_process_
) {
1656 RenderThread::Get()->ScheduleIdleHandler(
1657 kInitialExtensionIdleHandlerDelayMs
);
1660 // Tell the browser process when an event has been dispatched with a lazy
1661 // background page active.
1662 const Extension
* extension
= extensions_
.GetByID(extension_id
);
1663 if (extension
&& BackgroundInfo::HasLazyBackgroundPage(extension
) &&
1664 module_name
== kEventBindings
&&
1665 function_name
== kEventDispatchFunction
) {
1666 RenderView
* background_view
=
1667 ExtensionHelper::GetBackgroundPage(extension_id
);
1668 if (background_view
) {
1669 background_view
->Send(new ExtensionHostMsg_EventAck(
1670 background_view
->GetRoutingID()));
1675 } // namespace extensions