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