Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(560)

Unified Diff: chrome/renderer/extensions/extension_dispatcher.cc

Issue 9386001: Implement a module system for the extension bindings JS. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix compile errors Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/renderer/extensions/extension_dispatcher.cc
diff --git a/chrome/renderer/extensions/extension_dispatcher.cc b/chrome/renderer/extensions/extension_dispatcher.cc
index e59922c3aedf30a9dded01cffcd1059275da5494..99635bc869f82d38ea8df097cd087d91ade587a4 100644
--- a/chrome/renderer/extensions/extension_dispatcher.cc
+++ b/chrome/renderer/extensions/extension_dispatcher.cc
@@ -4,7 +4,10 @@
#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"
@@ -22,6 +25,9 @@
#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"
@@ -34,6 +40,19 @@
#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;
@@ -62,7 +81,8 @@ ExtensionDispatcher::ExtensionDispatcher()
: is_webkit_initialized_(false),
webrequest_adblock_(false),
webrequest_adblock_plus_(false),
- webrequest_other_(false) {
+ webrequest_other_(false),
+ source_map_(&ResourceBundle::GetSharedInstance()) {
const CommandLine& command_line = *(CommandLine::ForCurrentProcess());
is_extension_process_ =
command_line.HasSwitch(switches::kExtensionProcess) ||
@@ -74,6 +94,7 @@ ExtensionDispatcher::ExtensionDispatcher()
}
user_script_slave_.reset(new UserScriptSlave(&extensions_));
+ PopulateSourceMap();
}
ExtensionDispatcher::~ExtensionDispatcher() {
@@ -111,25 +132,6 @@ void ExtensionDispatcher::WebKitInitialized() {
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();
@@ -291,55 +293,203 @@ bool ExtensionDispatcher::AllowScriptExtension(
int extension_group,
int world_id) {
g_hack_extension_group = extension_group;
+ return true;
+}
- // NULL in unit tests.
- if (!RenderThread::Get())
- return true;
+bool ExtensionDispatcher::AllowCustomAPI(WebFrame* frame,
+ const std::string& custom_binding_api_name,
Matt Perry 2012/03/01 23:23:06 indent is wonky here
koz (OOO until 15th September) 2012/03/02 01:13:58 Done.
+ int world_id) {
+ 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);
+}
- // 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;
+base::StringPiece GetResource(int resource_id) {
Aaron Boodman 2012/03/01 07:24:26 Dead code?
koz (OOO until 15th September) 2012/03/02 01:13:58 Done.
+ return ResourceBundle::GetSharedInstance().GetRawDataResource(resource_id);
+}
- // If the V8 extension is not restricted, allow it to run anywhere.
- if (!restricted_v8_extensions_.count(v8_extension_name))
- return true;
+SourceMap* GetOrCreateSourceMap() {
Aaron Boodman 2012/03/01 07:24:26 Dead code.
koz (OOO until 15th September) 2012/03/02 01:13:58 Done.
+ static ResourceBundleSourceMap* source_map;
+ if (source_map == NULL) {
+ source_map =
+ new ResourceBundleSourceMap(&ResourceBundle::GetSharedInstance());
+ }
- // Extension-only bindings should be restricted to content scripts and
- // extension-blessed URLs.
- ChromeV8Context::ContextType context_type =
- ExtensionGroupToContextType(extension_group);
+ return source_map;
+}
- 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);
- }
+class ChromeHiddenNativeHandler : public NativeHandler {
Aaron Boodman 2012/03/01 07:24:26 Global definitions in a cc file should be in an an
koz (OOO until 15th September) 2012/03/02 01:13:58 Done.
+ 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,
+ 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_);
+ }
- return true;
+ 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_));
}
- return false;
+ private:
+ ExtensionDispatcher* extension_dispatcher_;
+ bool is_bindings_allowed_;
+ WebFrame* frame_;
+ int world_id_;
+};
+
+void ExtensionDispatcher::RegisterNativeHandlers(ModuleSystem* module_system,
+ ChromeV8Context* context,
+ bool is_bindings_allowed) {
+ 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)));
+
+ // 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()));
+}
+
+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);
+
+ // 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);
+ source_map_.RegisterSource("windows", IDR_WINDOWS_CUSTOM_BINDINGS_JS);
}
void ExtensionDispatcher::DidCreateScriptContext(
@@ -356,11 +506,35 @@ void ExtensionDispatcher::DidCreateScriptContext(
ExtensionGroupToContextType(extension_group));
v8_context_set_.Add(context);
+ bool is_bindings_allowed =
+ context->context_type() == ChromeV8Context::CONTENT_SCRIPT ||
+ extensions_.ExtensionBindingsAllowed(ExtensionURLInfo(
+ frame->document().securityOrigin(),
+ UserScriptSlave::GetDataSourceURLForFrame(frame)));
+
+ ModuleSystem* module_system = new ModuleSystem(&source_map_);
Aaron Boodman 2012/03/01 07:24:26 Make this a scoped_ptr, and use module_system.Pass
koz (OOO until 15th September) 2012/03/02 01:13:58 Done.
+ RegisterNativeHandlers(module_system, context, is_bindings_allowed);
+
+ module_system->RegisterNativeHandler("chrome_hidden",
+ scoped_ptr<NativeHandler>(new ChromeHiddenNativeHandler()));
+ module_system->RegisterNativeHandler("print",
+ scoped_ptr<NativeHandler>(new PrintNativeHandler()));
+ module_system->RegisterNativeHandler("context_info",
+ scoped_ptr<NativeHandler>(new ContextInfoNativeHandler(
+ this,
+ is_bindings_allowed,
+ frame,
+ world_id)));
+
+ context->set_module_system(scoped_ptr<ModuleSystem>(module_system));
+
const Extension* extension = extensions_.GetByID(context->extension_id());
int manifest_version = 1;
if (extension)
manifest_version = extension->manifest_version();
+ module_system->Require("setup_bindings");
+
context->DispatchOnLoadEvent(
is_extension_process_,
ChromeRenderProcessObserver::is_incognito_process(),
@@ -391,12 +565,6 @@ void ExtensionDispatcher::WillReleaseScriptContext(
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();
}

Powered by Google App Engine
This is Rietveld 408576698