| Index: chrome/renderer/extensions/extension_dispatcher.cc
|
| ===================================================================
|
| --- chrome/renderer/extensions/extension_dispatcher.cc (revision 125813)
|
| +++ chrome/renderer/extensions/extension_dispatcher.cc (working copy)
|
| @@ -4,10 +4,7 @@
|
|
|
| #include "chrome/renderer/extensions/extension_dispatcher.h"
|
|
|
| -#include "base/callback.h"
|
| #include "base/command_line.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/string_piece.h"
|
| #include "chrome/common/child_process_logging.h"
|
| #include "chrome/common/chrome_switches.h"
|
| #include "chrome/common/extensions/extension.h"
|
| @@ -25,9 +22,6 @@
|
| #include "chrome/renderer/extensions/schema_generated_bindings.h"
|
| #include "chrome/renderer/extensions/user_script_slave.h"
|
| #include "chrome/renderer/extensions/webstore_bindings.h"
|
| -#include "chrome/renderer/module_system.h"
|
| -#include "chrome/renderer/native_handler.h"
|
| -#include "chrome/renderer/resource_bundle_source_map.h"
|
| #include "content/public/renderer/render_thread.h"
|
| #include "grit/renderer_resources.h"
|
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h"
|
| @@ -41,19 +35,6 @@
|
| #include "ui/base/resource/resource_bundle.h"
|
| #include "v8/include/v8.h"
|
|
|
| -#include "chrome/renderer/extensions/chrome_private_custom_bindings.h"
|
| -#include "chrome/renderer/extensions/context_menus_custom_bindings.h"
|
| -#include "chrome/renderer/extensions/experimental.socket_custom_bindings.h"
|
| -#include "chrome/renderer/extensions/extension_custom_bindings.h"
|
| -#include "chrome/renderer/extensions/file_browser_handler_custom_bindings.h"
|
| -#include "chrome/renderer/extensions/file_browser_private_custom_bindings.h"
|
| -#include "chrome/renderer/extensions/i18n_custom_bindings.h"
|
| -#include "chrome/renderer/extensions/page_actions_custom_bindings.h"
|
| -#include "chrome/renderer/extensions/page_capture_custom_bindings.h"
|
| -#include "chrome/renderer/extensions/tabs_custom_bindings.h"
|
| -#include "chrome/renderer/extensions/tts_custom_bindings.h"
|
| -#include "chrome/renderer/extensions/web_request_custom_bindings.h"
|
| -
|
| namespace {
|
|
|
| static const int64 kInitialExtensionIdleHandlerDelayMs = 5*1000;
|
| @@ -65,75 +46,6 @@
|
| return ChromeV8Context::OTHER;
|
| }
|
|
|
| -class ChromeHiddenNativeHandler : public NativeHandler {
|
| - public:
|
| - ChromeHiddenNativeHandler() {
|
| - RouteFunction("GetChromeHidden",
|
| - base::Bind(&ChromeHiddenNativeHandler::GetChromeHidden,
|
| - base::Unretained(this)));
|
| - }
|
| -
|
| - v8::Handle<v8::Value> GetChromeHidden(const v8::Arguments& args) {
|
| - return ChromeV8Context::GetOrCreateChromeHidden(v8::Context::GetCurrent());
|
| - }
|
| -};
|
| -
|
| -class PrintNativeHandler : public NativeHandler {
|
| - public:
|
| - PrintNativeHandler() {
|
| - RouteFunction("Print",
|
| - base::Bind(&PrintNativeHandler::Print,
|
| - base::Unretained(this)));
|
| - }
|
| -
|
| - v8::Handle<v8::Value> Print(const v8::Arguments& args) {
|
| - if (args.Length() < 1)
|
| - return v8::Undefined();
|
| -
|
| - std::vector<std::string> components;
|
| - for (int i = 0; i < args.Length(); ++i)
|
| - components.push_back(*v8::String::Utf8Value(args[i]->ToString()));
|
| -
|
| - LOG(ERROR) << JoinString(components, ',');
|
| - return v8::Undefined();
|
| - }
|
| -};
|
| -
|
| -class ContextInfoNativeHandler : public NativeHandler {
|
| - public:
|
| - explicit ContextInfoNativeHandler(ExtensionDispatcher* extension_dispatcher,
|
| - bool is_bindings_allowed,
|
| - WebKit::WebFrame* frame,
|
| - int world_id)
|
| - : extension_dispatcher_(extension_dispatcher),
|
| - is_bindings_allowed_(is_bindings_allowed),
|
| - frame_(frame),
|
| - world_id_(world_id) {
|
| - RouteFunction("IsBindingsAllowed",
|
| - base::Bind(&ContextInfoNativeHandler::IsBindingsAllowed,
|
| - base::Unretained(this)));
|
| - RouteFunction("IsAPIAllowed",
|
| - base::Bind(&ContextInfoNativeHandler::IsAPIAllowed,
|
| - base::Unretained(this)));
|
| - }
|
| -
|
| - v8::Handle<v8::Value> IsBindingsAllowed(const v8::Arguments& args) {
|
| - return v8::Boolean::New(is_bindings_allowed_);
|
| - }
|
| -
|
| - v8::Handle<v8::Value> IsAPIAllowed(const v8::Arguments& args) {
|
| - std::string custom_api_name = *v8::String::AsciiValue(args[0]->ToString());
|
| - return v8::Boolean::New(extension_dispatcher_->AllowCustomAPI(
|
| - frame_, custom_api_name, world_id_));
|
| - }
|
| -
|
| - private:
|
| - ExtensionDispatcher* extension_dispatcher_;
|
| - bool is_bindings_allowed_;
|
| - WebKit::WebFrame* frame_;
|
| - int world_id_;
|
| -};
|
| -
|
| }
|
|
|
| using namespace extensions;
|
| @@ -152,8 +64,7 @@
|
| : is_webkit_initialized_(false),
|
| webrequest_adblock_(false),
|
| webrequest_adblock_plus_(false),
|
| - webrequest_other_(false),
|
| - source_map_(&ResourceBundle::GetSharedInstance()) {
|
| + webrequest_other_(false) {
|
| const CommandLine& command_line = *(CommandLine::ForCurrentProcess());
|
| is_extension_process_ =
|
| command_line.HasSwitch(switches::kExtensionProcess) ||
|
| @@ -165,7 +76,6 @@
|
| }
|
|
|
| user_script_slave_.reset(new UserScriptSlave(&extensions_));
|
| - PopulateSourceMap();
|
| }
|
|
|
| ExtensionDispatcher::~ExtensionDispatcher() {
|
| @@ -203,6 +113,25 @@
|
| RenderThread::Get(), &RenderThread::IdleHandler);
|
| }
|
|
|
| + RegisterExtension(new AppBindings(this), false);
|
| + RegisterExtension(new WebstoreBindings(this), false);
|
| +
|
| + // Add v8 extensions related to chrome extensions.
|
| + RegisterExtension(new ChromeV8Extension(
|
| + "extensions/json_schema.js", IDR_JSON_SCHEMA_JS, NULL), true);
|
| + RegisterExtension(EventBindings::Get(this), true);
|
| + RegisterExtension(MiscellaneousBindings::Get(this), true);
|
| + RegisterExtension(SchemaGeneratedBindings::Get(this), true);
|
| + RegisterExtension(new ChromeV8Extension(
|
| + "extensions/apitest.js", IDR_EXTENSION_APITEST_JS, NULL), true);
|
| +
|
| + std::vector<v8::Extension*> custom_bindings =
|
| + custom_bindings_util::GetAll(this);
|
| + for (std::vector<v8::Extension*>::iterator it = custom_bindings.begin();
|
| + it != custom_bindings.end(); ++it) {
|
| + RegisterExtension(*it, true);
|
| + }
|
| +
|
| // Initialize host permissions for any extensions that were activated before
|
| // WebKit was initialized.
|
| for (std::set<std::string>::iterator iter = active_extension_ids_.begin();
|
| @@ -370,121 +299,55 @@
|
| int extension_group,
|
| int world_id) {
|
| g_hack_extension_group = extension_group;
|
| - return true;
|
| -}
|
|
|
| -bool ExtensionDispatcher::AllowCustomAPI(
|
| - WebFrame* frame,
|
| - const std::string& custom_binding_api_name,
|
| - int world_id) {
|
| - std::string extension_id = GetExtensionID(frame, world_id);
|
| - if (test_extension_id_ == extension_id)
|
| + // NULL in unit tests.
|
| + if (!RenderThread::Get())
|
| return true;
|
| - const Extension* extension = extensions_.GetByID(extension_id);
|
| - if (!extension) {
|
| - // This can happen when a resource is blocked due to CSP; a valid
|
| - // chrome-extension:// URL is navigated to, so it passes the initial
|
| - // checks, but the URL gets changed to "chrome-extension://invalid"
|
| - // afterwards (see chrome_content_renderer_client.cc). An extension
|
| - // page still gets loaded, just for the extension with ID "invalid",
|
| - // which of course isn't found so GetById extension will be NULL.
|
| - //
|
| - // Reference: http://crbug.com/111614.
|
| - CHECK_EQ("invalid", extension_id);
|
| - return false;
|
| - }
|
| - return custom_bindings_util::AllowAPIInjection(
|
| - custom_binding_api_name, *extension, this);
|
| -}
|
|
|
| -void ExtensionDispatcher::RegisterNativeHandlers(ModuleSystem* module_system,
|
| - ChromeV8Context* context) {
|
| - module_system->RegisterNativeHandler("app",
|
| - scoped_ptr<NativeHandler>(new AppBindings(this, context)));
|
| - module_system->RegisterNativeHandler("webstore",
|
| - scoped_ptr<NativeHandler>(new WebstoreBindings(this, context)));
|
| - module_system->RegisterNativeHandler("event_bindings",
|
| - scoped_ptr<NativeHandler>(EventBindings::Get(this)));
|
| - module_system->RegisterNativeHandler("miscellaneous_bindings",
|
| - scoped_ptr<NativeHandler>(MiscellaneousBindings::Get(this)));
|
| - module_system->RegisterNativeHandler("schema_generated_bindings",
|
| - scoped_ptr<NativeHandler>(SchemaGeneratedBindings::Get(this)));
|
| + // If we don't know about it, it was added by WebCore, so we should allow it.
|
| + if (!RenderThread::Get()->IsRegisteredExtension(v8_extension_name))
|
| + return true;
|
|
|
| - // Custom bindings.
|
| - module_system->RegisterNativeHandler("chrome_private",
|
| - scoped_ptr<NativeHandler>(
|
| - new ChromePrivateCustomBindings(this)));
|
| - module_system->RegisterNativeHandler("context_menus",
|
| - scoped_ptr<NativeHandler>(new ContextMenusCustomBindings()));
|
| - module_system->RegisterNativeHandler("extension",
|
| - scoped_ptr<NativeHandler>(
|
| - new ExtensionCustomBindings(this)));
|
| - module_system->RegisterNativeHandler("experimental_socket",
|
| - scoped_ptr<NativeHandler>(new ExperimentalSocketCustomBindings()));
|
| - module_system->RegisterNativeHandler("file_browser_handler",
|
| - scoped_ptr<NativeHandler>(new FileBrowserHandlerCustomBindings()));
|
| - module_system->RegisterNativeHandler("file_browser_private",
|
| - scoped_ptr<NativeHandler>(new FileBrowserPrivateCustomBindings()));
|
| - module_system->RegisterNativeHandler("i18n",
|
| - scoped_ptr<NativeHandler>(new I18NCustomBindings()));
|
| - module_system->RegisterNativeHandler("page_actions",
|
| - scoped_ptr<NativeHandler>(
|
| - new PageActionsCustomBindings(this)));
|
| - module_system->RegisterNativeHandler("page_capture",
|
| - scoped_ptr<NativeHandler>(new PageCaptureCustomBindings()));
|
| - module_system->RegisterNativeHandler("tabs",
|
| - scoped_ptr<NativeHandler>(new TabsCustomBindings()));
|
| - module_system->RegisterNativeHandler("tts",
|
| - scoped_ptr<NativeHandler>(new TTSCustomBindings()));
|
| - module_system->RegisterNativeHandler("web_request",
|
| - scoped_ptr<NativeHandler>(new WebRequestCustomBindings()));
|
| -}
|
| + // If the V8 extension is not restricted, allow it to run anywhere.
|
| + if (!restricted_v8_extensions_.count(v8_extension_name))
|
| + return true;
|
|
|
| -void ExtensionDispatcher::PopulateSourceMap() {
|
| - source_map_.RegisterSource("app", IDR_APP_BINDINGS_JS);
|
| - source_map_.RegisterSource("webstore", IDR_WEBSTORE_BINDINGS_JS);
|
| - source_map_.RegisterSource("event_bindings", IDR_EVENT_BINDINGS_JS);
|
| - source_map_.RegisterSource("miscellaneous_bindings",
|
| - IDR_MISCELLANEOUS_BINDINGS_JS);
|
| - source_map_.RegisterSource("schema_generated_bindings",
|
| - IDR_SCHEMA_GENERATED_BINDINGS_JS);
|
| - source_map_.RegisterSource("json_schema", IDR_JSON_SCHEMA_JS);
|
| - source_map_.RegisterSource("apitest", IDR_EXTENSION_APITEST_JS);
|
| - source_map_.RegisterSource("setup_bindings", IDR_SETUP_BINDINGS_JS);
|
| + // Extension-only bindings should be restricted to content scripts and
|
| + // extension-blessed URLs.
|
| + ChromeV8Context::ContextType context_type =
|
| + ExtensionGroupToContextType(extension_group);
|
|
|
| - // Custom bindings.
|
| - source_map_.RegisterSource("browserAction",
|
| - IDR_BROWSER_ACTION_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("chromePrivate",
|
| - IDR_CHROME_PRIVATE_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("contentSettings",
|
| - IDR_CONTENT_SETTINGS_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("contextMenus",
|
| - IDR_CONTEXT_MENUS_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("devtools", IDR_DEVTOOLS_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("experimental.declarative",
|
| - IDR_EXPERIMENTAL_DECLARATIVE_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("experimental.socket",
|
| - IDR_EXPERIMENTAL_SOCKET_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("extension", IDR_EXTENSION_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("fileBrowserHandler",
|
| - IDR_FILE_BROWSER_HANDLER_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("fileBrowserPrivate",
|
| - IDR_FILE_BROWSER_PRIVATE_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("i18n", IDR_I18N_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("input.ime", IDR_INPUT_IME_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("omnibox", IDR_OMNIBOX_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("pageActions",
|
| - IDR_PAGE_ACTIONS_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("pageAction", IDR_PAGE_ACTION_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("pageCapture",
|
| - IDR_PAGE_CAPTURE_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("storage", IDR_STORAGE_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("tabs", IDR_TABS_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("tts", IDR_TTS_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("ttsEngine", IDR_TTS_ENGINE_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("types", IDR_TYPES_CUSTOM_BINDINGS_JS);
|
| - source_map_.RegisterSource("webRequest", IDR_WEB_REQUEST_CUSTOM_BINDINGS_JS);
|
| + if (context_type == ChromeV8Context::CONTENT_SCRIPT ||
|
| + extensions_.ExtensionBindingsAllowed(ExtensionURLInfo(
|
| + frame->document().securityOrigin(),
|
| + UserScriptSlave::GetDataSourceURLForFrame(frame)))) {
|
| + // If the extension is a custom API binding, only allow if the extension
|
| + // has permission to use the API.
|
| + std::string custom_binding_api_name =
|
| + custom_bindings_util::GetAPIName(v8_extension_name);
|
| + if (!custom_binding_api_name.empty()) {
|
| + std::string extension_id = GetExtensionID(frame, world_id);
|
| + const Extension* extension = extensions_.GetByID(extension_id);
|
| + if (!extension) {
|
| + // This can happen when a resource is blocked due to CSP; a valid
|
| + // chrome-extension:// URL is navigated to, so it passes the initial
|
| + // checks, but the URL gets changed to "chrome-extension://invalid"
|
| + // afterwards (see chrome_content_renderer_client.cc). An extension
|
| + // page still gets loaded, just for the extension with ID "invalid",
|
| + // which of course isn't found so GetById extension will be NULL.
|
| + //
|
| + // Reference: http://crbug.com/111614.
|
| + CHECK_EQ("invalid", extension_id);
|
| + return false;
|
| + }
|
| + return custom_bindings_util::AllowAPIInjection(
|
| + custom_binding_api_name, *extension, this);
|
| + }
|
| +
|
| + return true;
|
| + }
|
| +
|
| + return false;
|
| }
|
|
|
| void ExtensionDispatcher::DidCreateScriptContext(
|
| @@ -493,49 +356,19 @@
|
| // TODO(koz): If the caller didn't pass extension_group, use the last value.
|
| if (extension_group == -1)
|
| extension_group = g_hack_extension_group;
|
| -
|
| - std::string extension_id = GetExtensionID(frame, world_id);
|
| ChromeV8Context* context =
|
| new ChromeV8Context(
|
| v8_context,
|
| frame,
|
| - extension_id,
|
| + GetExtensionID(frame, world_id),
|
| ExtensionGroupToContextType(extension_group));
|
| v8_context_set_.Add(context);
|
|
|
| - scoped_ptr<ModuleSystem> module_system(new ModuleSystem(&source_map_));
|
| - RegisterNativeHandlers(module_system.get(), context);
|
| -
|
| - bool is_bindings_allowed =
|
| - IsTestExtensionId(extension_id) ||
|
| - context->context_type() == ChromeV8Context::CONTENT_SCRIPT ||
|
| - extensions_.ExtensionBindingsAllowed(ExtensionURLInfo(
|
| - frame->document().securityOrigin(),
|
| - UserScriptSlave::GetDataSourceURLForFrame(frame)));
|
| -
|
| - module_system->RegisterNativeHandler("chrome_hidden",
|
| - scoped_ptr<NativeHandler>(new ChromeHiddenNativeHandler()));
|
| - module_system->RegisterNativeHandler("context_info",
|
| - scoped_ptr<NativeHandler>(new ContextInfoNativeHandler(
|
| - this,
|
| - is_bindings_allowed,
|
| - frame,
|
| - world_id)));
|
| - module_system->RegisterNativeHandler("print",
|
| - scoped_ptr<NativeHandler>(new PrintNativeHandler()));
|
| -
|
| const Extension* extension = extensions_.GetByID(context->extension_id());
|
| int manifest_version = 1;
|
| if (extension)
|
| manifest_version = extension->manifest_version();
|
|
|
| - module_system->RunString("var chrome; chrome = chrome || {};",
|
| - "setup-chrome-object");
|
| - module_system->Require("setup_bindings");
|
| - module_system->set_natives_enabled(false);
|
| -
|
| - context->set_module_system(module_system.Pass());
|
| -
|
| context->DispatchOnLoadEvent(
|
| is_extension_process_,
|
| ChromeRenderProcessObserver::is_incognito_process(),
|
| @@ -566,6 +399,12 @@
|
|
|
| context->DispatchOnUnloadEvent();
|
|
|
| + ChromeV8Extension::InstanceSet extensions = ChromeV8Extension::GetAll();
|
| + for (ChromeV8Extension::InstanceSet::const_iterator iter = extensions.begin();
|
| + iter != extensions.end(); ++iter) {
|
| + (*iter)->ContextWillBeReleased(context);
|
| + }
|
| +
|
| v8_context_set_.Remove(context);
|
| VLOG(1) << "Num tracked contexts: " << v8_context_set_.size();
|
| }
|
| @@ -575,7 +414,7 @@
|
| }
|
|
|
| bool ExtensionDispatcher::IsTestExtensionId(const std::string& id) {
|
| - return !test_extension_id_.empty() && id == test_extension_id_;
|
| + return id == test_extension_id_;
|
| }
|
|
|
| void ExtensionDispatcher::OnActivateApplication(
|
|
|