diff options
author | koz@chromium.org <koz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-13 02:09:41 +0000 |
---|---|---|
committer | koz@chromium.org <koz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-13 02:09:41 +0000 |
commit | 9fb990b32d4de5697fa848e03a6bf4d11fcd0417 (patch) | |
tree | c6dd811b2fd92bf95afe4107e3f78ae86e255319 /chrome/renderer/extensions | |
parent | af885dd7caf0455a05f15aac48fa221191266706 (diff) | |
download | chromium_src-9fb990b32d4de5697fa848e03a6bf4d11fcd0417.zip chromium_src-9fb990b32d4de5697fa848e03a6bf4d11fcd0417.tar.gz chromium_src-9fb990b32d4de5697fa848e03a6bf4d11fcd0417.tar.bz2 |
Implement a module system for the extension bindings JS.
BUG=104100
TEST=existing browser tests
Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=125132
Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=125801
Review URL: http://codereview.chromium.org/9386001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@126306 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer/extensions')
43 files changed, 501 insertions, 813 deletions
diff --git a/chrome/renderer/extensions/app_bindings.cc b/chrome/renderer/extensions/app_bindings.cc index 21ee438..34c8047 100644 --- a/chrome/renderer/extensions/app_bindings.cc +++ b/chrome/renderer/extensions/app_bindings.cc @@ -53,93 +53,41 @@ const char* kMissingClientIdError = "Missing clientId parameter"; const char* kInvalidClientIdError = "Invalid clientId"; const char* kInvalidCallbackIdError = "Invalid callbackId"; - -class AppBindingsHandler : public ChromeV8ExtensionHandler { - public: - AppBindingsHandler(ExtensionDispatcher* dispatcher, ChromeV8Context* context); - - // ChromeV8ExtensionHandler - virtual v8::Handle<v8::Value> HandleNativeFunction( - const std::string& name, - const v8::Arguments& arguments) OVERRIDE; - - // IPC::Channel::Listener - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - - private: - v8::Handle<v8::Value> GetIsInstalled(const v8::Arguments& args); - v8::Handle<v8::Value> Install(const v8::Arguments& args); - v8::Handle<v8::Value> GetDetails(const v8::Arguments& args); - v8::Handle<v8::Value> GetDetailsForFrame(const v8::Arguments& args); - v8::Handle<v8::Value> GetAppNotifyChannel(const v8::Arguments& args); - - v8::Handle<v8::Value> GetDetailsForFrameImpl(WebKit::WebFrame* frame); - - void OnGetAppNotifyChannelResponse(const std::string& channel_id, - const std::string& error, - int callback_id); - - ExtensionDispatcher* dispatcher_; - DISALLOW_COPY_AND_ASSIGN(AppBindingsHandler); -}; - } // namespace -AppBindings::AppBindings(ExtensionDispatcher* dispatcher) - : ChromeV8Extension("extensions/app.js", IDR_APP_BINDINGS_JS, - dispatcher) { -} - -ChromeV8ExtensionHandler* AppBindings::CreateHandler( - ChromeV8Context* context) { - return new AppBindingsHandler(extension_dispatcher(), context); -} - - - -AppBindingsHandler::AppBindingsHandler(ExtensionDispatcher* dispatcher, - ChromeV8Context* context) - : ChromeV8ExtensionHandler(context), - dispatcher_(dispatcher) { +AppBindings::AppBindings(ExtensionDispatcher* dispatcher, + ChromeV8Context* context) + : ChromeV8Extension(dispatcher), + ChromeV8ExtensionHandler(context) { + RouteFunction("GetIsInstalled", + base::Bind(&AppBindings::GetIsInstalled, base::Unretained(this))); + RouteFunction("Install", + base::Bind(&AppBindings::Install, base::Unretained(this))); + RouteFunction("GetDetails", + base::Bind(&AppBindings::GetDetails, base::Unretained(this))); + RouteFunction("GetDetailsForFrame", + base::Bind(&AppBindings::GetDetailsForFrame, base::Unretained(this))); + RouteFunction("GetAppNotifyChannel", + base::Bind(&AppBindings::GetAppNotifyChannel, base::Unretained(this))); } -v8::Handle<v8::Value> AppBindingsHandler::HandleNativeFunction( - const std::string& name, const v8::Arguments& args) { - // TODO(aa): Create a helper map of callback that can be used in either - // extensions or handlers. - if (name == "GetIsInstalled") { - return GetIsInstalled(args); - } else if (name == "Install") { - return Install(args); - } else if (name == "GetDetails") { - return GetDetails(args); - } else if (name == "GetDetailsForFrame") { - return GetDetailsForFrame(args); - } else if (name == "GetAppNotifyChannel") { - return GetAppNotifyChannel(args); - } else { - CHECK(false) << "Unknown native function: " << name; - } - - return v8::Undefined(); -} -v8::Handle<v8::Value> AppBindingsHandler::GetIsInstalled( +v8::Handle<v8::Value> AppBindings::GetIsInstalled( const v8::Arguments& args) { // TODO(aa): Hm, maybe ExtensionBindingsContext should have GetExtension() // afterall? const ::Extension* extension = - dispatcher_->extensions()->GetByID(context_->extension_id()); + extension_dispatcher_->extensions()->GetByID(context_->extension_id()); // TODO(aa): Why only hosted app? // TODO(aa): GARRR - why is there IsExtensionActive and IsApplicationActive!? bool result = extension && extension->is_hosted_app() && - dispatcher_->IsApplicationActive(extension->id()); + extension_dispatcher_->IsApplicationActive(extension->id()); return v8::Boolean::New(result); } -v8::Handle<v8::Value> AppBindingsHandler::Install(const v8::Arguments& args) { +v8::Handle<v8::Value> AppBindings::Install(const v8::Arguments& args) { content::RenderView* render_view = context_->GetRenderView(); CHECK(render_view); @@ -153,13 +101,13 @@ v8::Handle<v8::Value> AppBindingsHandler::Install(const v8::Arguments& args) { return v8::Undefined(); } -v8::Handle<v8::Value> AppBindingsHandler::GetDetails( +v8::Handle<v8::Value> AppBindings::GetDetails( const v8::Arguments& args) { CHECK(context_->web_frame()); return GetDetailsForFrameImpl(context_->web_frame()); } -v8::Handle<v8::Value> AppBindingsHandler::GetDetailsForFrame( +v8::Handle<v8::Value> AppBindings::GetDetailsForFrame( const v8::Arguments& args) { CHECK(context_->web_frame()); if (!CheckAccessToAppDetails(context_->web_frame())) @@ -186,12 +134,12 @@ v8::Handle<v8::Value> AppBindingsHandler::GetDetailsForFrame( return GetDetailsForFrameImpl(target_frame); } -v8::Handle<v8::Value> AppBindingsHandler::GetDetailsForFrameImpl( +v8::Handle<v8::Value> AppBindings::GetDetailsForFrameImpl( WebFrame* frame) { const ::Extension* extension = - dispatcher_->extensions()->GetExtensionOrAppByURL(ExtensionURLInfo( - frame->document().securityOrigin(), - frame->document().url())); + extension_dispatcher_->extensions()->GetExtensionOrAppByURL( + ExtensionURLInfo(frame->document().securityOrigin(), + frame->document().url())); if (!extension) return v8::Null(); @@ -203,7 +151,7 @@ v8::Handle<v8::Value> AppBindingsHandler::GetDetailsForFrameImpl( frame->mainWorldScriptContext()); } -v8::Handle<v8::Value> AppBindingsHandler::GetAppNotifyChannel( +v8::Handle<v8::Value> AppBindings::GetAppNotifyChannel( const v8::Arguments& args) { // Read the required 'clientId' value out of the object at args[0]. std::string client_id; @@ -242,8 +190,8 @@ v8::Handle<v8::Value> AppBindingsHandler::GetAppNotifyChannel( return v8::Undefined(); } -bool AppBindingsHandler::OnMessageReceived(const IPC::Message& message) { - IPC_BEGIN_MESSAGE_MAP(AppBindingsHandler, message) +bool AppBindings::OnMessageReceived(const IPC::Message& message) { + IPC_BEGIN_MESSAGE_MAP(AppBindings, message) IPC_MESSAGE_HANDLER(ExtensionMsg_GetAppNotifyChannelResponse, OnGetAppNotifyChannelResponse) IPC_MESSAGE_UNHANDLED(CHECK(false) << "Unhandled IPC message") @@ -251,7 +199,7 @@ bool AppBindingsHandler::OnMessageReceived(const IPC::Message& message) { return true; } -void AppBindingsHandler::OnGetAppNotifyChannelResponse( +void AppBindings::OnGetAppNotifyChannelResponse( const std::string& channel_id, const std::string& error, int callback_id) { v8::HandleScope handle_scope; v8::Context::Scope context_scope(context_->v8_context()); diff --git a/chrome/renderer/extensions/app_bindings.h b/chrome/renderer/extensions/app_bindings.h index 9455ba2..e27c770 100644 --- a/chrome/renderer/extensions/app_bindings.h +++ b/chrome/renderer/extensions/app_bindings.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -14,21 +14,34 @@ #include "base/compiler_specific.h" #include "chrome/renderer/extensions/chrome_v8_extension.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" class ChromeV8Context; // Implements the chrome.app JavaScript object. // // TODO(aa): Add unit testing for this class. -class AppBindings : public ChromeV8Extension { +class AppBindings : public ChromeV8Extension, public ChromeV8ExtensionHandler { public: - explicit AppBindings(ExtensionDispatcher* dispatcher); - - protected: - virtual ChromeV8ExtensionHandler* CreateHandler( - ChromeV8Context* context) OVERRIDE; + explicit AppBindings(ExtensionDispatcher* dispatcher, + ChromeV8Context* context); private: + // IPC::Channel::Listener + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + v8::Handle<v8::Value> GetIsInstalled(const v8::Arguments& args); + v8::Handle<v8::Value> Install(const v8::Arguments& args); + v8::Handle<v8::Value> GetDetails(const v8::Arguments& args); + v8::Handle<v8::Value> GetDetailsForFrame(const v8::Arguments& args); + v8::Handle<v8::Value> GetAppNotifyChannel(const v8::Arguments& args); + + v8::Handle<v8::Value> GetDetailsForFrameImpl(WebKit::WebFrame* frame); + + void OnGetAppNotifyChannelResponse(const std::string& channel_id, + const std::string& error, + int callback_id); + DISALLOW_COPY_AND_ASSIGN(AppBindings); }; diff --git a/chrome/renderer/extensions/chrome_private_custom_bindings.cc b/chrome/renderer/extensions/chrome_private_custom_bindings.cc index a1e4fbb..2e8aa86 100644 --- a/chrome/renderer/extensions/chrome_private_custom_bindings.cc +++ b/chrome/renderer/extensions/chrome_private_custom_bindings.cc @@ -18,15 +18,10 @@ namespace extensions { ChromePrivateCustomBindings::ChromePrivateCustomBindings( - int dependency_count, - const char** dependencies, ExtensionDispatcher* extension_dispatcher) - : ChromeV8Extension( - "extensions/chrome_private_custom_bindings.js", - IDR_CHROME_PRIVATE_CUSTOM_BINDINGS_JS, - dependency_count, - dependencies, - extension_dispatcher) {} + : ChromeV8Extension(extension_dispatcher) { + RouteStaticFunction("DecodeJPEG", &DecodeJPEG); +} // static v8::Handle<v8::Value> ChromePrivateCustomBindings::DecodeJPEG( @@ -87,12 +82,4 @@ v8::Handle<v8::Value> ChromePrivateCustomBindings::DecodeJPEG( return bitmap_array; } -v8::Handle<v8::FunctionTemplate> ChromePrivateCustomBindings::GetNativeFunction( - v8::Handle<v8::String> name) { - if (name->Equals(v8::String::New("DecodeJPEG"))) - return v8::FunctionTemplate::New(DecodeJPEG, v8::External::New(this)); - - return ChromeV8Extension::GetNativeFunction(name); -} - } // namespace extensions diff --git a/chrome/renderer/extensions/chrome_private_custom_bindings.h b/chrome/renderer/extensions/chrome_private_custom_bindings.h index d1bfdb9..0d6fd5e 100644 --- a/chrome/renderer/extensions/chrome_private_custom_bindings.h +++ b/chrome/renderer/extensions/chrome_private_custom_bindings.h @@ -15,14 +15,9 @@ namespace extensions { // Implements custom bindings for the chromePrivate API. class ChromePrivateCustomBindings : public ChromeV8Extension { public: - ChromePrivateCustomBindings( - int dependency_count, - const char** dependencies, + explicit ChromePrivateCustomBindings( ExtensionDispatcher* extension_dispatcher); - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( - v8::Handle<v8::String> name) OVERRIDE; - private: // Decodes supplied JPEG byte array to image pixel array. static v8::Handle<v8::Value> DecodeJPEG(const v8::Arguments& args); diff --git a/chrome/renderer/extensions/chrome_v8_context.h b/chrome/renderer/extensions/chrome_v8_context.h index 11a4a87..3faf9d2 100644 --- a/chrome/renderer/extensions/chrome_v8_context.h +++ b/chrome/renderer/extensions/chrome_v8_context.h @@ -9,6 +9,7 @@ #include <string> #include "base/basictypes.h" +#include "chrome/renderer/module_system.h" #include "v8/include/v8.h" namespace WebKit { @@ -60,6 +61,10 @@ class ChromeV8Context { return context_type_; } + void set_module_system(scoped_ptr<ModuleSystem> module_system) { + module_system_ = module_system.Pass(); + } + // Returns a special Chrome-specific hidden object that is associated with a // context, but not reachable from the JavaScript in that context. This is // used by our v8::Extension implementations as a way to share code and as a @@ -113,6 +118,9 @@ class ChromeV8Context { // The type of context. ContextType context_type_; + // Owns and structures the JS that is injected to set up extension bindings. + scoped_ptr<ModuleSystem> module_system_; + DISALLOW_COPY_AND_ASSIGN(ChromeV8Context); }; diff --git a/chrome/renderer/extensions/chrome_v8_extension.cc b/chrome/renderer/extensions/chrome_v8_extension.cc index 35b5153..791b1f5 100644 --- a/chrome/renderer/extensions/chrome_v8_extension.cc +++ b/chrome/renderer/extensions/chrome_v8_extension.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -33,11 +33,6 @@ static base::LazyInstance<ChromeV8Extension::InstanceSet> g_instances = // static -base::StringPiece ChromeV8Extension::GetStringResource(int resource_id) { - return ResourceBundle::GetSharedInstance().GetRawDataResource(resource_id); -} - -// static content::RenderView* ChromeV8Extension::GetCurrentRenderView() { WebFrame* webframe = WebFrame::frameForCurrentContext(); DCHECK(webframe) << "RetrieveCurrentFrame called when not in a V8 context."; @@ -53,27 +48,8 @@ content::RenderView* ChromeV8Extension::GetCurrentRenderView() { return renderview; } -ChromeV8Extension::ChromeV8Extension(const char* name, int resource_id, - ExtensionDispatcher* extension_dispatcher) - : v8::Extension(name, - GetStringResource(resource_id).data(), - 0, // num dependencies - NULL, // dependencies array - GetStringResource(resource_id).size()), // source length - extension_dispatcher_(extension_dispatcher) { - g_instances.Get().insert(this); -} - -ChromeV8Extension::ChromeV8Extension(const char* name, int resource_id, - int dependency_count, - const char** dependencies, - ExtensionDispatcher* extension_dispatcher) - : v8::Extension(name, - GetStringResource(resource_id).data(), - dependency_count, - dependencies, - GetStringResource(resource_id).size()), - extension_dispatcher_(extension_dispatcher) { +ChromeV8Extension::ChromeV8Extension(ExtensionDispatcher* extension_dispatcher) + : extension_dispatcher_(extension_dispatcher) { g_instances.Get().insert(this); } @@ -86,19 +62,6 @@ const ChromeV8Extension::InstanceSet& ChromeV8Extension::GetAll() { return g_instances.Get(); } -void ChromeV8Extension::ContextWillBeReleased(ChromeV8Context* context) { - handlers_.erase(context); -} - -ChromeV8ExtensionHandler* ChromeV8Extension::GetHandler( - ChromeV8Context* context) const { - HandlerMap::const_iterator iter = handlers_.find(context); - if (iter == handlers_.end()) - return NULL; - else - return iter->second.get(); -} - const Extension* ChromeV8Extension::GetExtensionForCurrentRenderView() const { content::RenderView* renderview = GetCurrentRenderView(); if (!renderview) @@ -152,61 +115,3 @@ bool ChromeV8Extension::CheckCurrentContextAccessToExtensionAPI( return true; } - -v8::Handle<v8::FunctionTemplate> - ChromeV8Extension::GetNativeFunction(v8::Handle<v8::String> name) { - if (name->Equals(v8::String::New("GetChromeHidden"))) { - return v8::FunctionTemplate::New(GetChromeHidden); - } - - if (name->Equals(v8::String::New("Print"))) { - return v8::FunctionTemplate::New(Print); - } - - return v8::FunctionTemplate::New(HandleNativeFunction, - v8::External::New(this)); -} - -// static -v8::Handle<v8::Value> ChromeV8Extension::HandleNativeFunction( - const v8::Arguments& arguments) { - ChromeV8Extension* self = GetFromArguments<ChromeV8Extension>(arguments); - ChromeV8Context* context = - self->extension_dispatcher()->v8_context_set().GetCurrent(); - CHECK(context) << "Unknown V8 context. Maybe a native function is getting " - << "called during parse of a v8 extension, before the context " - << "has been registered."; - - ChromeV8ExtensionHandler* handler = self->GetHandler(context); - if (!handler) { - handler = self->CreateHandler(context); - if (handler) - self->handlers_[context] = linked_ptr<ChromeV8ExtensionHandler>(handler); - } - CHECK(handler) << "No handler for v8 extension: " << self->name(); - - std::string name = *v8::String::AsciiValue(arguments.Callee()->GetName()); - return handler->HandleNativeFunction(name, arguments); -} - -ChromeV8ExtensionHandler* ChromeV8Extension::CreateHandler( - ChromeV8Context* context) { - return NULL; -} - -v8::Handle<v8::Value> ChromeV8Extension::GetChromeHidden( - const v8::Arguments& args) { - return ChromeV8Context::GetOrCreateChromeHidden(v8::Context::GetCurrent()); -} - -v8::Handle<v8::Value> ChromeV8Extension::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(); -} diff --git a/chrome/renderer/extensions/chrome_v8_extension.h b/chrome/renderer/extensions/chrome_v8_extension.h index 511273f..7e4b8e8 100644 --- a/chrome/renderer/extensions/chrome_v8_extension.h +++ b/chrome/renderer/extensions/chrome_v8_extension.h @@ -10,6 +10,7 @@ #include "base/memory/linked_ptr.h" #include "base/string_piece.h" #include "chrome/renderer/extensions/chrome_v8_extension_handler.h" +#include "chrome/renderer/native_handler.h" #include "v8/include/v8.h" #include <map> @@ -26,31 +27,17 @@ class RenderView; // This is a base class for chrome extension bindings. Common features that // are shared by different modules go here. -class ChromeV8Extension : public v8::Extension { +// TODO(koz): Rename this to ExtensionNativeModule. +class ChromeV8Extension : public NativeHandler { public: typedef std::set<ChromeV8Extension*> InstanceSet; static const InstanceSet& GetAll(); - ChromeV8Extension(const char* name, - int resource_id, - ExtensionDispatcher* extension_dispatcher); - ChromeV8Extension(const char* name, - int resource_id, - int dependency_count, - const char** dependencies, - ExtensionDispatcher* extension_dispatcher); + explicit ChromeV8Extension(ExtensionDispatcher* extension_dispatcher); virtual ~ChromeV8Extension(); ExtensionDispatcher* extension_dispatcher() { return extension_dispatcher_; } - void ContextWillBeReleased(ChromeV8Context* context); - - // Derived classes should call this at the end of their implementation in - // order to expose common native functions, like GetChromeHidden, to the - // v8 extension. - virtual v8::Handle<v8::FunctionTemplate> - GetNativeFunction(v8::Handle<v8::String> name) OVERRIDE; - protected: template<class T> static T* GetFromArguments(const v8::Arguments& args) { @@ -73,32 +60,12 @@ class ChromeV8Extension : public v8::Extension { bool CheckCurrentContextAccessToExtensionAPI( const std::string& function_name) const; - // Create a handler for |context|. If a subclass of ChromeV8Extension wishes - // to support handlers, it should override this. - virtual ChromeV8ExtensionHandler* CreateHandler(ChromeV8Context* context); - // Returns the chromeHidden object for the current context. static v8::Handle<v8::Value> GetChromeHidden(const v8::Arguments& args); ExtensionDispatcher* extension_dispatcher_; private: - static base::StringPiece GetStringResource(int resource_id); - - // Helper to print from bindings javascript. - static v8::Handle<v8::Value> Print(const v8::Arguments& args); - - // Handle a native function call from JavaScript. - static v8::Handle<v8::Value> HandleNativeFunction(const v8::Arguments& args); - - // Get the handler instance for |context|, or NULL if no such context exists. - ChromeV8ExtensionHandler* GetHandler(ChromeV8Context* context) const; - - // Map of all current handlers. - typedef std::map<ChromeV8Context*, - linked_ptr<ChromeV8ExtensionHandler> > HandlerMap; - HandlerMap handlers_; - DISALLOW_COPY_AND_ASSIGN(ChromeV8Extension); }; diff --git a/chrome/renderer/extensions/chrome_v8_extension_handler.h b/chrome/renderer/extensions/chrome_v8_extension_handler.h index f933fc9..301b9f6 100644 --- a/chrome/renderer/extensions/chrome_v8_extension_handler.h +++ b/chrome/renderer/extensions/chrome_v8_extension_handler.h @@ -15,11 +15,10 @@ class ChromeV8Context; // Base class for context-scoped handlers used with ChromeV8Extension. +// TODO(koz): Rename/refactor this somehow. Maybe just pull it into +// ChromeV8Extension. class ChromeV8ExtensionHandler : public IPC::Channel::Listener { public: - virtual v8::Handle<v8::Value> HandleNativeFunction( - const std::string& name, - const v8::Arguments& arguments) = 0; virtual ~ChromeV8ExtensionHandler(); // IPC::Channel::Listener diff --git a/chrome/renderer/extensions/context_menus_custom_bindings.cc b/chrome/renderer/extensions/context_menus_custom_bindings.cc index bfb6114..db3b3d9 100644 --- a/chrome/renderer/extensions/context_menus_custom_bindings.cc +++ b/chrome/renderer/extensions/context_menus_custom_bindings.cc @@ -7,19 +7,9 @@ #include "grit/renderer_resources.h" #include "v8/include/v8.h" -namespace extensions { +namespace { -ContextMenusCustomBindings::ContextMenusCustomBindings( - int dependency_count, - const char** dependencies) - : ChromeV8Extension( - "extensions/context_menus_custom_bindings.js", - IDR_CONTEXT_MENUS_CUSTOM_BINDINGS_JS, - dependency_count, - dependencies, - NULL) {} - -static v8::Handle<v8::Value> GetNextContextMenuId(const v8::Arguments& args) { +v8::Handle<v8::Value> GetNextContextMenuId(const v8::Arguments& args) { // Note: this works because contextMenus.create() only works in the // extension process. If that API is opened up to content scripts, this // will need to change. See crbug.com/77023 @@ -27,12 +17,13 @@ static v8::Handle<v8::Value> GetNextContextMenuId(const v8::Arguments& args) { return v8::Integer::New(next_context_menu_id++); } -v8::Handle<v8::FunctionTemplate> ContextMenusCustomBindings::GetNativeFunction( - v8::Handle<v8::String> name) { - if (name->Equals(v8::String::New("GetNextContextMenuId"))) - return v8::FunctionTemplate::New(GetNextContextMenuId); +} // namespace + +namespace extensions { - return ChromeV8Extension::GetNativeFunction(name); +ContextMenusCustomBindings::ContextMenusCustomBindings() + : ChromeV8Extension(NULL) { + RouteStaticFunction("GetNextContextMenuId", &GetNextContextMenuId); } } // extensions diff --git a/chrome/renderer/extensions/context_menus_custom_bindings.h b/chrome/renderer/extensions/context_menus_custom_bindings.h index 1b31e50..18d3b38 100644 --- a/chrome/renderer/extensions/context_menus_custom_bindings.h +++ b/chrome/renderer/extensions/context_menus_custom_bindings.h @@ -13,10 +13,7 @@ namespace extensions { // Implements custom bindings for the contextMenus API. class ContextMenusCustomBindings : public ChromeV8Extension { public: - ContextMenusCustomBindings(int dependency_count, const char** dependencies); - - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( - v8::Handle<v8::String> name) OVERRIDE; + ContextMenusCustomBindings(); }; } // extensions diff --git a/chrome/renderer/extensions/custom_bindings_util.cc b/chrome/renderer/extensions/custom_bindings_util.cc index b9dfa84..5de0470b 100644 --- a/chrome/renderer/extensions/custom_bindings_util.cc +++ b/chrome/renderer/extensions/custom_bindings_util.cc @@ -31,83 +31,6 @@ namespace extensions { namespace custom_bindings_util { -std::vector<v8::Extension*> GetAll(ExtensionDispatcher* extension_dispatcher) { - // Must match kResourceIDs. - static const char* kJavascriptFiles[] = { - "extensions/browser_action_custom_bindings.js", - "extensions/content_settings_custom_bindings.js", - "extensions/experimental.declarative_custom_bindings.js", - "extensions/devtools_custom_bindings.js", - "extensions/input.ime_custom_bindings.js", - "extensions/omnibox_custom_bindings.js", - "extensions/page_action_custom_bindings.js", - "extensions/storage_custom_bindings.js", - "extensions/tts_engine_custom_bindings.js", - "extensions/types_custom_bindings.js", - }; - static const size_t kJavascriptFilesSize = arraysize(kJavascriptFiles); - - // Must match kJavascriptFiles. - static const int kResourceIDs[] = { - IDR_BROWSER_ACTION_CUSTOM_BINDINGS_JS, - IDR_CONTENT_SETTINGS_CUSTOM_BINDINGS_JS, - IDR_EXPERIMENTAL_DECLARATIVE_CUSTOM_BINDINGS_JS, - IDR_DEVTOOLS_CUSTOM_BINDINGS_JS, - IDR_INPUT_IME_CUSTOM_BINDINGS_JS, - IDR_OMNIBOX_CUSTOM_BINDINGS_JS, - IDR_PAGE_ACTION_CUSTOM_BINDINGS_JS, - IDR_STORAGE_CUSTOM_BINDINGS_JS, - IDR_TTS_ENGINE_CUSTOM_BINDINGS_JS, - IDR_TYPES_CUSTOM_BINDINGS_JS, - }; - static const size_t kResourceIDsSize = arraysize(kResourceIDs); - - static const char* kDependencies[] = { - "extensions/schema_generated_bindings.js", - }; - static const size_t kDependencyCount = arraysize(kDependencies); - - std::vector<v8::Extension*> result; - - // Custom bindings that have native code parts. - result.push_back(new ChromePrivateCustomBindings( - kDependencyCount, kDependencies, extension_dispatcher)); - result.push_back(new ContextMenusCustomBindings( - kDependencyCount, kDependencies)); - result.push_back(new ExtensionCustomBindings( - kDependencyCount, kDependencies, extension_dispatcher)); - result.push_back(new ExperimentalSocketCustomBindings( - kDependencyCount, kDependencies)); - result.push_back(new FileBrowserHandlerCustomBindings( - kDependencyCount, kDependencies)); - result.push_back(new FileBrowserPrivateCustomBindings( - kDependencyCount, kDependencies)); - result.push_back(new I18NCustomBindings( - kDependencyCount, kDependencies)); - result.push_back(new PageActionsCustomBindings( - kDependencyCount, kDependencies, extension_dispatcher)); - result.push_back(new PageCaptureCustomBindings( - kDependencyCount, kDependencies)); - result.push_back(new TabsCustomBindings( - kDependencyCount, kDependencies)); - result.push_back(new TTSCustomBindings( - kDependencyCount, kDependencies)); - result.push_back(new WebRequestCustomBindings( - kDependencyCount, kDependencies)); - - // Pure JavaScript custom bindings. - CHECK_EQ(kJavascriptFilesSize, kResourceIDsSize); - for (size_t i = 0; i < kJavascriptFilesSize; ++i) { - result.push_back(new ChromeV8Extension( - kJavascriptFiles[i], - kResourceIDs[i], - kDependencyCount, kDependencies, - NULL)); - } - - return result; -} - // Extracts the name of an API from the name of the V8 extension which contains // custom bindings for it (see kCustomBindingNames). std::string GetAPIName(const std::string& v8_extension_name) { diff --git a/chrome/renderer/extensions/custom_bindings_util.h b/chrome/renderer/extensions/custom_bindings_util.h index f4d6fe3..73d026d 100644 --- a/chrome/renderer/extensions/custom_bindings_util.h +++ b/chrome/renderer/extensions/custom_bindings_util.h @@ -24,9 +24,6 @@ namespace extensions { // bindings. namespace custom_bindings_util { -// Creates V8 extensions for all custom bindings. -std::vector<v8::Extension*> GetAll(ExtensionDispatcher* extension_dispatcher); - // Extracts the name of an API from the name of the V8 extension which contains // custom bindings for it. // Returns an empty string if the extension is not for a custom binding. diff --git a/chrome/renderer/extensions/event_bindings.cc b/chrome/renderer/extensions/event_bindings.cc index 9bab21a..f187f27 100644 --- a/chrome/renderer/extensions/event_bindings.cc +++ b/chrome/renderer/extensions/event_bindings.cc @@ -39,25 +39,26 @@ using content::RenderThread; namespace { +// A map of event names to the number of contexts listening to that event. +// We notify the browser about event listeners when we transition between 0 +// and 1. +typedef std::map<std::string, int> EventListenerCounts; + +// A map of extension IDs to listener counts for that extension. +base::LazyInstance<std::map<std::string, EventListenerCounts> > + g_listener_counts = LAZY_INSTANCE_INITIALIZER; + +// TODO(koz): Merge this into EventBindings. class ExtensionImpl : public ChromeV8Extension { public: + explicit ExtensionImpl(ExtensionDispatcher* dispatcher) - : ChromeV8Extension("extensions/event.js", - IDR_EVENT_BINDINGS_JS, - dispatcher) { + : ChromeV8Extension(dispatcher) { + RouteStaticFunction("AttachEvent", &AttachEvent); + RouteStaticFunction("DetachEvent", &DetachEvent); } ~ExtensionImpl() {} - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( - v8::Handle<v8::String> name) { - if (name->Equals(v8::String::New("AttachEvent"))) { - return v8::FunctionTemplate::New(AttachEvent, v8::External::New(this)); - } else if (name->Equals(v8::String::New("DetachEvent"))) { - return v8::FunctionTemplate::New(DetachEvent, v8::External::New(this)); - } - return ChromeV8Extension::GetNativeFunction(name); - } - // Attach an event name to an object. static v8::Handle<v8::Value> AttachEvent(const v8::Arguments& args) { DCHECK(args.Length() == 1); @@ -76,7 +77,7 @@ class ExtensionImpl : public ChromeV8Extension { return v8::Undefined(); EventListenerCounts& listener_counts = - self->listener_counts_[context->extension_id()]; + g_listener_counts.Get()[context->extension_id()]; if (++listener_counts[event_name] == 1) { content::RenderThread::Get()->Send( new ExtensionHostMsg_AddListener(context->extension_id(), @@ -110,7 +111,7 @@ class ExtensionImpl : public ChromeV8Extension { return v8::Undefined(); EventListenerCounts& listener_counts = - self->listener_counts_[context->extension_id()]; + g_listener_counts.Get()[context->extension_id()]; std::string event_name(*v8::String::AsciiValue(args[0])); bool is_manual = args[1]->BooleanValue(); @@ -135,10 +136,6 @@ class ExtensionImpl : public ChromeV8Extension { } private: - // A map of event names to the number of contexts listening to that event. - // We notify the browser about event listeners when we transition between 0 - // and 1. - typedef std::map<std::string, int> EventListenerCounts; bool IsLazyBackgroundPage(const std::string& extension_id) { content::RenderView* render_view = GetCurrentRenderView(); @@ -151,14 +148,10 @@ class ExtensionImpl : public ChromeV8Extension { return (extension && !extension->background_page_persists() && helper->view_type() == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); } - - // A map of extension IDs to listener counts for that extension. - std::map<std::string, EventListenerCounts> listener_counts_; }; } // namespace -v8::Extension* EventBindings::Get(ExtensionDispatcher* dispatcher) { - static v8::Extension* extension = new ExtensionImpl(dispatcher); - return extension; +ChromeV8Extension* EventBindings::Get(ExtensionDispatcher* dispatcher) { + return new ExtensionImpl(dispatcher); } diff --git a/chrome/renderer/extensions/event_bindings.h b/chrome/renderer/extensions/event_bindings.h index 64ada22..baa2004 100644 --- a/chrome/renderer/extensions/event_bindings.h +++ b/chrome/renderer/extensions/event_bindings.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,6 +6,7 @@ #define CHROME_RENDERER_EXTENSIONS_EVENT_BINDINGS_H_ #pragma once +class ChromeV8Extension; class ExtensionDispatcher; namespace v8 { @@ -15,7 +16,7 @@ class Extension; // This class deals with the javascript bindings related to Event objects. class EventBindings { public: - static v8::Extension* Get(ExtensionDispatcher* dispatcher); + static ChromeV8Extension* Get(ExtensionDispatcher* dispatcher); }; #endif // CHROME_RENDERER_EXTENSIONS_EVENT_BINDINGS_H_ diff --git a/chrome/renderer/extensions/experimental.socket_custom_bindings.cc b/chrome/renderer/extensions/experimental.socket_custom_bindings.cc index 11d34bb..8dd096b 100644 --- a/chrome/renderer/extensions/experimental.socket_custom_bindings.cc +++ b/chrome/renderer/extensions/experimental.socket_custom_bindings.cc @@ -11,32 +11,22 @@ #include "grit/renderer_resources.h" #include "v8/include/v8.h" -namespace extensions { +namespace { -ExperimentalSocketCustomBindings::ExperimentalSocketCustomBindings( - int dependency_count, - const char** dependencies) - : ChromeV8Extension( - "extensions/experimental.socket_custom_bindings.js", - IDR_EXPERIMENTAL_SOCKET_CUSTOM_BINDINGS_JS, - dependency_count, - dependencies, - NULL) {} - -static v8::Handle<v8::Value> GetNextSocketEventId(const v8::Arguments& args) { +v8::Handle<v8::Value> GetNextSocketEventId(const v8::Arguments& args) { // Note: this works because the socket API only works in the extension // process, not content scripts. static int next_event_id = 1; return v8::Integer::New(next_event_id++); } -v8::Handle<v8::FunctionTemplate> -ExperimentalSocketCustomBindings::GetNativeFunction( - v8::Handle<v8::String> name) { - if (name->Equals(v8::String::New("GetNextSocketEventId"))) - return v8::FunctionTemplate::New(GetNextSocketEventId); +} // namespace + +namespace extensions { - return ChromeV8Extension::GetNativeFunction(name); +ExperimentalSocketCustomBindings::ExperimentalSocketCustomBindings() + : ChromeV8Extension(NULL) { + RouteStaticFunction("GetNextSocketEventId", &GetNextSocketEventId); } } // extensions diff --git a/chrome/renderer/extensions/experimental.socket_custom_bindings.h b/chrome/renderer/extensions/experimental.socket_custom_bindings.h index a444fa1..32a7f7d 100644 --- a/chrome/renderer/extensions/experimental.socket_custom_bindings.h +++ b/chrome/renderer/extensions/experimental.socket_custom_bindings.h @@ -13,11 +13,7 @@ namespace extensions { // Implements custom bindings for the experimental.socket API. class ExperimentalSocketCustomBindings : public ChromeV8Extension { public: - ExperimentalSocketCustomBindings( - int dependency_count, const char** dependencies); - - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( - v8::Handle<v8::String> name) OVERRIDE; + ExperimentalSocketCustomBindings(); }; } // extensions diff --git a/chrome/renderer/extensions/extension_custom_bindings.cc b/chrome/renderer/extensions/extension_custom_bindings.cc index 6c9947c..c4895cd 100644 --- a/chrome/renderer/extensions/extension_custom_bindings.cc +++ b/chrome/renderer/extensions/extension_custom_bindings.cc @@ -111,15 +111,11 @@ class ExtensionViewAccumulator : public content::RenderViewVisitor { } // namespace ExtensionCustomBindings::ExtensionCustomBindings( - int dependency_count, - const char** dependencies, ExtensionDispatcher* extension_dispatcher) - : ChromeV8Extension( - "extensions/extension_custom_bindings.js", - IDR_EXTENSION_CUSTOM_BINDINGS_JS, - dependency_count, - dependencies, - extension_dispatcher) {} + : ChromeV8Extension(extension_dispatcher) { + RouteStaticFunction("GetExtensionViews", &GetExtensionViews); + RouteStaticFunction("OpenChannelToExtension", &OpenChannelToExtension); +} // static v8::Handle<v8::Value> ExtensionCustomBindings::GetExtensionViews( @@ -172,18 +168,6 @@ v8::Handle<v8::Value> ExtensionCustomBindings::GetExtensionViews( return accumulator.views(); } -v8::Handle<v8::FunctionTemplate> ExtensionCustomBindings::GetNativeFunction( - v8::Handle<v8::String> name) { - if (name->Equals(v8::String::New("GetExtensionViews"))) { - return v8::FunctionTemplate::New(GetExtensionViews, - v8::External::New(this)); - } else if (name->Equals(v8::String::New("OpenChannelToExtension"))) { - return v8::FunctionTemplate::New(OpenChannelToExtension); - } - - return ChromeV8Extension::GetNativeFunction(name); -} - // static v8::Handle<v8::Value> ExtensionCustomBindings::OpenChannelToExtension( const v8::Arguments& args) { diff --git a/chrome/renderer/extensions/extension_custom_bindings.h b/chrome/renderer/extensions/extension_custom_bindings.h index d8ac77c..59cf77a 100644 --- a/chrome/renderer/extensions/extension_custom_bindings.h +++ b/chrome/renderer/extensions/extension_custom_bindings.h @@ -15,13 +15,7 @@ namespace extensions { // Implements custom bindings for the extension API. class ExtensionCustomBindings : public ChromeV8Extension { public: - ExtensionCustomBindings( - int dependency_count, - const char** dependencies, - ExtensionDispatcher* extension_dispatcher); - - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( - v8::Handle<v8::String> name) OVERRIDE; + explicit ExtensionCustomBindings(ExtensionDispatcher* extension_dispatcher); private: static v8::Handle<v8::Value> GetExtensionViews(const v8::Arguments& args); diff --git a/chrome/renderer/extensions/extension_dispatcher.cc b/chrome/renderer/extensions/extension_dispatcher.cc index 23c57e4..cd1834c 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" @@ -35,9 +41,34 @@ #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" + using content::RenderThread; +using extensions::ChromePrivateCustomBindings; +using extensions::ContextMenusCustomBindings; +using extensions::ExperimentalSocketCustomBindings; +using extensions::ExtensionCustomBindings; +using extensions::FileBrowserHandlerCustomBindings; +using extensions::FileBrowserPrivateCustomBindings; +using extensions::I18NCustomBindings; using extensions::MiscellaneousBindings; +using extensions::PageActionsCustomBindings; +using extensions::PageCaptureCustomBindings; using extensions::SchemaGeneratedBindings; +using extensions::TTSCustomBindings; +using extensions::TabsCustomBindings; +using extensions::WebRequestCustomBindings; using WebKit::WebDataSource; using WebKit::WebDocument; using WebKit::WebFrame; @@ -60,13 +91,83 @@ ChromeV8Context::ContextType ExtensionGroupToContextType(int extension_group) { 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_; +}; + } 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) || @@ -78,6 +179,7 @@ ExtensionDispatcher::ExtensionDispatcher() } user_script_slave_.reset(new UserScriptSlave(&extensions_)); + PopulateSourceMap(); } ExtensionDispatcher::~ExtensionDispatcher() { @@ -115,24 +217,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 = 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(); @@ -300,53 +384,121 @@ 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; - - // 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; - - // If the V8 extension is not restricted, allow it to run anywhere. - if (!restricted_v8_extensions_.count(v8_extension_name)) - return true; - - // Extension-only bindings should be restricted to content scripts and - // extension-blessed URLs. - ChromeV8Context::ContextType context_type = - ExtensionGroupToContextType(extension_group); - - 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 = 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 util::AllowAPIInjection(custom_binding_api_name, *extension, this); - } - +bool ExtensionDispatcher::AllowCustomAPI( + WebFrame* frame, + const std::string& custom_binding_api_name, + int world_id) { + std::string extension_id = GetExtensionID(frame, world_id); + if (IsTestExtensionId(extension_id)) 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 false; + return 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))); + + // 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); } void ExtensionDispatcher::DidCreateScriptContext( @@ -355,19 +507,49 @@ void ExtensionDispatcher::DidCreateScriptContext( // 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, - GetExtensionID(frame, world_id), + extension_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(), @@ -398,12 +580,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(); } @@ -413,7 +589,7 @@ void ExtensionDispatcher::SetTestExtensionId(const std::string& id) { } bool ExtensionDispatcher::IsTestExtensionId(const std::string& id) { - return id == test_extension_id_; + return !test_extension_id_.empty() && id == test_extension_id_; } void ExtensionDispatcher::OnActivateApplication( diff --git a/chrome/renderer/extensions/extension_dispatcher.h b/chrome/renderer/extensions/extension_dispatcher.h index e72c269..b1dfb40 100644 --- a/chrome/renderer/extensions/extension_dispatcher.h +++ b/chrome/renderer/extensions/extension_dispatcher.h @@ -15,8 +15,10 @@ #include "content/public/renderer/render_process_observer.h" #include "chrome/common/extensions/extension_set.h" #include "chrome/renderer/extensions/chrome_v8_context_set.h" +#include "chrome/renderer/resource_bundle_source_map.h" #include "v8/include/v8.h" +class ModuleSystem; class GURL; class URLPattern; class UserScriptSlave; @@ -55,12 +57,18 @@ class ExtensionDispatcher : public content::RenderProcessObserver { bool IsApplicationActive(const std::string& extension_id) const; bool IsExtensionActive(const std::string& extension_id) const; + // Whether or not we should set up custom bindings for this api. + bool AllowCustomAPI(WebKit::WebFrame* frame, + const std::string& custom_binding_api_name, + int world_id); + // See WebKit::WebPermissionClient::allowScriptExtension // TODO(koz): Remove once WebKit no longer calls this. bool AllowScriptExtension(WebKit::WebFrame* frame, const std::string& v8_extension_name, int extension_group); + // TODO(koz): Remove once WebKit no longer calls this. bool AllowScriptExtension(WebKit::WebFrame* frame, const std::string& v8_extension_name, int extension_group, @@ -137,6 +145,12 @@ class ExtensionDispatcher : public content::RenderProcessObserver { const Extension* extension, const URLPatternSet& origins); + void RegisterNativeHandlers(ModuleSystem* module_system, + ChromeV8Context* context); + + // Inserts static source code into |source_map_|. + void PopulateSourceMap(); + // Finds the extension ID for the current context. This is determined from // |world_id| if it's non-zero, or the URL in |frame| if it is. std::string GetExtensionID(WebKit::WebFrame* frame, int world_id); @@ -182,6 +196,8 @@ class ExtensionDispatcher : public content::RenderProcessObserver { bool webrequest_adblock_plus_; bool webrequest_other_; + ResourceBundleSourceMap source_map_; + DISALLOW_COPY_AND_ASSIGN(ExtensionDispatcher); }; diff --git a/chrome/renderer/extensions/file_browser_handler_custom_bindings.cc b/chrome/renderer/extensions/file_browser_handler_custom_bindings.cc index 0688839..015d0b5 100644 --- a/chrome/renderer/extensions/file_browser_handler_custom_bindings.cc +++ b/chrome/renderer/extensions/file_browser_handler_custom_bindings.cc @@ -13,18 +13,9 @@ #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" -namespace extensions { - -FileBrowserHandlerCustomBindings::FileBrowserHandlerCustomBindings( - int dependency_count, - const char** dependencies) - : ChromeV8Extension("extensions/file_browser_handler_custom_bindings.js", - IDR_FILE_BROWSER_HANDLER_CUSTOM_BINDINGS_JS, - dependency_count, - dependencies, - NULL) {} +namespace { -static v8::Handle<v8::Value> GetExternalFileEntry(const v8::Arguments& args) { +v8::Handle<v8::Value> GetExternalFileEntry(const v8::Arguments& args) { // TODO(zelidrag): Make this magic work on other platforms when file browser // matures enough on ChromeOS. #if defined(OS_CHROMEOS) @@ -54,13 +45,14 @@ static v8::Handle<v8::Value> GetExternalFileEntry(const v8::Arguments& args) { #endif } -v8::Handle<v8::FunctionTemplate> -FileBrowserHandlerCustomBindings::GetNativeFunction( - v8::Handle<v8::String> name) { - if (name->Equals(v8::String::New("GetExternalFileEntry"))) - return v8::FunctionTemplate::New(GetExternalFileEntry); - else - return ChromeV8Extension::GetNativeFunction(name); +} // namespace + +namespace extensions { + +FileBrowserHandlerCustomBindings::FileBrowserHandlerCustomBindings() + : ChromeV8Extension(NULL) { + RouteStaticFunction("GetExternalFileEntry", &GetExternalFileEntry); } + } // namespace extensions diff --git a/chrome/renderer/extensions/file_browser_handler_custom_bindings.h b/chrome/renderer/extensions/file_browser_handler_custom_bindings.h index 23ec5a8..354686b 100644 --- a/chrome/renderer/extensions/file_browser_handler_custom_bindings.h +++ b/chrome/renderer/extensions/file_browser_handler_custom_bindings.h @@ -14,13 +14,9 @@ namespace extensions { // Custom bindings for the fileBrowserHandler API. class FileBrowserHandlerCustomBindings : public ChromeV8Extension { public: - FileBrowserHandlerCustomBindings( - int dependency_count, const char** dependencies); + FileBrowserHandlerCustomBindings(); private: - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( - v8::Handle<v8::String> name) OVERRIDE; - DISALLOW_COPY_AND_ASSIGN(FileBrowserHandlerCustomBindings); }; diff --git a/chrome/renderer/extensions/file_browser_private_custom_bindings.cc b/chrome/renderer/extensions/file_browser_private_custom_bindings.cc index a36e606..1731552 100644 --- a/chrome/renderer/extensions/file_browser_private_custom_bindings.cc +++ b/chrome/renderer/extensions/file_browser_private_custom_bindings.cc @@ -13,16 +13,7 @@ #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" -namespace extensions { - -FileBrowserPrivateCustomBindings::FileBrowserPrivateCustomBindings( - int dependency_count, - const char** dependencies) - : ChromeV8Extension("extensions/file_browser_private_custom_bindings.js", - IDR_FILE_BROWSER_PRIVATE_CUSTOM_BINDINGS_JS, - dependency_count, - dependencies, - NULL) {} +namespace { static v8::Handle<v8::Value> GetLocalFileSystem( const v8::Arguments& args) { @@ -40,13 +31,13 @@ static v8::Handle<v8::Value> GetLocalFileSystem( WebKit::WebString::fromUTF8(path.c_str())); } -v8::Handle<v8::FunctionTemplate> -FileBrowserPrivateCustomBindings::GetNativeFunction( - v8::Handle<v8::String> name) { - if (name->Equals(v8::String::New("GetLocalFileSystem"))) - return v8::FunctionTemplate::New(GetLocalFileSystem); +} // namespace + +namespace extensions { - return ChromeV8Extension::GetNativeFunction(name); +FileBrowserPrivateCustomBindings::FileBrowserPrivateCustomBindings() + : ChromeV8Extension(NULL) { + RouteStaticFunction("GetLocalFileSystem", &GetLocalFileSystem); } } // namespace extensions diff --git a/chrome/renderer/extensions/file_browser_private_custom_bindings.h b/chrome/renderer/extensions/file_browser_private_custom_bindings.h index d987a06..191c0dd 100644 --- a/chrome/renderer/extensions/file_browser_private_custom_bindings.h +++ b/chrome/renderer/extensions/file_browser_private_custom_bindings.h @@ -14,13 +14,9 @@ namespace extensions { // Custom bindings for the fileBrowserPrivate API. class FileBrowserPrivateCustomBindings : public ChromeV8Extension { public: - FileBrowserPrivateCustomBindings( - int dependency_count, const char** dependencies); + FileBrowserPrivateCustomBindings(); private: - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( - v8::Handle<v8::String> name) OVERRIDE; - DISALLOW_COPY_AND_ASSIGN(FileBrowserPrivateCustomBindings); }; diff --git a/chrome/renderer/extensions/i18n_custom_bindings.cc b/chrome/renderer/extensions/i18n_custom_bindings.cc index 982acbf..afd4be7 100644 --- a/chrome/renderer/extensions/i18n_custom_bindings.cc +++ b/chrome/renderer/extensions/i18n_custom_bindings.cc @@ -12,21 +12,9 @@ namespace extensions { -I18NCustomBindings::I18NCustomBindings( - int dependency_count, const char** dependencies) - : ChromeV8Extension( - "extensions/i18n_custom_bindings.js", - IDR_I18N_CUSTOM_BINDINGS_JS, - dependency_count, - dependencies, - NULL) {} - -v8::Handle<v8::FunctionTemplate> I18NCustomBindings::GetNativeFunction( - v8::Handle<v8::String> name) { - if (name->Equals(v8::String::New("GetL10nMessage"))) - return v8::FunctionTemplate::New(GetL10nMessage); - - return ChromeV8Extension::GetNativeFunction(name); +I18NCustomBindings::I18NCustomBindings() + : ChromeV8Extension(NULL) { + RouteStaticFunction("GetL10nMessage", &GetL10nMessage); } // static diff --git a/chrome/renderer/extensions/i18n_custom_bindings.h b/chrome/renderer/extensions/i18n_custom_bindings.h index 1cc8743..e0ca0df 100644 --- a/chrome/renderer/extensions/i18n_custom_bindings.h +++ b/chrome/renderer/extensions/i18n_custom_bindings.h @@ -13,10 +13,7 @@ namespace extensions { // Implements custom bindings for the i18n API. class I18NCustomBindings : public ChromeV8Extension { public: - I18NCustomBindings(int dependency_count, const char** dependencies); - - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( - v8::Handle<v8::String> name) OVERRIDE; + I18NCustomBindings(); private: static v8::Handle<v8::Value> GetL10nMessage(const v8::Arguments& args); diff --git a/chrome/renderer/extensions/json_schema_unittest.cc b/chrome/renderer/extensions/json_schema_unittest.cc index 1e76b41..c4b0614 100644 --- a/chrome/renderer/extensions/json_schema_unittest.cc +++ b/chrome/renderer/extensions/json_schema_unittest.cc @@ -25,15 +25,14 @@ class JsonSchemaTest : public V8UnitTest { std::string code = ResourceBundle::GetSharedInstance().GetRawDataResource( IDR_JSON_SCHEMA_JS).as_string(); - // This is a nasty hack, but it is easier to test the code if we don't use - // it as a v8 extension. So replace the only bit that relies on that with a - // more easily testable implementation. - ReplaceFirstSubstringAfterOffset(&code, 0, - "native function GetChromeHidden();", - "function GetChromeHidden() {\n" - " if (!this.chromeHidden) this.chromeHidden = {};\n" - " return this.chromeHidden;\n" - "}"); + // json_schema.js expects to have requireNative() defined. + ExecuteScriptInContext( + "function requireNative(id) {" + " return {" + " GetChromeHidden: function() { return {}; }," + " };" + "}", + "test-code"); ExecuteScriptInContext(code, kJsonSchema); // Add the test functions to the context. diff --git a/chrome/renderer/extensions/miscellaneous_bindings.cc b/chrome/renderer/extensions/miscellaneous_bindings.cc index 31a8923..25fc895 100644 --- a/chrome/renderer/extensions/miscellaneous_bindings.cc +++ b/chrome/renderer/extensions/miscellaneous_bindings.cc @@ -62,31 +62,18 @@ static void ClearPortData(int port_id) { } const char kPortClosedError[] = "Attempting to use a disconnected port object"; -const char* kExtensionDeps[] = { "extensions/event.js" }; class ExtensionImpl : public ChromeV8Extension { public: explicit ExtensionImpl(ExtensionDispatcher* dispatcher) - : ChromeV8Extension("extensions/miscellaneous_bindings.js", - IDR_MISCELLANEOUS_BINDINGS_JS, - arraysize(kExtensionDeps), kExtensionDeps, - dispatcher) { + : ChromeV8Extension(dispatcher) { + RouteStaticFunction("CloseChannel", &CloseChannel); + RouteStaticFunction("PortAddRef", &PortAddRef); + RouteStaticFunction("PortRelease", &PortRelease); + RouteStaticFunction("PostMessage", &PostMessage); } - ~ExtensionImpl() {} - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( - v8::Handle<v8::String> name) { - if (name->Equals(v8::String::New("PostMessage"))) { - return v8::FunctionTemplate::New(PostMessage); - } else if (name->Equals(v8::String::New("CloseChannel"))) { - return v8::FunctionTemplate::New(CloseChannel); - } else if (name->Equals(v8::String::New("PortAddRef"))) { - return v8::FunctionTemplate::New(PortAddRef); - } else if (name->Equals(v8::String::New("PortRelease"))) { - return v8::FunctionTemplate::New(PortRelease); - } - return ChromeV8Extension::GetNativeFunction(name); - } + ~ExtensionImpl() {} // Sends a message along the given channel. static v8::Handle<v8::Value> PostMessage(const v8::Arguments& args) { @@ -155,9 +142,8 @@ class ExtensionImpl : public ChromeV8Extension { namespace extensions { -v8::Extension* MiscellaneousBindings::Get(ExtensionDispatcher* dispatcher) { - static v8::Extension* extension = new ExtensionImpl(dispatcher); - return extension; +ChromeV8Extension* MiscellaneousBindings::Get(ExtensionDispatcher* dispatcher) { + return new ExtensionImpl(dispatcher); } void MiscellaneousBindings::DeliverMessage( diff --git a/chrome/renderer/extensions/miscellaneous_bindings.h b/chrome/renderer/extensions/miscellaneous_bindings.h index 1db641b..0df26fa 100644 --- a/chrome/renderer/extensions/miscellaneous_bindings.h +++ b/chrome/renderer/extensions/miscellaneous_bindings.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -10,6 +10,7 @@ #include "chrome/renderer/extensions/chrome_v8_context_set.h" +class ChromeV8Extension; class ExtensionDispatcher; namespace content { @@ -30,7 +31,7 @@ namespace extensions { class MiscellaneousBindings { public: // Creates an instance of the extension. - static v8::Extension* Get(ExtensionDispatcher* dispatcher); + static ChromeV8Extension* Get(ExtensionDispatcher* dispatcher); // Delivers a message sent using content script messaging to some of the // contexts in |bindings_context_set|. If |restrict_to_render_view| is diff --git a/chrome/renderer/extensions/page_actions_custom_bindings.cc b/chrome/renderer/extensions/page_actions_custom_bindings.cc index 0d9d61a..b6e86ee 100644 --- a/chrome/renderer/extensions/page_actions_custom_bindings.cc +++ b/chrome/renderer/extensions/page_actions_custom_bindings.cc @@ -14,15 +14,10 @@ namespace extensions { PageActionsCustomBindings::PageActionsCustomBindings( - int dependency_count, - const char** dependencies, ExtensionDispatcher* extension_dispatcher) - : ChromeV8Extension( - "extensions/page_actions_custom_bindings.js", - IDR_PAGE_ACTIONS_CUSTOM_BINDINGS_JS, - dependency_count, - dependencies, - extension_dispatcher) {} + : ChromeV8Extension(extension_dispatcher) { + RouteStaticFunction("GetCurrentPageActions", &GetCurrentPageActions); +} // static v8::Handle<v8::Value> PageActionsCustomBindings::GetCurrentPageActions( @@ -45,15 +40,4 @@ v8::Handle<v8::Value> PageActionsCustomBindings::GetCurrentPageActions( return page_action_vector; } - -v8::Handle<v8::FunctionTemplate> PageActionsCustomBindings::GetNativeFunction( - v8::Handle<v8::String> name) { - if (name->Equals(v8::String::New("GetCurrentPageActions"))) { - return v8::FunctionTemplate::New(GetCurrentPageActions, - v8::External::New(this)); - } - - return ChromeV8Extension::GetNativeFunction(name); -} - } // extensions diff --git a/chrome/renderer/extensions/page_actions_custom_bindings.h b/chrome/renderer/extensions/page_actions_custom_bindings.h index 09e68d9..1faad35 100644 --- a/chrome/renderer/extensions/page_actions_custom_bindings.h +++ b/chrome/renderer/extensions/page_actions_custom_bindings.h @@ -15,13 +15,7 @@ namespace extensions { // Implements custom bindings for the pageActions API. class PageActionsCustomBindings : public ChromeV8Extension { public: - PageActionsCustomBindings( - int dependency_count, - const char** dependencies, - ExtensionDispatcher* extension_dispatcher); - - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( - v8::Handle<v8::String> name) OVERRIDE; + explicit PageActionsCustomBindings(ExtensionDispatcher* extension_dispatcher); private: static v8::Handle<v8::Value> GetCurrentPageActions(const v8::Arguments& args); diff --git a/chrome/renderer/extensions/page_capture_custom_bindings.cc b/chrome/renderer/extensions/page_capture_custom_bindings.cc index e37cdab..c7e41ea 100644 --- a/chrome/renderer/extensions/page_capture_custom_bindings.cc +++ b/chrome/renderer/extensions/page_capture_custom_bindings.cc @@ -13,18 +13,15 @@ namespace extensions { -PageCaptureCustomBindings::PageCaptureCustomBindings( - int dependency_count, - const char** dependencies) - : ChromeV8Extension( - "extensions/page_capture_custom_bindings.js", - IDR_PAGE_CAPTURE_CUSTOM_BINDINGS_JS, - dependency_count, - dependencies, - NULL) {} - -// Creates a Blob with the content of the specified file. -static v8::Handle<v8::Value> CreateBlob(const v8::Arguments& args) { +PageCaptureCustomBindings::PageCaptureCustomBindings() + : ChromeV8Extension(NULL) { + RouteStaticFunction("CreateBlob", &CreateBlob); + RouteStaticFunction("SendResponseAck", &SendResponseAck); +} + +// static +v8::Handle<v8::Value> PageCaptureCustomBindings::CreateBlob( + const v8::Arguments& args) { CHECK(args.Length() == 2); CHECK(args[0]->IsString()); CHECK(args[1]->IsInt32()); @@ -48,15 +45,4 @@ v8::Handle<v8::Value> PageCaptureCustomBindings::SendResponseAck( return v8::Undefined(); } -v8::Handle<v8::FunctionTemplate> PageCaptureCustomBindings::GetNativeFunction( - v8::Handle<v8::String> name) { - if (name->Equals(v8::String::New("CreateBlob"))) { - return v8::FunctionTemplate::New(CreateBlob, v8::External::New(this)); - } else if (name->Equals(v8::String::New("SendResponseAck"))) { - return v8::FunctionTemplate::New(SendResponseAck, v8::External::New(this)); - } - - return ChromeV8Extension::GetNativeFunction(name); -} - } // namespace extensions diff --git a/chrome/renderer/extensions/page_capture_custom_bindings.h b/chrome/renderer/extensions/page_capture_custom_bindings.h index a6ec433..4796e13 100644 --- a/chrome/renderer/extensions/page_capture_custom_bindings.h +++ b/chrome/renderer/extensions/page_capture_custom_bindings.h @@ -13,12 +13,11 @@ namespace extensions { // Implements custom bindings for the pageCapture API. class PageCaptureCustomBindings : public ChromeV8Extension { public: - PageCaptureCustomBindings(int dependency_count, const char** dependencies); - - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( - v8::Handle<v8::String> name) OVERRIDE; + PageCaptureCustomBindings(); private: + // Creates a Blob with the content of the specified file. + static v8::Handle<v8::Value> CreateBlob(const v8::Arguments& args); static v8::Handle<v8::Value> SendResponseAck(const v8::Arguments& args); }; diff --git a/chrome/renderer/extensions/schema_generated_bindings.cc b/chrome/renderer/extensions/schema_generated_bindings.cc index c0e0725..eda15d8 100644 --- a/chrome/renderer/extensions/schema_generated_bindings.cc +++ b/chrome/renderer/extensions/schema_generated_bindings.cc @@ -51,13 +51,6 @@ using WebKit::WebSecurityOrigin; namespace { -const char* kExtensionDeps[] = { - "extensions/event.js", - "extensions/json_schema.js", - "extensions/miscellaneous_bindings.js", - "extensions/apitest.js" -}; - // Contains info relevant to a pending API request. struct PendingRequest { public : @@ -77,11 +70,12 @@ base::LazyInstance<PendingRequestMap> g_pending_requests = class ExtensionImpl : public ChromeV8Extension { public: explicit ExtensionImpl(ExtensionDispatcher* extension_dispatcher) - : ChromeV8Extension("extensions/schema_generated_bindings.js", - IDR_SCHEMA_GENERATED_BINDINGS_JS, - arraysize(kExtensionDeps), - kExtensionDeps, - extension_dispatcher) { + : ChromeV8Extension(extension_dispatcher) { + RouteStaticFunction("GetExtensionAPIDefinition", + &GetExtensionAPIDefinition); + RouteStaticFunction("GetNextRequestId", &GetNextRequestId); + RouteStaticFunction("StartRequest", &StartRequest); + RouteStaticFunction("SetIconCommon", &SetIconCommon); } ~ExtensionImpl() { @@ -94,24 +88,6 @@ class ExtensionImpl : public ChromeV8Extension { } } - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( - v8::Handle<v8::String> name) OVERRIDE { - if (name->Equals(v8::String::New("GetExtensionAPIDefinition"))) { - return v8::FunctionTemplate::New(GetExtensionAPIDefinition, - v8::External::New(this)); - } else if (name->Equals(v8::String::New("GetNextRequestId"))) { - return v8::FunctionTemplate::New(GetNextRequestId); - } else if (name->Equals(v8::String::New("StartRequest"))) { - return v8::FunctionTemplate::New(StartRequest, - v8::External::New(this)); - } else if (name->Equals(v8::String::New("SetIconCommon"))) { - return v8::FunctionTemplate::New(SetIconCommon, - v8::External::New(this)); - } - - return ChromeV8Extension::GetNativeFunction(name); - } - private: static v8::Handle<v8::Value> GetV8SchemaForAPI( ExtensionImpl* self, @@ -347,12 +323,9 @@ class ExtensionImpl : public ChromeV8Extension { namespace extensions { -v8::Extension* SchemaGeneratedBindings::Get( +ChromeV8Extension* SchemaGeneratedBindings::Get( ExtensionDispatcher* extension_dispatcher) { - static v8::Extension* extension = new ExtensionImpl(extension_dispatcher); - CHECK_EQ(extension_dispatcher, - static_cast<ExtensionImpl*>(extension)->extension_dispatcher()); - return extension; + return new ExtensionImpl(extension_dispatcher); } // static diff --git a/chrome/renderer/extensions/schema_generated_bindings.h b/chrome/renderer/extensions/schema_generated_bindings.h index 1785171..e50ed96 100644 --- a/chrome/renderer/extensions/schema_generated_bindings.h +++ b/chrome/renderer/extensions/schema_generated_bindings.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -10,6 +10,7 @@ class ExtensionDispatcher; class ChromeV8ContextSet; +class ChromeV8Extension; namespace v8 { class Extension; @@ -21,7 +22,7 @@ namespace extensions { // declarations in chrome/common/extensions/api/. class SchemaGeneratedBindings { public: - static v8::Extension* Get(ExtensionDispatcher* extension_dispatcher); + static ChromeV8Extension* Get(ExtensionDispatcher* extension_dispatcher); // Handles a response to an API request. Sets |extension_id|. static void HandleResponse(const ChromeV8ContextSet& contexts, diff --git a/chrome/renderer/extensions/tabs_custom_bindings.cc b/chrome/renderer/extensions/tabs_custom_bindings.cc index abb2262..3d908bb 100644 --- a/chrome/renderer/extensions/tabs_custom_bindings.cc +++ b/chrome/renderer/extensions/tabs_custom_bindings.cc @@ -15,14 +15,10 @@ namespace extensions { -TabsCustomBindings::TabsCustomBindings( - int dependency_count, const char** dependencies) - : ChromeV8Extension( - "extensions/tabs_custom_bindings.js", - IDR_TABS_CUSTOM_BINDINGS_JS, - dependency_count, - dependencies, - NULL) {} +TabsCustomBindings::TabsCustomBindings() + : ChromeV8Extension(NULL) { + RouteStaticFunction("OpenChannelToTab", &OpenChannelToTab); +} // static v8::Handle<v8::Value> TabsCustomBindings::OpenChannelToTab( @@ -47,12 +43,4 @@ v8::Handle<v8::Value> TabsCustomBindings::OpenChannelToTab( return v8::Undefined(); } -v8::Handle<v8::FunctionTemplate> TabsCustomBindings::GetNativeFunction( - v8::Handle<v8::String> name) { - if (name->Equals(v8::String::New("OpenChannelToTab"))) - return v8::FunctionTemplate::New(OpenChannelToTab); - - return ChromeV8Extension::GetNativeFunction(name); -} - } // extensions diff --git a/chrome/renderer/extensions/tabs_custom_bindings.h b/chrome/renderer/extensions/tabs_custom_bindings.h index 0700a43..ec06979 100644 --- a/chrome/renderer/extensions/tabs_custom_bindings.h +++ b/chrome/renderer/extensions/tabs_custom_bindings.h @@ -13,10 +13,7 @@ namespace extensions { // Implements custom bindings for the tabs API. class TabsCustomBindings : public ChromeV8Extension { public: - TabsCustomBindings(int dependency_count, const char** dependencies); - - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( - v8::Handle<v8::String> name) OVERRIDE; + TabsCustomBindings(); private: // Creates a new messaging channel to the tab with the given ID. diff --git a/chrome/renderer/extensions/tts_custom_bindings.cc b/chrome/renderer/extensions/tts_custom_bindings.cc index dca526a..33e1887 100644 --- a/chrome/renderer/extensions/tts_custom_bindings.cc +++ b/chrome/renderer/extensions/tts_custom_bindings.cc @@ -13,30 +13,18 @@ namespace extensions { -TTSCustomBindings::TTSCustomBindings( - int dependency_count, - const char** dependencies) - : ChromeV8Extension( - "extensions/tts_custom_bindings.js", - IDR_TTS_CUSTOM_BINDINGS_JS, - dependency_count, - dependencies, - NULL) {} +TTSCustomBindings::TTSCustomBindings() + : ChromeV8Extension(NULL) { + RouteStaticFunction("GetNextTTSEventId", &GetNextTTSEventId); +} -static v8::Handle<v8::Value> GetNextTTSEventId(const v8::Arguments& args) { +// static +v8::Handle<v8::Value> TTSCustomBindings::GetNextTTSEventId( + const v8::Arguments& args) { // Note: this works because the TTS API only works in the // extension process, not content scripts. static int next_tts_event_id = 1; return v8::Integer::New(next_tts_event_id++); } -v8::Handle<v8::FunctionTemplate> -TTSCustomBindings::GetNativeFunction( - v8::Handle<v8::String> name) { - if (name->Equals(v8::String::New("GetNextTTSEventId"))) - return v8::FunctionTemplate::New(GetNextTTSEventId); - - return ChromeV8Extension::GetNativeFunction(name); -} - } // extensions diff --git a/chrome/renderer/extensions/tts_custom_bindings.h b/chrome/renderer/extensions/tts_custom_bindings.h index c7598eb..c99a03a 100644 --- a/chrome/renderer/extensions/tts_custom_bindings.h +++ b/chrome/renderer/extensions/tts_custom_bindings.h @@ -13,10 +13,10 @@ namespace extensions { // Implements custom bindings for the tts API. class TTSCustomBindings : public ChromeV8Extension { public: - TTSCustomBindings(int dependency_count, const char** dependencies); + TTSCustomBindings(); - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( - v8::Handle<v8::String> name) OVERRIDE; + private: + static v8::Handle<v8::Value> GetNextTTSEventId(const v8::Arguments& args); }; } // extensions diff --git a/chrome/renderer/extensions/web_request_custom_bindings.cc b/chrome/renderer/extensions/web_request_custom_bindings.cc index 3246926..83f716c 100644 --- a/chrome/renderer/extensions/web_request_custom_bindings.cc +++ b/chrome/renderer/extensions/web_request_custom_bindings.cc @@ -12,18 +12,15 @@ namespace extensions { -WebRequestCustomBindings::WebRequestCustomBindings( - int dependency_count, - const char** dependencies) - : ChromeV8Extension( - "extensions/web_request_custom_bindings.js", - IDR_WEB_REQUEST_CUSTOM_BINDINGS_JS, - dependency_count, - dependencies, - NULL) {} +WebRequestCustomBindings::WebRequestCustomBindings() + : ChromeV8Extension(NULL) { + RouteStaticFunction("GetUniqueSubEventName", &GetUniqueSubEventName); +} // Attach an event name to an object. -static v8::Handle<v8::Value> GetUniqueSubEventName(const v8::Arguments& args) { +// static +v8::Handle<v8::Value> WebRequestCustomBindings::GetUniqueSubEventName( + const v8::Arguments& args) { static int next_event_id = 0; DCHECK(args.Length() == 1); DCHECK(args[0]->IsString()); @@ -33,13 +30,5 @@ static v8::Handle<v8::Value> GetUniqueSubEventName(const v8::Arguments& args) { return v8::String::New(unique_event_name.c_str()); } -v8::Handle<v8::FunctionTemplate> WebRequestCustomBindings::GetNativeFunction( - v8::Handle<v8::String> name) { - if (name->Equals(v8::String::New("GetUniqueSubEventName"))) - return v8::FunctionTemplate::New(GetUniqueSubEventName); - - return ChromeV8Extension::GetNativeFunction(name); -} - } // extensions diff --git a/chrome/renderer/extensions/web_request_custom_bindings.h b/chrome/renderer/extensions/web_request_custom_bindings.h index 285ae88..028c37d 100644 --- a/chrome/renderer/extensions/web_request_custom_bindings.h +++ b/chrome/renderer/extensions/web_request_custom_bindings.h @@ -13,10 +13,10 @@ namespace extensions { // Implements custom bindings for the webRequest API. class WebRequestCustomBindings : public ChromeV8Extension { public: - WebRequestCustomBindings(int dependency_count, const char** dependencies); + WebRequestCustomBindings(); - virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( - v8::Handle<v8::String> name) OVERRIDE; + private: + static v8::Handle<v8::Value> GetUniqueSubEventName(const v8::Arguments& args); }; } // extensions diff --git a/chrome/renderer/extensions/webstore_bindings.cc b/chrome/renderer/extensions/webstore_bindings.cc index 5991e6a..7214db9 100644 --- a/chrome/renderer/extensions/webstore_bindings.cc +++ b/chrome/renderer/extensions/webstore_bindings.cc @@ -13,7 +13,6 @@ #include "grit/renderer_resources.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebNodeList.h" #include "v8/include/v8.h" @@ -48,69 +47,17 @@ const char kInvalidWebstoreItemUrlError[] = // (successful or not) via OnInlineWebstoreInstallResponse. int g_next_install_id = 0; -class WebstoreBindingsHandler : public ChromeV8ExtensionHandler { - public: - WebstoreBindingsHandler( - ExtensionDispatcher* dispatcher, ChromeV8Context* context); - - // ChromeV8ExtensionHandler - virtual v8::Handle<v8::Value> HandleNativeFunction( - const std::string& name, - const v8::Arguments& arguments) OVERRIDE; - - // IPC::Channel::Listener - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - - private: - v8::Handle<v8::Value> Install(const v8::Arguments& args); - - void OnInlineWebstoreInstallResponse( - int install_id, bool success, const std::string& error); - - // Extracts a Web Store item ID from a <link rel="chrome-webstore-item" - // href="https://chrome.google.com/webstore/detail/id"> node found in the - // frame. On success, true will be returned and the |webstore_item_id| - // parameter will be populated with the ID. On failure, false will be returned - // and |error| will be populated with the error. - static bool GetWebstoreItemIdFromFrame( - WebFrame* frame, const std::string& preferred_store_link_url, - std::string* webstore_item_id, std::string* error); - - ExtensionDispatcher* dispatcher_; - DISALLOW_COPY_AND_ASSIGN(WebstoreBindingsHandler); -}; - } // anonymous namespace -WebstoreBindings::WebstoreBindings(ExtensionDispatcher* dispatcher) - : ChromeV8Extension("extensions/webstore.js", IDR_WEBSTORE_BINDINGS_JS, - dispatcher) { -} - -ChromeV8ExtensionHandler* WebstoreBindings::CreateHandler( - ChromeV8Context* context) { - return new WebstoreBindingsHandler(extension_dispatcher(), context); -} - -WebstoreBindingsHandler::WebstoreBindingsHandler( - ExtensionDispatcher* dispatcher, +WebstoreBindings::WebstoreBindings(ExtensionDispatcher* dispatcher, ChromeV8Context* context) - : ChromeV8ExtensionHandler(context), - dispatcher_(dispatcher) { -} - -v8::Handle<v8::Value> WebstoreBindingsHandler::HandleNativeFunction( - const std::string& name, const v8::Arguments& args) { - if (name == "Install") { - return Install(args); - } else { - CHECK(false) << "Unknown native function: " << name; - } - - return v8::Undefined(); + : ChromeV8Extension(dispatcher), + ChromeV8ExtensionHandler(context) { + RouteFunction("Install", + base::Bind(&WebstoreBindings::Install, base::Unretained(this))); } -v8::Handle<v8::Value> WebstoreBindingsHandler::Install( +v8::Handle<v8::Value> WebstoreBindings::Install( const v8::Arguments& args) { WebFrame* frame = WebFrame::frameForCurrentContext(); if (!frame || !frame->view()) @@ -161,7 +108,7 @@ v8::Handle<v8::Value> WebstoreBindingsHandler::Install( } // static -bool WebstoreBindingsHandler::GetWebstoreItemIdFromFrame( +bool WebstoreBindings::GetWebstoreItemIdFromFrame( WebFrame* frame, const std::string& preferred_store_link_url, std::string* webstore_item_id, std::string* error) { if (frame != frame->top()) { @@ -247,8 +194,8 @@ bool WebstoreBindingsHandler::GetWebstoreItemIdFromFrame( return false; } -bool WebstoreBindingsHandler::OnMessageReceived(const IPC::Message& message) { - IPC_BEGIN_MESSAGE_MAP(WebstoreBindingsHandler, message) +bool WebstoreBindings::OnMessageReceived(const IPC::Message& message) { + IPC_BEGIN_MESSAGE_MAP(WebstoreBindings, message) IPC_MESSAGE_HANDLER(ExtensionMsg_InlineWebstoreInstallResponse, OnInlineWebstoreInstallResponse) IPC_MESSAGE_UNHANDLED(CHECK(false) << "Unhandled IPC message") @@ -256,7 +203,7 @@ bool WebstoreBindingsHandler::OnMessageReceived(const IPC::Message& message) { return true; } -void WebstoreBindingsHandler::OnInlineWebstoreInstallResponse( +void WebstoreBindings::OnInlineWebstoreInstallResponse( int install_id, bool success, const std::string& error) { diff --git a/chrome/renderer/extensions/webstore_bindings.h b/chrome/renderer/extensions/webstore_bindings.h index 098f888..33ac48e 100644 --- a/chrome/renderer/extensions/webstore_bindings.h +++ b/chrome/renderer/extensions/webstore_bindings.h @@ -8,21 +8,37 @@ #include "base/compiler_specific.h" #include "chrome/renderer/extensions/chrome_v8_extension.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" class ChromeV8Context; // A V8 extension that creates an object at window.chrome.webstore. This object // allows JavaScript to initiate inline installs of apps that are listed in the // Chrome Web Store (CWS). -class WebstoreBindings : public ChromeV8Extension { +class WebstoreBindings : public ChromeV8Extension, + public ChromeV8ExtensionHandler { public: - explicit WebstoreBindings(ExtensionDispatcher* dispatcher); + explicit WebstoreBindings(ExtensionDispatcher* dispatcher, + ChromeV8Context* context); - protected: - virtual ChromeV8ExtensionHandler* CreateHandler( - ChromeV8Context* context) OVERRIDE; + // IPC::Channel::Listener + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; private: + v8::Handle<v8::Value> Install(const v8::Arguments& args); + + void OnInlineWebstoreInstallResponse( + int install_id, bool success, const std::string& error); + + // Extracts a Web Store item ID from a <link rel="chrome-webstore-item" + // href="https://chrome.google.com/webstore/detail/id"> node found in the + // frame. On success, true will be returned and the |webstore_item_id| + // parameter will be populated with the ID. On failure, false will be returned + // and |error| will be populated with the error. + static bool GetWebstoreItemIdFromFrame( + WebKit::WebFrame* frame, const std::string& preferred_store_link_url, + std::string* webstore_item_id, std::string* error); + DISALLOW_COPY_AND_ASSIGN(WebstoreBindings); }; |