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"
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
{
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
);
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
{
155 explicit TestFeaturesNativeHandler(ChromeV8Context
* context
)
156 : ObjectBackedNativeHandler(context
) {
157 RouteFunction("GetAPIFeatures",
158 base::Bind(&TestFeaturesNativeHandler::GetAPIFeatures
,
159 base::Unretained(this)));
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
{
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)));
190 void IsProcessingUserGesture(
191 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
192 args
.GetReturnValue().Set(v8::Boolean::New(
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]),
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]),
218 class V8ContextNativeHandler
: public ObjectBackedNativeHandler
{
220 V8ContextNativeHandler(ChromeV8Context
* context
, Dispatcher
* dispatcher
)
221 : ObjectBackedNativeHandler(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)));
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(
256 args
.GetReturnValue().Set(context
->module_system()->NewInstance());
259 ChromeV8Context
* context_
;
260 Dispatcher
* dispatcher_
;
263 class ChromeNativeHandler
: public ObjectBackedNativeHandler
{
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
{
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)
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
{
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
) {
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
) {
325 RenderView
* render_view
= context()->GetRenderView();
326 if (IsContextLazyBackgroundPage(render_view
, context()->extension())) {
327 render_view
->Send(new ExtensionHostMsg_DecrementLazyKeepaliveCount(
328 render_view
->GetRoutingID()));
333 bool IsContextLazyBackgroundPage(RenderView
* render_view
,
334 const Extension
* extension
) {
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
{
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)));
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();
446 arguments
.push_back(converter
->ToV8Value(*it
, context
->v8_context()));
449 context
->module_system()->CallModuleMethod(
450 module_name
, method_name
, &arguments
);
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));
478 PopulateLazyBindingsMap();
481 Dispatcher::~Dispatcher() {
484 bool Dispatcher::OnControlMessageReceived(const IPC::Message
& message
) {
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()
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
);
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 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
,
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(),
614 MessagingBindings::DeliverMessage(
615 v8_context_set_
.GetAll(),
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
) {
634 scoped_refptr
<const Extension
> extension
= i
->ConvertToExtension(&error
);
635 if (!extension
.get()) {
636 extension_load_errors_
[i
->id
] = error
;
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
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 {
691 active_extension_ids_
.find(extension_id
) != active_extension_ids_
.end();
693 CHECK(extensions_
.Contains(extension_id
));
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
705 if (object
->HasRealNamedCallbackProperty(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
);
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
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;
746 if (runtime_is_available
)
747 RegisterBinding("runtime", context
);
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
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
);
765 // Internal APIs are included via require(api_name) from internal code
766 // rather than chrome[api_name].
767 if (feature
->IsInternal())
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
)
775 if (context
->IsAnyFeatureAvailableToContext(*feature
))
776 RegisterBinding(api_name
, context
);
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.
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;
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
>();
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())
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,
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(
868 scoped_ptr
<NativeHandler
>(new BindingGeneratingNativeHandler(
872 module_system
->SetNativeLazyField(bind_object
,
877 module_system
->SetLazyField(bind_object
,
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
)));
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(
933 module_system
->RegisterNativeHandler("file_browser_private",
934 scoped_ptr
<NativeHandler
>(new FileBrowserPrivateCustomBindings(
936 module_system
->RegisterNativeHandler("i18n",
937 scoped_ptr
<NativeHandler
>(
938 new I18NCustomBindings(this, context
)));
939 module_system
->RegisterNativeHandler(
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
)));
966 void Dispatcher::PopulateSourceMap() {
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
);
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
);
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"))
1099 (*lazy_binding
->second
)(module_system
, chrome
);
1101 module_system
->Require(api
);
1105 void Dispatcher::DidCreateScriptContext(
1106 WebFrame
* frame
, v8::Handle
<v8::Context
> v8_context
, int extension_group
,
1108 #if !defined(ENABLE_EXTENSIONS)
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"));
1129 Feature::Context context_type
= ClassifyJavaScriptContext(
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
);
1140 InitOriginPermissions(extension
, context_type
);
1143 scoped_ptr
<ModuleSystem
> module_system(new ModuleSystem(context
,
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(
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");
1225 // TODO(asargent) We need a whitelist for webview experimental.
1227 std::string id_hash
= base::SHA1HashString(extension
->id());
1228 std::string hexencoded_id_hash
= base::HexEncode(id_hash
.c_str(),
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");
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");
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())
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
);
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
);
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
];
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
1347 RenderThread::Get()->ScheduleIdleHandler(kInitialExtensionIdleHandlerDelayMs
);
1349 UpdateActiveExtensions();
1351 if (is_webkit_initialized_
) {
1352 DOMActivityLogger::AttachToWorld(DOMActivityLogger::kMainWorldId
,
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
1362 if (context_type
== Feature::BLESSED_EXTENSION_CONTEXT
&&
1363 extension
->HasAPIPermission(APIPermission::kManagement
)) {
1364 WebSecurityPolicy::addOriginAccessWhitelistEntry(
1366 WebString::fromUTF8(content::kChromeUIScheme
),
1367 WebString::fromUTF8(chrome::kChromeUIExtensionIconHost
),
1371 AddOrRemoveOriginPermissions(
1372 UpdatedExtensionPermissionsInfo::ADDED
,
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
)(
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(
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
);
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
;
1443 case UpdatedExtensionPermissionsInfo::ADDED
:
1444 new_active
= PermissionSet::CreateUnion(old_active
.get(), delta
.get());
1446 case UpdatedExtensionPermissionsInfo::REMOVED
:
1448 PermissionSet::CreateDifference(old_active
.get(), delta
.get());
1452 PermissionsData::SetActivePermissions(extension
, new_active
);
1453 AddOrRemoveOriginPermissions(reason
, extension
, explicit_hosts
);
1454 AddOrRemoveBindings(extension
->id());
1457 void Dispatcher::OnUpdateTabSpecificPermissions(
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.
1468 if (view
&& view
->GetPageId() != page_id
)
1471 const Extension
* extension
= extensions_
.GetByID(extension_id
);
1475 PermissionsData::UpdateTabSpecificPermissions(
1478 new PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
1479 origin_set
, URLPatternSet()));
1482 void Dispatcher::OnClearTabSpecificPermissions(
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
);
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
))
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
,
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
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());
1544 return SandboxedPageInfo::IsSandboxedPage(extension
, url
.path());
1550 Feature::Context
Dispatcher::ClassifyJavaScriptContext(
1551 const Extension
* extension
,
1552 int extension_group
,
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
;
1594 return Feature::WEB_PAGE_CONTEXT
;
1596 return Feature::UNSPECIFIED_CONTEXT
;
1599 void Dispatcher::OnExtensionResponse(int request_id
,
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 {
1609 DLOG(ERROR
) << "Not in a v8::Context";
1613 if (!context
->extension()) {
1614 context
->isolate()->ThrowException(v8::Exception::Error(
1615 v8::String::NewFromUtf8(context
->isolate(), "Not in an extension.")));
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())));
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(
1651 NULL
, // all render views
1652 base::Bind(&CallModuleMethod
,
1653 local_event_bindings
,
1654 kEventDispatchFunction
,
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
;
1667 web_user_gesture
.reset(new WebScopedUserGesture
);
1669 v8_context_set_
.ForEach(
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
1700 port_to_tab_id_map_
.erase(port_id
);
1703 } // namespace extensions