diff options
Diffstat (limited to 'chrome/renderer/extensions')
7 files changed, 221 insertions, 26 deletions
diff --git a/chrome/renderer/extensions/contextMenus_custom_bindings.cc b/chrome/renderer/extensions/contextMenus_custom_bindings.cc new file mode 100644 index 0000000..a1b5049 --- /dev/null +++ b/chrome/renderer/extensions/contextMenus_custom_bindings.cc @@ -0,0 +1,38 @@ +// 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. + +#include "chrome/renderer/extensions/contextMenus_custom_bindings.h" + +#include "grit/renderer_resources.h" +#include "v8/include/v8.h" + +namespace extensions { + +ContextMenusCustomBindings::ContextMenusCustomBindings( + int dependency_count, + const char** dependencies) + : ChromeV8Extension( + "extensions/contextMenus_custom_bindings.js", + IDR_CONTEXTMENUS_CUSTOM_BINDINGS_JS, + dependency_count, + dependencies, + NULL) {} + +static 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 + static int next_context_menu_id = 1; + 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); + + return ChromeV8Extension::GetNativeFunction(name); +} + +} // extensions diff --git a/chrome/renderer/extensions/contextMenus_custom_bindings.h b/chrome/renderer/extensions/contextMenus_custom_bindings.h new file mode 100644 index 0000000..8acd2bd --- /dev/null +++ b/chrome/renderer/extensions/contextMenus_custom_bindings.h @@ -0,0 +1,24 @@ +// 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. + +#ifndef CHROME_RENDERER_EXTENSIONS_CONTEXTMENUS_CUSTOM_BINDINGS_H_ +#define CHROME_RENDERER_EXTENSIONS_CONTEXTMENUS_CUSTOM_BINDINGS_H_ +#pragma once + +#include "chrome/renderer/extensions/chrome_v8_extension.h" + +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; +}; + +} // extensions + +#endif // CHROME_RENDERER_EXTENSIONS_CONTEXTMENUS_CUSTOM_BINDINGS_H_ diff --git a/chrome/renderer/extensions/custom_bindings_util.cc b/chrome/renderer/extensions/custom_bindings_util.cc new file mode 100644 index 0000000..c17740f --- /dev/null +++ b/chrome/renderer/extensions/custom_bindings_util.cc @@ -0,0 +1,70 @@ +// 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. + +#include "chrome/renderer/extensions/custom_bindings_util.h" + +#include <map> + +#include "base/string_util.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/renderer/extensions/chrome_v8_extension.h" +#include "chrome/renderer/extensions/contextMenus_custom_bindings.h" +#include "base/logging.h" +#include "grit/renderer_resources.h" +#include "v8/include/v8.h" + +namespace extensions { + +namespace custom_bindings_util { + +std::vector<v8::Extension*> GetAll() { + static const char* kDependencies[] = { + "extensions/schema_generated_bindings.js", + }; + static const size_t kDependencyCount = arraysize(kDependencies); + + std::vector<v8::Extension*> result; + + result.push_back( + new ContextMenusCustomBindings(kDependencyCount, kDependencies)); + + 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) { + // Extract the name of the API from the v8 extension name. + // This is "${api_name}" in "extensions/${api_name}_custom_bindings.js". + std::string prefix = "extensions/"; + const bool kCaseSensitive = true; + if (!StartsWithASCII(v8_extension_name, prefix, kCaseSensitive)) + return ""; + + std::string suffix = "_custom_bindings.js"; + if (!EndsWith(v8_extension_name, suffix, kCaseSensitive)) + return ""; + + return v8_extension_name.substr( + prefix.size(), + v8_extension_name.size() - prefix.size() - suffix.size()); +} + +bool AllowAPIInjection(const std::string& api_name, + const Extension& extension) { + CHECK(api_name != ""); + + // As in ExtensionAPI::GetSchemasForExtension, we need to allow any bindings + // for an API that the extension *might* have permission to use. + if (!extension.required_permission_set()->HasAnyAccessToAPI(api_name) && + !extension.optional_permission_set()->HasAnyAccessToAPI(api_name)) { + return false; + } + + return true; +} + +} // namespace custom_bindings_util + +} // namespace extensions diff --git a/chrome/renderer/extensions/custom_bindings_util.h b/chrome/renderer/extensions/custom_bindings_util.h new file mode 100644 index 0000000..9832386 --- /dev/null +++ b/chrome/renderer/extensions/custom_bindings_util.h @@ -0,0 +1,44 @@ +// 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. + +#ifndef CHROME_RENDERER_EXTENSIONS_CUSTOM_BINDINGS_UTIL_H_ +#define CHROME_RENDERER_EXTENSIONS_CUSTOM_BINDINGS_UTIL_H_ +#pragma once + +#include <string> +#include <vector> + +#include "chrome/renderer/extensions/chrome_v8_extension.h" + +class Extension; + +namespace v8 { +class Extension; +} + +namespace extensions { + +// Utilities for managing the set of V8 extensions for extension API custom +// bindings. +namespace custom_bindings_util { + +// Creates V8 extensions for all custom bindings. +std::vector<v8::Extension*> GetAll(); + +// 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. +std::string GetAPIName(const std::string& v8_extension_name); + +// Returns whether the custom binding for an API should be allowed to run for +// |extension|. This is based on whether the extension has any permission +// (required or optional) for that API. +bool AllowAPIInjection(const std::string& api_name, + const Extension& extension); + +} // namespace custom_bindings_util + +} // namespace extensions + +#endif // CHROME_RENDERER_EXTENSIONS_CUSTOM_BINDINGS_UTIL_H_ diff --git a/chrome/renderer/extensions/extension_dispatcher.cc b/chrome/renderer/extensions/extension_dispatcher.cc index 13a0655..b1663cd 100644 --- a/chrome/renderer/extensions/extension_dispatcher.cc +++ b/chrome/renderer/extensions/extension_dispatcher.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. @@ -16,6 +16,7 @@ #include "chrome/renderer/extensions/chrome_v8_context.h" #include "chrome/renderer/extensions/chrome_v8_extension.h" #include "chrome/renderer/extensions/chrome_webstore_bindings.h" +#include "chrome/renderer/extensions/custom_bindings_util.h" #include "chrome/renderer/extensions/event_bindings.h" #include "chrome/renderer/extensions/extension_groups.h" #include "chrome/renderer/extensions/file_browser_private_bindings.h" @@ -39,8 +40,8 @@ static const int64 kInitialExtensionIdleHandlerDelayMs = 5*1000; static const int64 kMaxExtensionIdleHandlerDelayMs = 5*60*1000; } -using extensions::MiscellaneousBindings; -using extensions::SchemaGeneratedBindings; +using namespace extensions; + using WebKit::WebDataSource; using WebKit::WebDocument; using WebKit::WebFrame; @@ -115,6 +116,12 @@ void ExtensionDispatcher::WebKitInitialized() { RegisterExtension(new ChromeV8Extension( "extensions/apitest.js", IDR_EXTENSION_APITEST_JS, NULL), true); + std::vector<v8::Extension*> custom_bindings = custom_bindings_util::GetAll(); + 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(); @@ -286,6 +293,21 @@ bool ExtensionDispatcher::AllowScriptExtension( 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()) { + const Extension* extension = + extensions_.GetByID(GetExtensionID(frame, world_id)); + // TODO(kalman): there appears to be a race condition, particularly hit + // on windows tests, causing this check to fail. It should be a check. + if (!extension) + return true; + return custom_bindings_util::AllowAPIInjection( + custom_binding_api_name, *extension); + } + return true; } @@ -294,19 +316,8 @@ bool ExtensionDispatcher::AllowScriptExtension( void ExtensionDispatcher::DidCreateScriptContext( WebFrame* frame, v8::Handle<v8::Context> v8_context, int world_id) { - std::string extension_id; - if (!test_extension_id_.empty()) { - extension_id = test_extension_id_; - } else if (world_id != 0) { - extension_id = user_script_slave_->GetExtensionIdForIsolatedWorld(world_id); - } else { - GURL frame_url = UserScriptSlave::GetDataSourceURLForFrame(frame); - extension_id = extensions_.GetExtensionOrAppIDByURL( - ExtensionURLInfo(frame->document().securityOrigin(), frame_url)); - } - ChromeV8Context* context = - new ChromeV8Context(v8_context, frame, extension_id); + new ChromeV8Context(v8_context, frame, GetExtensionID(frame, world_id)); v8_context_set_.Add(context); context->DispatchOnLoadEvent( @@ -316,6 +327,20 @@ void ExtensionDispatcher::DidCreateScriptContext( VLOG(1) << "Num tracked contexts: " << v8_context_set_.size(); } +std::string ExtensionDispatcher::GetExtensionID(WebFrame* frame, int world_id) { + if (!test_extension_id_.empty()) { + return test_extension_id_; + } else if (world_id != 0) { + // Isolated worlds (content script). + return user_script_slave_->GetExtensionIdForIsolatedWorld(world_id); + } else { + // Extension pages (chrome-extension:// URLs). + GURL frame_url = UserScriptSlave::GetDataSourceURLForFrame(frame); + return extensions_.GetExtensionOrAppIDByURL( + ExtensionURLInfo(frame->document().securityOrigin(), frame_url)); + } +} + void ExtensionDispatcher::WillReleaseScriptContext( WebFrame* frame, v8::Handle<v8::Context> v8_context, int world_id) { ChromeV8Context* context = v8_context_set_.GetByV8Context(v8_context); diff --git a/chrome/renderer/extensions/extension_dispatcher.h b/chrome/renderer/extensions/extension_dispatcher.h index ea48e03..9796430 100644 --- a/chrome/renderer/extensions/extension_dispatcher.h +++ b/chrome/renderer/extensions/extension_dispatcher.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. @@ -137,6 +137,10 @@ class ExtensionDispatcher : public content::RenderProcessObserver { const Extension* extension, const URLPatternSet& origins); + // 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); + // True if this renderer is running extensions. bool is_extension_process_; diff --git a/chrome/renderer/extensions/schema_generated_bindings.cc b/chrome/renderer/extensions/schema_generated_bindings.cc index baf484c..bd6fd47 100644 --- a/chrome/renderer/extensions/schema_generated_bindings.cc +++ b/chrome/renderer/extensions/schema_generated_bindings.cc @@ -195,8 +195,6 @@ class ExtensionImpl : public ChromeV8Extension { return v8::FunctionTemplate::New(GetNextRequestId); } else if (name->Equals(v8::String::New("OpenChannelToTab"))) { return v8::FunctionTemplate::New(OpenChannelToTab); - } else if (name->Equals(v8::String::New("GetNextContextMenuId"))) { - return v8::FunctionTemplate::New(GetNextContextMenuId); } else if (name->Equals(v8::String::New("GetNextSocketEventId"))) { return v8::FunctionTemplate::New(GetNextSocketEventId); } else if (name->Equals(v8::String::New("GetNextTtsEventId"))) { @@ -477,14 +475,6 @@ class ExtensionImpl : public ChromeV8Extension { return v8::Undefined(); } - static 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 - static int next_context_menu_id = 1; - return v8::Integer::New(next_context_menu_id++); - } - static v8::Handle<v8::Value> GetNextTtsEventId(const v8::Arguments& args) { // Note: this works because the TTS API only works in the // extension process, not content scripts. |