diff options
author | koz@chromium.org <koz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-03 23:28:03 +0000 |
---|---|---|
committer | koz@chromium.org <koz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-03 23:28:03 +0000 |
commit | e3e778724e5f96d204a9d34912ffb5c4786ad289 (patch) | |
tree | d56b5acb84cfe0957de0a4dfd9cbbbda06eb055d | |
parent | 06c8245612efb10678949002650362c842396219 (diff) | |
download | chromium_src-e3e778724e5f96d204a9d34912ffb5c4786ad289.zip chromium_src-e3e778724e5f96d204a9d34912ffb5c4786ad289.tar.gz chromium_src-e3e778724e5f96d204a9d34912ffb5c4786ad289.tar.bz2 |
Revert 185709
> Set up V8 bindings for extension/app APIs when they're first used, not on
> context creation. This should gives us a significant reduction in extension/app
> startup time and slightly better memory usage.
>
> It also gives us better error messages, the chance to complete the
> implementation of API features, and eventually the ability to expose select
> extension APIs (e.g. extension.sendMessage) to web pages.
>
> BUG=163678,120070,55316,177163
> TBR=ben@chromium.org
>
> Review URL: https://chromiumcodereview.appspot.com/11571014
TBR=cduvall@chromium.org
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@185815 0039d316-1c4b-4281-b951-d872f2087c98
112 files changed, 1229 insertions, 2065 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_match.cc b/chrome/browser/autocomplete/autocomplete_match.cc index eeec15d..7de2ec1 100644 --- a/chrome/browser/autocomplete/autocomplete_match.cc +++ b/chrome/browser/autocomplete/autocomplete_match.cc @@ -343,7 +343,7 @@ void AutocompleteMatch::AddLastClassificationIfNecessary( // static string16 AutocompleteMatch::SanitizeString(const string16& text) { // NOTE: This logic is mirrored by |sanitizeString()| in - // omnibox_custom_bindings.js. + // schema_generated_bindings.js. string16 result; TrimWhitespace(text, TRIM_LEADING, &result); RemoveChars(result, kInvalidChars, &result); diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi index e0d2e6c..624bae38 100644 --- a/chrome/chrome_renderer.gypi +++ b/chrome/chrome_renderer.gypi @@ -98,9 +98,8 @@ 'renderer/extensions/miscellaneous_bindings.h', 'renderer/extensions/module_system.cc', 'renderer/extensions/module_system.h', + 'renderer/extensions/native_handler.cc', 'renderer/extensions/native_handler.h', - 'renderer/extensions/object_backed_native_handler.cc', - 'renderer/extensions/object_backed_native_handler.h', 'renderer/extensions/page_actions_custom_bindings.cc', 'renderer/extensions/page_actions_custom_bindings.h', 'renderer/extensions/page_capture_custom_bindings.cc', @@ -111,8 +110,6 @@ 'renderer/extensions/resource_request_policy.h', 'renderer/extensions/runtime_custom_bindings.cc', 'renderer/extensions/runtime_custom_bindings.h', - 'renderer/extensions/binding_generating_native_handler.cc', - 'renderer/extensions/binding_generating_native_handler.h', 'renderer/extensions/send_request_natives.cc', 'renderer/extensions/send_request_natives.h', 'renderer/extensions/set_icon_natives.cc', @@ -146,16 +143,15 @@ 'renderer/net/renderer_net_predictor.cc', 'renderer/net/renderer_net_predictor.h', 'renderer/net_benchmarking_extension.cc', - 'renderer/net_benchmarking_extension.h', + 'renderer/net_benchmarking_extension.h', 'renderer/one_click_signin_agent.cc', 'renderer/one_click_signin_agent.h', 'renderer/playback_extension.cc', 'renderer/playback_extension.h', 'renderer/resource_bundle_source_map.cc', 'renderer/resource_bundle_source_map.h', + 'renderer/resources/extensions/apitest.js', 'renderer/resources/extensions/app_custom_bindings.js', - 'renderer/resources/extensions/app_window_custom_bindings.js', - 'renderer/resources/extensions/binding.js', 'renderer/resources/extensions/browser_action_custom_bindings.js', 'renderer/resources/extensions/content_watcher.js', 'renderer/resources/extensions/context_menus_custom_bindings.js', @@ -179,10 +175,10 @@ 'renderer/resources/extensions/page_capture_custom_bindings.js', 'renderer/resources/extensions/platform_app.js', 'renderer/resources/extensions/runtime_custom_bindings.js', + 'renderer/resources/extensions/schema_generated_bindings.js', 'renderer/resources/extensions/send_request.js', 'renderer/resources/extensions/set_icon.js', 'renderer/resources/extensions/system_indicator_custom_bindings.js', - 'renderer/resources/extensions/test_custom_bindings.js', 'renderer/resources/extensions/tts_custom_bindings.js', 'renderer/resources/extensions/tts_engine_custom_bindings.js', 'renderer/resources/extensions/types_custom_bindings.js', diff --git a/chrome/common/extensions/api/extension_api.cc b/chrome/common/extensions/api/extension_api.cc index f280bba..20021a3 100644 --- a/chrome/common/extensions/api/extension_api.cc +++ b/chrome/common/extensions/api/extension_api.cc @@ -543,7 +543,7 @@ void RemoveDisallowedAPIs(const Extension& extension, } // namespace -std::set<std::string> ExtensionAPI::GetAPIsForContext( +scoped_ptr<std::set<std::string> > ExtensionAPI::GetAPIsForContext( Feature::Context context, const Extension* extension, const GURL& url) { // We're forced to load all schemas now because we need to know the metadata // about every API -- and the metadata is stored in the schemas themselves. @@ -601,28 +601,17 @@ std::set<std::string> ExtensionAPI::GetAPIsForContext( // Filter out all non-API features and remove the feature type part of the // name. - std::set<std::string> result; + scoped_ptr<std::set<std::string> > result(new std::set<std::string>()); for (std::set<std::string>::iterator iter = temp_result.begin(); iter != temp_result.end(); ++iter) { std::string feature_type; std::string feature_name; SplitDependencyName(*iter, &feature_type, &feature_name); if (feature_type == "api") - result.insert(feature_name); + result->insert(feature_name); } - return result; -} - -std::set<std::string> ExtensionAPI::GetAllAPINames() { - std::set<std::string> result; - for (SchemaMap::iterator i = schemas_.begin(); i != schemas_.end(); ++i) - result.insert(i->first); - for (UnloadedSchemaMap::iterator i = unloaded_schemas_.begin(); - i != unloaded_schemas_.end(); ++i) { - result.insert(i->first); - } - return result; + return result.Pass(); } Feature* ExtensionAPI::GetFeature(const std::string& full_name) { diff --git a/chrome/common/extensions/api/extension_api.h b/chrome/common/extensions/api/extension_api.h index 128129e..b74bdcc 100644 --- a/chrome/common/extensions/api/extension_api.h +++ b/chrome/common/extensions/api/extension_api.h @@ -88,11 +88,9 @@ class ExtensionAPI : public FeatureProvider { // Gets the APIs available to |context| given an |extension| and |url|. The // extension or URL may not be relevant to all contexts, and may be left // NULL/empty. - std::set<std::string> GetAPIsForContext( + scoped_ptr<std::set<std::string> > GetAPIsForContext( Feature::Context context, const Extension* extension, const GURL& url); - std::set<std::string> GetAllAPINames(); - // Gets a Feature object describing the API with the specified |full_name|. // This can be either an API namespace (like history, or // experimental.bookmarks), or it can be an individual function or event. @@ -160,8 +158,7 @@ class ExtensionAPI : public FeatureProvider { // Map from each API that hasn't been loaded yet to the schema which defines // it. Note that there may be multiple APIs per schema. - typedef std::map<std::string, base::StringPiece> UnloadedSchemaMap; - UnloadedSchemaMap unloaded_schemas_; + std::map<std::string, base::StringPiece> unloaded_schemas_; // Schemas for each namespace. typedef std::map<std::string, linked_ptr<const DictionaryValue> > SchemaMap; diff --git a/chrome/common/extensions/api/extension_api_unittest.cc b/chrome/common/extensions/api/extension_api_unittest.cc index 8584a1e..125085c 100644 --- a/chrome/common/extensions/api/extension_api_unittest.cc +++ b/chrome/common/extensions/api/extension_api_unittest.cc @@ -235,29 +235,32 @@ TEST(ExtensionAPI, ExtensionWithUnprivilegedAPIs) { scoped_ptr<ExtensionAPI> extension_api( ExtensionAPI::CreateWithDefaultConfiguration()); - std::set<std::string> privileged_apis = extension_api->GetAPIsForContext( - Feature::BLESSED_EXTENSION_CONTEXT, extension.get(), GURL()); + scoped_ptr<std::set<std::string> > privileged_apis = + extension_api->GetAPIsForContext( + Feature::BLESSED_EXTENSION_CONTEXT, extension.get(), GURL()); - std::set<std::string> unprivileged_apis = extension_api->GetAPIsForContext( - Feature::UNBLESSED_EXTENSION_CONTEXT, extension.get(), GURL()); + scoped_ptr<std::set<std::string> > unprivileged_apis = + extension_api->GetAPIsForContext( + Feature::UNBLESSED_EXTENSION_CONTEXT, extension.get(), GURL()); - std::set<std::string> content_script_apis = extension_api->GetAPIsForContext( - Feature::CONTENT_SCRIPT_CONTEXT, extension.get(), GURL()); + scoped_ptr<std::set<std::string> > content_script_apis = + extension_api->GetAPIsForContext( + Feature::CONTENT_SCRIPT_CONTEXT, extension.get(), GURL()); // "storage" is completely unprivileged. - EXPECT_EQ(1u, privileged_apis.count("storage")); - EXPECT_EQ(1u, unprivileged_apis.count("storage")); - EXPECT_EQ(1u, content_script_apis.count("storage")); + EXPECT_EQ(1u, privileged_apis->count("storage")); + EXPECT_EQ(1u, unprivileged_apis->count("storage")); + EXPECT_EQ(1u, content_script_apis->count("storage")); // "extension" is partially unprivileged. - EXPECT_EQ(1u, privileged_apis.count("extension")); - EXPECT_EQ(1u, unprivileged_apis.count("extension")); - EXPECT_EQ(1u, content_script_apis.count("extension")); + EXPECT_EQ(1u, privileged_apis->count("extension")); + EXPECT_EQ(1u, unprivileged_apis->count("extension")); + EXPECT_EQ(1u, content_script_apis->count("extension")); // "history" is entirely privileged. - EXPECT_EQ(1u, privileged_apis.count("history")); - EXPECT_EQ(0u, unprivileged_apis.count("history")); - EXPECT_EQ(0u, content_script_apis.count("history")); + EXPECT_EQ(1u, privileged_apis->count("history")); + EXPECT_EQ(0u, unprivileged_apis->count("history")); + EXPECT_EQ(0u, content_script_apis->count("history")); } TEST(ExtensionAPI, ExtensionWithDependencies) { @@ -268,10 +271,10 @@ TEST(ExtensionAPI, ExtensionWithDependencies) { CreateExtensionWithPermission("ttsEngine"); scoped_ptr<ExtensionAPI> api( ExtensionAPI::CreateWithDefaultConfiguration()); - std::set<std::string> apis = api->GetAPIsForContext( + scoped_ptr<std::set<std::string> > apis = api->GetAPIsForContext( Feature::BLESSED_EXTENSION_CONTEXT, extension.get(), GURL()); - EXPECT_EQ(1u, apis.count("ttsEngine")); - EXPECT_EQ(1u, apis.count("tts")); + EXPECT_EQ(1u, apis->count("ttsEngine")); + EXPECT_EQ(1u, apis->count("tts")); } // Conversely, extension with the "tts" permission but not the "ttsEngine" @@ -281,18 +284,18 @@ TEST(ExtensionAPI, ExtensionWithDependencies) { CreateExtensionWithPermission("tts"); scoped_ptr<ExtensionAPI> api( ExtensionAPI::CreateWithDefaultConfiguration()); - std::set<std::string> apis = api->GetAPIsForContext( + scoped_ptr<std::set<std::string> > apis = api->GetAPIsForContext( Feature::BLESSED_EXTENSION_CONTEXT, extension.get(), GURL()); - EXPECT_EQ(0u, apis.count("ttsEngine")); - EXPECT_EQ(1u, apis.count("tts")); + EXPECT_EQ(0u, apis->count("ttsEngine")); + EXPECT_EQ(1u, apis->count("tts")); } } bool MatchesURL( ExtensionAPI* api, const std::string& api_name, const std::string& url) { - std::set<std::string> apis = + scoped_ptr<std::set<std::string> > apis = api->GetAPIsForContext(Feature::WEB_PAGE_CONTEXT, NULL, GURL(url)); - return apis.count(api_name); + return apis->count(api_name); } TEST(ExtensionAPI, URLMatching) { diff --git a/chrome/common/extensions/api/test.json b/chrome/common/extensions/api/test.json index add13d8..17ad531 100644 --- a/chrome/common/extensions/api/test.json +++ b/chrome/common/extensions/api/test.json @@ -104,205 +104,6 @@ ] } ] - }, - { - "name": "callbackAdded", - "type": "function", - "unprivileged": true, - "nocompile": true, - "parameters": [] - }, - { - "name": "runNextTest", - "type": "function", - "unprivileged": true, - "nocompile": true, - "parameters": [] - }, - { - "name": "fail", - "type": "function", - "unprivileged": true, - "nocompile": true, - "parameters": [ - {"type": "any", "name": "message", "optional": true} - ] - }, - { - "name": "succeed", - "type": "function", - "unprivileged": true, - "nocompile": true, - "parameters": [ - {"type": "any", "name": "message", "optional": true} - ] - }, - { - "name": "assertTrue", - "type": "function", - "unprivileged": true, - "nocompile": true, - "parameters": [ - { - "name": "test", - "choices": [ - {"type": "string"}, - {"type": "boolean"} - ] - }, - {"type": "string", "name": "message", "optional": true} - ] - }, - { - "name": "assertFalse", - "type": "function", - "unprivileged": true, - "nocompile": true, - "parameters": [ - { - "name": "test", - "choices": [ - {"type": "string"}, - {"type": "boolean"} - ] - }, - {"type": "string", "name": "message", "optional": true} - ] - }, - { - "name": "assertBool", - "type": "function", - "unprivileged": true, - "nocompile": true, - "parameters": [ - { - "name": "test", - "choices": [ - {"type": "string"}, - {"type": "boolean"} - ] - }, - {"type": "boolean", "name": "expected"}, - {"type": "string", "name": "message", "optional": true} - ] - }, - { - "name": "checkDeepEq", - "type": "function", - "unprivileged": true, - "nocompile": true, - "allowAmbiguousOptionalArguments": true, - "parameters": [ - // These need to be optional because they can be null. - {"type": "any", "name": "expected", "optional": true}, - {"type": "any", "name": "actual", "optional": true} - ] - }, - { - "name": "assertEq", - "type": "function", - "unprivileged": true, - "nocompile": true, - "allowAmbiguousOptionalArguments": true, - "parameters": [ - // These need to be optional because they can be null. - {"type": "any", "name": "expected", "optional": true}, - {"type": "any", "name": "actual", "optional": true}, - {"type": "string", "name": "message", "optional": true} - ] - }, - { - "name": "assertNoLastError", - "type": "function", - "unprivileged": true, - "nocompile": true, - "parameters": [] - }, - { - "name": "assertLastError", - "type": "function", - "unprivileged": true, - "nocompile": true, - "parameters": [ - {"type": "string", "name": "expectedError"} - ] - }, - { - "name": "callback", - "type": "function", - "unprivileged": true, - "nocompile": true, - "parameters": [ - {"type": "function", "name": "func", "optional": true}, - {"type": "string", "name": "expectedError", "optional": true} - ] - }, - { - "name": "listenOnce", - "type": "function", - "unprivileged": true, - "nocompile": true, - "parameters": [ - // TODO(cduvall): Make this a $ref to events.Event. - {"type": "any", "name": "event"}, - {"type": "function", "name": "func"} - ] - }, - { - "name": "listenForever", - "type": "function", - "unprivileged": true, - "nocompile": true, - "parameters": [ - // TODO(cduvall): Make this a $ref to events.Event. - {"type": "any", "name": "event"}, - {"type": "function", "name": "func"} - ] - }, - { - "name": "callbackPass", - "type": "function", - "unprivileged": true, - "nocompile": true, - "parameters": [ - {"type": "function", "name": "func", "optional": true} - ] - }, - { - "name": "callbackFail", - "type": "function", - "unprivileged": true, - "nocompile": true, - "parameters": [ - {"type": "string", "name": "expectedError"}, - {"type": "function", "name": "func", "optional": true} - ] - }, - { - "name": "runTests", - "type": "function", - "unprivileged": true, - "nocompile": true, - "parameters": [ - { - "type": "array", - "name": "tests", - "items": {"type": "function"} - } - ] - }, - { - "name": "getApiDefinitions", - "type": "function", - "nocompile": true, - "parameters": [ - { - "type": "array", - "name": "apiNames", - "optional": true, - "items": {"type": "string"} - } - ] } ], "events": [ diff --git a/chrome/common/extensions/features/feature.cc b/chrome/common/extensions/features/feature.cc index f5eb37c..c245468 100644 --- a/chrome/common/extensions/features/feature.cc +++ b/chrome/common/extensions/features/feature.cc @@ -55,12 +55,6 @@ chrome::VersionInfo::Channel Feature::GetDefaultChannel() { return kDefaultChannel; } -// static -Feature::Availability Feature::CreateAvailability(AvailabilityResult result, - const std::string& message) { - return Availability(result, message); -} - Feature::~Feature() {} } // namespace extensions diff --git a/chrome/common/extensions/features/feature.h b/chrome/common/extensions/features/feature.h index 6eaa3a3..e3964b1 100644 --- a/chrome/common/extensions/features/feature.h +++ b/chrome/common/extensions/features/feature.h @@ -75,7 +75,6 @@ class Feature { private: friend class SimpleFeature; - friend class Feature; // Instances should be created via Feature::CreateAvailability. Availability(AvailabilityResult result, const std::string& message) @@ -87,10 +86,6 @@ class Feature { virtual ~Feature(); - // Used by ChromeV8Context until the feature system is fully functional. - static Availability CreateAvailability(AvailabilityResult result, - const std::string& message); - // Gets the current channel as seen by the Feature system. static chrome::VersionInfo::Channel GetCurrentChannel(); diff --git a/chrome/renderer/extensions/api_definitions_natives.cc b/chrome/renderer/extensions/api_definitions_natives.cc index 85f86b3..1bdd767 100644 --- a/chrome/renderer/extensions/api_definitions_natives.cc +++ b/chrome/renderer/extensions/api_definitions_natives.cc @@ -12,10 +12,8 @@ const char kInvalidExtensionNamespace[] = "Invalid extension namespace"; namespace extensions { -ApiDefinitionsNatives::ApiDefinitionsNatives(Dispatcher* dispatcher, - ChromeV8Context* context) - : ChromeV8Extension(dispatcher, context->v8_context()), - context_(context) { +ApiDefinitionsNatives::ApiDefinitionsNatives(Dispatcher* dispatcher) + : ChromeV8Extension(dispatcher) { RouteFunction("GetExtensionAPIDefinition", base::Bind(&ApiDefinitionsNatives::GetExtensionAPIDefinition, base::Unretained(this))); @@ -23,7 +21,10 @@ ApiDefinitionsNatives::ApiDefinitionsNatives(Dispatcher* dispatcher, v8::Handle<v8::Value> ApiDefinitionsNatives::GetExtensionAPIDefinition( const v8::Arguments& args) { - std::set<std::string> available_apis(context_->GetAvailableExtensionAPIs()); + ChromeV8Context* v8_context = dispatcher()->v8_context_set().GetCurrent(); + CHECK(v8_context); + + std::set<std::string> available_apis(v8_context->GetAvailableExtensionAPIs()); if (args.Length() == 0) return dispatcher()->v8_schema_registry()->GetSchemas(available_apis); diff --git a/chrome/renderer/extensions/api_definitions_natives.h b/chrome/renderer/extensions/api_definitions_natives.h index f8801e5..45b46b6 100644 --- a/chrome/renderer/extensions/api_definitions_natives.h +++ b/chrome/renderer/extensions/api_definitions_natives.h @@ -10,14 +10,12 @@ #include "v8/include/v8.h" -class ChromeV8Context; - namespace extensions { // Native functions for JS to get access to the schemas for extension APIs. class ApiDefinitionsNatives : public ChromeV8Extension { public: - ApiDefinitionsNatives(Dispatcher* dispatcher, ChromeV8Context* context); + explicit ApiDefinitionsNatives(Dispatcher* dispatcher); private: // Returns the list of schemas that are available to the calling context @@ -25,8 +23,6 @@ class ApiDefinitionsNatives : public ChromeV8Extension { // of all schemas that are available to the calling context. v8::Handle<v8::Value> GetExtensionAPIDefinition(const v8::Arguments& args); - ChromeV8Context* context_; - DISALLOW_COPY_AND_ASSIGN(ApiDefinitionsNatives); }; diff --git a/chrome/renderer/extensions/app_bindings.cc b/chrome/renderer/extensions/app_bindings.cc index 97472b9..aea0606 100644 --- a/chrome/renderer/extensions/app_bindings.cc +++ b/chrome/renderer/extensions/app_bindings.cc @@ -57,8 +57,9 @@ const char* kInvalidCallbackIdError = "Invalid callbackId"; } // namespace -AppBindings::AppBindings(Dispatcher* dispatcher, ChromeV8Context* context) - : ChromeV8Extension(dispatcher, context->v8_context()), +AppBindings::AppBindings(Dispatcher* dispatcher, + ChromeV8Context* context) + : ChromeV8Extension(dispatcher), ChromeV8ExtensionHandler(context) { RouteFunction("GetIsInstalled", base::Bind(&AppBindings::GetIsInstalled, base::Unretained(this))); diff --git a/chrome/renderer/extensions/app_bindings.h b/chrome/renderer/extensions/app_bindings.h index 99028e4..2fff69c 100644 --- a/chrome/renderer/extensions/app_bindings.h +++ b/chrome/renderer/extensions/app_bindings.h @@ -24,7 +24,8 @@ class ChromeV8Context; class AppBindings : public ChromeV8Extension, public ChromeV8ExtensionHandler { public: - AppBindings(Dispatcher* dispatcher, ChromeV8Context* context); + explicit AppBindings(Dispatcher* dispatcher, + ChromeV8Context* context); private: // IPC::Listener diff --git a/chrome/renderer/extensions/app_runtime_custom_bindings.cc b/chrome/renderer/extensions/app_runtime_custom_bindings.cc index 60fbace9..0dd73c5 100644 --- a/chrome/renderer/extensions/app_runtime_custom_bindings.cc +++ b/chrome/renderer/extensions/app_runtime_custom_bindings.cc @@ -55,9 +55,8 @@ v8::Handle<v8::Value> CreateBlob(const v8::Arguments &args) { namespace extensions { -AppRuntimeCustomBindings::AppRuntimeCustomBindings( - Dispatcher* dispatcher, - v8::Handle<v8::Context> context) : ChromeV8Extension(dispatcher, context) { +AppRuntimeCustomBindings::AppRuntimeCustomBindings() + : ChromeV8Extension(NULL) { RouteStaticFunction("DeserializeString", &DeserializeString); RouteStaticFunction("SerializeToString", &SerializeToString); RouteStaticFunction("CreateBlob", &CreateBlob); diff --git a/chrome/renderer/extensions/app_runtime_custom_bindings.h b/chrome/renderer/extensions/app_runtime_custom_bindings.h index c691300..5dd8346 100644 --- a/chrome/renderer/extensions/app_runtime_custom_bindings.h +++ b/chrome/renderer/extensions/app_runtime_custom_bindings.h @@ -12,8 +12,7 @@ namespace extensions { // The native component of custom bindings for the chrome.app.runtime API. class AppRuntimeCustomBindings : public ChromeV8Extension { public: - AppRuntimeCustomBindings(Dispatcher* dispatcher, - v8::Handle<v8::Context> context); + AppRuntimeCustomBindings(); private: DISALLOW_COPY_AND_ASSIGN(AppRuntimeCustomBindings); diff --git a/chrome/renderer/extensions/app_window_custom_bindings.cc b/chrome/renderer/extensions/app_window_custom_bindings.cc index 67388cf..29325d5 100644 --- a/chrome/renderer/extensions/app_window_custom_bindings.cc +++ b/chrome/renderer/extensions/app_window_custom_bindings.cc @@ -49,9 +49,8 @@ class DidCreateDocumentElementObserver : public content::RenderViewObserver { Dispatcher* dispatcher_; }; -AppWindowCustomBindings::AppWindowCustomBindings( - Dispatcher* dispatcher, - v8::Handle<v8::Context> context) : ChromeV8Extension(dispatcher, context) { +AppWindowCustomBindings::AppWindowCustomBindings(Dispatcher* dispatcher) + : ChromeV8Extension(dispatcher) { RouteFunction("GetView", base::Bind(&AppWindowCustomBindings::GetView, base::Unretained(this))); @@ -159,7 +158,7 @@ v8::Handle<v8::Value> AppWindowCustomBindings::GetView( // need to make sure the security origin is set up before returning the DOM // reference. A better way to do this would be to have the browser pass the // opener through so opener_id is set in RenderViewImpl's constructor. - content::RenderView* render_view = GetRenderView(); + content::RenderView* render_view = GetCurrentRenderView(); if (!render_view) return v8::Undefined(); WebKit::WebFrame* opener = render_view->GetWebView()->mainFrame(); diff --git a/chrome/renderer/extensions/app_window_custom_bindings.h b/chrome/renderer/extensions/app_window_custom_bindings.h index be84aa0..6333097 100644 --- a/chrome/renderer/extensions/app_window_custom_bindings.h +++ b/chrome/renderer/extensions/app_window_custom_bindings.h @@ -13,8 +13,7 @@ class Dispatcher; // Implements custom bindings for the app.window API. class AppWindowCustomBindings : public ChromeV8Extension { public: - AppWindowCustomBindings(Dispatcher* dispatcher, - v8::Handle<v8::Context> context); + explicit AppWindowCustomBindings(Dispatcher* dispatcher); private: v8::Handle<v8::Value> GetView(const v8::Arguments& args); diff --git a/chrome/renderer/extensions/binding_generating_native_handler.cc b/chrome/renderer/extensions/binding_generating_native_handler.cc deleted file mode 100644 index 22c45c5..0000000 --- a/chrome/renderer/extensions/binding_generating_native_handler.cc +++ /dev/null @@ -1,39 +0,0 @@ -// 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/binding_generating_native_handler.h" - -#include "chrome/renderer/extensions/module_system.h" - -namespace extensions { - -BindingGeneratingNativeHandler::BindingGeneratingNativeHandler( - ModuleSystem* module_system, - const std::string& api_name, - const std::string& bind_to) - : module_system_(module_system), - api_name_(api_name), - bind_to_(bind_to) { -} - -v8::Handle<v8::Object> BindingGeneratingNativeHandler::NewInstance() { - v8::HandleScope scope; - v8::Handle<v8::Object> binding = v8::Handle<v8::Object>::Cast( - v8::Handle<v8::Object>::Cast(module_system_->Require( - "binding"))->Get(v8::String::New("Binding"))); - v8::Handle<v8::Function> create = v8::Handle<v8::Function>::Cast( - binding->Get(v8::String::New("create"))); - v8::Handle<v8::Value> argv[] = { v8::String::New(api_name_.c_str()) }; - v8::Handle<v8::Object> binding_instance = v8::Handle<v8::Object>::Cast( - create->Call(binding, 1, argv)); - v8::Handle<v8::Function> generate = v8::Handle<v8::Function>::Cast( - binding_instance->Get(v8::String::New("generate"))); - v8::Handle<v8::Value> compiled_schema = - generate->Call(binding_instance, 0, NULL); - v8::Handle<v8::Object> object = v8::Object::New(); - object->Set(v8::String::New(bind_to_.c_str()), compiled_schema); - return scope.Close(object); -} - -} // extensions diff --git a/chrome/renderer/extensions/binding_generating_native_handler.h b/chrome/renderer/extensions/binding_generating_native_handler.h deleted file mode 100644 index 9fefb30..0000000 --- a/chrome/renderer/extensions/binding_generating_native_handler.h +++ /dev/null @@ -1,38 +0,0 @@ -// 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_BINDING_GENERATING_NATIVE_HANDLER_H_ -#define CHROME_RENDERER_EXTENSIONS_BINDING_GENERATING_NATIVE_HANDLER_H_ - -#include <string> - -#include "base/compiler_specific.h" -#include "chrome/renderer/extensions/native_handler.h" - -namespace extensions { - -class ModuleSystem; - -// Generates API bindings based on the JSON/IDL schemas. This is done by -// creating a |Binding| (from binding.js) for the schema and generating the -// bindings from that. -class BindingGeneratingNativeHandler : public NativeHandler { - public: - // Generates binding for |api_name|, and sets the |bind_to| property on the - // Object returned by |NewInstance| to the generated binding. - BindingGeneratingNativeHandler(ModuleSystem* module_system, - const std::string& api_name, - const std::string& bind_to); - - virtual v8::Handle<v8::Object> NewInstance() OVERRIDE; - - private: - ModuleSystem* module_system_; - std::string api_name_; - std::string bind_to_; -}; - -} // extensions - -#endif // CHROME_RENDERER_EXTENSIONS_BINDING_GENERATING_NATIVE_HANDLER_H_ diff --git a/chrome/renderer/extensions/chrome_v8_context.cc b/chrome/renderer/extensions/chrome_v8_context.cc index 3d326ed..2abc772 100644 --- a/chrome/renderer/extensions/chrome_v8_context.cc +++ b/chrome/renderer/extensions/chrome_v8_context.cc @@ -12,7 +12,6 @@ #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_set.h" #include "chrome/renderer/extensions/chrome_v8_extension.h" -#include "chrome/renderer/extensions/module_system.h" #include "chrome/renderer/extensions/user_script_slave.h" #include "content/public/renderer/render_view.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" @@ -24,10 +23,6 @@ namespace extensions { namespace { const char kChromeHidden[] = "chromeHidden"; -const char kUnavailableMessage[] = "You do not have permission to access this " - "API. Ensure that the required permission " - "or manifest property is included in your " - "manifest.json."; const char kValidateCallbacks[] = "validateCallbacks"; const char kValidateAPI[] = "validateAPI"; @@ -42,8 +37,7 @@ ChromeV8Context::ChromeV8Context(v8::Handle<v8::Context> v8_context, v8_context)), web_frame_(web_frame), extension_(extension), - context_type_(context_type), - available_extension_apis_initialized_(false) { + context_type_(context_type) { VLOG(1) << "Created context:\n" << " extension id: " << GetExtensionID() << "\n" << " frame: " << web_frame_ << "\n" @@ -56,12 +50,6 @@ ChromeV8Context::~ChromeV8Context() { v8_context_.Dispose(v8_context_->GetIsolate()); } -void ChromeV8Context::Invalidate() { - if (module_system_) - module_system_->Invalidate(); - web_frame_ = NULL; -} - std::string ChromeV8Context::GetExtensionID() { return extension_ ? extension_->id() : ""; } @@ -78,11 +66,11 @@ v8::Handle<v8::Value> ChromeV8Context::GetOrCreateChromeHidden( global->SetHiddenValue(v8::String::New(kChromeHidden), hidden); if (DCHECK_IS_ON()) { - // Tell bindings.js to validate callbacks and events against their schema - // definitions. + // Tell schema_generated_bindings.js to validate callbacks and events + // against their schema definitions. v8::Local<v8::Object>::Cast(hidden)->Set( v8::String::New(kValidateCallbacks), v8::True()); - // Tell bindings.js to validate API for ambiguity. + // Tell schema_generated_bindings.js to validate API for ambiguity. v8::Local<v8::Object>::Cast(hidden)->Set( v8::String::New(kValidateAPI), v8::True()); } @@ -111,9 +99,9 @@ bool ChromeV8Context::CallChromeHiddenMethod( v8::Handle<v8::Value>* result) const { v8::Context::Scope context_scope(v8_context_); - // ChromeV8ContextSet calls Invalidate() and then schedules a task to delete - // this object. This check prevents a race from attempting to execute script - // on a NULL web_frame_. + // ChromeV8ContextSet calls clear_web_frame() and then schedules a task to + // delete this object. This check prevents a race from attempting to execute + // script on a NULL web_frame_. if (!web_frame_) return false; @@ -153,28 +141,15 @@ bool ChromeV8Context::CallChromeHiddenMethod( } const std::set<std::string>& ChromeV8Context::GetAvailableExtensionAPIs() { - if (!available_extension_apis_initialized_) { + if (!available_extension_apis_.get()) { available_extension_apis_ = ExtensionAPI::GetSharedInstance()->GetAPIsForContext( context_type_, extension_, - UserScriptSlave::GetDataSourceURLForFrame(web_frame_)); - available_extension_apis_initialized_ = true; + UserScriptSlave::GetDataSourceURLForFrame( + web_frame_)).Pass(); } - return available_extension_apis_; -} - -Feature::Availability ChromeV8Context::GetAvailability( - const std::string& api_name) { - const std::set<std::string>& available_apis = GetAvailableExtensionAPIs(); - - // TODO(cduvall/kalman): Switch to ExtensionAPI::IsAvailable() once Features - // are complete. - if (available_apis.find(api_name) != available_apis.end()) - return Feature::CreateAvailability(Feature::IS_AVAILABLE, ""); - - return Feature::CreateAvailability(Feature::INVALID_CONTEXT, - kUnavailableMessage); + return *(available_extension_apis_.get()); } void ChromeV8Context::DispatchOnLoadEvent(bool is_incognito_process, diff --git a/chrome/renderer/extensions/chrome_v8_context.h b/chrome/renderer/extensions/chrome_v8_context.h index e170f5c..8c71c04 100644 --- a/chrome/renderer/extensions/chrome_v8_context.h +++ b/chrome/renderer/extensions/chrome_v8_context.h @@ -36,10 +36,6 @@ class ChromeV8Context { Feature::Context context_type); ~ChromeV8Context(); - // Clears the WebFrame for this contexts and invalidates the associated - // ModuleSystem. - void Invalidate(); - v8::Handle<v8::Context> v8_context() const { return v8_context_; } @@ -51,6 +47,9 @@ class ChromeV8Context { WebKit::WebFrame* web_frame() const { return web_frame_; } + void clear_web_frame() { + web_frame_ = NULL; + } Feature::Context context_type() const { return context_type_; @@ -101,8 +100,6 @@ class ChromeV8Context { // APIs are available, returns an empty set. const std::set<std::string>& GetAvailableExtensionAPIs(); - Feature::Availability GetAvailability(const std::string& api_name); - // Returns a string description of the type of context this is. std::string GetContextTypeDescription(); @@ -131,8 +128,7 @@ class ChromeV8Context { scoped_ptr<ModuleSystem> module_system_; // The extension APIs available to this context. - std::set<std::string> available_extension_apis_; - bool available_extension_apis_initialized_; + scoped_ptr<std::set<std::string> > available_extension_apis_; DISALLOW_COPY_AND_ASSIGN(ChromeV8Context); }; diff --git a/chrome/renderer/extensions/chrome_v8_context_set.cc b/chrome/renderer/extensions/chrome_v8_context_set.cc index 88f7f98..0be3ece 100644 --- a/chrome/renderer/extensions/chrome_v8_context_set.cc +++ b/chrome/renderer/extensions/chrome_v8_context_set.cc @@ -75,7 +75,7 @@ void ChromeV8ContextSet::Add(ChromeV8Context* context) { void ChromeV8ContextSet::Remove(ChromeV8Context* context) { if (contexts_.erase(context)) { - context->Invalidate(); + context->clear_web_frame(); MessageLoop::current()->DeleteSoon(FROM_HERE, context); } } diff --git a/chrome/renderer/extensions/chrome_v8_extension.cc b/chrome/renderer/extensions/chrome_v8_extension.cc index 4d2a048..a5cbf03 100644 --- a/chrome/renderer/extensions/chrome_v8_extension.cc +++ b/chrome/renderer/extensions/chrome_v8_extension.cc @@ -25,33 +25,61 @@ using WebKit::WebView; namespace extensions { -ChromeV8Extension::ChromeV8Extension(Dispatcher* dispatcher) - : ObjectBackedNativeHandler(v8::Context::GetCurrent()), - dispatcher_(dispatcher) { +namespace { + +static base::LazyInstance<ChromeV8Extension::InstanceSet> g_instances = + LAZY_INSTANCE_INITIALIZER; + +} // namespace + +// static +content::RenderView* ChromeV8Extension::GetCurrentRenderView() { + WebFrame* webframe = WebFrame::frameForCurrentContext(); + DCHECK(webframe) << "RetrieveCurrentFrame called when not in a V8 context."; + if (!webframe) + return NULL; + + WebView* webview = webframe->view(); + if (!webview) + return NULL; // can happen during closing + + content::RenderView* renderview = content::RenderView::FromWebView(webview); + DCHECK(renderview) << "Encountered a WebView without a WebViewDelegate"; + return renderview; } -ChromeV8Extension::ChromeV8Extension(Dispatcher* dispatcher, - v8::Handle<v8::Context> context) - : ObjectBackedNativeHandler(context), +ChromeV8Extension::ChromeV8Extension(Dispatcher* dispatcher) + // TODO(svenpanne) It would be nice to remove the GetCurrent() call and use + // an additional constructor parameter instead, but this would involve too + // many changes for now. + : NativeHandler(v8::Isolate::GetCurrent()), dispatcher_(dispatcher) { + g_instances.Get().insert(this); } ChromeV8Extension::~ChromeV8Extension() { + g_instances.Get().erase(this); } -ChromeV8Context* ChromeV8Extension::GetContext() { - CHECK(dispatcher_); - return dispatcher_->v8_context_set().GetByV8Context(v8_context()); +// static +const ChromeV8Extension::InstanceSet& ChromeV8Extension::GetAll() { + return g_instances.Get(); } -content::RenderView* ChromeV8Extension::GetRenderView() { - ChromeV8Context* context = GetContext(); - return context ? context->GetRenderView() : NULL; -} +const Extension* ChromeV8Extension::GetExtensionForCurrentRenderView() const { + content::RenderView* renderview = GetCurrentRenderView(); + if (!renderview) + return NULL; // this can happen as a tab is closing. + + WebDocument document = renderview->GetWebView()->mainFrame()->document(); + GURL url = document.url(); + const ExtensionSet* extensions = dispatcher_->extensions(); + if (!extensions->ExtensionBindingsAllowed( + ExtensionURLInfo(document.securityOrigin(), url))) + return NULL; -const Extension* ChromeV8Extension::GetExtensionForRenderView() { - ChromeV8Context* context = GetContext(); - return context ? context->extension() : NULL; + return extensions->GetExtensionOrAppByURL( + ExtensionURLInfo(document.securityOrigin(), url)); } } // namespace extensions diff --git a/chrome/renderer/extensions/chrome_v8_extension.h b/chrome/renderer/extensions/chrome_v8_extension.h index 28251e9..e12af64 100644 --- a/chrome/renderer/extensions/chrome_v8_extension.h +++ b/chrome/renderer/extensions/chrome_v8_extension.h @@ -9,7 +9,7 @@ #include "base/memory/linked_ptr.h" #include "base/string_piece.h" #include "chrome/renderer/extensions/chrome_v8_extension_handler.h" -#include "chrome/renderer/extensions/object_backed_native_handler.h" +#include "chrome/renderer/extensions/native_handler.h" #include "v8/include/v8.h" #include <map> @@ -26,30 +26,19 @@ class ChromeV8Context; class Dispatcher; class Extension; -// DEPRECATED. -// // This is a base class for chrome extension bindings. Common features that // are shared by different modules go here. -// -// TODO(kalman): Delete this class entirely, it has no value anymore. -// Custom bindings should extend ObjectBackedNativeHandler. -class ChromeV8Extension : public ObjectBackedNativeHandler { +// TODO(koz): Rename this to ExtensionNativeModule. +class ChromeV8Extension : public NativeHandler { public: - // EXTRA DEPRECATED. DO NOT USE THIS CONSTRUCTOR. It doesn't work in subtle - // cases. - explicit ChromeV8Extension(Dispatcher* dispatcher); + typedef std::set<ChromeV8Extension*> InstanceSet; + static const InstanceSet& GetAll(); - ChromeV8Extension(Dispatcher* dispatcher, v8::Handle<v8::Context> context); + explicit ChromeV8Extension(Dispatcher* dispatcher); virtual ~ChromeV8Extension(); Dispatcher* dispatcher() { return dispatcher_; } - ChromeV8Context* GetContext(); - - // Shortcuts through to the context's render view and extension. - content::RenderView* GetRenderView(); - const Extension* GetExtensionForRenderView(); - protected: template<class T> static T* GetFromArguments(const v8::Arguments& args) { @@ -58,6 +47,17 @@ class ChromeV8Extension : public ObjectBackedNativeHandler { return result; } + // Gets the render view for the current v8 context. + static content::RenderView* GetCurrentRenderView(); + + // Note: do not call this function before or during the chromeHidden.onLoad + // event dispatch. The URL might not have been committed yet and might not + // be an extension URL. + const Extension* GetExtensionForCurrentRenderView() const; + + // Returns the chromeHidden object for the current context. + static v8::Handle<v8::Value> GetChromeHidden(const v8::Arguments& args); + Dispatcher* dispatcher_; private: diff --git a/chrome/renderer/extensions/dispatcher.cc b/chrome/renderer/extensions/dispatcher.cc index c085cbd..770a771 100644 --- a/chrome/renderer/extensions/dispatcher.cc +++ b/chrome/renderer/extensions/dispatcher.cc @@ -8,7 +8,6 @@ #include "base/command_line.h" #include "base/memory/scoped_ptr.h" #include "base/string_piece.h" -#include "base/string_split.h" #include "chrome/common/child_process_logging.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_version_info.h" @@ -16,7 +15,6 @@ #include "chrome/common/extensions/background_info.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_messages.h" -#include "chrome/common/extensions/features/feature.h" #include "chrome/common/extensions/manifest.h" #include "chrome/common/extensions/permissions/permission_set.h" #include "chrome/common/url_constants.h" @@ -26,7 +24,6 @@ #include "chrome/renderer/extensions/app_bindings.h" #include "chrome/renderer/extensions/app_runtime_custom_bindings.h" #include "chrome/renderer/extensions/app_window_custom_bindings.h" -#include "chrome/renderer/extensions/binding_generating_native_handler.h" #include "chrome/renderer/extensions/chrome_v8_context.h" #include "chrome/renderer/extensions/chrome_v8_extension.h" #include "chrome/renderer/extensions/content_watcher.h" @@ -42,7 +39,7 @@ #include "chrome/renderer/extensions/media_galleries_custom_bindings.h" #include "chrome/renderer/extensions/miscellaneous_bindings.h" #include "chrome/renderer/extensions/module_system.h" -#include "chrome/renderer/extensions/object_backed_native_handler.h" +#include "chrome/renderer/extensions/native_handler.h" #include "chrome/renderer/extensions/page_actions_custom_bindings.h" #include "chrome/renderer/extensions/page_capture_custom_bindings.h" #include "chrome/renderer/extensions/request_sender.h" @@ -93,97 +90,24 @@ static const char kEventDispatchFunction[] = "Event.dispatchEvent"; static const char kOnSuspendEvent[] = "runtime.onSuspend"; static const char kOnSuspendCanceledEvent[] = "runtime.onSuspendCanceled"; -static v8::Handle<v8::Object> GetOrCreateChrome( - v8::Handle<v8::Context> context) { - v8::Handle<v8::String> chrome_string(v8::String::New("chrome")); - v8::Handle<v8::Object> global(context->Global()); - v8::Handle<v8::Value> chrome(global->Get(chrome_string)); - if (chrome.IsEmpty() || chrome->IsUndefined()) { - v8::Handle<v8::Object> chrome_object(v8::Object::New()); - global->Set(chrome_string, chrome_object); - return chrome_object; - } - CHECK(chrome->IsObject()); - return chrome->ToObject(); -} - -class SchemaRegistryNativeHandler : public ObjectBackedNativeHandler { +class ChromeHiddenNativeHandler : public NativeHandler { public: - SchemaRegistryNativeHandler(V8SchemaRegistry* registry, - v8::Handle<v8::Context> context) - : ObjectBackedNativeHandler(context), - registry_(registry) { - RouteFunction("GetSchema", - base::Bind(&SchemaRegistryNativeHandler::GetSchema, - base::Unretained(this))); - } - - private: - v8::Handle<v8::Value> GetSchema(const v8::Arguments& args) { - return registry_->GetSchema(*v8::String::AsciiValue(args[0])); - } - - V8SchemaRegistry* registry_; -}; - -class V8ContextNativeHandler : public ObjectBackedNativeHandler { - public: - explicit V8ContextNativeHandler(ChromeV8Context* context) - : ObjectBackedNativeHandler(context->v8_context()), - context_(context) { - RouteFunction("GetAvailability", - base::Bind(&V8ContextNativeHandler::GetAvailability, - base::Unretained(this))); - } - - private: - v8::Handle<v8::Value> GetAvailability(const v8::Arguments& args) { - CHECK_EQ(args.Length(), 1); - std::string api_name = *v8::String::AsciiValue(args[0]->ToString()); - Feature::Availability availability = context_->GetAvailability(api_name); - - v8::Handle<v8::Object> ret = v8::Object::New(); - ret->Set(v8::String::New("is_available"), - v8::Boolean::New(availability.is_available())); - ret->Set(v8::String::New("message"), - v8::String::New(availability.message().c_str())); - return ret; - } - - ChromeV8Context* context_; -}; - -class ChromeHiddenNativeHandler : public ObjectBackedNativeHandler { - public: - explicit ChromeHiddenNativeHandler(v8::Handle<v8::Context> context) - : ObjectBackedNativeHandler(context) { + explicit ChromeHiddenNativeHandler(v8::Isolate* isolate) + : NativeHandler(isolate) { RouteFunction("GetChromeHidden", base::Bind(&ChromeHiddenNativeHandler::GetChromeHidden, base::Unretained(this))); } v8::Handle<v8::Value> GetChromeHidden(const v8::Arguments& args) { - return ChromeV8Context::GetOrCreateChromeHidden(v8_context()); - } -}; - -class ChromeNativeHandler : public ObjectBackedNativeHandler { - public: - explicit ChromeNativeHandler(v8::Handle<v8::Context> context) - : ObjectBackedNativeHandler(context) { - RouteFunction("GetChrome", - base::Bind(&ChromeNativeHandler::GetChrome, base::Unretained(this))); - } - - v8::Handle<v8::Value> GetChrome(const v8::Arguments& args) { - return GetOrCreateChrome(v8_context()); + return ChromeV8Context::GetOrCreateChromeHidden(v8::Context::GetCurrent()); } }; -class PrintNativeHandler : public ObjectBackedNativeHandler { +class PrintNativeHandler : public NativeHandler { public: - explicit PrintNativeHandler(v8::Handle<v8::Context> context) - : ObjectBackedNativeHandler(context) { + explicit PrintNativeHandler(v8::Isolate* isolate) + : NativeHandler(isolate) { RouteFunction("Print", base::Bind(&PrintNativeHandler::Print, base::Unretained(this))); @@ -215,8 +139,7 @@ class LazyBackgroundPageNativeHandler : public ChromeV8Extension { } v8::Handle<v8::Value> IncrementKeepaliveCount(const v8::Arguments& args) { - ChromeV8Context* context = - dispatcher()->v8_context_set().GetByV8Context(v8_context()); + ChromeV8Context* context = dispatcher()->v8_context_set().GetCurrent(); if (!context) return v8::Undefined(); RenderView* render_view = context->GetRenderView(); @@ -228,8 +151,7 @@ class LazyBackgroundPageNativeHandler : public ChromeV8Extension { } v8::Handle<v8::Value> DecrementKeepaliveCount(const v8::Arguments& args) { - ChromeV8Context* context = - dispatcher()->v8_context_set().GetByV8Context(v8_context()); + ChromeV8Context* context = dispatcher()->v8_context_set().GetCurrent(); if (!context) return v8::Undefined(); RenderView* render_view = context->GetRenderView(); @@ -317,12 +239,13 @@ class ProcessInfoNativeHandler : public ChromeV8Extension { bool send_request_disabled_; }; -class LoggingNativeHandler : public ObjectBackedNativeHandler { +class LoggingNativeHandler : public NativeHandler { public: - explicit LoggingNativeHandler(v8::Handle<v8::Context> context) - : ObjectBackedNativeHandler(context) { + explicit LoggingNativeHandler(v8::Isolate* isolate) + : NativeHandler(isolate) { RouteFunction("DCHECK", - base::Bind(&LoggingNativeHandler::Dcheck, base::Unretained(this))); + base::Bind(&LoggingNativeHandler::Dcheck, + base::Unretained(this))); } v8::Handle<v8::Value> Dcheck(const v8::Arguments& args) { @@ -348,6 +271,7 @@ class LoggingNativeHandler : public ObjectBackedNativeHandler { } } DCHECK(check_value) << error_message; + LOG(WARNING) << error_message; return v8::Undefined(); } @@ -379,6 +303,20 @@ void InstallWebstoreBindings(ModuleSystem* module_system, "chromeHiddenWebstore"); } +static v8::Handle<v8::Object> GetOrCreateChrome( + v8::Handle<v8::Context> context) { + v8::Handle<v8::String> chrome_string(v8::String::New("chrome")); + v8::Handle<v8::Object> global(context->Global()); + v8::Handle<v8::Value> chrome(global->Get(chrome_string)); + if (chrome.IsEmpty() || chrome->IsUndefined()) { + v8::Handle<v8::Object> chrome_object(v8::Object::New()); + global->Set(chrome_string, chrome_object); + return chrome_object; + } + CHECK(chrome->IsObject()); + return chrome->ToObject(); +} + } // namespace Dispatcher::Dispatcher() @@ -399,7 +337,7 @@ Dispatcher::Dispatcher() } user_script_slave_.reset(new UserScriptSlave(&extensions_)); - request_sender_.reset(new RequestSender(this)); + request_sender_.reset(new RequestSender(this, &v8_context_set_)); PopulateSourceMap(); PopulateLazyBindingsMap(); } @@ -623,128 +561,58 @@ bool Dispatcher::AllowScriptExtension(WebFrame* frame, return true; } -v8::Handle<v8::Object> Dispatcher::GetOrCreateObject( - v8::Handle<v8::Object> object, - const std::string& field) { - v8::HandleScope handle_scope; - v8::Handle<v8::String> key = v8::String::New(field.c_str()); - // This little dance is for APIs that may be unavailable but have available - // children. For example, chrome.app can be unavailable, while - // chrome.app.runtime is available. The lazy getter for chrome.app must be - // deleted, so that there isn't an error when accessing chrome.app.runtime. - if (object->Has(key)) { - v8::Handle<v8::Value> value = object->Get(key); - if (value->IsObject()) - return handle_scope.Close(v8::Handle<v8::Object>::Cast(value)); - else - object->Delete(key); - } - - v8::Handle<v8::Object> new_object = v8::Object::New(); - object->Set(key, new_object); - return handle_scope.Close(new_object); -} - -void Dispatcher::RegisterSchemaGeneratedBindings( - ModuleSystem* module_system, - ChromeV8Context* context, - v8::Handle<v8::Context> v8_context) { - std::set<std::string> apis = - ExtensionAPI::GetSharedInstance()->GetAllAPINames(); - for (std::set<std::string>::iterator it = apis.begin(); - it != apis.end(); ++it) { - const std::string& api_name = *it; - - std::vector<std::string> split; - base::SplitString(api_name, '.', &split); - - v8::Handle<v8::Object> bind_object = GetOrCreateChrome(v8_context); - for (size_t i = 0; i < split.size() - 1; ++i) - bind_object = GetOrCreateObject(bind_object, split[i]); - - if (lazy_bindings_map_.find(api_name) != lazy_bindings_map_.end()) { - InstallBindings(module_system, v8_context, api_name); - } else if (!source_map_.Contains(api_name)) { - module_system->RegisterNativeHandler( - api_name, - scoped_ptr<NativeHandler>(new BindingGeneratingNativeHandler( - module_system, - api_name, - "binding"))); - module_system->SetNativeLazyField(bind_object, - split.back(), - api_name, - "binding"); - } else { - module_system->SetLazyField(bind_object, - split.back(), - api_name, - "binding"); - } - } -} - void Dispatcher::RegisterNativeHandlers(ModuleSystem* module_system, ChromeV8Context* context) { module_system->RegisterNativeHandler("event_bindings", - scoped_ptr<NativeHandler>( - EventBindings::Create(this, context->v8_context()))); + scoped_ptr<NativeHandler>(EventBindings::Get(this))); module_system->RegisterNativeHandler("miscellaneous_bindings", - scoped_ptr<NativeHandler>( - MiscellaneousBindings::Get(this, context->v8_context()))); + scoped_ptr<NativeHandler>(MiscellaneousBindings::Get(this))); module_system->RegisterNativeHandler("apiDefinitions", - scoped_ptr<NativeHandler>(new ApiDefinitionsNatives(this, context))); + scoped_ptr<NativeHandler>(new ApiDefinitionsNatives(this))); module_system->RegisterNativeHandler("sendRequest", scoped_ptr<NativeHandler>( - new SendRequestNatives(this, request_sender_.get(), context))); + new SendRequestNatives(this, request_sender_.get()))); module_system->RegisterNativeHandler("setIcon", scoped_ptr<NativeHandler>( - new SetIconNatives(this, request_sender_.get(), context))); + new SetIconNatives(this, request_sender_.get()))); module_system->RegisterNativeHandler("contentWatcherNative", content_watcher_->MakeNatives()); // Natives used by multiple APIs. module_system->RegisterNativeHandler("file_system_natives", - scoped_ptr<NativeHandler>(new FileSystemNatives(context->v8_context()))); + scoped_ptr<NativeHandler>(new FileSystemNatives())); // Custom bindings. module_system->RegisterNativeHandler("app", scoped_ptr<NativeHandler>(new AppBindings(this, context))); module_system->RegisterNativeHandler("app_runtime", - scoped_ptr<NativeHandler>( - new AppRuntimeCustomBindings(this, context->v8_context()))); + scoped_ptr<NativeHandler>(new AppRuntimeCustomBindings())); module_system->RegisterNativeHandler("app_window", - scoped_ptr<NativeHandler>( - new AppWindowCustomBindings(this, context->v8_context()))); + scoped_ptr<NativeHandler>(new AppWindowCustomBindings(this))); module_system->RegisterNativeHandler("context_menus", scoped_ptr<NativeHandler>(new ContextMenusCustomBindings())); module_system->RegisterNativeHandler("extension", scoped_ptr<NativeHandler>( - new ExtensionCustomBindings(this, context->v8_context()))); + new ExtensionCustomBindings(this))); module_system->RegisterNativeHandler("sync_file_system", scoped_ptr<NativeHandler>(new SyncFileSystemCustomBindings())); module_system->RegisterNativeHandler("file_browser_handler", - scoped_ptr<NativeHandler>(new FileBrowserHandlerCustomBindings( - context->v8_context()))); + scoped_ptr<NativeHandler>(new FileBrowserHandlerCustomBindings())); module_system->RegisterNativeHandler("file_browser_private", - scoped_ptr<NativeHandler>(new FileBrowserPrivateCustomBindings( - context->v8_context()))); + scoped_ptr<NativeHandler>(new FileBrowserPrivateCustomBindings())); module_system->RegisterNativeHandler("i18n", - scoped_ptr<NativeHandler>( - new I18NCustomBindings(this, context->v8_context()))); + scoped_ptr<NativeHandler>(new I18NCustomBindings())); module_system->RegisterNativeHandler("mediaGalleries", scoped_ptr<NativeHandler>(new MediaGalleriesCustomBindings())); module_system->RegisterNativeHandler("page_actions", scoped_ptr<NativeHandler>( new PageActionsCustomBindings(this))); module_system->RegisterNativeHandler("page_capture", - scoped_ptr<NativeHandler>( - new PageCaptureCustomBindings(this, context->v8_context()))); + scoped_ptr<NativeHandler>(new PageCaptureCustomBindings())); module_system->RegisterNativeHandler("runtime", - scoped_ptr<NativeHandler>(new RuntimeCustomBindings(this, context))); + scoped_ptr<NativeHandler>(new RuntimeCustomBindings(context))); module_system->RegisterNativeHandler("tabs", - scoped_ptr<NativeHandler>( - new TabsCustomBindings(this, context->v8_context()))); + scoped_ptr<NativeHandler>(new TabsCustomBindings())); module_system->RegisterNativeHandler("tts", scoped_ptr<NativeHandler>(new TTSCustomBindings())); module_system->RegisterNativeHandler("web_request", @@ -757,9 +625,11 @@ void Dispatcher::PopulateSourceMap() { 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", IDR_JSON_JS); source_map_.RegisterSource("json_schema", IDR_JSON_SCHEMA_JS); - source_map_.RegisterSource("test", IDR_TEST_CUSTOM_BINDINGS_JS); + source_map_.RegisterSource("apitest", IDR_EXTENSION_APITEST_JS); // Libraries. source_map_.RegisterSource("contentWatcher", IDR_CONTENT_WATCHER_JS); @@ -828,16 +698,13 @@ void Dispatcher::PopulateSourceMap() { source_map_.RegisterSource("webRequestInternal", IDR_WEB_REQUEST_INTERNAL_CUSTOM_BINDINGS_JS); source_map_.RegisterSource("webstore", IDR_WEBSTORE_CUSTOM_BINDINGS_JS); - source_map_.RegisterSource("binding", IDR_BINDING_JS); // Platform app sources that are not API-specific.. source_map_.RegisterSource("tagWatcher", IDR_TAG_WATCHER_JS); - // Note: webView not webview so that this doesn't interfere with the - // chrome.webview API bindings. - source_map_.RegisterSource("webView", IDR_WEB_VIEW_JS); - source_map_.RegisterSource("webViewExperimental", + source_map_.RegisterSource("webview", IDR_WEB_VIEW_JS); + source_map_.RegisterSource("webview.experimental", IDR_WEB_VIEW_EXPERIMENTAL_JS); - source_map_.RegisterSource("denyWebView", IDR_WEB_VIEW_DENY_JS); + source_map_.RegisterSource("denyWebview", IDR_WEB_VIEW_DENY_JS); source_map_.RegisterSource("platformApp", IDR_PLATFORM_APP_JS); source_map_.RegisterSource("injectAppTitlebar", IDR_INJECT_APP_TITLEBAR_JS); } @@ -909,21 +776,15 @@ void Dispatcher::DidCreateScriptContext( RegisterNativeHandlers(module_system.get(), context); - module_system->RegisterNativeHandler("chrome", - scoped_ptr<NativeHandler>(new ChromeNativeHandler(v8_context))); + v8::Isolate* isolate = v8_context->GetIsolate(); module_system->RegisterNativeHandler("chrome_hidden", - scoped_ptr<NativeHandler>(new ChromeHiddenNativeHandler(v8_context))); + scoped_ptr<NativeHandler>(new ChromeHiddenNativeHandler(isolate))); module_system->RegisterNativeHandler("print", - scoped_ptr<NativeHandler>(new PrintNativeHandler(v8_context))); + scoped_ptr<NativeHandler>(new PrintNativeHandler(isolate))); module_system->RegisterNativeHandler("lazy_background_page", scoped_ptr<NativeHandler>(new LazyBackgroundPageNativeHandler(this))); module_system->RegisterNativeHandler("logging", - scoped_ptr<NativeHandler>(new LoggingNativeHandler(v8_context))); - module_system->RegisterNativeHandler("schema_registry", - scoped_ptr<NativeHandler>( - new SchemaRegistryNativeHandler(v8_schema_registry(), v8_context))); - module_system->RegisterNativeHandler("v8_context", - scoped_ptr<NativeHandler>(new V8ContextNativeHandler(context))); + scoped_ptr<NativeHandler>(new LoggingNativeHandler(isolate))); int manifest_version = extension ? extension->manifest_version() : 1; bool send_request_disabled = @@ -947,20 +808,25 @@ void Dispatcher::DidCreateScriptContext( InstallBindings(module_system.get(), v8_context, "app"); InstallBindings(module_system.get(), v8_context, "webstore"); break; + case Feature::BLESSED_EXTENSION_CONTEXT: case Feature::UNBLESSED_EXTENSION_CONTEXT: case Feature::CONTENT_SCRIPT_CONTEXT: { - if (extension && !extension->is_platform_app()) - module_system->Require("miscellaneous_bindings"); module_system->Require("json"); // see paranoid comment in json.js + module_system->Require("miscellaneous_bindings"); + module_system->Require("schema_generated_bindings"); + module_system->Require("apitest"); // TODO(kalman): move this code back out of the switch and execute it // regardless of |context_type|. ExtensionAPI knows how to return the // correct APIs, however, until it doesn't have a 2MB overhead we can't // load it in every process. - RegisterSchemaGeneratedBindings(module_system.get(), - context, - v8_context); + const std::set<std::string>& apis = context->GetAvailableExtensionAPIs(); + for (std::set<std::string>::const_iterator i = apis.begin(); + i != apis.end(); ++i) { + InstallBindings(module_system.get(), v8_context, *i); + } + break; } } @@ -970,14 +836,11 @@ void Dispatcher::DidCreateScriptContext( module_system->Require("platformApp"); if (context_type == Feature::BLESSED_EXTENSION_CONTEXT) { - // Note: setting up the WebView class here, not the chrome.webview API. - // The API will be automatically set up when first used. - if (extension->HasAPIPermission(APIPermission::kWebView)) { - module_system->Require("webView"); - if (Feature::GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV) - module_system->Require("webViewExperimental"); - } else { - module_system->Require("denyWebView"); + bool has_permission = extension->HasAPIPermission(APIPermission::kWebView); + module_system->Require(has_permission ? "webview" : "denyWebview"); + if (has_permission && + Feature::GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV) { + module_system->Require("webview.experimental"); } } @@ -1019,8 +882,6 @@ void Dispatcher::WillReleaseScriptContext( return; context->DispatchOnUnloadEvent(); - // TODO(kalman): add an invalidation observer interface to ChromeV8Context. - request_sender_->InvalidateContext(context); v8_context_set_.Remove(context); VLOG(1) << "Num tracked contexts: " << v8_context_set_.size(); @@ -1257,8 +1118,9 @@ void Dispatcher::OnExtensionResponse(int request_id, request_sender_->HandleResponse(request_id, success, response, error); } -bool Dispatcher::CheckContextAccessToExtensionAPI( - const std::string& function_name, ChromeV8Context* context) const { +bool Dispatcher::CheckCurrentContextAccessToExtensionAPI( + const std::string& function_name) const { + ChromeV8Context* context = v8_context_set().GetCurrent(); if (!context) { DLOG(ERROR) << "Not in a v8::Context"; return false; diff --git a/chrome/renderer/extensions/dispatcher.h b/chrome/renderer/extensions/dispatcher.h index c6c0e7a..a3a5275 100644 --- a/chrome/renderer/extensions/dispatcher.h +++ b/chrome/renderer/extensions/dispatcher.h @@ -120,8 +120,8 @@ class Dispatcher : public content::RenderProcessObserver { // Checks that the current context contains an extension that has permission // to execute the specified function. If it does not, a v8 exception is thrown // and the method returns false. Otherwise returns true. - bool CheckContextAccessToExtensionAPI( - const std::string& function_name, ChromeV8Context* context) const; + bool CheckCurrentContextAccessToExtensionAPI( + const std::string& function_name) const; private: friend class RenderViewTest; @@ -189,9 +189,6 @@ class Dispatcher : public content::RenderProcessObserver { void RegisterNativeHandlers(ModuleSystem* module_system, ChromeV8Context* context); - void RegisterSchemaGeneratedBindings(ModuleSystem* module_system, - ChromeV8Context* context, - v8::Handle<v8::Context> v8_context); // Inserts static source code into |source_map_|. void PopulateSourceMap(); @@ -214,11 +211,6 @@ class Dispatcher : public content::RenderProcessObserver { int extension_group, const ExtensionURLInfo& url_info); - // Gets |field| from |object| or creates it as an empty object if it doesn't - // exist. - v8::Handle<v8::Object> GetOrCreateObject(v8::Handle<v8::Object> object, - const std::string& field); - // True if this renderer is running extensions. bool is_extension_process_; diff --git a/chrome/renderer/extensions/event_bindings.cc b/chrome/renderer/extensions/event_bindings.cc index bbf16f5..12435a5 100644 --- a/chrome/renderer/extensions/event_bindings.cc +++ b/chrome/renderer/extensions/event_bindings.cc @@ -72,9 +72,8 @@ base::LazyInstance<EventFilter> g_event_filter = LAZY_INSTANCE_INITIALIZER; // TODO(koz): Merge this into EventBindings. class ExtensionImpl : public ChromeV8Extension { public: - explicit ExtensionImpl(Dispatcher* dispatcher, - v8::Handle<v8::Context> v8_context) - : ChromeV8Extension(dispatcher, v8_context) { + explicit ExtensionImpl(Dispatcher* dispatcher) + : ChromeV8Extension(dispatcher) { RouteStaticFunction("AttachEvent", &AttachEvent); RouteStaticFunction("DetachEvent", &DetachEvent); RouteStaticFunction("AttachFilteredEvent", &AttachFilteredEvent); @@ -95,10 +94,10 @@ class ExtensionImpl : public ChromeV8Extension { std::string event_name = *v8::String::AsciiValue(args[0]->ToString()); Dispatcher* dispatcher = self->dispatcher(); const ChromeV8ContextSet& context_set = dispatcher->v8_context_set(); - ChromeV8Context* context = context_set.GetByV8Context(self->v8_context()); + ChromeV8Context* context = context_set.GetCurrent(); CHECK(context); - if (!dispatcher->CheckContextAccessToExtensionAPI(event_name, context)) + if (!dispatcher->CheckCurrentContextAccessToExtensionAPI(event_name)) return v8::Undefined(); std::string extension_id = context->GetExtensionID(); @@ -112,7 +111,7 @@ class ExtensionImpl : public ChromeV8Extension { // This is called the first time the page has added a listener. Since // the background page is the only lazy page, we know this is the first // time this listener has been registered. - if (IsLazyBackgroundPage(self->GetRenderView(), context->extension())) { + if (IsLazyBackgroundPage(context->extension())) { content::RenderThread::Get()->Send( new ExtensionHostMsg_AddLazyListener(extension_id, event_name)); } @@ -132,7 +131,7 @@ class ExtensionImpl : public ChromeV8Extension { ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args); Dispatcher* dispatcher = self->dispatcher(); const ChromeV8ContextSet& context_set = dispatcher->v8_context_set(); - ChromeV8Context* context = context_set.GetByV8Context(self->v8_context()); + ChromeV8Context* context = context_set.GetCurrent(); if (!context) return v8::Undefined(); @@ -149,8 +148,7 @@ class ExtensionImpl : public ChromeV8Extension { // removed. If the context is the background page, and it removes the // last listener manually, then we assume that it is no longer interested // in being awakened for this event. - if (is_manual && IsLazyBackgroundPage(self->GetRenderView(), - context->extension())) { + if (is_manual && IsLazyBackgroundPage(context->extension())) { content::RenderThread::Get()->Send( new ExtensionHostMsg_RemoveLazyListener(extension_id, event_name)); } @@ -171,14 +169,14 @@ class ExtensionImpl : public ChromeV8Extension { ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args); Dispatcher* dispatcher = self->dispatcher(); const ChromeV8ContextSet& context_set = dispatcher->v8_context_set(); - ChromeV8Context* context = context_set.GetByV8Context(self->v8_context()); + ChromeV8Context* context = context_set.GetCurrent(); DCHECK(context); if (!context) return v8::Integer::New(-1); std::string event_name = *v8::String::AsciiValue(args[0]); // This method throws an exception if it returns false. - if (!dispatcher->CheckContextAccessToExtensionAPI(event_name, context)) + if (!dispatcher->CheckCurrentContextAccessToExtensionAPI(event_name)) return v8::Undefined(); std::string extension_id = context->GetExtensionID(); @@ -190,8 +188,8 @@ class ExtensionImpl : public ChromeV8Extension { content::V8ValueConverter::create()); base::DictionaryValue* filter_dict = NULL; - base::Value* filter_value = - converter->FromV8Value(args[1]->ToObject(), context->v8_context()); + base::Value* filter_value = converter->FromV8Value(args[1]->ToObject(), + v8::Context::GetCurrent()); if (!filter_value) return v8::Integer::New(-1); if (!filter_value->GetAsDictionary(&filter_dict)) { @@ -206,8 +204,7 @@ class ExtensionImpl : public ChromeV8Extension { // Only send IPCs the first time a filter gets added. if (AddFilter(event_name, extension_id, filter.get())) { - bool lazy = IsLazyBackgroundPage(self->GetRenderView(), - context->extension()); + bool lazy = IsLazyBackgroundPage(context->extension()); content::RenderThread::Get()->Send( new ExtensionHostMsg_AddFilteredListener(extension_id, event_name, *filter, lazy)); @@ -256,7 +253,7 @@ class ExtensionImpl : public ChromeV8Extension { ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args); Dispatcher* dispatcher = self->dispatcher(); const ChromeV8ContextSet& context_set = dispatcher->v8_context_set(); - ChromeV8Context* context = context_set.GetByV8Context(self->v8_context()); + ChromeV8Context* context = context_set.GetCurrent(); if (!context) return v8::Undefined(); @@ -273,8 +270,7 @@ class ExtensionImpl : public ChromeV8Extension { // Only send IPCs the last time a filter gets removed. if (RemoveFilter(event_name, extension_id, event_matcher->value())) { - bool lazy = is_manual && IsLazyBackgroundPage(self->GetRenderView(), - context->extension()); + bool lazy = is_manual && IsLazyBackgroundPage(context->extension()); content::RenderThread::Get()->Send( new ExtensionHostMsg_RemoveFilteredListener(extension_id, event_name, *event_matcher->value(), @@ -315,10 +311,11 @@ class ExtensionImpl : public ChromeV8Extension { } private: - static bool IsLazyBackgroundPage(content::RenderView* render_view, - const Extension* extension) { + static bool IsLazyBackgroundPage(const Extension* extension) { + content::RenderView* render_view = GetCurrentRenderView(); if (!render_view) return false; + ExtensionHelper* helper = ExtensionHelper::Get(render_view); return (extension && BackgroundInfo::HasLazyBackgroundPage(extension) && helper->view_type() == chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); @@ -334,9 +331,8 @@ class ExtensionImpl : public ChromeV8Extension { } // namespace // static -ChromeV8Extension* EventBindings::Create(Dispatcher* dispatcher, - v8::Handle<v8::Context> context) { - return new ExtensionImpl(dispatcher, context); +ChromeV8Extension* EventBindings::Get(Dispatcher* dispatcher) { + return new ExtensionImpl(dispatcher); } } // namespace extensions diff --git a/chrome/renderer/extensions/event_bindings.h b/chrome/renderer/extensions/event_bindings.h index a263ad3..9051dae 100644 --- a/chrome/renderer/extensions/event_bindings.h +++ b/chrome/renderer/extensions/event_bindings.h @@ -5,7 +5,9 @@ #ifndef CHROME_RENDERER_EXTENSIONS_EVENT_BINDINGS_H_ #define CHROME_RENDERER_EXTENSIONS_EVENT_BINDINGS_H_ -#include "v8/include/v8.h" +namespace v8 { +class Extension; +} namespace extensions { class ChromeV8Extension; @@ -15,8 +17,7 @@ class EventFilter; // This class deals with the javascript bindings related to Event objects. class EventBindings { public: - static ChromeV8Extension* Create(Dispatcher* dispatcher, - v8::Handle<v8::Context> context); + static ChromeV8Extension* Get(Dispatcher* dispatcher); }; } // namespace extensions diff --git a/chrome/renderer/extensions/event_unittest.cc b/chrome/renderer/extensions/event_unittest.cc index 8258b42..edd47c0 100644 --- a/chrome/renderer/extensions/event_unittest.cc +++ b/chrome/renderer/extensions/event_unittest.cc @@ -62,9 +62,6 @@ class EventUnittest : public ModuleSystemTest { OverrideNativeHandler("chrome_hidden", "var chromeHidden = {};" "exports.GetChromeHidden = function() { return chromeHidden; };"); - OverrideNativeHandler("chrome", - "var chrome = {};" - "exports.GetChrome = function() { return chrome; };"); OverrideNativeHandler("sendRequest", "exports.sendRequest = function() {};"); OverrideNativeHandler("apiDefinitions", @@ -82,10 +79,9 @@ TEST_F(EventUnittest, AddRemoveTwoListeners) { ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get()); RegisterModule("test", "var assert = requireNative('assert');" - "require('event');" - "var Event = requireNative('chrome').GetChrome().Event;" + "var event = require('event');" "var eventBindings = requireNative('event_bindings');" - "var myEvent = new Event('named-event');" + "var myEvent = new event.Event('named-event');" "var cb1 = function() {};" "var cb2 = function() {};" "myEvent.addListener(cb1);" @@ -101,11 +97,10 @@ TEST_F(EventUnittest, OnUnloadDetachesAllListeners) { ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get()); RegisterModule("test", "var assert = requireNative('assert');" - "require('event');" - "var Event = requireNative('chrome').GetChrome().Event;" + "var event = require('event');" "var eventBindings = requireNative('event_bindings');" "var chromeHidden = requireNative('chrome_hidden').GetChromeHidden();" - "var myEvent = new Event('named-event');" + "var myEvent = new event.Event('named-event');" "var cb1 = function() {};" "var cb2 = function() {};" "myEvent.addListener(cb1);" @@ -119,11 +114,10 @@ TEST_F(EventUnittest, OnUnloadDetachesAllListenersEvenDupes) { ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get()); RegisterModule("test", "var assert = requireNative('assert');" - "require('event');" - "var Event = requireNative('chrome').GetChrome().Event;" + "var event = require('event');" "var eventBindings = requireNative('event_bindings');" "var chromeHidden = requireNative('chrome_hidden').GetChromeHidden();" - "var myEvent = new Event('named-event');" + "var myEvent = new event.Event('named-event');" "var cb1 = function() {};" "myEvent.addListener(cb1);" "myEvent.addListener(cb1);" @@ -135,13 +129,12 @@ TEST_F(EventUnittest, OnUnloadDetachesAllListenersEvenDupes) { TEST_F(EventUnittest, EventsThatSupportRulesMustHaveAName) { ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get()); RegisterModule("test", - "require('event');" - "var Event = requireNative('chrome').GetChrome().Event;" + "var event = require('event');" "var eventOpts = {supportsRules: true};" "var assert = requireNative('assert');" "var caught = false;" "try {" - " var myEvent = new Event(undefined, undefined, eventOpts);" + " var myEvent = new event.Event(undefined, undefined, eventOpts);" "} catch (e) {" " caught = true;" "}" @@ -152,11 +145,10 @@ TEST_F(EventUnittest, EventsThatSupportRulesMustHaveAName) { TEST_F(EventUnittest, NamedEventDispatch) { ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get()); RegisterModule("test", - "require('event');" - "var Event = requireNative('chrome').GetChrome().Event;" + "var event = require('event');" "var chromeHidden = requireNative('chrome_hidden').GetChromeHidden();" "var assert = requireNative('assert');" - "var e = new Event('myevent');" + "var e = new event.Event('myevent');" "var called = false;" "e.addListener(function() { called = true; });" "chromeHidden.Event.dispatchEvent('myevent', []);" @@ -167,10 +159,9 @@ TEST_F(EventUnittest, NamedEventDispatch) { TEST_F(EventUnittest, AddListenerWithFiltersThrowsErrorByDefault) { ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get()); RegisterModule("test", - "require('event');" - "var Event = requireNative('chrome').GetChrome().Event;" + "var event = require('event');" "var assert = requireNative('assert');" - "var e = new Event('myevent');" + "var e = new event.Event('myevent');" "var filter = [{" " url: {hostSuffix: 'google.com'}," "}];" @@ -187,12 +178,11 @@ TEST_F(EventUnittest, AddListenerWithFiltersThrowsErrorByDefault) { TEST_F(EventUnittest, FilteredEventsAttachment) { ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get()); RegisterModule("test", - "require('event');" - "var Event = requireNative('chrome').GetChrome().Event;" + "var event = require('event');" "var assert = requireNative('assert');" "var bindings = requireNative('event_bindings');" "var eventOpts = {supportsListeners: true, supportsFilters: true};" - "var e = new Event('myevent', undefined, eventOpts);" + "var e = new event.Event('myevent', undefined, eventOpts);" "var cb = function() {};" "var filters = {url: [{hostSuffix: 'google.com'}]};" "e.addListener(cb, filters);" @@ -205,12 +195,11 @@ TEST_F(EventUnittest, FilteredEventsAttachment) { TEST_F(EventUnittest, DetachFilteredEvent) { ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get()); RegisterModule("test", - "require('event');" - "var Event = requireNative('chrome').GetChrome().Event;" + "var event = require('event');" "var assert = requireNative('assert');" "var bindings = requireNative('event_bindings');" "var eventOpts = {supportsListeners: true, supportsFilters: true};" - "var e = new Event('myevent', undefined, eventOpts);" + "var e = new event.Event('myevent', undefined, eventOpts);" "var cb1 = function() {};" "var cb2 = function() {};" "var filters = {url: [{hostSuffix: 'google.com'}]};" @@ -224,12 +213,11 @@ TEST_F(EventUnittest, DetachFilteredEvent) { TEST_F(EventUnittest, AttachAndRemoveSameFilteredEventListener) { ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get()); RegisterModule("test", - "require('event');" - "var Event = requireNative('chrome').GetChrome().Event;" + "var event = require('event');" "var assert = requireNative('assert');" "var bindings = requireNative('event_bindings');" "var eventOpts = {supportsListeners: true, supportsFilters: true};" - "var e = new Event('myevent', undefined, eventOpts);" + "var e = new event.Event('myevent', undefined, eventOpts);" "var cb = function() {};" "var filters = {url: [{hostSuffix: 'google.com'}]};" "e.addListener(cb, filters);" @@ -245,11 +233,10 @@ TEST_F(EventUnittest, AttachAndRemoveSameFilteredEventListener) { TEST_F(EventUnittest, AddingFilterWithUrlFieldNotAListThrowsException) { ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get()); RegisterModule("test", - "require('event');" - "var Event = requireNative('chrome').GetChrome().Event;" + "var event = require('event');" "var assert = requireNative('assert');" "var eventOpts = {supportsListeners: true, supportsFilters: true};" - "var e = new Event('myevent', undefined, eventOpts);" + "var e = new event.Event('myevent', undefined, eventOpts);" "var cb = function() {};" "var filters = {url: {hostSuffix: 'google.com'}};" "var caught = false;" @@ -265,11 +252,10 @@ TEST_F(EventUnittest, AddingFilterWithUrlFieldNotAListThrowsException) { TEST_F(EventUnittest, MaxListeners) { ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get()); RegisterModule("test", - "require('event');" - "var Event = requireNative('chrome').GetChrome().Event;" + "var event = require('event');" "var assert = requireNative('assert');" "var eventOpts = {supportsListeners: true, maxListeners: 1};" - "var e = new Event('myevent', undefined, eventOpts);" + "var e = new event.Event('myevent', undefined, eventOpts);" "var cb = function() {};" "var caught = false;" "try {" diff --git a/chrome/renderer/extensions/extension_custom_bindings.cc b/chrome/renderer/extensions/extension_custom_bindings.cc index 2c290e52..1cc5e099 100644 --- a/chrome/renderer/extensions/extension_custom_bindings.cc +++ b/chrome/renderer/extensions/extension_custom_bindings.cc @@ -26,10 +26,8 @@ namespace { } // namespace -ExtensionCustomBindings::ExtensionCustomBindings( - Dispatcher* dispatcher, - v8::Handle<v8::Context> context) - : ChromeV8Extension(dispatcher, context) { +ExtensionCustomBindings::ExtensionCustomBindings(Dispatcher* dispatcher) + : ChromeV8Extension(dispatcher) { RouteStaticFunction("GetExtensionViews", &GetExtensionViews); } @@ -74,7 +72,7 @@ v8::Handle<v8::Value> ExtensionCustomBindings::GetExtensionViews( ExtensionCustomBindings* v8_extension = GetFromArguments<ExtensionCustomBindings>(args); const Extension* extension = - v8_extension->GetExtensionForRenderView(); + v8_extension->GetExtensionForCurrentRenderView(); if (!extension) return v8::Undefined(); diff --git a/chrome/renderer/extensions/extension_custom_bindings.h b/chrome/renderer/extensions/extension_custom_bindings.h index 5123a6c..01d27df3 100644 --- a/chrome/renderer/extensions/extension_custom_bindings.h +++ b/chrome/renderer/extensions/extension_custom_bindings.h @@ -13,8 +13,7 @@ class Dispatcher; // Implements custom bindings for the extension API. class ExtensionCustomBindings : public ChromeV8Extension { public: - explicit ExtensionCustomBindings(Dispatcher* dispatcher, - v8::Handle<v8::Context> context); + explicit ExtensionCustomBindings(Dispatcher* dispatcher); private: static v8::Handle<v8::Value> GetExtensionViews(const v8::Arguments& args); diff --git a/chrome/renderer/extensions/extension_helper.cc b/chrome/renderer/extensions/extension_helper.cc index c0e513d..c97c22a 100644 --- a/chrome/renderer/extensions/extension_helper.cc +++ b/chrome/renderer/extensions/extension_helper.cc @@ -509,7 +509,8 @@ void ExtensionHelper::DidDownloadApplicationIcon(ImageResourceFetcher* fetcher, if (current_size > kMaxIconSize - actual_icon_size) { AddMessageToRootConsole( content::CONSOLE_MESSAGE_LEVEL_ERROR, - "Icons are too large. Maximum total size for app icons is 128 KB."); + ASCIIToUTF16("Icons are too large. " + "Maximum total size for app icons is 128 KB.")); return; } actual_icon_size += current_size; @@ -521,11 +522,6 @@ void ExtensionHelper::DidDownloadApplicationIcon(ImageResourceFetcher* fetcher, } void ExtensionHelper::AddMessageToRootConsole(ConsoleMessageLevel level, - const std::string& message) { - AddMessageToRootConsole(level, ASCIIToUTF16(message)); -} - -void ExtensionHelper::AddMessageToRootConsole(ConsoleMessageLevel level, const string16& message) { if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { WebConsoleMessage::Level target_level = WebConsoleMessage::LevelLog; diff --git a/chrome/renderer/extensions/extension_helper.h b/chrome/renderer/extensions/extension_helper.h index 350f4a0..8eb414f 100644 --- a/chrome/renderer/extensions/extension_helper.h +++ b/chrome/renderer/extensions/extension_helper.h @@ -64,10 +64,6 @@ class ExtensionHelper int browser_window_id() const { return browser_window_id_; } chrome::ViewType view_type() const { return view_type_; } - // Helper to add a logging message to the root frame's console. - void AddMessageToRootConsole(content::ConsoleMessageLevel level, - const std::string& message); - private: // RenderViewObserver implementation. virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; @@ -115,7 +111,7 @@ class ExtensionHelper void DidDownloadApplicationIcon(webkit_glue::ImageResourceFetcher* fetcher, const SkBitmap& image); - // Helper to add a logging message to the root frame's console. + // Helper to add an logging message to the root frame's console. void AddMessageToRootConsole(content::ConsoleMessageLevel level, const string16& message); diff --git a/chrome/renderer/extensions/file_browser_handler_custom_bindings.cc b/chrome/renderer/extensions/file_browser_handler_custom_bindings.cc index ad0238c..78800db 100644 --- a/chrome/renderer/extensions/file_browser_handler_custom_bindings.cc +++ b/chrome/renderer/extensions/file_browser_handler_custom_bindings.cc @@ -13,19 +13,9 @@ #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" -namespace extensions { - -FileBrowserHandlerCustomBindings::FileBrowserHandlerCustomBindings( - v8::Handle<v8::Context> context) - : ChromeV8Extension(NULL, context) { - RouteFunction( - "GetExternalFileEntry", - base::Bind(&FileBrowserHandlerCustomBindings::GetExternalFileEntry, - base::Unretained(this))); -} +namespace { -v8::Handle<v8::Value> FileBrowserHandlerCustomBindings::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) @@ -43,8 +33,7 @@ v8::Handle<v8::Value> FileBrowserHandlerCustomBindings::GetExternalFileEntry( v8::String::New("fileFullPath")))); bool is_directory = file_def->Get(v8::String::New("fileIsDirectory"))->ToBoolean()->Value(); - WebKit::WebFrame* webframe = - WebKit::WebFrame::frameForContext(v8_context()); + WebKit::WebFrame* webframe = WebKit::WebFrame::frameForCurrentContext(); return webframe->createFileEntry( WebKit::WebFileSystem::TypeExternal, WebKit::WebString::fromUTF8(file_system_name.c_str()), @@ -56,4 +45,14 @@ v8::Handle<v8::Value> FileBrowserHandlerCustomBindings::GetExternalFileEntry( #endif } +} // 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 cf9c1ad..a34769d 100644 --- a/chrome/renderer/extensions/file_browser_handler_custom_bindings.h +++ b/chrome/renderer/extensions/file_browser_handler_custom_bindings.h @@ -13,11 +13,9 @@ namespace extensions { // Custom bindings for the fileBrowserHandler API. class FileBrowserHandlerCustomBindings : public ChromeV8Extension { public: - explicit FileBrowserHandlerCustomBindings(v8::Handle<v8::Context> context); + FileBrowserHandlerCustomBindings(); private: - v8::Handle<v8::Value> GetExternalFileEntry(const v8::Arguments& args); - 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 364dfa4..355e838 100644 --- a/chrome/renderer/extensions/file_browser_private_custom_bindings.cc +++ b/chrome/renderer/extensions/file_browser_private_custom_bindings.cc @@ -13,18 +13,9 @@ #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" -namespace extensions { - -FileBrowserPrivateCustomBindings::FileBrowserPrivateCustomBindings( - v8::Handle<v8::Context> context) - : ChromeV8Extension(NULL, context) { - RouteFunction( - "GetLocalFileSystem", - base::Bind(&FileBrowserPrivateCustomBindings::GetLocalFileSystem, - base::Unretained(this))); -} +namespace { -v8::Handle<v8::Value> FileBrowserPrivateCustomBindings::GetLocalFileSystem( +static v8::Handle<v8::Value> GetLocalFileSystem( const v8::Arguments& args) { DCHECK(args.Length() == 2); DCHECK(args[0]->IsString()); @@ -32,7 +23,7 @@ v8::Handle<v8::Value> FileBrowserPrivateCustomBindings::GetLocalFileSystem( std::string name(*v8::String::Utf8Value(args[0])); std::string path(*v8::String::Utf8Value(args[1])); - WebKit::WebFrame* webframe = WebKit::WebFrame::frameForContext(v8_context()); + WebKit::WebFrame* webframe = WebKit::WebFrame::frameForCurrentContext(); DCHECK(webframe); return webframe->createFileSystem( WebKit::WebFileSystem::TypeExternal, @@ -40,4 +31,13 @@ v8::Handle<v8::Value> FileBrowserPrivateCustomBindings::GetLocalFileSystem( WebKit::WebString::fromUTF8(path.c_str())); } +} // namespace + +namespace extensions { + +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 20c7065..f1fce16 100644 --- a/chrome/renderer/extensions/file_browser_private_custom_bindings.h +++ b/chrome/renderer/extensions/file_browser_private_custom_bindings.h @@ -13,9 +13,7 @@ namespace extensions { // Custom bindings for the fileBrowserPrivate API. class FileBrowserPrivateCustomBindings : public ChromeV8Extension { public: - explicit FileBrowserPrivateCustomBindings(v8::Handle<v8::Context> context); - - v8::Handle<v8::Value> GetLocalFileSystem(const v8::Arguments& args); + FileBrowserPrivateCustomBindings(); private: DISALLOW_COPY_AND_ASSIGN(FileBrowserPrivateCustomBindings); diff --git a/chrome/renderer/extensions/file_system_natives.cc b/chrome/renderer/extensions/file_system_natives.cc index 7812fe0..81fbf92 100644 --- a/chrome/renderer/extensions/file_system_natives.cc +++ b/chrome/renderer/extensions/file_system_natives.cc @@ -18,23 +18,14 @@ #include "webkit/fileapi/file_system_types.h" #include "webkit/fileapi/file_system_util.h" -namespace extensions { - -FileSystemNatives::FileSystemNatives(v8::Handle<v8::Context> context) - : ObjectBackedNativeHandler(context) { - RouteFunction("GetFileEntry", - base::Bind(&FileSystemNatives::GetFileEntry, base::Unretained(this))); - RouteFunction("GetIsolatedFileSystem", - base::Bind(&FileSystemNatives::GetIsolatedFileSystem, - base::Unretained(this))); -} +namespace { -v8::Handle<v8::Value> FileSystemNatives::GetIsolatedFileSystem( +static v8::Handle<v8::Value> GetIsolatedFileSystem( const v8::Arguments& args) { DCHECK(args.Length() == 1 || args.Length() == 2); DCHECK(args[0]->IsString()); std::string file_system_id(*v8::String::Utf8Value(args[0])); - WebKit::WebFrame* webframe = WebKit::WebFrame::frameForContext(v8_context()); + WebKit::WebFrame* webframe = WebKit::WebFrame::frameForCurrentContext(); DCHECK(webframe); GURL context_url = @@ -63,8 +54,7 @@ v8::Handle<v8::Value> FileSystemNatives::GetIsolatedFileSystem( WebKit::WebString::fromUTF8(root)); } -v8::Handle<v8::Value> FileSystemNatives::GetFileEntry( - const v8::Arguments& args) { +static v8::Handle<v8::Value> GetFileEntry(const v8::Arguments& args) { DCHECK(args.Length() == 5); DCHECK(args[0]->IsString()); std::string type_string = *v8::String::Utf8Value(args[0]->ToString()); @@ -87,7 +77,7 @@ v8::Handle<v8::Value> FileSystemNatives::GetFileEntry( DCHECK(args[4]->IsBoolean()); bool is_directory = args[4]->BooleanValue(); - WebKit::WebFrame* webframe = WebKit::WebFrame::frameForContext(v8_context()); + WebKit::WebFrame* webframe = WebKit::WebFrame::frameForCurrentContext(); DCHECK(webframe); return webframe->createFileEntry( type, @@ -97,4 +87,14 @@ v8::Handle<v8::Value> FileSystemNatives::GetFileEntry( is_directory); } +} // namespace + +namespace extensions { + +FileSystemNatives::FileSystemNatives() + : ChromeV8Extension(NULL) { + RouteStaticFunction("GetFileEntry", &GetFileEntry); + RouteStaticFunction("GetIsolatedFileSystem", &GetIsolatedFileSystem); +} + } // namespace extensions diff --git a/chrome/renderer/extensions/file_system_natives.h b/chrome/renderer/extensions/file_system_natives.h index 6768eae..c57a9a9 100644 --- a/chrome/renderer/extensions/file_system_natives.h +++ b/chrome/renderer/extensions/file_system_natives.h @@ -6,19 +6,16 @@ #define CHROME_RENDERER_EXTENSIONS_FILE_SYSTEM_NATIVES_H_ #include "base/compiler_specific.h" -#include "chrome/renderer/extensions/object_backed_native_handler.h" +#include "chrome/renderer/extensions/chrome_v8_extension.h" namespace extensions { // Custom bindings for the nativeFileSystem API. -class FileSystemNatives : public ObjectBackedNativeHandler { +class FileSystemNatives : public ChromeV8Extension { public: - explicit FileSystemNatives(v8::Handle<v8::Context> context); + FileSystemNatives(); private: - v8::Handle<v8::Value> GetFileEntry(const v8::Arguments& args); - v8::Handle<v8::Value> GetIsolatedFileSystem(const v8::Arguments& args); - DISALLOW_COPY_AND_ASSIGN(FileSystemNatives); }; diff --git a/chrome/renderer/extensions/i18n_custom_bindings.cc b/chrome/renderer/extensions/i18n_custom_bindings.cc index 44ee27b..7dfcb0f 100644 --- a/chrome/renderer/extensions/i18n_custom_bindings.cc +++ b/chrome/renderer/extensions/i18n_custom_bindings.cc @@ -12,17 +12,14 @@ namespace extensions { -I18NCustomBindings::I18NCustomBindings(Dispatcher* dispatcher, - v8::Handle<v8::Context> context) - : ChromeV8Extension(dispatcher, context) { +I18NCustomBindings::I18NCustomBindings() + : ChromeV8Extension(NULL) { RouteStaticFunction("GetL10nMessage", &GetL10nMessage); } // static v8::Handle<v8::Value> I18NCustomBindings::GetL10nMessage( const v8::Arguments& args) { - I18NCustomBindings* self = GetFromArguments<I18NCustomBindings>(args); - if (args.Length() != 3 || !args[0]->IsString()) { NOTREACHED() << "Bad arguments"; return v8::Undefined(); @@ -41,7 +38,7 @@ v8::Handle<v8::Value> I18NCustomBindings::GetL10nMessage( if (!l10n_messages) { // Get the current RenderView so that we can send a routed IPC message // from the correct source. - content::RenderView* renderview = self->GetRenderView(); + content::RenderView* renderview = GetCurrentRenderView(); if (!renderview) return v8::Undefined(); diff --git a/chrome/renderer/extensions/i18n_custom_bindings.h b/chrome/renderer/extensions/i18n_custom_bindings.h index faa9db7..beab173 100644 --- a/chrome/renderer/extensions/i18n_custom_bindings.h +++ b/chrome/renderer/extensions/i18n_custom_bindings.h @@ -12,7 +12,7 @@ namespace extensions { // Implements custom bindings for the i18n API. class I18NCustomBindings : public ChromeV8Extension { public: - I18NCustomBindings(Dispatcher* dispatcher, v8::Handle<v8::Context> context); + 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 32c7fab..08c12d2 100644 --- a/chrome/renderer/extensions/json_schema_unittest.cc +++ b/chrome/renderer/extensions/json_schema_unittest.cc @@ -27,17 +27,12 @@ class JsonSchemaTest : public V8UnitTest { std::string code = ResourceBundle::GetSharedInstance().GetRawDataResource( IDR_JSON_SCHEMA_JS).as_string(); - // json_schema.js expects to have require() and requireNative() defined. + // json_schema.js expects to have requireNative() defined. ExecuteScriptInContext( "function requireNative(id) {" " return {" " GetChromeHidden: function() { return {}; }," " };" - "}" - "function require(id) {" - " return {" - " loadRefDependency: function(foo) { return {}; }," - " };" "}", "test-code"); ExecuteScriptInContext(code, kJsonSchema); diff --git a/chrome/renderer/extensions/miscellaneous_bindings.cc b/chrome/renderer/extensions/miscellaneous_bindings.cc index 35d24bd..facdec7 100644 --- a/chrome/renderer/extensions/miscellaneous_bindings.cc +++ b/chrome/renderer/extensions/miscellaneous_bindings.cc @@ -65,9 +65,8 @@ const char kPortClosedError[] = "Attempting to use a disconnected port object"; class ExtensionImpl : public extensions::ChromeV8Extension { public: - explicit ExtensionImpl(extensions::Dispatcher* dispatcher, - v8::Handle<v8::Context> context) - : extensions::ChromeV8Extension(dispatcher, context) { + explicit ExtensionImpl(extensions::Dispatcher* dispatcher) + : extensions::ChromeV8Extension(dispatcher) { RouteStaticFunction("CloseChannel", &CloseChannel); RouteStaticFunction("PortAddRef", &PortAddRef); RouteStaticFunction("PortRelease", &PortRelease); @@ -79,8 +78,7 @@ class ExtensionImpl : public extensions::ChromeV8Extension { // Sends a message along the given channel. static v8::Handle<v8::Value> PostMessage(const v8::Arguments& args) { - ExtensionImpl* self = GetFromArguments<ExtensionImpl>(args); - content::RenderView* renderview = self->GetRenderView(); + content::RenderView* renderview = GetCurrentRenderView(); if (!renderview) return v8::Undefined(); @@ -180,10 +178,8 @@ class ExtensionImpl : public extensions::ChromeV8Extension { namespace extensions { -ChromeV8Extension* MiscellaneousBindings::Get( - Dispatcher* dispatcher, - v8::Handle<v8::Context> context) { - return new ExtensionImpl(dispatcher, context); +ChromeV8Extension* MiscellaneousBindings::Get(Dispatcher* dispatcher) { + return new ExtensionImpl(dispatcher); } // static diff --git a/chrome/renderer/extensions/miscellaneous_bindings.h b/chrome/renderer/extensions/miscellaneous_bindings.h index d6ecd4a..c1cb1ef 100644 --- a/chrome/renderer/extensions/miscellaneous_bindings.h +++ b/chrome/renderer/extensions/miscellaneous_bindings.h @@ -30,8 +30,7 @@ class Dispatcher; class MiscellaneousBindings { public: // Creates an instance of the extension. - static ChromeV8Extension* Get(Dispatcher* dispatcher, - v8::Handle<v8::Context> context); + static ChromeV8Extension* Get(Dispatcher* dispatcher); // Dispatches the Port.onConnect content script messaging event to some // contexts in |contexts|. If |restrict_to_render_view| is specified, only diff --git a/chrome/renderer/extensions/module_system.cc b/chrome/renderer/extensions/module_system.cc index 74e7d3d..31146c8 100644 --- a/chrome/renderer/extensions/module_system.cc +++ b/chrome/renderer/extensions/module_system.cc @@ -6,10 +6,6 @@ #include "base/bind.h" #include "base/stl_util.h" -#include "base/stringprintf.h" -#include "chrome/common/extensions/extension_messages.h" -#include "chrome/renderer/extensions/chrome_v8_context.h" -#include "content/public/renderer/render_view.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebScopedMicrotaskSuppression.h" namespace { @@ -25,35 +21,28 @@ namespace extensions { ModuleSystem::ModuleSystem(v8::Handle<v8::Context> context, SourceMap* source_map) - : ObjectBackedNativeHandler(context), + : NativeHandler(context->GetIsolate()), + context_(v8::Persistent<v8::Context>::New(context->GetIsolate(), + context)), source_map_(source_map), - natives_enabled_(0), - is_valid_(true) { + natives_enabled_(0) { RouteFunction("require", base::Bind(&ModuleSystem::RequireForJs, base::Unretained(this))); RouteFunction("requireNative", - base::Bind(&ModuleSystem::RequireNative, base::Unretained(this))); + base::Bind(&ModuleSystem::GetNative, base::Unretained(this))); - v8::Handle<v8::Object> global(context->Global()); + v8::Handle<v8::Object> global(context_->Global()); global->SetHiddenValue(v8::String::New(kModulesField), v8::Object::New()); global->SetHiddenValue(v8::String::New(kModuleSystem), v8::External::New(this)); } ModuleSystem::~ModuleSystem() { - Invalidate(); -} - -bool ModuleSystem::Invalidate() { - if (!ObjectBackedNativeHandler::Invalidate()) - return false; - v8::HandleScope handle_scope; // Deleting this value here prevents future lazy field accesses from // referencing ModuleSystem after it has been freed. - v8_context()->Global()->DeleteHiddenValue(v8::String::New(kModuleSystem)); - - return true; + context_->Global()->DeleteHiddenValue(v8::String::New(kModuleSystem)); + context_.Dispose(context_->GetIsolate()); } ModuleSystem::NativesEnabledScope::NativesEnabledScope( @@ -69,7 +58,6 @@ ModuleSystem::NativesEnabledScope::~NativesEnabledScope() { // static bool ModuleSystem::IsPresentInCurrentContext() { - // XXX(kalman): Not sure if this is safe. Investigate. v8::Handle<v8::Object> global(v8::Context::GetCurrent()->Global()); if (global.IsEmpty()) return false; @@ -85,10 +73,13 @@ void ModuleSystem::HandleException(const v8::TryCatch& try_catch) { } // static -std::string ModuleSystem::CreateExceptionString(const v8::TryCatch& try_catch) { +void ModuleSystem::DumpException(const v8::TryCatch& try_catch) { + v8::HandleScope handle_scope; + v8::Handle<v8::Message> message(try_catch.Message()); if (message.IsEmpty()) { - return "try_catch has no message"; + LOG(ERROR) << "try_catch has no message"; + return; } std::string resource_name = "<unknown resource>"; @@ -101,16 +92,6 @@ std::string ModuleSystem::CreateExceptionString(const v8::TryCatch& try_catch) { if (!message->Get().IsEmpty()) error_message = *v8::String::Utf8Value(message->Get()); - return base::StringPrintf("%s:%d: %s", - resource_name.c_str(), - message->GetLineNumber(), - error_message.c_str()); -} - -// static -void ModuleSystem::DumpException(const v8::TryCatch& try_catch) { - v8::HandleScope handle_scope; - std::string stack_trace = "<stack trace unavailable>"; if (!try_catch.StackTrace().IsEmpty()) { v8::String::Utf8Value stack_value(try_catch.StackTrace()); @@ -120,13 +101,14 @@ void ModuleSystem::DumpException(const v8::TryCatch& try_catch) { stack_trace = "<could not convert stack trace to string>"; } - LOG(ERROR) << CreateExceptionString(try_catch) << "{" << stack_trace << "}"; + LOG(ERROR) << "[" << resource_name << "(" << message->GetLineNumber() << ")] " + << error_message + << "{" << stack_trace << "}"; } -v8::Handle<v8::Value> ModuleSystem::Require(const std::string& module_name) { +void ModuleSystem::Require(const std::string& module_name) { v8::HandleScope handle_scope; - return handle_scope.Close( - RequireForJsInner(v8::String::New(module_name.c_str()))); + RequireForJsInner(v8::String::New(module_name.c_str())); } v8::Handle<v8::Value> ModuleSystem::RequireForJs(const v8::Arguments& args) { @@ -137,9 +119,8 @@ v8::Handle<v8::Value> ModuleSystem::RequireForJs(const v8::Arguments& args) { v8::Handle<v8::Value> ModuleSystem::RequireForJsInner( v8::Handle<v8::String> module_name) { - CHECK(is_valid_); v8::HandleScope handle_scope; - v8::Handle<v8::Object> global(v8_context()->Global()); + v8::Handle<v8::Object> global(v8::Context::GetCurrent()->Global()); v8::Handle<v8::Object> modules(v8::Handle<v8::Object>::Cast( global->GetHiddenValue(v8::String::New(kModulesField)))); v8::Handle<v8::Value> exports(modules->Get(module_name)); @@ -179,11 +160,10 @@ v8::Handle<v8::Value> ModuleSystem::RequireForJsInner( return handle_scope.Close(exports); } -v8::Local<v8::Value> ModuleSystem::CallModuleMethod( - const std::string& module_name, - const std::string& method_name) { +void ModuleSystem::CallModuleMethod(const std::string& module_name, + const std::string& method_name) { std::vector<v8::Handle<v8::Value> > args; - return CallModuleMethod(module_name, method_name, &args); + CallModuleMethod(module_name, method_name, &args); } v8::Local<v8::Value> ModuleSystem::CallModuleMethod( @@ -203,7 +183,8 @@ v8::Local<v8::Value> ModuleSystem::CallModuleMethod( return v8::Local<v8::Value>(); v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(value); - v8::Handle<v8::Object> global(v8_context()->Global()); + // TODO(jeremya/koz): refer to context_ here, not the current context. + v8::Handle<v8::Object> global(v8::Context::GetCurrent()->Global()); v8::Local<v8::Value> result; { WebKit::WebScopedMicrotaskSuppression suppression; @@ -216,10 +197,6 @@ v8::Local<v8::Value> ModuleSystem::CallModuleMethod( return handle_scope.Close(result); } -bool ModuleSystem::HasNativeHandler(const std::string& name) { - return native_handler_map_.find(name) != native_handler_map_.end(); -} - void ModuleSystem::RegisterNativeHandler(const std::string& name, scoped_ptr<NativeHandler> native_handler) { native_handler_map_[name] = @@ -236,29 +213,13 @@ void ModuleSystem::RunString(const std::string& code, const std::string& name) { } // static -v8::Handle<v8::Value> ModuleSystem::NativeLazyFieldGetter( - v8::Local<v8::String> property, const v8::AccessorInfo& info) { - return LazyFieldGetterInner(property, - info, - &ModuleSystem::RequireNativeFromString); -} - -// static v8::Handle<v8::Value> ModuleSystem::LazyFieldGetter( v8::Local<v8::String> property, const v8::AccessorInfo& info) { - return LazyFieldGetterInner(property, info, &ModuleSystem::Require); -} - -// static -v8::Handle<v8::Value> ModuleSystem::LazyFieldGetterInner( - v8::Local<v8::String> property, - const v8::AccessorInfo& info, - GetModuleFunc get_module) { CHECK(!info.Data().IsEmpty()); CHECK(info.Data()->IsObject()); v8::HandleScope handle_scope; v8::Handle<v8::Object> parameters = v8::Handle<v8::Object>::Cast(info.Data()); - v8::Handle<v8::Object> global(parameters->CreationContext()->Global()); + v8::Handle<v8::Object> global(v8::Context::GetCurrent()->Global()); v8::Handle<v8::Value> module_system_value = global->GetHiddenValue(v8::String::New(kModuleSystem)); if (module_system_value.IsEmpty() || module_system_value->IsUndefined()) { @@ -268,78 +229,38 @@ v8::Handle<v8::Value> ModuleSystem::LazyFieldGetterInner( ModuleSystem* module_system = static_cast<ModuleSystem*>( v8::Handle<v8::External>::Cast(module_system_value)->Value()); - std::string name = *v8::String::AsciiValue( - parameters->Get(v8::String::New(kModuleName))->ToString()); - - // HACK(kalman): Switch to the context of the owner module system while - // lazily requiring modules. - // - // It seems to be a common incorrect assumption throughout code that the - // current context is the owner context. This makes that assumption true for - // at least the period where the JavaScript is first evaluated, which is when - // things are most likely to go wrong. - v8::Context::Scope context_scope(parameters->CreationContext()); - - NativesEnabledScope natives_enabled_scope(module_system); - - v8::TryCatch try_catch; - v8::Handle<v8::Object> module = v8::Handle<v8::Object>::Cast( - (module_system->*get_module)(name)); - if (try_catch.HasCaught()) { - module_system->HandleException(try_catch); - return handle_scope.Close(v8::Handle<v8::Value>()); + v8::Handle<v8::Object> module; + { + NativesEnabledScope scope(module_system); + module = v8::Handle<v8::Object>::Cast(module_system->RequireForJsInner( + parameters->Get(v8::String::New(kModuleName))->ToString())); } - if (module.IsEmpty()) return handle_scope.Close(v8::Handle<v8::Value>()); v8::Handle<v8::String> field = parameters->Get(v8::String::New(kModuleField))->ToString(); - v8::Local<v8::Value> new_field = module->Get(field); - v8::Handle<v8::Object> object = info.This(); - // Delete the getter and set this field to |new_field| so the same object is - // returned every time a certain API is accessed. - if (!new_field->IsUndefined()) { - object->Delete(property); - object->Set(property, new_field); - } - return handle_scope.Close(new_field); + return handle_scope.Close(module->Get(field)); } void ModuleSystem::SetLazyField(v8::Handle<v8::Object> object, const std::string& field, const std::string& module_name, const std::string& module_field) { - SetLazyField(object, field, module_name, module_field, - &ModuleSystem::LazyFieldGetter); -} - -void ModuleSystem::SetLazyField(v8::Handle<v8::Object> object, - const std::string& field, - const std::string& module_name, - const std::string& module_field, - v8::AccessorGetter getter) { v8::HandleScope handle_scope; v8::Handle<v8::Object> parameters = v8::Object::New(); parameters->Set(v8::String::New(kModuleName), v8::String::New(module_name.c_str())); parameters->Set(v8::String::New(kModuleField), v8::String::New(module_field.c_str())); + object->SetAccessor(v8::String::New(field.c_str()), - getter, + &ModuleSystem::LazyFieldGetter, NULL, parameters); } -void ModuleSystem::SetNativeLazyField(v8::Handle<v8::Object> object, - const std::string& field, - const std::string& module_name, - const std::string& module_field) { - SetLazyField(object, field, module_name, module_field, - &ModuleSystem::NativeLazyFieldGetter); -} - v8::Handle<v8::Value> ModuleSystem::RunString(v8::Handle<v8::String> code, v8::Handle<v8::String> name) { v8::HandleScope handle_scope; @@ -369,18 +290,13 @@ v8::Handle<v8::Value> ModuleSystem::GetSource( return handle_scope.Close(source_map_->GetSource(module_name)); } -v8::Handle<v8::Value> ModuleSystem::RequireNative(const v8::Arguments& args) { +v8::Handle<v8::Value> ModuleSystem::GetNative(const v8::Arguments& args) { CHECK_EQ(1, args.Length()); - std::string native_name = *v8::String::AsciiValue(args[0]->ToString()); - return RequireNativeFromString(native_name); -} - -v8::Handle<v8::Value> ModuleSystem::RequireNativeFromString( - const std::string& native_name) { if (natives_enabled_ == 0) return ThrowException("Natives disabled"); + std::string native_name = *v8::String::AsciiValue(args[0]->ToString()); if (overridden_native_handlers_.count(native_name) > 0u) - return RequireForJsInner(v8::String::New(native_name.c_str())); + return RequireForJs(args); NativeHandlerMap::iterator i = native_handler_map_.find(native_name); if (i == native_handler_map_.end()) return v8::Undefined(); diff --git a/chrome/renderer/extensions/module_system.h b/chrome/renderer/extensions/module_system.h index 2521d67..be03f2a 100644 --- a/chrome/renderer/extensions/module_system.h +++ b/chrome/renderer/extensions/module_system.h @@ -8,7 +8,7 @@ #include "base/compiler_specific.h" #include "base/memory/linked_ptr.h" #include "base/memory/scoped_ptr.h" -#include "chrome/renderer/extensions/object_backed_native_handler.h" +#include "chrome/renderer/extensions/native_handler.h" #include "v8/include/v8.h" #include <map> @@ -34,7 +34,7 @@ namespace extensions { // Note that a ModuleSystem must be used only in conjunction with a single // v8::Context. // TODO(koz): Rename this to JavaScriptModuleSystem. -class ModuleSystem : public ObjectBackedNativeHandler { +class ModuleSystem : public NativeHandler { public: class SourceMap { public: @@ -61,7 +61,7 @@ class ModuleSystem : public ObjectBackedNativeHandler { }; // |source_map| is a weak pointer. - ModuleSystem(v8::Handle<v8::Context> context, SourceMap* source_map); + explicit ModuleSystem(v8::Handle<v8::Context> context, SourceMap* source_map); virtual ~ModuleSystem(); // Returns true if the current context has a ModuleSystem installed in it. @@ -72,13 +72,15 @@ class ModuleSystem : public ObjectBackedNativeHandler { // Require the specified module. This is the equivalent of calling // require('module_name') from the loaded JS files. - v8::Handle<v8::Value> Require(const std::string& module_name); + void Require(const std::string& module_name); v8::Handle<v8::Value> Require(const v8::Arguments& args); + v8::Handle<v8::Value> RequireForJs(const v8::Arguments& args); + v8::Handle<v8::Value> RequireForJsInner(v8::Handle<v8::String> module_name); // Calls the specified method exported by the specified module. This is // equivalent to calling require('module_name').method_name() from JS. - v8::Local<v8::Value> CallModuleMethod(const std::string& module_name, - const std::string& method_name); + void CallModuleMethod(const std::string& module_name, + const std::string& method_name); // Calls the specified method exported by the specified module. This is // equivalent to calling require('module_name').method_name(args) from JS. @@ -92,8 +94,6 @@ class ModuleSystem : public ObjectBackedNativeHandler { // |native_handler|. void RegisterNativeHandler(const std::string& name, scoped_ptr<NativeHandler> native_handler); - // Check if a native handler has been registered for this |name|. - bool HasNativeHandler(const std::string& name); // Causes requireNative(|name|) to look for its module in |source_map_| // instead of using a registered native handler. This can be used in unit @@ -106,11 +106,6 @@ class ModuleSystem : public ObjectBackedNativeHandler { // Retrieves the lazily defined field specified by |property|. static v8::Handle<v8::Value> LazyFieldGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info); - // Retrieves the lazily defined field specified by |property| on a native - // object. - static v8::Handle<v8::Value> NativeLazyFieldGetter( - v8::Local<v8::String> property, - const v8::AccessorInfo& info); // Make |object|.|field| lazily evaluate to the result of // require(|module_name|)[|module_field|]. @@ -119,27 +114,16 @@ class ModuleSystem : public ObjectBackedNativeHandler { const std::string& module_name, const std::string& module_field); - // Make |object|.|field| lazily evaluate to the result of - // requireNative(|module_name|)[|module_field|]. - void SetNativeLazyField(v8::Handle<v8::Object> object, - const std::string& field, - const std::string& module_name, - const std::string& module_field); - void set_exception_handler(scoped_ptr<ExceptionHandler> handler) { exception_handler_ = handler.Pass(); } - virtual bool Invalidate() OVERRIDE; - private: typedef std::map<std::string, linked_ptr<NativeHandler> > NativeHandlerMap; // Called when an exception is thrown but not caught. void HandleException(const v8::TryCatch& try_catch); - static std::string CreateExceptionString(const v8::TryCatch& try_catch); - // Ensure that require_ has been evaluated from require.js. void EnsureRequireLoaded(); @@ -148,25 +132,6 @@ class ModuleSystem : public ObjectBackedNativeHandler { v8::Handle<v8::Value> RunString(v8::Handle<v8::String> code, v8::Handle<v8::String> name); - v8::Handle<v8::Value> RequireForJs(const v8::Arguments& args); - v8::Handle<v8::Value> RequireForJsInner(v8::Handle<v8::String> module_name); - - // Sets a lazy field using the specified |getter|. - void SetLazyField(v8::Handle<v8::Object> object, - const std::string& field, - const std::string& module_name, - const std::string& module_field, - v8::AccessorGetter getter); - - typedef v8::Handle<v8::Value> (ModuleSystem::*GetModuleFunc)( - const std::string&); - // Base implementation of a LazyFieldGetter that can be customized by passing - // in a |get_module| function. - static v8::Handle<v8::Value> LazyFieldGetterInner( - v8::Local<v8::String> property, - const v8::AccessorInfo& info, - GetModuleFunc get_module); - // Return the named source file stored in the source map. // |args[0]| - the name of a source file in source_map_. v8::Handle<v8::Value> GetSource(v8::Handle<v8::String> source_name); @@ -174,8 +139,7 @@ class ModuleSystem : public ObjectBackedNativeHandler { // Return an object that contains the native methods defined by the named // NativeHandler. // |args[0]| - the name of a native handler object. - v8::Handle<v8::Value> RequireNativeFromString(const std::string& native_name); - v8::Handle<v8::Value> RequireNative(const v8::Arguments& args); + v8::Handle<v8::Value> GetNative(const v8::Arguments& args); // Wraps |source| in a (function(require, requireNative, exports) {...}). v8::Handle<v8::String> WrapSource(v8::Handle<v8::String> source); @@ -183,6 +147,9 @@ class ModuleSystem : public ObjectBackedNativeHandler { // Throws an exception in the calling JS context. v8::Handle<v8::Value> ThrowException(const std::string& message); + // The context that this ModuleSystem is for. + v8::Persistent<v8::Context> context_; + // A map from module names to the JS source for that module. GetSource() // performs a lookup on this map. SourceMap* source_map_; @@ -194,9 +161,6 @@ class ModuleSystem : public ObjectBackedNativeHandler { // pinned natives as enabled. int natives_enabled_; - // Set to false if |context_| has been deleted and this should not be used. - bool is_valid_; - // Called when an exception is thrown but not caught in JS. scoped_ptr<ExceptionHandler> exception_handler_; diff --git a/chrome/renderer/extensions/module_system_unittest.cc b/chrome/renderer/extensions/module_system_unittest.cc index 4c88cca..f5f7db6 100644 --- a/chrome/renderer/extensions/module_system_unittest.cc +++ b/chrome/renderer/extensions/module_system_unittest.cc @@ -6,15 +6,13 @@ #include "base/memory/scoped_ptr.h" #include "chrome/renderer/extensions/module_system.h" -// TODO(cduvall/kalman): Put this file in extensions namespace. using extensions::ModuleSystem; using extensions::NativeHandler; -using extensions::ObjectBackedNativeHandler; -class CounterNatives : public ObjectBackedNativeHandler { +class CounterNatives : public NativeHandler { public: - explicit CounterNatives(v8::Handle<v8::Context> context) - : ObjectBackedNativeHandler(context), counter_(0) { + explicit CounterNatives(v8::Isolate* isolate) + : NativeHandler(isolate), counter_(0) { RouteFunction("Get", base::Bind(&CounterNatives::Get, base::Unretained(this))); RouteFunction("Increment", base::Bind(&CounterNatives::Increment, @@ -175,7 +173,7 @@ TEST_F(ModuleSystemTest, TestLazyFieldIsOnlyEvaledOnce) { ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get()); module_system_->RegisterNativeHandler( "counter", - scoped_ptr<NativeHandler>(new CounterNatives(v8::Context::GetCurrent()))); + scoped_ptr<NativeHandler>(new CounterNatives(v8::Isolate::GetCurrent()))); RegisterModule("lazy", "requireNative('counter').Increment();" "exports.x = 5;"); @@ -229,7 +227,7 @@ TEST_F(ModuleSystemTest, TestModulesOnlyGetEvaledOnce) { ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get()); module_system_->RegisterNativeHandler( "counter", - scoped_ptr<NativeHandler>(new CounterNatives(v8::Context::GetCurrent()))); + scoped_ptr<NativeHandler>(new CounterNatives(v8::Isolate::GetCurrent()))); RegisterModule("incrementsWhenEvaled", "requireNative('counter').Increment();"); diff --git a/chrome/renderer/extensions/object_backed_native_handler.cc b/chrome/renderer/extensions/native_handler.cc index f57d579..3c41ea5 100644 --- a/chrome/renderer/extensions/object_backed_native_handler.cc +++ b/chrome/renderer/extensions/native_handler.cc @@ -2,34 +2,32 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/renderer/extensions/object_backed_native_handler.h" +#include "chrome/renderer/extensions/native_handler.h" -#include "base/logging.h" #include "base/memory/linked_ptr.h" +#include "base/logging.h" #include "chrome/renderer/extensions/module_system.h" #include "v8/include/v8.h" namespace extensions { -ObjectBackedNativeHandler::ObjectBackedNativeHandler( - v8::Handle<v8::Context> context) - : v8_context_(context), +NativeHandler::NativeHandler(v8::Isolate* isolate) + : isolate_(isolate), object_template_( - v8::Persistent<v8::ObjectTemplate>::New(context->GetIsolate(), - v8::ObjectTemplate::New())), - is_valid_(true) { + v8::Persistent<v8::ObjectTemplate>::New(isolate, + v8::ObjectTemplate::New())) { } -ObjectBackedNativeHandler::~ObjectBackedNativeHandler() { +NativeHandler::~NativeHandler() { + object_template_.Dispose(isolate_); } -v8::Handle<v8::Object> ObjectBackedNativeHandler::NewInstance() { +v8::Handle<v8::Object> NativeHandler::NewInstance() { return object_template_->NewInstance(); } // static -v8::Handle<v8::Value> ObjectBackedNativeHandler::Router( - const v8::Arguments& args) { +v8::Handle<v8::Value> NativeHandler::Router(const v8::Arguments& args) { // It is possible for JS code to execute after ModuleSystem has been deleted // in which case the native handlers will also have been deleted, making // HandlerFunction below point to freed memory. @@ -42,7 +40,7 @@ v8::Handle<v8::Value> ObjectBackedNativeHandler::Router( return handler_function->Run(args); } -void ObjectBackedNativeHandler::RouteFunction(const std::string& name, +void NativeHandler::RouteFunction(const std::string& name, const HandlerFunction& handler_function) { linked_ptr<HandlerFunction> function(new HandlerFunction(handler_function)); // TODO(koz): Investigate using v8's MakeWeak() function instead of holding @@ -54,21 +52,11 @@ void ObjectBackedNativeHandler::RouteFunction(const std::string& name, object_template_->Set(name.c_str(), function_template); } -void ObjectBackedNativeHandler::RouteStaticFunction(const std::string& name, +void NativeHandler::RouteStaticFunction(const std::string& name, const HandlerFunc handler_func) { v8::Handle<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(handler_func, v8::External::New(this)); object_template_->Set(name.c_str(), function_template); } -bool ObjectBackedNativeHandler::Invalidate() { - if (!is_valid_) - return false; - - object_template_.Dispose(v8_context_->GetIsolate()); - - is_valid_ = false; - return true; -} - } // extensions diff --git a/chrome/renderer/extensions/native_handler.h b/chrome/renderer/extensions/native_handler.h index 36ef991..fd6bda6 100644 --- a/chrome/renderer/extensions/native_handler.h +++ b/chrome/renderer/extensions/native_handler.h @@ -5,21 +5,55 @@ #ifndef CHROME_RENDERER_EXTENSIONS_NATIVE_HANDLER_H_ #define CHROME_RENDERER_EXTENSIONS_NATIVE_HANDLER_H_ +#include "base/bind.h" +#include "base/memory/linked_ptr.h" #include "v8/include/v8.h" +#include <string> +#include <vector> + namespace extensions { +// A NativeHandler is a factory for JS objects with functions on them that map +// to native C++ functions. Subclasses should call RouteFunction() in their +// constructor to define functions on the created JS objects. +// // NativeHandlers are intended to be used with a ModuleSystem. The ModuleSystem // will assume ownership of the NativeHandler, and as a ModuleSystem is tied to // a single v8::Context, this implies that NativeHandlers will also be tied to -// a single v8::Context. +// a single v8::context. // TODO(koz): Rename this to NativeJavaScriptModule. class NativeHandler { public: - virtual ~NativeHandler() {} + explicit NativeHandler(v8::Isolate* isolate); + virtual ~NativeHandler(); + + // Create an object with bindings to the native functions defined through + // RouteFunction(). + virtual v8::Handle<v8::Object> NewInstance(); + + protected: + typedef v8::Handle<v8::Value> (*HandlerFunc)(const v8::Arguments&); + typedef base::Callback<v8::Handle<v8::Value>(const v8::Arguments&)> + HandlerFunction; + + // Installs a new 'route' from |name| to |handler_function|. This means that + // NewInstance()s of this NativeHandler will have a property |name| which + // will be handled by |handler_function|. + void RouteFunction(const std::string& name, + const HandlerFunction& handler_function); + + void RouteStaticFunction(const std::string& name, + const HandlerFunc handler_func); + + private: + static v8::Handle<v8::Value> Router(const v8::Arguments& args); + + std::vector<linked_ptr<HandlerFunction> > handler_functions_; + v8::Isolate* isolate_; + v8::Persistent<v8::ObjectTemplate> object_template_; - // Create a new instance of the object this handler specifies. - virtual v8::Handle<v8::Object> NewInstance() = 0; + DISALLOW_COPY_AND_ASSIGN(NativeHandler); }; } // extensions diff --git a/chrome/renderer/extensions/object_backed_native_handler.h b/chrome/renderer/extensions/object_backed_native_handler.h deleted file mode 100644 index 8c7e658..0000000 --- a/chrome/renderer/extensions/object_backed_native_handler.h +++ /dev/null @@ -1,70 +0,0 @@ -// 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_OBJECT_BACKED_NATIVE_HANDLER_H_ -#define CHROME_RENDERER_EXTENSIONS_OBJECT_BACKED_NATIVE_HANDLER_H_ - -#include <string> -#include <vector> - -#include "base/bind.h" -#include "base/memory/linked_ptr.h" -#include "chrome/renderer/extensions/native_handler.h" -#include "v8/include/v8.h" - -namespace extensions { - -// An ObjectBackedNativeHandler is a factory for JS objects with functions on -// them that map to native C++ functions. Subclasses should call RouteFunction() -// in their constructor to define functions on the created JS objects. -class ObjectBackedNativeHandler : public NativeHandler { - public: - explicit ObjectBackedNativeHandler(v8::Handle<v8::Context> context); - virtual ~ObjectBackedNativeHandler(); - - // Create an object with bindings to the native functions defined through - // RouteFunction(). - virtual v8::Handle<v8::Object> NewInstance() OVERRIDE; - - protected: - typedef v8::Handle<v8::Value> (*HandlerFunc)(const v8::Arguments&); - typedef base::Callback<v8::Handle<v8::Value>(const v8::Arguments&)> - HandlerFunction; - - // Installs a new 'route' from |name| to |handler_function|. This means that - // NewInstance()s of this ObjectBackedNativeHandler will have a property - // |name| which will be handled by |handler_function|. - void RouteFunction(const std::string& name, - const HandlerFunction& handler_function); - - void RouteStaticFunction(const std::string& name, - const HandlerFunc handler_func); - - // Invalidate this object so it cannot be used any more. This is needed - // because it's possible for this to outlive |v8_context_|. Invalidate must - // be called before this happens. - // - // Subclasses may override to invalidate their own V8 state, but always - // call superclass eventually. - // - // This must be idempotent. Returns true if it was the first time this was - // called, false otherwise. - virtual bool Invalidate(); - - v8::Handle<v8::Context> v8_context() { return v8_context_; } - - private: - static v8::Handle<v8::Value> Router(const v8::Arguments& args); - - std::vector<linked_ptr<HandlerFunction> > handler_functions_; - v8::Handle<v8::Context> v8_context_; - v8::Persistent<v8::ObjectTemplate> object_template_; - bool is_valid_; - - DISALLOW_COPY_AND_ASSIGN(ObjectBackedNativeHandler); -}; - -} // extensions - -#endif // CHROME_RENDERER_EXTENSIONS_OBJECT_BACKED_NATIVE_HANDLER_H_ diff --git a/chrome/renderer/extensions/page_capture_custom_bindings.cc b/chrome/renderer/extensions/page_capture_custom_bindings.cc index 3b684b9..c7e41ea 100644 --- a/chrome/renderer/extensions/page_capture_custom_bindings.cc +++ b/chrome/renderer/extensions/page_capture_custom_bindings.cc @@ -13,10 +13,8 @@ namespace extensions { -PageCaptureCustomBindings::PageCaptureCustomBindings( - Dispatcher* dispatcher, - v8::Handle<v8::Context> context) - : ChromeV8Extension(dispatcher, context) { +PageCaptureCustomBindings::PageCaptureCustomBindings() + : ChromeV8Extension(NULL) { RouteStaticFunction("CreateBlob", &CreateBlob); RouteStaticFunction("SendResponseAck", &SendResponseAck); } @@ -39,9 +37,7 @@ v8::Handle<v8::Value> PageCaptureCustomBindings::SendResponseAck( CHECK(args.Length() == 1); CHECK(args[0]->IsInt32()); - PageCaptureCustomBindings* self = - GetFromArguments<PageCaptureCustomBindings>(args); - content::RenderView* render_view = self->GetRenderView(); + content::RenderView* render_view = GetCurrentRenderView(); if (render_view) { render_view->Send(new ExtensionHostMsg_ResponseAck( render_view->GetRoutingID(), args[0]->Int32Value())); diff --git a/chrome/renderer/extensions/page_capture_custom_bindings.h b/chrome/renderer/extensions/page_capture_custom_bindings.h index 2881769..d6ac69d 100644 --- a/chrome/renderer/extensions/page_capture_custom_bindings.h +++ b/chrome/renderer/extensions/page_capture_custom_bindings.h @@ -12,8 +12,7 @@ namespace extensions { // Implements custom bindings for the pageCapture API. class PageCaptureCustomBindings : public ChromeV8Extension { public: - PageCaptureCustomBindings(Dispatcher* dispatcher, - v8::Handle<v8::Context> context); + PageCaptureCustomBindings(); private: // Creates a Blob with the content of the specified file. diff --git a/chrome/renderer/extensions/request_sender.cc b/chrome/renderer/extensions/request_sender.cc index a9269ae..e77aebf 100644 --- a/chrome/renderer/extensions/request_sender.cc +++ b/chrome/renderer/extensions/request_sender.cc @@ -7,6 +7,7 @@ #include "base/values.h" #include "chrome/common/extensions/extension_messages.h" #include "chrome/renderer/extensions/chrome_v8_context.h" +#include "chrome/renderer/extensions/chrome_v8_context_set.h" #include "chrome/renderer/extensions/dispatcher.h" #include "content/public/renderer/render_view.h" #include "content/public/renderer/v8_value_converter.h" @@ -21,18 +22,23 @@ namespace extensions { // Contains info relevant to a pending API request. struct PendingRequest { public : - PendingRequest(ChromeV8Context* context, - ChromeV8Context* caller_context, - const std::string& name) - : name(name), context(context), caller_context(caller_context) { + PendingRequest(v8::Persistent<v8::Context> context, const std::string& name, + const std::string& extension_id) + : context(context), name(name), extension_id(extension_id) { } + ~PendingRequest() { + context.Dispose(context->GetIsolate()); + } + + v8::Persistent<v8::Context> context; std::string name; - ChromeV8Context* context; - ChromeV8Context* caller_context; + std::string extension_id; }; -RequestSender::RequestSender(Dispatcher* dispatcher) : dispatcher_(dispatcher) { +RequestSender::RequestSender(Dispatcher* dispatcher, + ChromeV8ContextSet* context_set) + : dispatcher_(dispatcher), context_set_(context_set) { } RequestSender::~RequestSender() { @@ -53,15 +59,18 @@ linked_ptr<PendingRequest> RequestSender::RemoveRequest(int request_id) { return result; } -void RequestSender::StartRequest(ChromeV8Context* context, - const std::string& name, +void RequestSender::StartRequest(const std::string& name, int request_id, bool has_callback, bool for_io_thread, base::ListValue* value_args) { + ChromeV8Context* current_context = context_set_->GetCurrent(); + if (!current_context) + return; + // Get the current RenderView so that we can send a routed IPC message from // the correct source. - content::RenderView* renderview = context->GetRenderView(); + content::RenderView* renderview = current_context->GetRenderView(); if (!renderview) return; @@ -73,25 +82,25 @@ void RequestSender::StartRequest(ChromeV8Context* context, } // TODO(koz): See if we can make this a CHECK. - if (!dispatcher_->CheckContextAccessToExtensionAPI(name, context)) + if (!dispatcher_->CheckCurrentContextAccessToExtensionAPI(name)) return; GURL source_url; WebKit::WebSecurityOrigin source_origin; - WebKit::WebFrame* webframe = context->web_frame(); + WebKit::WebFrame* webframe = current_context->web_frame(); if (webframe) { source_url = webframe->document().url(); source_origin = webframe->document().securityOrigin(); } - std::string extension_id = context->GetExtensionID(); - // Insert the current context into the PendingRequest because that's the - // context that we call back on. - InsertRequest( - request_id, - new PendingRequest(context, - dispatcher_->v8_context_set().GetCurrent(), - name)); + v8::Local<v8::Context> ctx = v8::Context::GetCurrent(); + v8::Persistent<v8::Context> v8_context = + v8::Persistent<v8::Context>::New(ctx->GetIsolate(), ctx); + DCHECK(!v8_context.IsEmpty()); + + std::string extension_id = current_context->GetExtensionID(); + InsertRequest(request_id, new PendingRequest( + v8_context, name, extension_id)); ExtensionHostMsg_Request_Params params; params.name = name; @@ -119,10 +128,16 @@ void RequestSender::HandleResponse(int request_id, linked_ptr<PendingRequest> request = RemoveRequest(request_id); if (!request.get()) { - // This can happen if a context is destroyed while a request is in flight. + // This should not be able to happen since we only remove requests when + // they are handled. + LOG(ERROR) << "Could not find specified request id: " << request_id; return; } + ChromeV8Context* v8_context = context_set_->GetByV8Context(request->context); + if (!v8_context) + return; // The frame went away. + v8::HandleScope handle_scope; scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); @@ -130,15 +145,15 @@ void RequestSender::HandleResponse(int request_id, v8::Integer::New(request_id), v8::String::New(request->name.c_str()), v8::Boolean::New(success), - converter->ToV8Value(&responseList, request->context->v8_context()), + converter->ToV8Value(&responseList, v8_context->v8_context()), v8::String::New(error.c_str()) }; v8::Handle<v8::Value> retval; - CHECK(request->context->CallChromeHiddenMethod("handleResponse", - arraysize(argv), - argv, - &retval)); + CHECK(v8_context->CallChromeHiddenMethod("handleResponse", + arraysize(argv), + argv, + &retval)); // In debug, the js will validate the callback parameters and return a // string if a validation error has occured. if (DCHECK_IS_ON()) { @@ -149,14 +164,4 @@ void RequestSender::HandleResponse(int request_id, } } -void RequestSender::InvalidateContext(ChromeV8Context* context) { - for (PendingRequestMap::iterator it = pending_requests_.begin(); - it != pending_requests_.end();) { - if (it->second->context == context) - pending_requests_.erase(it++); - else - ++it; - } -} - } // namespace extensions diff --git a/chrome/renderer/extensions/request_sender.h b/chrome/renderer/extensions/request_sender.h index b1463fd..a7bbdb8 100644 --- a/chrome/renderer/extensions/request_sender.h +++ b/chrome/renderer/extensions/request_sender.h @@ -16,7 +16,7 @@ class ListValue; } namespace extensions { -class ChromeV8Context; +class ChromeV8ContextSet; class Dispatcher; struct PendingRequest; @@ -25,17 +25,15 @@ struct PendingRequest; // extension host and routing the responses back to the caller. class RequestSender { public: - explicit RequestSender(Dispatcher* dispatcher); + explicit RequestSender(Dispatcher* dispatcher, + ChromeV8ContextSet* context_set); ~RequestSender(); // Makes a call to the API function |name| that is to be handled by the // extension host. The response to this request will be received in // HandleResponse(). // TODO(koz): Remove |request_id| and generate that internally. - // There are multiple of these per render view though, so we'll - // need to vend the IDs centrally. - void StartRequest(ChromeV8Context* target_context, - const std::string& name, + void StartRequest(const std::string& name, int request_id, bool has_callback, bool for_io_thread, @@ -47,9 +45,6 @@ class RequestSender { const base::ListValue& response, const std::string& error); - // Notifies this that a context is no longer valid. - // TODO(kalman): Do this in a generic/safe way. - void InvalidateContext(ChromeV8Context* context); private: typedef std::map<int, linked_ptr<PendingRequest> > PendingRequestMap; @@ -59,6 +54,7 @@ class RequestSender { Dispatcher* dispatcher_; PendingRequestMap pending_requests_; + ChromeV8ContextSet* context_set_; DISALLOW_COPY_AND_ASSIGN(RequestSender); }; diff --git a/chrome/renderer/extensions/runtime_custom_bindings.cc b/chrome/renderer/extensions/runtime_custom_bindings.cc index 22af19c..211ad62 100644 --- a/chrome/renderer/extensions/runtime_custom_bindings.cc +++ b/chrome/renderer/extensions/runtime_custom_bindings.cc @@ -18,10 +18,8 @@ using content::V8ValueConverter; namespace extensions { -RuntimeCustomBindings::RuntimeCustomBindings(Dispatcher* dispatcher, - ChromeV8Context* context) - : ChromeV8Extension(dispatcher, context->v8_context()), - context_(context) { +RuntimeCustomBindings::RuntimeCustomBindings(ChromeV8Context* context) + : ChromeV8Extension(NULL), context_(context) { RouteFunction("GetManifest", base::Bind(&RuntimeCustomBindings::GetManifest, base::Unretained(this))); RouteStaticFunction("OpenChannelToExtension", &OpenChannelToExtension); @@ -35,8 +33,7 @@ v8::Handle<v8::Value> RuntimeCustomBindings::OpenChannelToExtension( const v8::Arguments& args) { // Get the current RenderView so that we can send a routed IPC message from // the correct source. - RuntimeCustomBindings* self = GetFromArguments<RuntimeCustomBindings>(args); - content::RenderView* renderview = self->GetRenderView(); + content::RenderView* renderview = GetCurrentRenderView(); if (!renderview) return v8::Undefined(); @@ -64,8 +61,7 @@ v8::Handle<v8::Value> RuntimeCustomBindings::OpenChannelToNativeApp( const v8::Arguments& args) { // Get the current RenderView so that we can send a routed IPC message from // the correct source. - RuntimeCustomBindings* self = GetFromArguments<RuntimeCustomBindings>(args); - content::RenderView* renderview = self->GetRenderView(); + content::RenderView* renderview = GetCurrentRenderView(); if (!renderview) return v8::Undefined(); diff --git a/chrome/renderer/extensions/runtime_custom_bindings.h b/chrome/renderer/extensions/runtime_custom_bindings.h index 84ddf04..c2d2509 100644 --- a/chrome/renderer/extensions/runtime_custom_bindings.h +++ b/chrome/renderer/extensions/runtime_custom_bindings.h @@ -17,7 +17,7 @@ namespace extensions { // The native component of custom bindings for the chrome.runtime API. class RuntimeCustomBindings : public ChromeV8Extension { public: - RuntimeCustomBindings(Dispatcher* dispatcher, ChromeV8Context* context); + explicit RuntimeCustomBindings(ChromeV8Context* context); virtual ~RuntimeCustomBindings(); diff --git a/chrome/renderer/extensions/send_request_natives.cc b/chrome/renderer/extensions/send_request_natives.cc index f0249b1..b788a8a 100644 --- a/chrome/renderer/extensions/send_request_natives.cc +++ b/chrome/renderer/extensions/send_request_natives.cc @@ -13,11 +13,8 @@ using content::V8ValueConverter; namespace extensions { SendRequestNatives::SendRequestNatives(Dispatcher* dispatcher, - RequestSender* request_sender, - ChromeV8Context* context) - : ChromeV8Extension(dispatcher, context->v8_context()), - request_sender_(request_sender), - context_(context) { + RequestSender* request_sender) + : ChromeV8Extension(dispatcher), request_sender_(request_sender) { RouteFunction("GetNextRequestId", base::Bind(&SendRequestNatives::GetNextRequestId, base::Unretained(this))); @@ -45,21 +42,21 @@ v8::Handle<v8::Value> SendRequestNatives::StartRequest( scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); // See http://crbug.com/149880. The context menus APIs relies on this, but - // we shouldn't really be doing it (e.g. for the sake of the storage API). + // we shouln't really be doing it (e.g. for the sake of the storage API). converter->SetFunctionAllowed(true); if (!preserve_null_in_objects) converter->SetStripNullFromObjects(true); - scoped_ptr<Value> value_args(converter->FromV8Value(args[1], v8_context())); + scoped_ptr<Value> value_args( + converter->FromV8Value(args[1], v8::Context::GetCurrent())); if (!value_args.get() || !value_args->IsType(Value::TYPE_LIST)) { NOTREACHED() << "Unable to convert args passed to StartRequest"; return v8::Undefined(); } - request_sender_->StartRequest( - context_, name, request_id, has_callback, for_io_thread, - static_cast<ListValue*>(value_args.get())); + request_sender_->StartRequest(name, request_id, has_callback, for_io_thread, + static_cast<ListValue*>(value_args.get())); return v8::Undefined(); } diff --git a/chrome/renderer/extensions/send_request_natives.h b/chrome/renderer/extensions/send_request_natives.h index d8546f3..d92ffe3 100644 --- a/chrome/renderer/extensions/send_request_natives.h +++ b/chrome/renderer/extensions/send_request_natives.h @@ -17,9 +17,7 @@ class RequestSender; // the browser. class SendRequestNatives : public ChromeV8Extension { public: - SendRequestNatives(Dispatcher* dispatcher, - RequestSender* request_sender, - ChromeV8Context* context); + SendRequestNatives(Dispatcher* dispatcher, RequestSender* request_sender); private: v8::Handle<v8::Value> GetNextRequestId(const v8::Arguments& args); @@ -29,8 +27,6 @@ class SendRequestNatives : public ChromeV8Extension { RequestSender* request_sender_; - ChromeV8Context* context_; - DISALLOW_COPY_AND_ASSIGN(SendRequestNatives); }; diff --git a/chrome/renderer/extensions/set_icon_natives.cc b/chrome/renderer/extensions/set_icon_natives.cc index 084c5a8..369cb07 100644 --- a/chrome/renderer/extensions/set_icon_natives.cc +++ b/chrome/renderer/extensions/set_icon_natives.cc @@ -24,11 +24,9 @@ const char kNoMemory[] = "Chrome was unable to initialize icon."; namespace extensions { SetIconNatives::SetIconNatives(Dispatcher* dispatcher, - RequestSender* request_sender, - ChromeV8Context* context) - : ChromeV8Extension(dispatcher, context->v8_context()), - request_sender_(request_sender), - context_(context) { + RequestSender* request_sender) + : ChromeV8Extension(dispatcher), + request_sender_(request_sender) { RouteFunction( "SetIconCommon", base::Bind(&SetIconNatives::SetIconCommon, base::Unretained(this))); @@ -138,8 +136,7 @@ v8::Handle<v8::Value> SetIconNatives::SetIconCommon( bool has_callback = args[3]->BooleanValue(); bool for_io_thread = args[4]->BooleanValue(); - request_sender_->StartRequest(context_, - name, + request_sender_->StartRequest(name, request_id, has_callback, for_io_thread, diff --git a/chrome/renderer/extensions/set_icon_natives.h b/chrome/renderer/extensions/set_icon_natives.h index 7e0352a..b03bcee 100644 --- a/chrome/renderer/extensions/set_icon_natives.h +++ b/chrome/renderer/extensions/set_icon_natives.h @@ -20,9 +20,7 @@ class RequestSender; // Functions exposed to extension JS to implement the setIcon extension API. class SetIconNatives : public ChromeV8Extension { public: - SetIconNatives(Dispatcher* dispatcher, - RequestSender* request_sender, - ChromeV8Context* context); + SetIconNatives(Dispatcher* dispatcher, RequestSender* request_sender); private: bool ConvertImageDataToBitmapValue(const v8::Local<v8::Object> image_data, @@ -30,11 +28,8 @@ class SetIconNatives : public ChromeV8Extension { bool ConvertImageDataSetToBitmapValueSet(const v8::Arguments& args, DictionaryValue* bitmap_value); v8::Handle<v8::Value> SetIconCommon(const v8::Arguments& args); - RequestSender* request_sender_; - ChromeV8Context* context_; - DISALLOW_COPY_AND_ASSIGN(SetIconNatives); }; diff --git a/chrome/renderer/extensions/tabs_custom_bindings.cc b/chrome/renderer/extensions/tabs_custom_bindings.cc index 7d16093..5492d34 100644 --- a/chrome/renderer/extensions/tabs_custom_bindings.cc +++ b/chrome/renderer/extensions/tabs_custom_bindings.cc @@ -13,9 +13,8 @@ namespace extensions { -TabsCustomBindings::TabsCustomBindings(Dispatcher* dispatcher, - v8::Handle<v8::Context> context) - : ChromeV8Extension(dispatcher, context) { +TabsCustomBindings::TabsCustomBindings() + : ChromeV8Extension(NULL) { RouteStaticFunction("OpenChannelToTab", &OpenChannelToTab); } @@ -24,8 +23,7 @@ v8::Handle<v8::Value> TabsCustomBindings::OpenChannelToTab( const v8::Arguments& args) { // Get the current RenderView so that we can send a routed IPC message from // the correct source. - TabsCustomBindings* self = GetFromArguments<TabsCustomBindings>(args); - content::RenderView* renderview = self->GetRenderView(); + content::RenderView* renderview = GetCurrentRenderView(); if (!renderview) return v8::Undefined(); diff --git a/chrome/renderer/extensions/tabs_custom_bindings.h b/chrome/renderer/extensions/tabs_custom_bindings.h index 2ac19bb..0576212 100644 --- a/chrome/renderer/extensions/tabs_custom_bindings.h +++ b/chrome/renderer/extensions/tabs_custom_bindings.h @@ -12,7 +12,7 @@ namespace extensions { // Implements custom bindings for the tabs API. class TabsCustomBindings : public ChromeV8Extension { public: - TabsCustomBindings(Dispatcher* dispatcher, v8::Handle<v8::Context> context); + TabsCustomBindings(); private: // Creates a new messaging channel to the tab with the given ID. diff --git a/chrome/renderer/extensions/v8_schema_registry.h b/chrome/renderer/extensions/v8_schema_registry.h index 17eb667..ab3ecf0 100644 --- a/chrome/renderer/extensions/v8_schema_registry.h +++ b/chrome/renderer/extensions/v8_schema_registry.h @@ -24,10 +24,10 @@ class V8SchemaRegistry { // Returns a v8::Array with all the schemas for the APIs in |apis|. v8::Handle<v8::Array> GetSchemas(const std::set<std::string>& apis); + private: // Returns a v8::Object for the schema for |api|, possibly from the cache. v8::Handle<v8::Object> GetSchema(const std::string& api); - private: // Cache of schemas. typedef std::map<std::string, v8::Persistent<v8::Object> > SchemaCache; SchemaCache schema_cache_; diff --git a/chrome/renderer/resources/extensions/test_custom_bindings.js b/chrome/renderer/resources/extensions/apitest.js index 300ba42..52414c2 100644 --- a/chrome/renderer/resources/extensions/test_custom_bindings.js +++ b/chrome/renderer/resources/extensions/apitest.js @@ -2,20 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// test_custom_bindings.js +// extension_apitest.js // mini-framework for ExtensionApiTest browser tests -var binding = require('binding').Binding.create('test'); + chrome.test = chrome.test || {}; -var chrome = requireNative('chrome').GetChrome(); -var GetExtensionAPIDefinition = - requireNative('apiDefinitions').GetExtensionAPIDefinition; - -binding.registerCustomHook(function(api) { - var chromeTest = api.compiledApi; - var apiFunctions = api.apiFunctions; - - chromeTest.tests = chromeTest.tests || []; + chrome.test.tests = chrome.test.tests || []; var currentTest = null; var lastTest = null; @@ -32,14 +24,14 @@ binding.registerCustomHook(function(api) { function testDone() { // Use setTimeout here to allow previous test contexts to be // eligible for garbage collection. - setTimeout(chromeTest.runNextTest, 0); + setTimeout(chrome.test.runNextTest, 0); } function allTestsDone() { if (testsFailed == 0) { - chromeTest.notifyPass(); + chrome.test.notifyPass(); } else { - chromeTest.notifyFail('Failed ' + testsFailed + ' of ' + + chrome.test.notifyFail('Failed ' + testsFailed + ' of ' + testCount + ' tests'); } @@ -50,28 +42,28 @@ binding.registerCustomHook(function(api) { var pendingCallbacks = 0; - apiFunctions.setHandleRequest('callbackAdded', function() { + chrome.test.callbackAdded = function() { pendingCallbacks++; var called = false; return function() { - chromeTest.assertFalse(called, 'callback has already been run'); + chrome.test.assertFalse(called, 'callback has already been run'); called = true; pendingCallbacks--; if (pendingCallbacks == 0) { - chromeTest.succeed(); + chrome.test.succeed(); } }; - }); + }; - apiFunctions.setHandleRequest('runNextTest', function() { + chrome.test.runNextTest = function() { // There may have been callbacks which were interrupted by failure // exceptions. pendingCallbacks = 0; lastTest = currentTest; - currentTest = chromeTest.tests.shift(); + currentTest = chrome.test.tests.shift(); if (!currentTest) { allTestsDone(); @@ -79,19 +71,19 @@ binding.registerCustomHook(function(api) { } try { - chromeTest.log("( RUN ) " + testName(currentTest)); + chrome.test.log("( RUN ) " + testName(currentTest)); currentTest.call(); } catch (e) { if (e !== failureException) - chromeTest.fail('uncaught exception: ' + e); + chrome.test.fail('uncaught exception: ' + e); } - }); + }; - apiFunctions.setHandleRequest('fail', function(message) { - chromeTest.log("( FAILED ) " + testName(currentTest)); + chrome.test.fail = function(message) { + chrome.test.log("( FAILED ) " + testName(currentTest)); var stack = {}; - Error.captureStackTrace(stack, chromeTest.fail); + Error.captureStackTrace(stack, chrome.test.fail); if (!message) message = "FAIL (no message)"; @@ -103,24 +95,23 @@ binding.registerCustomHook(function(api) { // Interrupt the rest of the test. throw failureException; - }); + }; - apiFunctions.setHandleRequest('succeed', function() { + chrome.test.succeed = function() { console.log("[SUCCESS] " + testName(currentTest)); - chromeTest.log("( SUCCESS )"); + chrome.test.log("( SUCCESS )"); testDone(); - }); + }; - apiFunctions.setHandleRequest('assertTrue', function(test, message) { - chromeTest.assertBool(test, true, message); - }); + chrome.test.assertTrue = function(test, message) { + chrome.test.assertBool(test, true, message); + }; - apiFunctions.setHandleRequest('assertFalse', function(test, message) { - chromeTest.assertBool(test, false, message); - }); + chrome.test.assertFalse = function(test, message) { + chrome.test.assertBool(test, false, message); + }; - apiFunctions.setHandleRequest('assertBool', - function(test, expected, message) { + chrome.test.assertBool = function(test, expected, message) { if (test !== expected) { if (typeof(test) == "string") { if (message) @@ -128,11 +119,11 @@ binding.registerCustomHook(function(api) { else message = test; } - chromeTest.fail(message); + chrome.test.fail(message); } - }); + }; - apiFunctions.setHandleRequest('checkDeepEq', function(expected, actual) { + chrome.test.checkDeepEq = function (expected, actual) { if ((expected === null) != (actual === null)) return false; @@ -155,7 +146,7 @@ binding.registerCustomHook(function(api) { var eq = true; switch (typeof(expected[p])) { case 'object': - eq = chromeTest.checkDeepEq(expected[p], actual[p]); + eq = chrome.test.checkDeepEq(expected[p], actual[p]); break; case 'function': eq = (typeof(actual[p]) != 'undefined' && @@ -170,45 +161,44 @@ binding.registerCustomHook(function(api) { return false; } return true; - }); + }; - apiFunctions.setHandleRequest('assertEq', - function(expected, actual, message) { + chrome.test.assertEq = function(expected, actual, message) { var error_msg = "API Test Error in " + testName(currentTest); if (message) error_msg += ": " + message; if (typeof(expected) == 'object') { - if (!chromeTest.checkDeepEq(expected, actual)) { - chromeTest.fail(error_msg + + if (!chrome.test.checkDeepEq(expected, actual)) { + chrome.test.fail(error_msg + "\nActual: " + JSON.stringify(actual) + "\nExpected: " + JSON.stringify(expected)); } return; } if (expected != actual) { - chromeTest.fail(error_msg + + chrome.test.fail(error_msg + "\nActual: " + actual + "\nExpected: " + expected); } if (typeof(expected) != typeof(actual)) { - chromeTest.fail(error_msg + + chrome.test.fail(error_msg + " (type mismatch)\nActual Type: " + typeof(actual) + "\nExpected Type:" + typeof(expected)); } - }); + }; - apiFunctions.setHandleRequest('assertNoLastError', function() { + chrome.test.assertNoLastError = function() { if (chrome.runtime.lastError != undefined) { - chromeTest.fail("lastError.message == " + + chrome.test.fail("lastError.message == " + chrome.runtime.lastError.message); } - }); + }; - apiFunctions.setHandleRequest('assertLastError', function(expectedError) { - chromeTest.assertEq(typeof(expectedError), 'string'); - chromeTest.assertTrue(chrome.runtime.lastError != undefined, + chrome.test.assertLastError = function(expectedError) { + chrome.test.assertEq(typeof(expectedError), 'string'); + chrome.test.assertTrue(chrome.runtime.lastError != undefined, "No lastError, but expected " + expectedError); - chromeTest.assertEq(expectedError, chrome.runtime.lastError.message); - }); + chrome.test.assertEq(expectedError, chrome.runtime.lastError.message); + } function safeFunctionApply(func, args) { try { @@ -216,23 +206,23 @@ binding.registerCustomHook(function(api) { func.apply(null, args); } catch (e) { var msg = "uncaught exception " + e; - chromeTest.fail(msg); + chrome.test.fail(msg); } }; // Wrapper for generating test functions, that takes care of calling // assertNoLastError() and (optionally) succeed() for you. - apiFunctions.setHandleRequest('callback', function(func, expectedError) { + chrome.test.callback = function(func, expectedError) { if (func) { - chromeTest.assertEq(typeof(func), 'function'); + chrome.test.assertEq(typeof(func), 'function'); } - var callbackCompleted = chromeTest.callbackAdded(); + var callbackCompleted = chrome.test.callbackAdded(); return function() { if (expectedError == null) { - chromeTest.assertNoLastError(); + chrome.test.assertNoLastError(); } else { - chromeTest.assertLastError(expectedError); + chrome.test.assertLastError(expectedError); } if (func) { @@ -241,20 +231,20 @@ binding.registerCustomHook(function(api) { callbackCompleted(); }; - }); + }; - apiFunctions.setHandleRequest('listenOnce', function(event, func) { - var callbackCompleted = chromeTest.callbackAdded(); + chrome.test.listenOnce = function(event, func) { + var callbackCompleted = chrome.test.callbackAdded(); var listener = function() { event.removeListener(listener); safeFunctionApply(func, arguments); callbackCompleted(); }; event.addListener(listener); - }); + }; - apiFunctions.setHandleRequest('listenForever', function(event, func) { - var callbackCompleted = chromeTest.callbackAdded(); + chrome.test.listenForever = function(event, func) { + var callbackCompleted = chrome.test.callbackAdded(); var listener = function() { safeFunctionApply(func, arguments); @@ -267,25 +257,18 @@ binding.registerCustomHook(function(api) { event.addListener(listener); return done; - }); - - apiFunctions.setHandleRequest('callbackPass', function(func) { - return chromeTest.callback(func); - }); - - apiFunctions.setHandleRequest('callbackFail', function(expectedError, func) { - return chromeTest.callback(func, expectedError); - }); + }; - apiFunctions.setHandleRequest('runTests', function(tests) { - chromeTest.tests = tests; - testCount = chromeTest.tests.length; - chromeTest.runNextTest(); - }); + chrome.test.callbackPass = function(func) { + return chrome.test.callback(func); + }; - apiFunctions.setHandleRequest('getApiDefinitions', function(apiNames) { - return GetExtensionAPIDefinition(); - }); -}); + chrome.test.callbackFail = function(expectedError, func) { + return chrome.test.callback(func, expectedError); + }; -exports.binding = binding.generate(); + chrome.test.runTests = function(tests) { + chrome.test.tests = tests; + testCount = chrome.test.tests.length; + chrome.test.runNextTest(); + }; diff --git a/chrome/renderer/resources/extensions/app_custom_bindings.js b/chrome/renderer/resources/extensions/app_custom_bindings.js index 0b9dd89..1a8bbcc 100644 --- a/chrome/renderer/resources/extensions/app_custom_bindings.js +++ b/chrome/renderer/resources/extensions/app_custom_bindings.js @@ -2,11 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the app API. +// Custom bindings for the app API. var appNatives = requireNative('app'); -var chrome = requireNative('chrome').GetChrome(); -var GetAvailability = requireNative('v8_context').GetAvailability; // This becomes chrome.app var app = { @@ -45,7 +43,7 @@ var chromeHiddenApp = { // appNotification stuff. // -// TODO(kalman): move this stuff to its own custom binding. +// TODO(kalman): move this stuff to its own custom bindings. // It will be bit tricky since I'll need to look into why there are // permissions defined for app notifications, yet this always sets it up? var callbacks = {}; @@ -69,11 +67,8 @@ app.installState = function getInstallState(callback) { appNatives.GetInstallState(callbackId); }; -// These must match the names in InstallAppbinding() in +// These must match the names in InstallAppBindings() in // chrome/renderer/extensions/dispatcher.cc. -var availability = GetAvailability('app'); -if (availability.is_available) { - exports.chromeApp = app; - exports.chromeAppNotifications = appNotifications; - exports.chromeHiddenApp = chromeHiddenApp; -} +exports.chromeApp = app; +exports.chromeAppNotifications = appNotifications; +exports.chromeHiddenApp = chromeHiddenApp; diff --git a/chrome/renderer/resources/extensions/app_runtime_custom_bindings.js b/chrome/renderer/resources/extensions/app_runtime_custom_bindings.js index a50c964..0a70fc4 100644 --- a/chrome/renderer/resources/extensions/app_runtime_custom_bindings.js +++ b/chrome/renderer/resources/extensions/app_runtime_custom_bindings.js @@ -2,12 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the chrome.app.runtime API. - -var binding = require('binding').Binding.create('app.runtime'); +// Custom bindings for the chrome.app.runtime API. var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); -var chrome = requireNative('chrome').GetChrome(); var fileSystemHelpers = requireNative('file_system_natives'); var GetIsolatedFileSystem = fileSystemHelpers.GetIsolatedFileSystem; var appNatives = requireNative('app_runtime'); @@ -52,5 +49,3 @@ chromeHidden.Event.registerArgumentMassager('app.runtime.onLaunched', dispatch([]); } }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/app_window_custom_bindings.js b/chrome/renderer/resources/extensions/app_window_custom_bindings.js index a145f67..1bb5bef 100644 --- a/chrome/renderer/resources/extensions/app_window_custom_bindings.js +++ b/chrome/renderer/resources/extensions/app_window_custom_bindings.js @@ -2,21 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the app_window API. +// Custom bindings for the app_window API. -var Binding = require('binding').Binding; var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); -var chrome = requireNative('chrome').GetChrome(); var sendRequest = require('sendRequest').sendRequest; var appWindowNatives = requireNative('app_window'); var forEach = require('utils').forEach; var GetView = appWindowNatives.GetView; var OnContextReady = appWindowNatives.OnContextReady; -var appWindow = Binding.create('app.window'); -appWindow.registerCustomHook(function(bindingsAPI) { +chromeHidden.registerCustomHook('app.window', function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; - apiFunctions.setCustomCallback('create', function(name, request, windowParams) { var view = null; @@ -85,12 +81,10 @@ appWindow.registerCustomHook(function(bindingsAPI) { // This is an internal function, but needs to be bound with setHandleRequest // because it is called from a different JS context. apiFunctions.setHandleRequest('initializeAppWindow', function(params) { - var currentWindowInternal = - Binding.create('app.currentWindowInternal').generate(); var AppWindow = function() {}; - forEach(currentWindowInternal, function(fn) { + forEach(chromeHidden.internalAPIs.app.currentWindowInternal, function(fn) { AppWindow.prototype[fn] = - currentWindowInternal[fn]; + chromeHidden.internalAPIs.app.currentWindowInternal[fn]; }); AppWindow.prototype.moveTo = window.moveTo.bind(window); AppWindow.prototype.resizeTo = window.resizeTo.bind(window); @@ -154,5 +148,3 @@ chromeHidden.updateAppWindowProperties = function(update) { (oldData.maximized && !update.maximized)) currentWindow["onRestored"].dispatch(); }; - -exports.binding = appWindow.generate(); diff --git a/chrome/renderer/resources/extensions/binding.js b/chrome/renderer/resources/extensions/binding.js deleted file mode 100644 index d6fb4df..0000000 --- a/chrome/renderer/resources/extensions/binding.js +++ /dev/null @@ -1,407 +0,0 @@ -// 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. - -require('json_schema'); -require('event_bindings'); -var schemaRegistry = requireNative('schema_registry'); -var sendRequest = require('sendRequest').sendRequest; -var utils = require('utils'); -var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); -var chrome = requireNative('chrome').GetChrome(); -var schemaUtils = require('schemaUtils'); -var process = requireNative('process'); -var manifestVersion = process.GetManifestVersion(); -var extensionId = process.GetExtensionId(); -var contextType = process.GetContextType(); -var GetAvailability = requireNative('v8_context').GetAvailability; -var logging = requireNative('logging'); - -// Stores the name and definition of each API function, with methods to -// modify their behaviour (such as a custom way to handle requests to the -// API, a custom callback, etc). -function APIFunctions() { - this.apiFunctions_ = {}; - this.unavailableApiFunctions_ = {}; -} - -APIFunctions.prototype.register = function(apiName, apiFunction) { - this.apiFunctions_[apiName] = apiFunction; -}; - -// Registers a function as existing but not available, meaning that calls to -// the set* methods that reference this function should be ignored rather -// than throwing Errors. -APIFunctions.prototype.registerUnavailable = function(apiName) { - this.unavailableApiFunctions_[apiName] = apiName; -}; - -APIFunctions.prototype.setHook_ = - function(apiName, propertyName, customizedFunction) { - if (this.unavailableApiFunctions_.hasOwnProperty(apiName)) - return; - if (!this.apiFunctions_.hasOwnProperty(apiName)) - throw new Error('Tried to set hook for unknown API "' + apiName + '"'); - this.apiFunctions_[apiName][propertyName] = customizedFunction; -}; - -APIFunctions.prototype.setHandleRequest = - function(apiName, customizedFunction) { - return this.setHook_(apiName, 'handleRequest', customizedFunction); -}; - -APIFunctions.prototype.setUpdateArgumentsPostValidate = - function(apiName, customizedFunction) { - return this.setHook_( - apiName, 'updateArgumentsPostValidate', customizedFunction); -}; - -APIFunctions.prototype.setUpdateArgumentsPreValidate = - function(apiName, customizedFunction) { - return this.setHook_( - apiName, 'updateArgumentsPreValidate', customizedFunction); -}; - -APIFunctions.prototype.setCustomCallback = - function(apiName, customizedFunction) { - return this.setHook_(apiName, 'customCallback', customizedFunction); -}; - -function CustomBindingsObject() { -} - -CustomBindingsObject.prototype.setSchema = function(schema) { - // The functions in the schema are in list form, so we move them into a - // dictionary for easier access. - var self = this; - self.functionSchemas = {}; - schema.functions.forEach(function(f) { - self.functionSchemas[f.name] = { - name: f.name, - definition: f - } - }); -}; - -// Get the platform from navigator.appVersion. -function getPlatform() { - var platforms = [ - [/CrOS Touch/, "chromeos touch"], - [/CrOS/, "chromeos"], - [/Linux/, "linux"], - [/Mac/, "mac"], - [/Win/, "win"], - ]; - - for (var i = 0; i < platforms.length; i++) { - if (platforms[i][0].test(navigator.appVersion)) { - return platforms[i][1]; - } - } - return "unknown"; -} - -function isPlatformSupported(schemaNode, platform) { - return !schemaNode.platforms || - schemaNode.platforms.indexOf(platform) > -1; -} - -function isManifestVersionSupported(schemaNode, manifestVersion) { - return !schemaNode.maximumManifestVersion || - manifestVersion <= schemaNode.maximumManifestVersion; -} - -function isSchemaNodeSupported(schemaNode, platform, manifestVersion) { - return isPlatformSupported(schemaNode, platform) && - isManifestVersionSupported(schemaNode, manifestVersion); -} - -var platform = getPlatform(); - -function Binding(schema) { - this.schema_ = schema; - this.apiFunctions_ = new APIFunctions(); - this.customEvent_ = null; - this.customTypes_ = {}; - this.customHooks_ = []; -}; - -Binding.create = function(apiName) { - return new Binding(schemaRegistry.GetSchema(apiName)); -}; - -Binding.prototype = { - // The API through which the ${api_name}_custom_bindings.js files customize - // their API bindings beyond what can be generated. - // - // There are 2 types of customizations available: those which are required in - // order to do the schema generation (registerCustomEvent and - // registerCustomType), and those which can only run after the bindings have - // been generated (registerCustomHook). - // - - // Registers a custom type referenced via "$ref" fields in the API schema - // JSON. - registerCustomType: function(typeName, customTypeFactory) { - var customType = customTypeFactory(); - customType.prototype = new CustomBindingsObject(); - this.customTypes_[typeName] = customType; - }, - - // Registers a custom event type for the API identified by |namespace|. - // |event| is the event's constructor. - registerCustomEvent: function(event) { - this.customEvent_ = event; - }, - - // Registers a function |hook| to run after the schema for all APIs has been - // generated. The hook is passed as its first argument an "API" object to - // interact with, and second the current extension ID. See where - // |customHooks| is used. - registerCustomHook: function(fn) { - this.customHooks_.push(fn); - }, - - // TODO(kalman/cduvall): Refactor this so |runHooks_| is not needed. - runHooks_: function(api) { - this.customHooks_.forEach(function(hook) { - if (!isSchemaNodeSupported(this.schema_, platform, manifestVersion)) - return; - - if (!hook) - return; - - hook({ - apiFunctions: this.apiFunctions_, - schema: this.schema_, - compiledApi: api - }, extensionId, contextType); - }, this); - }, - - // Generates the bindings from |this.schema_| and integrates any custom - // bindings that might be present. - generate: function() { - var schema = this.schema_; - var customTypes = this.customTypes_; - - // TODO(kalman/cduvall): Make GetAvailability handle this, then delete the - // supporting code. - if (!isSchemaNodeSupported(schema, platform, manifestVersion)) - return; - - var availability = GetAvailability(schema.namespace); - if (!availability.is_available) { - console.error('chrome.' + schema.namespace + ' is not available: ' + - availability.message); - return; - } - - // See comment on internalAPIs at the top. - var mod = {}; - - var namespaces = schema.namespace.split('.'); - for (var index = 0, name; name = namespaces[index]; index++) { - mod[name] = mod[name] || {}; - mod = mod[name]; - } - - // Add types to global schemaValidator - if (schema.types) { - schema.types.forEach(function(t) { - if (!isSchemaNodeSupported(t, platform, manifestVersion)) - return; - - schemaUtils.schemaValidator.addTypes(t); - if (t.type == 'object' && this.customTypes_[t.id]) { - var parts = t.id.split("."); - this.customTypes_[t.id].prototype.setSchema(t); - mod[parts[parts.length - 1]] = this.customTypes_[t.id]; - } - }, this); - } - - // Returns whether access to the content of a schema should be denied, - // based on the presence of "unprivileged" and whether this is an - // extension process (versus e.g. a content script). - function isSchemaAccessAllowed(itemSchema) { - return (contextType == 'BLESSED_EXTENSION') || - schema.unprivileged || - itemSchema.unprivileged; - }; - - // Adds a getter that throws an access denied error to object |mod| - // for property |name|. - function addUnprivilegedAccessGetter(mod, name) { - mod.__defineGetter__(name, function() { - throw new Error( - '"' + name + '" can only be used in extension processes. See ' + - 'the content scripts documentation for more details.'); - }); - } - - // Setup Functions. - if (schema.functions) { - schema.functions.forEach(function(functionDef) { - if (functionDef.name in mod) { - throw new Error('Function ' + functionDef.name + - ' already defined in ' + schema.namespace); - } - - if (!isSchemaNodeSupported(functionDef, platform, manifestVersion)) { - this.apiFunctions_.registerUnavailable(functionDef.name); - return; - } - if (!isSchemaAccessAllowed(functionDef)) { - this.apiFunctions_.registerUnavailable(functionDef.name); - addUnprivilegedAccessGetter(mod, functionDef.name); - return; - } - - var apiFunction = {}; - apiFunction.definition = functionDef; - apiFunction.name = schema.namespace + '.' + functionDef.name; - - // TODO(aa): It would be best to run this in a unit test, but in order - // to do that we would need to better factor this code so that it - // doesn't depend on so much v8::Extension machinery. - if (chromeHidden.validateAPI && - schemaUtils.isFunctionSignatureAmbiguous( - apiFunction.definition)) { - throw new Error( - apiFunction.name + ' has ambiguous optional arguments. ' + - 'To implement custom disambiguation logic, add ' + - '"allowAmbiguousOptionalArguments" to the function\'s schema.'); - } - - this.apiFunctions_.register(functionDef.name, apiFunction); - - mod[functionDef.name] = (function() { - var args = Array.prototype.slice.call(arguments); - if (this.updateArgumentsPreValidate) - args = this.updateArgumentsPreValidate.apply(this, args); - - args = schemaUtils.normalizeArgumentsAndValidate(args, this); - if (this.updateArgumentsPostValidate) - args = this.updateArgumentsPostValidate.apply(this, args); - - var retval; - if (this.handleRequest) { - retval = this.handleRequest.apply(this, args); - } else { - var optArgs = { - customCallback: this.customCallback - }; - retval = sendRequest(this.name, args, - this.definition.parameters, - optArgs); - } - - // Validate return value if defined - only in debug. - if (chromeHidden.validateCallbacks && - this.definition.returns) { - schemaUtils.validate([retval], [this.definition.returns]); - } - return retval; - }).bind(apiFunction); - }, this); - } - - // Setup Events - if (schema.events) { - schema.events.forEach(function(eventDef) { - if (eventDef.name in mod) { - throw new Error('Event ' + eventDef.name + - ' already defined in ' + schema.namespace); - } - if (!isSchemaNodeSupported(eventDef, platform, manifestVersion)) - return; - if (!isSchemaAccessAllowed(eventDef)) { - addUnprivilegedAccessGetter(mod, eventDef.name); - return; - } - - var eventName = schema.namespace + "." + eventDef.name; - var options = eventDef.options || {}; - - if (eventDef.filters && eventDef.filters.length > 0) - options.supportsFilters = true; - - if (this.customEvent_) { - mod[eventDef.name] = new this.customEvent_( - eventName, eventDef.parameters, eventDef.extraParameters, - options); - } else if (eventDef.anonymous) { - mod[eventDef.name] = new chrome.Event(); - } else { - mod[eventDef.name] = new chrome.Event( - eventName, eventDef.parameters, options); - } - }, this); - } - - function addProperties(m, parentDef) { - var properties = parentDef.properties; - if (!properties) - return; - - utils.forEach(properties, function(propertyName, propertyDef) { - if (propertyName in m) - return; // TODO(kalman): be strict like functions/events somehow. - if (!isSchemaNodeSupported(propertyDef, platform, manifestVersion)) - return; - if (!isSchemaAccessAllowed(propertyDef)) { - addUnprivilegedAccessGetter(m, propertyName); - return; - } - - var value = propertyDef.value; - if (value) { - // Values may just have raw types as defined in the JSON, such - // as "WINDOW_ID_NONE": { "value": -1 }. We handle this here. - // TODO(kalman): enforce that things with a "value" property can't - // define their own types. - var type = propertyDef.type || typeof(value); - if (type === 'integer' || type === 'number') { - value = parseInt(value); - } else if (type === 'boolean') { - value = value === 'true'; - } else if (propertyDef['$ref']) { - if (propertyDef['$ref'] in customTypes) { - var constructor = customTypes[propertyDef['$ref']]; - } else { - var refParts = propertyDef['$ref'].split('.'); - // This should never try to load a $ref in the current namespace. - var constructor = utils.loadRefDependency( - propertyDef['$ref'])[refParts[refParts.length - 1]]; - } - if (!constructor) - throw new Error('No custom binding for ' + propertyDef['$ref']); - var args = value; - // For an object propertyDef, |value| is an array of constructor - // arguments, but we want to pass the arguments directly (i.e. - // not as an array), so we have to fake calling |new| on the - // constructor. - value = { __proto__: constructor.prototype }; - constructor.apply(value, args); - // Recursively add properties. - addProperties(value, propertyDef); - } else if (type === 'object') { - // Recursively add properties. - addProperties(value, propertyDef); - } else if (type !== 'string') { - throw new Error('NOT IMPLEMENTED (extension_api.json error): ' + - 'Cannot parse values for type "' + type + '"'); - } - m[propertyName] = value; - } - }); - }; - - addProperties(mod, schema); - this.runHooks_(mod); - return mod; - } -}; - -exports.Binding = Binding; diff --git a/chrome/renderer/resources/extensions/bluetooth_custom_bindings.js b/chrome/renderer/resources/extensions/bluetooth_custom_bindings.js index 9531b3a..e1f75f5 100644 --- a/chrome/renderer/resources/extensions/bluetooth_custom_bindings.js +++ b/chrome/renderer/resources/extensions/bluetooth_custom_bindings.js @@ -2,19 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the Bluetooth API. - -var binding = require('binding').Binding.create('bluetooth'); +// Custom bindings for the Bluetooth API. var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); -var chrome = requireNative('chrome').GetChrome(); var sendRequest = require('sendRequest').sendRequest; var lastError = require('lastError'); -// Use custom binding to create an undocumented event listener that will +// Use custom bindings to create an undocumented event listener that will // receive events about device discovery and call the event listener that was // provided with the request to begin discovery. -binding.registerCustomHook(function(api) { +chromeHidden.registerCustomHook('bluetooth', function(api) { var apiFunctions = api.apiFunctions; chromeHidden.bluetooth = {}; @@ -157,5 +154,3 @@ binding.registerCustomHook(function(api) { return args; }); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/browser_action_custom_bindings.js b/chrome/renderer/resources/extensions/browser_action_custom_bindings.js index d90ab18..9d1d92e 100644 --- a/chrome/renderer/resources/extensions/browser_action_custom_bindings.js +++ b/chrome/renderer/resources/extensions/browser_action_custom_bindings.js @@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the browserAction API. - -var binding = require('binding').Binding.create('browserAction'); +// Custom bindings for the browserAction API. +var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); var setIcon = require('setIcon').setIcon; -binding.registerCustomHook(function(bindingsAPI) { +chromeHidden.registerCustomHook('browserAction', function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setHandleRequest('setIcon', function(details, callback) { @@ -16,5 +15,3 @@ binding.registerCustomHook(function(bindingsAPI) { 'browser action'); }); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/content_settings_custom_bindings.js b/chrome/renderer/resources/extensions/content_settings_custom_bindings.js index 8347078..d92efc1 100644 --- a/chrome/renderer/resources/extensions/content_settings_custom_bindings.js +++ b/chrome/renderer/resources/extensions/content_settings_custom_bindings.js @@ -2,14 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the contentSettings API. - -var binding = require('binding').Binding.create('contentSettings'); +// Custom bindings for the contentSettings API. +var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); var sendRequest = require('sendRequest').sendRequest; var validate = require('schemaUtils').validate; -binding.registerCustomType('contentSettings.ContentSetting', function() { +chromeHidden.registerCustomType('contentSettings.ContentSetting', function() { function extendSchema(schema) { var extendedSchema = schema.slice(); extendedSchema.unshift({'type': 'string'}); @@ -52,5 +51,3 @@ binding.registerCustomType('contentSettings.ContentSetting', function() { return ContentSetting; }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/context_menus_custom_bindings.js b/chrome/renderer/resources/extensions/context_menus_custom_bindings.js index 4b0a936..e2629f7 100644 --- a/chrome/renderer/resources/extensions/context_menus_custom_bindings.js +++ b/chrome/renderer/resources/extensions/context_menus_custom_bindings.js @@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the contextMenus API. - -var binding = require('binding').Binding.create('contextMenus'); +// Custom bindings for the contextMenus API. var contextMenus = requireNative('context_menus'); var GetNextContextMenuId = contextMenus.GetNextContextMenuId; @@ -12,7 +10,7 @@ var sendRequest = require('sendRequest').sendRequest; var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); -binding.registerCustomHook(function(bindingsAPI) { +chromeHidden.registerCustomHook('contextMenus', function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; chromeHidden.contextMenus = {}; @@ -100,5 +98,3 @@ binding.registerCustomHook(function(bindingsAPI) { chromeHidden.contextMenus.stringIdHandlers = {}; }); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/declarative_content_custom_bindings.js b/chrome/renderer/resources/extensions/declarative_content_custom_bindings.js index 066413e..3655c46 100644 --- a/chrome/renderer/resources/extensions/declarative_content_custom_bindings.js +++ b/chrome/renderer/resources/extensions/declarative_content_custom_bindings.js @@ -2,21 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the declarativeContent API. - -var binding = require('binding').Binding.create('declarativeContent'); +// Custom bindings for the declarativeContent API. +var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); var utils = require('utils'); var validate = require('schemaUtils').validate; -binding.registerCustomHook( function(api) { - var declarativeContent = api.compiledApi; - +chromeHidden.registerCustomHook('declarativeContent', function(api) { // Returns the schema definition of type |typeId| defined in |namespace|. - function getSchema(typeId) { - return utils.lookup(api.schema.types, - 'id', - 'declarativeContent.' + typeId); + function getSchema(namespace, typeId) { + var apiSchema = utils.lookup(api.apiDefinitions, 'namespace', namespace); + var resultSchema = utils.lookup( + apiSchema.types, 'id', namespace + '.' + typeId); + return resultSchema; } // Helper function for the constructor of concrete datatypes of the @@ -31,17 +29,15 @@ binding.registerCustomHook( function(api) { } } instance.instanceType = 'declarativeContent.' + typeId; - var schema = getSchema(typeId); + var schema = getSchema('declarativeContent', typeId); validate([instance], [schema]); } // Setup all data types for the declarative content API. - declarativeContent.PageStateMatcher = function(parameters) { + chrome.declarativeContent.PageStateMatcher = function(parameters) { setupInstance(this, parameters, 'PageStateMatcher'); }; - declarativeContent.ShowPageAction = function(parameters) { + chrome.declarativeContent.ShowPageAction = function(parameters) { setupInstance(this, parameters, 'ShowPageAction'); }; }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/declarative_webrequest_custom_bindings.js b/chrome/renderer/resources/extensions/declarative_webrequest_custom_bindings.js index 9d0c3c5..f015bf7 100644 --- a/chrome/renderer/resources/extensions/declarative_webrequest_custom_bindings.js +++ b/chrome/renderer/resources/extensions/declarative_webrequest_custom_bindings.js @@ -2,23 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the declarativeWebRequest API. - -var binding = require('binding').Binding.create('declarativeWebRequest'); +// Custom bindings for the declarativeWebRequest API. var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); -var chrome = requireNative('chrome').GetChrome(); var utils = require('utils'); var validate = require('schemaUtils').validate; -binding.registerCustomHook(function(api) { - var declarativeWebRequest = api.compiledApi; - +chromeHidden.registerCustomHook('declarativeWebRequest', function(api) { // Returns the schema definition of type |typeId| defined in |namespace|. - function getSchema(typeId) { - return utils.lookup(api.schema.types, - 'id', - 'declarativeWebRequest.' + typeId); + function getSchema(namespace, typeId) { + var apiSchema = utils.lookup(api.apiDefinitions, 'namespace', namespace); + var resultSchema = utils.lookup( + apiSchema.types, 'id', namespace + '.' + typeId); + return resultSchema; } // Helper function for the constructor of concrete datatypes of the @@ -33,66 +29,64 @@ binding.registerCustomHook(function(api) { } } instance.instanceType = 'declarativeWebRequest.' + typeId; - var schema = getSchema(typeId); + var schema = getSchema('declarativeWebRequest', typeId); validate([instance], [schema]); } // Setup all data types for the declarative webRequest API. - declarativeWebRequest.RequestMatcher = function(parameters) { + chrome.declarativeWebRequest.RequestMatcher = function(parameters) { setupInstance(this, parameters, 'RequestMatcher'); }; - declarativeWebRequest.CancelRequest = function(parameters) { + chrome.declarativeWebRequest.CancelRequest = function(parameters) { setupInstance(this, parameters, 'CancelRequest'); }; - declarativeWebRequest.RedirectRequest = function(parameters) { + chrome.declarativeWebRequest.RedirectRequest = function(parameters) { setupInstance(this, parameters, 'RedirectRequest'); }; - declarativeWebRequest.SetRequestHeader = function(parameters) { + chrome.declarativeWebRequest.SetRequestHeader = function(parameters) { setupInstance(this, parameters, 'SetRequestHeader'); }; - declarativeWebRequest.RemoveRequestHeader = function(parameters) { + chrome.declarativeWebRequest.RemoveRequestHeader = function(parameters) { setupInstance(this, parameters, 'RemoveRequestHeader'); }; - declarativeWebRequest.AddResponseHeader = function(parameters) { + chrome.declarativeWebRequest.AddResponseHeader = function(parameters) { setupInstance(this, parameters, 'AddResponseHeader'); }; - declarativeWebRequest.RemoveResponseHeader = function(parameters) { + chrome.declarativeWebRequest.RemoveResponseHeader = function(parameters) { setupInstance(this, parameters, 'RemoveResponseHeader'); }; - declarativeWebRequest.RedirectToTransparentImage = + chrome.declarativeWebRequest.RedirectToTransparentImage = function(parameters) { setupInstance(this, parameters, 'RedirectToTransparentImage'); }; - declarativeWebRequest.RedirectToEmptyDocument = function(parameters) { + chrome.declarativeWebRequest.RedirectToEmptyDocument = function(parameters) { setupInstance(this, parameters, 'RedirectToEmptyDocument'); }; - declarativeWebRequest.RedirectByRegEx = function(parameters) { + chrome.declarativeWebRequest.RedirectByRegEx = function(parameters) { setupInstance(this, parameters, 'RedirectByRegEx'); }; - declarativeWebRequest.IgnoreRules = function(parameters) { + chrome.declarativeWebRequest.IgnoreRules = function(parameters) { setupInstance(this, parameters, 'IgnoreRules'); }; - declarativeWebRequest.AddRequestCookie = function(parameters) { + chrome.declarativeWebRequest.AddRequestCookie = function(parameters) { setupInstance(this, parameters, 'AddRequestCookie'); }; - declarativeWebRequest.AddResponseCookie = function(parameters) { + chrome.declarativeWebRequest.AddResponseCookie = function(parameters) { setupInstance(this, parameters, 'AddResponseCookie'); }; - declarativeWebRequest.EditRequestCookie = function(parameters) { + chrome.declarativeWebRequest.EditRequestCookie = function(parameters) { setupInstance(this, parameters, 'EditRequestCookie'); }; - declarativeWebRequest.EditResponseCookie = function(parameters) { + chrome.declarativeWebRequest.EditResponseCookie = function(parameters) { setupInstance(this, parameters, 'EditResponseCookie'); }; - declarativeWebRequest.RemoveRequestCookie = function(parameters) { + chrome.declarativeWebRequest.RemoveRequestCookie = function(parameters) { setupInstance(this, parameters, 'RemoveRequestCookie'); }; - declarativeWebRequest.RemoveResponseCookie = function(parameters) { + chrome.declarativeWebRequest.RemoveResponseCookie = function(parameters) { setupInstance(this, parameters, 'RemoveResponseCookie'); }; - declarativeWebRequest.SendMessageToExtension = function(parameters) { + chrome.declarativeWebRequest.SendMessageToExtension = function(parameters) { setupInstance(this, parameters, 'SendMessageToExtension'); }; }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/event.js b/chrome/renderer/resources/extensions/event.js index 59e04d5..4e99256 100644 --- a/chrome/renderer/resources/extensions/event.js +++ b/chrome/renderer/resources/extensions/event.js @@ -3,8 +3,6 @@ // found in the LICENSE file. var DCHECK = requireNative('logging').DCHECK; - // TODO(cduvall/kalman): json_schema shouldn't put things on chromeHidden. - require('json_schema'); var eventBindingsNatives = requireNative('event_bindings'); var AttachEvent = eventBindingsNatives.AttachEvent; var DetachEvent = eventBindingsNatives.DetachEvent; @@ -16,8 +14,8 @@ var validate = require('schemaUtils').validate; var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); - var chrome = requireNative('chrome').GetChrome(); - var schemaRegistry = requireNative('schema_registry'); + var GetExtensionAPIDefinition = + requireNative('apiDefinitions').GetExtensionAPIDefinition; // Schemas for the rule-style functions on the events API that // only need to be generated occasionally, so populate them lazily. @@ -32,7 +30,7 @@ function ensureRuleSchemasLoaded() { if (ruleFunctionSchemas.addRules) return; - var eventsSchema = schemaRegistry.GetSchema("events"); + var eventsSchema = GetExtensionAPIDefinition("events")[0]; var eventType = utils.lookup(eventsSchema.types, 'id', 'events.Event'); ruleFunctionSchemas.addRules = @@ -153,7 +151,7 @@ // // If opt_eventOptions exists, it is a dictionary that contains the boolean // entries "supportsListeners" and "supportsRules". - var Event = function(opt_eventName, opt_argSchemas, opt_eventOptions) { + chrome.Event = function(opt_eventName, opt_argSchemas, opt_eventOptions) { this.eventName_ = opt_eventName; this.listeners_ = []; this.eventOptions_ = chromeHidden.parseEventOptions(opt_eventOptions); @@ -229,7 +227,7 @@ }; // Registers a callback to be called when this event is dispatched. - Event.prototype.addListener = function(cb, filters) { + chrome.Event.prototype.addListener = function(cb, filters) { if (!this.eventOptions_.supportsListeners) throw new Error("This event does not support listeners."); if (this.eventOptions_.maxListeners && @@ -246,7 +244,7 @@ this.listeners_.push(listener); }; - Event.prototype.attach_ = function(listener) { + chrome.Event.prototype.attach_ = function(listener) { this.attachmentStrategy_.onAddedListener(listener); if (this.listeners_.length == 0) { allAttachedEvents[allAttachedEvents.length] = this; @@ -263,7 +261,7 @@ }; // Unregisters a callback. - Event.prototype.removeListener = function(cb) { + chrome.Event.prototype.removeListener = function(cb) { if (!this.eventOptions_.supportsListeners) throw new Error("This event does not support listeners."); var idx = this.findListener_(cb); @@ -291,19 +289,19 @@ }; // Test if the given callback is registered for this event. - Event.prototype.hasListener = function(cb) { + chrome.Event.prototype.hasListener = function(cb) { if (!this.eventOptions_.supportsListeners) throw new Error("This event does not support listeners."); return this.findListener_(cb) > -1; }; // Test if any callbacks are registered for this event. - Event.prototype.hasListeners = function() { + chrome.Event.prototype.hasListeners = function() { return this.getListenerCount() > 0; }; // Return the number of listeners on this event. - Event.prototype.getListenerCount = function() { + chrome.Event.prototype.getListenerCount = function() { if (!this.eventOptions_.supportsListeners) throw new Error("This event does not support listeners."); return this.listeners_.length; @@ -311,7 +309,7 @@ // Returns the index of the given callback if registered, or -1 if not // found. - Event.prototype.findListener_ = function(cb) { + chrome.Event.prototype.findListener_ = function(cb) { for (var i = 0; i < this.listeners_.length; i++) { if (this.listeners_[i].callback == cb) { return i; @@ -321,7 +319,7 @@ return -1; }; - Event.prototype.dispatch_ = function(args, listenerIDs) { + chrome.Event.prototype.dispatch_ = function(args, listenerIDs) { if (!this.eventOptions_.supportsListeners) throw new Error("This event does not support listeners."); var validationErrors = this.validateEventArgs_(args); @@ -351,28 +349,28 @@ } // Can be overridden to support custom dispatching. - Event.prototype.dispatchToListener = function(callback, args) { + chrome.Event.prototype.dispatchToListener = function(callback, args) { return callback.apply(null, args); } // Dispatches this event object to all listeners, passing all supplied // arguments to this function each listener. - Event.prototype.dispatch = function(varargs) { + chrome.Event.prototype.dispatch = function(varargs) { return this.dispatch_(Array.prototype.slice.call(arguments), undefined); }; // Detaches this event object from its name. - Event.prototype.detach_ = function() { + chrome.Event.prototype.detach_ = function() { this.attachmentStrategy_.detach(false); }; - Event.prototype.destroy_ = function() { + chrome.Event.prototype.destroy_ = function() { this.listeners_ = []; this.validateEventArgs_ = []; this.detach_(false); }; - Event.prototype.addRules = function(rules, opt_cb) { + chrome.Event.prototype.addRules = function(rules, opt_cb) { if (!this.eventOptions_.supportsRules) throw new Error("This event does not support rules."); @@ -422,7 +420,7 @@ ruleFunctionSchemas.addRules.parameters); } - Event.prototype.removeRules = function(ruleIdentifiers, opt_cb) { + chrome.Event.prototype.removeRules = function(ruleIdentifiers, opt_cb) { if (!this.eventOptions_.supportsRules) throw new Error("This event does not support rules."); ensureRuleSchemasLoaded(); @@ -435,7 +433,7 @@ ruleFunctionSchemas.removeRules.parameters); } - Event.prototype.getRules = function(ruleIdentifiers, cb) { + chrome.Event.prototype.getRules = function(ruleIdentifiers, cb) { if (!this.eventOptions_.supportsRules) throw new Error("This event does not support rules."); ensureRuleSchemasLoaded(); @@ -452,8 +450,8 @@ // Special load events: we don't use the DOM unload because that slows // down tab shutdown. On the other hand, onUnload might not always fire, // since Chrome will terminate renderers on shutdown (SuddenTermination). - chromeHidden.onLoad = new Event(); - chromeHidden.onUnload = new Event(); + chromeHidden.onLoad = new chrome.Event(); + chromeHidden.onUnload = new chrome.Event(); chromeHidden.dispatchOnLoad = chromeHidden.onLoad.dispatch.bind(chromeHidden.onLoad); @@ -473,4 +471,4 @@ console.error(msg); }; - chrome.Event = Event; + exports.Event = chrome.Event; diff --git a/chrome/renderer/resources/extensions/experimental.media_galleries_custom_bindings.js b/chrome/renderer/resources/extensions/experimental.media_galleries_custom_bindings.js index 8f82c4e..07b33d4 100644 --- a/chrome/renderer/resources/extensions/experimental.media_galleries_custom_bindings.js +++ b/chrome/renderer/resources/extensions/experimental.media_galleries_custom_bindings.js @@ -2,13 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the Media Gallery API. - -var binding = require('binding').Binding.create('experimental.mediaGalleries'); +// Custom bindings for the Media Gallery API. var mediaGalleriesNatives = requireNative('mediaGalleries'); -binding.registerCustomHook(function(bindingsAPI, extensionId) { +var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); + +chromeHidden.registerCustomHook('experimental.mediaGalleries', + function(bindingsAPI, extensionId) { var apiFunctions = bindingsAPI.apiFunctions; // extractEmbeddedThumbnails uses a renderer side handler so that it can @@ -19,5 +20,3 @@ binding.registerCustomHook(function(bindingsAPI, extensionId) { return mediaGalleriesNatives.ExtractEmbeddedThumbnails(fileEntry); }); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/experimental.offscreenTabs_custom_bindings.js b/chrome/renderer/resources/extensions/experimental.offscreenTabs_custom_bindings.js index 7903a3d..3635a2c 100644 --- a/chrome/renderer/resources/extensions/experimental.offscreenTabs_custom_bindings.js +++ b/chrome/renderer/resources/extensions/experimental.offscreenTabs_custom_bindings.js @@ -2,11 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the experimental offscreenTabs API. +// Custom bindings for the experimental offscreenTabs API. -var binding = require('binding').Binding.create('experimental.offscreenTabs'); +(function() { -binding.registerCustomHook( +native function GetChromeHidden(); + +GetChromeHidden().registerCustomHook( 'experimental.offscreenTabs', function(api) { var apiFunctions = api.apiFunctions; @@ -58,4 +60,4 @@ binding.registerCustomHook( function() { return validate(arguments, mouseEventFilter); }); }); -exports.binding = binding.generate(); +})(); diff --git a/chrome/renderer/resources/extensions/extension_custom_bindings.js b/chrome/renderer/resources/extensions/extension_custom_bindings.js index 61e5e16b..60b4f12 100644 --- a/chrome/renderer/resources/extensions/extension_custom_bindings.js +++ b/chrome/renderer/resources/extensions/extension_custom_bindings.js @@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the extension API. - -var binding = require('binding').Binding.create('extension'); +// Custom bindings for the extension API. var extensionNatives = requireNative('extension'); var GetExtensionViews = extensionNatives.GetExtensionViews; @@ -12,14 +10,22 @@ var runtimeNatives = requireNative('runtime'); var OpenChannelToExtension = runtimeNatives.OpenChannelToExtension; var OpenChannelToNativeApp = runtimeNatives.OpenChannelToNativeApp; var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); -var chrome = requireNative('chrome').GetChrome(); var sendMessageUpdateArguments = require('miscellaneous_bindings').sendMessageUpdateArguments; var inIncognitoContext = requireNative('process').InIncognitoContext(); var sendRequestIsDisabled = requireNative('process').IsSendRequestDisabled(); var contextType = requireNative('process').GetContextType(); + +chrome.extension = chrome.extension || {}; + var manifestVersion = requireNative('process').GetManifestVersion(); +if (manifestVersion < 2) { + chrome.self = chrome.extension; + chrome.extension.inIncognitoTab = inIncognitoContext; +} + +chrome.extension.inIncognitoContext = inIncognitoContext; // This should match chrome.windows.WINDOW_ID_NONE. // @@ -28,14 +34,8 @@ var manifestVersion = requireNative('process').GetManifestVersion(); // which may not be the case. var WINDOW_ID_NONE = -1; -binding.registerCustomHook(function(bindingsAPI, extensionId) { - var extension = bindingsAPI.compiledApi; - if (manifestVersion < 2) { - chrome.self = extension; - extension.inIncognitoTab = inIncognitoContext; - } - extension.inIncognitoContext = inIncognitoContext; - +chromeHidden.registerCustomHook('extension', + function(bindingsAPI, extensionId) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setHandleRequest('getViews', function(properties) { @@ -83,7 +83,7 @@ binding.registerCustomHook(function(bindingsAPI, extensionId) { // getters that throw exceptions. Assume that any getter is such a function. if (chrome.runtime.hasOwnProperty(alias) && chrome.runtime.__lookupGetter__(alias) === undefined) { - extension[alias] = chrome.runtime[alias]; + chrome.extension[alias] = chrome.runtime[alias]; } }); @@ -100,15 +100,14 @@ binding.registerCustomHook(function(bindingsAPI, extensionId) { }); if (sendRequestIsDisabled) { - extension.onRequest.addListener = function() { + chrome.extension.onRequest.addListener = function() { throw new Error(sendRequestIsDisabled); }; if (contextType == 'BLESSED_EXTENSION') { - extension.onRequestExternal.addListener = function() { + chrome.extension.onRequestExternal.addListener = function() { throw new Error(sendRequestIsDisabled); }; } } -}); -exports.binding = binding.generate(); +}); diff --git a/chrome/renderer/resources/extensions/file_browser_handler_custom_bindings.js b/chrome/renderer/resources/extensions/file_browser_handler_custom_bindings.js index 1fbe7b08c..17af969 100644 --- a/chrome/renderer/resources/extensions/file_browser_handler_custom_bindings.js +++ b/chrome/renderer/resources/extensions/file_browser_handler_custom_bindings.js @@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the fileBrowserHandler API. - -var binding = require('binding').Binding.create('fileBrowserHandler'); +// Custom bindings for the fileBrowserHandler API. var fileBrowserNatives = requireNative('file_browser_handler'); var GetExternalFileEntry = fileBrowserNatives.GetExternalFileEntry; var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); -var fileBrowserHandlerInternal = require('binding').Binding.create( - 'fileBrowserHandlerInternal').generate(); chromeHidden.Event.registerArgumentMassager('fileBrowserHandler.onExecute', function(args, dispatch) { @@ -32,7 +28,7 @@ chromeHidden.Event.registerArgumentMassager('fileBrowserHandler.onExecute', dispatch(args); }); -binding.registerCustomHook(function(bindingsAPI) { +chromeHidden.registerCustomHook('fileBrowserHandler', function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setHandleRequest('selectFile', @@ -50,9 +46,7 @@ binding.registerCustomHook(function(bindingsAPI) { externalCallback(result); } - return fileBrowserHandlerInternal.selectFile( + return chromeHidden.internalAPIs.fileBrowserHandlerInternal.selectFile( selectionParams, internalCallback.bind(null, callback)); }); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/file_browser_private_custom_bindings.js b/chrome/renderer/resources/extensions/file_browser_private_custom_bindings.js index 10c616e..0d9369d 100644 --- a/chrome/renderer/resources/extensions/file_browser_private_custom_bindings.js +++ b/chrome/renderer/resources/extensions/file_browser_private_custom_bindings.js @@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the fileBrowserPrivate API. - -var binding = require('binding').Binding.create('fileBrowserPrivate'); +// Custom bindings for the fileBrowserPrivate API. var fileBrowserPrivateNatives = requireNative('file_browser_private'); var GetLocalFileSystem = fileBrowserPrivateNatives.GetLocalFileSystem; @@ -12,7 +10,9 @@ var GetLocalFileSystem = fileBrowserPrivateNatives.GetLocalFileSystem; var fileBrowserNatives = requireNative('file_browser_handler'); var GetExternalFileEntry = fileBrowserNatives.GetExternalFileEntry; -binding.registerCustomHook(function(bindingsAPI) { +var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); + +chromeHidden.registerCustomHook('fileBrowserPrivate', function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setCustomCallback('requestLocalFileSystem', @@ -61,5 +61,3 @@ binding.registerCustomHook(function(bindingsAPI) { request.callback = null; }); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/file_system_custom_bindings.js b/chrome/renderer/resources/extensions/file_system_custom_bindings.js index 058a423..29e20e7 100644 --- a/chrome/renderer/resources/extensions/file_system_custom_bindings.js +++ b/chrome/renderer/resources/extensions/file_system_custom_bindings.js @@ -2,19 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the fileSystem API. - -var binding = require('binding').Binding.create('fileSystem'); +// Custom bindings for the fileSystem API. +var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); var fileSystemNatives = requireNative('file_system_natives'); var GetIsolatedFileSystem = fileSystemNatives.GetIsolatedFileSystem; var lastError = require('lastError'); var entryIdManager = require('entryIdManager'); -binding.registerCustomHook(function(bindingsAPI) { +chromeHidden.registerCustomHook('fileSystem', function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; - var fileSystem = bindingsAPI.compiledApi; - function bindFileEntryFunction(functionName) { apiFunctions.setUpdateArgumentsPostValidate( functionName, function(fileEntry, callback) { @@ -68,23 +65,21 @@ binding.registerCustomHook(function(bindingsAPI) { }); // TODO(benwells): Remove these deprecated versions of the functions. - fileSystem.getWritableFileEntry = function() { + chrome.fileSystem.getWritableFileEntry = function() { console.log("chrome.fileSystem.getWritableFileEntry is deprecated"); console.log("Please use chrome.fileSystem.getWritableEntry instead"); - fileSystem.getWritableEntry.apply(this, arguments); + chrome.fileSystem.getWritableEntry.apply(this, arguments); }; - fileSystem.isWritableFileEntry = function() { + chrome.fileSystem.isWritableFileEntry = function() { console.log("chrome.fileSystem.isWritableFileEntry is deprecated"); console.log("Please use chrome.fileSystem.isWritableEntry instead"); - fileSystem.isWritableEntry.apply(this, arguments); + chrome.fileSystem.isWritableEntry.apply(this, arguments); }; - fileSystem.chooseFile = function() { + chrome.fileSystem.chooseFile = function() { console.log("chrome.fileSystem.chooseFile is deprecated"); console.log("Please use chrome.fileSystem.chooseEntry instead"); - fileSystem.chooseEntry.apply(this, arguments); + chrome.fileSystem.chooseEntry.apply(this, arguments); }; }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/i18n_custom_bindings.js b/chrome/renderer/resources/extensions/i18n_custom_bindings.js index 39f5a7d..14120af 100644 --- a/chrome/renderer/resources/extensions/i18n_custom_bindings.js +++ b/chrome/renderer/resources/extensions/i18n_custom_bindings.js @@ -2,16 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the i18n API. - -var binding = require('binding').Binding.create('i18n'); +// Custom bindings for the i18n API. var i18nNatives = requireNative('i18n'); var GetL10nMessage = i18nNatives.GetL10nMessage; var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); -binding.registerCustomHook(function(bindingsAPI, extensionId) { +chromeHidden.registerCustomHook('i18n', function(bindingsAPI, extensionId) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setUpdateArgumentsPreValidate('getMessage', function() { @@ -34,5 +32,3 @@ binding.registerCustomHook(function(bindingsAPI, extensionId) { return GetL10nMessage(messageName, substitutions, extensionId); }); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/input.ime_custom_bindings.js b/chrome/renderer/resources/extensions/input.ime_custom_bindings.js index 79ab4a3..60b0105 100644 --- a/chrome/renderer/resources/extensions/input.ime_custom_bindings.js +++ b/chrome/renderer/resources/extensions/input.ime_custom_bindings.js @@ -2,15 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the input ime API. Only injected into the +// Custom bindings for the input ime API. Only injected into the // v8 contexts for extensions which have permission for the API. -var binding = require('binding').Binding.create('input.ime'); +var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); -binding.registerCustomHook(function(api) { - var input_ime = api.compiledApi; - - input_ime.onKeyEvent.dispatchToListener = function(callback, args) { +chromeHidden.registerCustomHook('input.ime', function() { + chrome.input.ime.onKeyEvent.dispatchToListener = function(callback, args) { var engineID = args[0]; var keyData = args[1]; @@ -20,21 +18,19 @@ binding.registerCustomHook(function(api) { } catch (e) { console.error('Error in event handler for onKeyEvent: ' + e.stack); } - if (!input_ime.onKeyEvent.async) - input_ime.keyEventHandled(keyData.requestId, result); + if (!chrome.input.ime.onKeyEvent.async) + chrome.input.ime.keyEventHandled(keyData.requestId, result); }; - input_ime.onKeyEvent.addListener = function(cb, opt_extraInfo) { - input_ime.onKeyEvent.async = false; + chrome.input.ime.onKeyEvent.addListener = function(cb, opt_extraInfo) { + chrome.input.ime.onKeyEvent.async = false; if (opt_extraInfo instanceof Array) { for (var i = 0; i < opt_extraInfo.length; ++i) { if (opt_extraInfo[i] == "async") { - input_ime.onKeyEvent.async = true; + chrome.input.ime.onKeyEvent.async = true; } } } chrome.Event.prototype.addListener.call(this, cb, null); }; }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/json_schema.js b/chrome/renderer/resources/extensions/json_schema.js index 44ea2a06..414356c 100644 --- a/chrome/renderer/resources/extensions/json_schema.js +++ b/chrome/renderer/resources/extensions/json_schema.js @@ -38,9 +38,7 @@ // additional properties will be validated. //============================================================================== -// TODO(cduvall): Make this file not depend on chromeHidden. var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); -var loadRefDependency = require('utils').loadRefDependency; function isInstanceOfClass(instance, className) { if (!instance) @@ -242,7 +240,6 @@ chromeHidden.JSONSchemaValidator.prototype.validate = // If the schema has a $ref property, the instance must validate against // that schema too. It must be present in this.types to be referenced. if (schema["$ref"]) { - loadRefDependency(schema["$ref"]); if (!this.types[schema["$ref"]]) this.addError(path, "unknownSchemaReference", [ schema["$ref"] ]); else diff --git a/chrome/renderer/resources/extensions/last_error.js b/chrome/renderer/resources/extensions/last_error.js index 5eb5c01..2b38a29 100644 --- a/chrome/renderer/resources/extensions/last_error.js +++ b/chrome/renderer/resources/extensions/last_error.js @@ -3,17 +3,16 @@ // found in the LICENSE file. requireNative('runtime'); -var GetAvailability = requireNative('v8_context').GetAvailability; function set(message) { var errorObject = { 'message': message }; - if (GetAvailability('extension').is_available) + if (chrome.extension) chrome.extension.lastError = errorObject; chrome.runtime.lastError = errorObject; }; function clear() { - if (GetAvailability('extension').is_available) + if (chrome.extension) delete chrome.extension.lastError; delete chrome.runtime.lastError; }; diff --git a/chrome/renderer/resources/extensions/media_galleries_custom_bindings.js b/chrome/renderer/resources/extensions/media_galleries_custom_bindings.js index 60ac567..f1f9edfe 100644 --- a/chrome/renderer/resources/extensions/media_galleries_custom_bindings.js +++ b/chrome/renderer/resources/extensions/media_galleries_custom_bindings.js @@ -2,15 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the Media Gallery API. - -var binding = require('binding').Binding.create('mediaGalleries'); +// Custom bindings for the Media Gallery API. var mediaGalleriesNatives = requireNative('mediaGalleries'); +var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); + var mediaGalleriesMetadata = {}; -binding.registerCustomHook(function(bindingsAPI, extensionId) { +chromeHidden.registerCustomHook('mediaGalleries', + function(bindingsAPI, extensionId) { var apiFunctions = bindingsAPI.apiFunctions; // getMediaFileSystems uses a custom callback so that it can instantiate and @@ -47,5 +48,3 @@ binding.registerCustomHook(function(bindingsAPI, extensionId) { return {}; }); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/miscellaneous_bindings.js b/chrome/renderer/resources/extensions/miscellaneous_bindings.js index e1469f8..147528c 100644 --- a/chrome/renderer/resources/extensions/miscellaneous_bindings.js +++ b/chrome/renderer/resources/extensions/miscellaneous_bindings.js @@ -8,10 +8,10 @@ // content scripts only. require('json_schema'); + require('event_bindings'); var json = require('json'); var lastError = require('lastError'); var miscNatives = requireNative('miscellaneous_bindings'); - var chrome = requireNative('chrome').GetChrome(); var CloseChannel = miscNatives.CloseChannel; var PortAddRef = miscNatives.PortAddRef; var PortRelease = miscNatives.PortRelease; diff --git a/chrome/renderer/resources/extensions/notification_custom_bindings.js b/chrome/renderer/resources/extensions/notification_custom_bindings.js index 0e2cd13..b88be09 100644 --- a/chrome/renderer/resources/extensions/notification_custom_bindings.js +++ b/chrome/renderer/resources/extensions/notification_custom_bindings.js @@ -4,12 +4,10 @@ // Custom bindings for the notification API. -var binding = require('binding').Binding.create('experimental.notification'); - +var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); var sendRequest = require('sendRequest').sendRequest; var imageUtil = require('imageUtil'); var lastError = require('lastError'); -var json = require('json'); function url_getter(context, key) { var f = function() { @@ -101,8 +99,8 @@ function genHandle(failure_function) { return function(id, input_notification_details, callback) { // TODO(dewittj): Remove this hack. This is used as a way to deep // copy a complex JSON object. - var notification_details = json.parse( - json.stringify(input_notification_details)); + var notification_details = JSON.parse( + JSON.stringify(input_notification_details)); var that = this; replaceNotificationOptionURLs(notification_details, function(success) { if (success) { @@ -126,6 +124,5 @@ var experimentalNotificationCustomHook = function(bindingsAPI, extensionId) { apiFunctions.setHandleRequest('update', handleCreate); }; -binding.registerCustomHook(experimentalNotificationCustomHook); - -exports.binding = binding.generate(); +chromeHidden.registerCustomHook('experimental.notification', + experimentalNotificationCustomHook); diff --git a/chrome/renderer/resources/extensions/omnibox_custom_bindings.js b/chrome/renderer/resources/extensions/omnibox_custom_bindings.js index fa0ced3..04ae181 100644 --- a/chrome/renderer/resources/extensions/omnibox_custom_bindings.js +++ b/chrome/renderer/resources/extensions/omnibox_custom_bindings.js @@ -2,11 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the omnibox API. Only injected into the v8 contexts +// Custom bindings for the omnibox API. Only injected into the v8 contexts // for extensions which have permission for the omnibox API. -var binding = require('binding').Binding.create('omnibox'); - var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); var sendRequest = require('sendRequest').sendRequest; @@ -81,7 +79,7 @@ function parseOmniboxDescription(input) { return result; } -binding.registerCustomHook(function(bindingsAPI) { +chromeHidden.registerCustomHook('omnibox', function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setHandleRequest('setDefaultSuggestion', function(details) { @@ -111,5 +109,3 @@ chromeHidden.Event.registerArgumentMassager('omnibox.onInputChanged', }; dispatch([text, suggestCallback]); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/page_action_custom_bindings.js b/chrome/renderer/resources/extensions/page_action_custom_bindings.js index 97a308e..b527374 100644 --- a/chrome/renderer/resources/extensions/page_action_custom_bindings.js +++ b/chrome/renderer/resources/extensions/page_action_custom_bindings.js @@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the pageAction API. - -var binding = require('binding').Binding.create('pageAction'); +// Custom bindings for the pageAction API. +var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); var setIcon = require('setIcon').setIcon; -binding.registerCustomHook(function(bindingsAPI) { +chromeHidden.registerCustomHook('pageAction', function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setHandleRequest('setIcon', function(details, callback) { @@ -16,5 +15,3 @@ binding.registerCustomHook(function(bindingsAPI) { 'page action'); }); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/page_actions_custom_bindings.js b/chrome/renderer/resources/extensions/page_actions_custom_bindings.js index 0b72e07..d5ec888 100644 --- a/chrome/renderer/resources/extensions/page_actions_custom_bindings.js +++ b/chrome/renderer/resources/extensions/page_actions_custom_bindings.js @@ -2,21 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the pageActions API. - -var binding = require('binding').Binding.create('pageActions'); +// Custom bindings for the pageActions API. var pageActionsNatives = requireNative('page_actions'); var GetCurrentPageActions = pageActionsNatives.GetCurrentPageActions; -binding.registerCustomHook(function(bindingsAPI, extensionId) { +var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); + +chromeHidden.registerCustomHook('pageActions', + function(bindingsAPI, extensionId) { var pageActions = GetCurrentPageActions(extensionId); - var pageActionsApi = bindingsAPI.compiledApi; var oldStyleEventName = 'pageActions'; for (var i = 0; i < pageActions.length; ++i) { // Setup events for each extension_id/page_action_id string we find. - pageActionsApi[pageActions[i]] = new chrome.Event(oldStyleEventName); + chrome.pageActions[pageActions[i]] = new chrome.Event(oldStyleEventName); } }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/page_capture_custom_bindings.js b/chrome/renderer/resources/extensions/page_capture_custom_bindings.js index f9147d7..15b82f9 100644 --- a/chrome/renderer/resources/extensions/page_capture_custom_bindings.js +++ b/chrome/renderer/resources/extensions/page_capture_custom_bindings.js @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the pageCapture API. - -var binding = require('binding').Binding.create('pageCapture'); +// Custom bindings for the pageCapture API. var pageCaptureNatives = requireNative('page_capture'); var CreateBlob = pageCaptureNatives.CreateBlob; var SendResponseAck = pageCaptureNatives.SendResponseAck; -binding.registerCustomHook(function(bindingsAPI) { +var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); + +chromeHidden.registerCustomHook('pageCapture', function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setCustomCallback('saveAsMHTML', @@ -27,5 +27,3 @@ binding.registerCustomHook(function(bindingsAPI) { SendResponseAck(request.id); }); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/permissions_custom_bindings.js b/chrome/renderer/resources/extensions/permissions_custom_bindings.js index e728080..b32a57d 100644 --- a/chrome/renderer/resources/extensions/permissions_custom_bindings.js +++ b/chrome/renderer/resources/extensions/permissions_custom_bindings.js @@ -2,23 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the Permissions API. - -var binding = require('binding').Binding.create('permissions'); +// Custom bindings for the Permissions API. +var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); var sendRequest = require('sendRequest').sendRequest; var lastError = require('lastError'); -// These custom binding are only necessary because it is not currently +// These custom bindings are only necessary because it is not currently // possible to have a union of types as the type of the items in an array. // Once that is fixed, this entire file should go away. // See, // https://code.google.com/p/chromium/issues/detail?id=162044 // https://code.google.com/p/chromium/issues/detail?id=162042 // TODO(bryeung): delete this file. -binding.registerCustomHook(function(api) { +chromeHidden.registerCustomHook('permissions', function(api) { var apiFunctions = api.apiFunctions; - var permissions = api.compiledApi; function maybeConvertToObject(str) { var parts = str.split('|'); @@ -82,14 +80,12 @@ binding.registerCustomHook(function(api) { // dispatchToListener call happens after argument validation, which works // around the problem that Permissions.permissions is supposed to be a list // of strings. - permissions.onAdded.dispatchToListener = function(callback, args) { + chrome.permissions.onAdded.dispatchToListener = function(callback, args) { for (var i = 0; i < args[0].permissions.length; i += 1) { args[0].permissions[i] = maybeConvertToObject(args[0].permissions[i]); } chrome.Event.prototype.dispatchToListener(callback, args); }; - permissions.onRemoved.dispatchToListener = - permissions.onAdded.dispatchToListener; + chrome.permissions.onRemoved.dispatchToListener = + chrome.permissions.onAdded.dispatchToListener; }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/runtime_custom_bindings.js b/chrome/renderer/resources/extensions/runtime_custom_bindings.js index 61be155..91d402b 100644 --- a/chrome/renderer/resources/extensions/runtime_custom_bindings.js +++ b/chrome/renderer/resources/extensions/runtime_custom_bindings.js @@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the runtime API. - -var binding = require('binding').Binding.create('runtime'); +// Custom bindings for the runtime API. var runtimeNatives = requireNative('runtime'); var extensionNatives = requireNative('extension'); @@ -15,15 +13,14 @@ var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); var sendMessageUpdateArguments = require('miscellaneous_bindings').sendMessageUpdateArguments; -binding.registerCustomHook(function(binding, id, contextType) { - var apiFunctions = binding.apiFunctions; - var runtime = binding.compiledApi; +chromeHidden.registerCustomHook('runtime', function(bindings, id, contextType) { + var apiFunctions = bindings.apiFunctions; // // Unprivileged APIs. // - runtime.id = id; + chrome.runtime.id = id; apiFunctions.setHandleRequest('getManifest', function() { return runtimeNatives.GetManifest(); @@ -43,14 +40,14 @@ binding.registerCustomHook(function(binding, id, contextType) { apiFunctions.setHandleRequest('sendMessage', function(targetId, message, responseCallback) { - var port = runtime.connect(targetId || runtime.id, + var port = chrome.runtime.connect(targetId || chrome.runtime.id, {name: chromeHidden.kMessageChannel}); chromeHidden.Port.sendMessageImpl(port, message, responseCallback); }); apiFunctions.setHandleRequest('sendNativeMessage', function(targetId, message, responseCallback) { - var port = runtime.connectNative(targetId); + var port = chrome.runtime.connectNative(targetId); chromeHidden.Port.sendMessageImpl(port, message, responseCallback); }); @@ -86,7 +83,7 @@ binding.registerCustomHook(function(binding, id, contextType) { apiFunctions.setHandleRequest('connect', function(targetId, connectInfo) { if (!targetId) - targetId = runtime.id; + targetId = chrome.runtime.id; var name = ''; if (connectInfo && connectInfo.name) name = connectInfo.name; @@ -94,7 +91,7 @@ binding.registerCustomHook(function(binding, id, contextType) { // Don't let orphaned content scripts communicate with their extension. // http://crbug.com/168263 if (!chromeHidden.wasUnloaded) { - var portId = OpenChannelToExtension(runtime.id, targetId, name); + var portId = OpenChannelToExtension(chrome.runtime.id, targetId, name); if (portId >= 0) return chromeHidden.Port.createPort(portId, name); } @@ -110,7 +107,7 @@ binding.registerCustomHook(function(binding, id, contextType) { apiFunctions.setHandleRequest('connectNative', function(nativeAppName) { if (!chromeHidden.wasUnloaded) { - var portId = OpenChannelToNativeApp(runtime.id, nativeAppName); + var portId = OpenChannelToNativeApp(chrome.runtime.id, nativeAppName); if (portId >= 0) return chromeHidden.Port.createPort(portId, ''); } @@ -127,5 +124,3 @@ binding.registerCustomHook(function(binding, id, contextType) { }); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/schema_generated_bindings.js b/chrome/renderer/resources/extensions/schema_generated_bindings.js new file mode 100644 index 0000000..65d5cad --- /dev/null +++ b/chrome/renderer/resources/extensions/schema_generated_bindings.js @@ -0,0 +1,437 @@ +// 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. + +// Generates the chrome.* API bindings from a list of schemas. + + // TODO(battre): cleanup the usage of packages everywhere, as described here + // http://codereview.chromium.org/10392008/diff/38/chrome/renderer/resources/extensions/schema_generated_bindings.js + + require('json_schema'); + require('event_bindings'); + var GetExtensionAPIDefinition = + requireNative('apiDefinitions').GetExtensionAPIDefinition; + var sendRequest = require('sendRequest').sendRequest; + var utils = require('utils'); + var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); + var schemaUtils = require('schemaUtils'); + + // The object to generate the bindings for "internal" APIs in, so that + // extensions can't directly call them (without access to chromeHidden), + // but are still needed for internal mechanisms of extensions (e.g. events). + // + // This is distinct to the "*Private" APIs which are controlled via + // having strict permissions and aren't generated *anywhere* unless needed. + var internalAPIs = {}; + chromeHidden.internalAPIs = internalAPIs; + + // Stores the name and definition of each API function, with methods to + // modify their behaviour (such as a custom way to handle requests to the + // API, a custom callback, etc). + function APIFunctions() { + this._apiFunctions = {}; + this._unavailableApiFunctions = {}; + } + APIFunctions.prototype.register = function(apiName, apiFunction) { + this._apiFunctions[apiName] = apiFunction; + }; + // Registers a function as existing but not available, meaning that calls to + // the set* methods that reference this function should be ignored rather + // than throwing Errors. + APIFunctions.prototype.registerUnavailable = function(apiName) { + this._unavailableApiFunctions[apiName] = apiName; + }; + APIFunctions.prototype._setHook = + function(apiName, propertyName, customizedFunction) { + if (this._unavailableApiFunctions.hasOwnProperty(apiName)) + return; + if (!this._apiFunctions.hasOwnProperty(apiName)) + throw new Error('Tried to set hook for unknown API "' + apiName + '"'); + this._apiFunctions[apiName][propertyName] = customizedFunction; + }; + APIFunctions.prototype.setHandleRequest = + function(apiName, customizedFunction) { + return this._setHook(apiName, 'handleRequest', customizedFunction); + }; + APIFunctions.prototype.setUpdateArgumentsPostValidate = + function(apiName, customizedFunction) { + return this._setHook( + apiName, 'updateArgumentsPostValidate', customizedFunction); + }; + APIFunctions.prototype.setUpdateArgumentsPreValidate = + function(apiName, customizedFunction) { + return this._setHook( + apiName, 'updateArgumentsPreValidate', customizedFunction); + }; + APIFunctions.prototype.setCustomCallback = + function(apiName, customizedFunction) { + return this._setHook(apiName, 'customCallback', customizedFunction); + }; + + var apiFunctions = new APIFunctions(); + + // Wraps the calls to the set* methods of APIFunctions with the namespace of + // an API, and validates that all calls to set* methods aren't prefixed with + // a namespace. + // + // For example, if constructed with 'browserAction', a call to + // handleRequest('foo') will be transformed into + // handleRequest('browserAction.foo'). + // + // Likewise, if a call to handleRequest is called with 'browserAction.foo', + // it will throw an error. + // + // These help with isolating custom bindings from each other. + function NamespacedAPIFunctions(namespace, delegate) { + var self = this; + function wrap(methodName) { + self[methodName] = function(apiName, customizedFunction) { + var prefix = namespace + '.'; + if (apiName.indexOf(prefix) === 0) { + throw new Error(methodName + ' called with "' + apiName + + '" which has a "' + prefix + '" prefix. ' + + 'This is unnecessary and must be left out.'); + } + return delegate[methodName].call(delegate, + prefix + apiName, customizedFunction); + }; + } + + wrap('contains'); + wrap('setHandleRequest'); + wrap('setUpdateArgumentsPostValidate'); + wrap('setUpdateArgumentsPreValidate'); + wrap('setCustomCallback'); + } + + // + // The API through which the ${api_name}_custom_bindings.js files customize + // their API bindings beyond what can be generated. + // + // There are 2 types of customizations available: those which are required in + // order to do the schema generation (registerCustomEvent and + // registerCustomType), and those which can only run after the bindings have + // been generated (registerCustomHook). + // + + // Registers a custom event type for the API identified by |namespace|. + // |event| is the event's constructor. + var customEvents = {}; + chromeHidden.registerCustomEvent = function(namespace, event) { + if (typeof(namespace) !== 'string') { + throw new Error("registerCustomEvent requires the namespace of the " + + "API as its first argument"); + } + customEvents[namespace] = event; + }; + + // Registers a function |hook| to run after the schema for all APIs has been + // generated. The hook is passed as its first argument an "API" object to + // interact with, and second the current extension ID. See where + // |customHooks| is used. + var customHooks = {}; + chromeHidden.registerCustomHook = function(namespace, fn) { + if (typeof(namespace) !== 'string') { + throw new Error("registerCustomHook requires the namespace of the " + + "API as its first argument"); + } + customHooks[namespace] = fn; + }; + + function CustomBindingsObject() { + } + CustomBindingsObject.prototype.setSchema = function(schema) { + // The functions in the schema are in list form, so we move them into a + // dictionary for easier access. + var self = this; + self.functionSchemas = {}; + schema.functions.forEach(function(f) { + self.functionSchemas[f.name] = { + name: f.name, + definition: f + } + }); + }; + + // Registers a custom type referenced via "$ref" fields in the API schema + // JSON. + var customTypes = {}; + chromeHidden.registerCustomType = function(typeName, customTypeFactory) { + var customType = customTypeFactory(); + customType.prototype = new CustomBindingsObject(); + customTypes[typeName] = customType; + }; + + // Get the platform from navigator.appVersion. + function getPlatform() { + var platforms = [ + [/CrOS Touch/, "chromeos touch"], + [/CrOS/, "chromeos"], + [/Linux/, "linux"], + [/Mac/, "mac"], + [/Win/, "win"], + ]; + + for (var i = 0; i < platforms.length; i++) { + if (platforms[i][0].test(navigator.appVersion)) { + return platforms[i][1]; + } + } + return "unknown"; + } + + function isPlatformSupported(schemaNode, platform) { + return !schemaNode.platforms || + schemaNode.platforms.indexOf(platform) > -1; + } + + function isManifestVersionSupported(schemaNode, manifestVersion) { + return !schemaNode.maximumManifestVersion || + manifestVersion <= schemaNode.maximumManifestVersion; + } + + function isSchemaNodeSupported(schemaNode, platform, manifestVersion) { + return isPlatformSupported(schemaNode, platform) && + isManifestVersionSupported(schemaNode, manifestVersion); + } + + chromeHidden.onLoad.addListener(function(extensionId, + contextType, + isIncognitoProcess, + manifestVersion) { + var apiDefinitions = GetExtensionAPIDefinition(); + + // Read api definitions and setup api functions in the chrome namespace. + var platform = getPlatform(); + + apiDefinitions.forEach(function(apiDef) { + // TODO(kalman): Remove this, or refactor schema_generated_bindings.js so + // that it isn't necessary. For now, chrome.app and chrome.webstore are + // entirely handwritten. + if (['app', 'webstore'].indexOf(apiDef.namespace) >= 0) + return; + + if (!isSchemaNodeSupported(apiDef, platform, manifestVersion)) + return; + + // See comment on internalAPIs at the top. + var mod = apiDef.internal ? internalAPIs : chrome; + + var namespaces = apiDef.namespace.split('.'); + for (var index = 0, name; name = namespaces[index]; index++) { + mod[name] = mod[name] || {}; + mod = mod[name]; + } + + // Add types to global schemaValidator + if (apiDef.types) { + apiDef.types.forEach(function(t) { + if (!isSchemaNodeSupported(t, platform, manifestVersion)) + return; + + schemaUtils.schemaValidator.addTypes(t); + if (t.type == 'object' && customTypes[t.id]) { + customTypes[t.id].prototype.setSchema(t); + } + }); + } + + // Returns whether access to the content of a schema should be denied, + // based on the presence of "unprivileged" and whether this is an + // extension process (versus e.g. a content script). + function isSchemaAccessAllowed(itemSchema) { + return (contextType == 'BLESSED_EXTENSION') || + apiDef.unprivileged || + itemSchema.unprivileged; + } + + // Adds a getter that throws an access denied error to object |mod| + // for property |name|. + function addUnprivilegedAccessGetter(mod, name) { + mod.__defineGetter__(name, function() { + throw new Error( + '"' + name + '" can only be used in extension processes. See ' + + 'the content scripts documentation for more details.'); + }); + } + + // Setup Functions. + if (apiDef.functions) { + apiDef.functions.forEach(function(functionDef) { + if (functionDef.name in mod) { + throw new Error('Function ' + functionDef.name + + ' already defined in ' + apiDef.namespace); + } + + var apiFunctionName = apiDef.namespace + "." + functionDef.name; + + if (!isSchemaNodeSupported(functionDef, platform, manifestVersion)) { + apiFunctions.registerUnavailable(apiFunctionName); + return; + } + if (!isSchemaAccessAllowed(functionDef)) { + apiFunctions.registerUnavailable(apiFunctionName); + addUnprivilegedAccessGetter(mod, functionDef.name); + return; + } + + var apiFunction = {}; + apiFunction.definition = functionDef; + apiFunction.name = apiFunctionName; + + // TODO(aa): It would be best to run this in a unit test, but in order + // to do that we would need to better factor this code so that it + // doesn't depend on so much v8::Extension machinery. + if (chromeHidden.validateAPI && + schemaUtils.isFunctionSignatureAmbiguous( + apiFunction.definition)) { + throw new Error( + apiFunction.name + ' has ambiguous optional arguments. ' + + 'To implement custom disambiguation logic, add ' + + '"allowAmbiguousOptionalArguments" to the function\'s schema.'); + } + + apiFunctions.register(apiFunction.name, apiFunction); + + mod[functionDef.name] = (function() { + var args = Array.prototype.slice.call(arguments); + if (this.updateArgumentsPreValidate) + args = this.updateArgumentsPreValidate.apply(this, args); + + args = schemaUtils.normalizeArgumentsAndValidate(args, this); + if (this.updateArgumentsPostValidate) + args = this.updateArgumentsPostValidate.apply(this, args); + + var retval; + if (this.handleRequest) { + retval = this.handleRequest.apply(this, args); + } else { + var optArgs = { + customCallback: this.customCallback + }; + retval = sendRequest(this.name, args, + this.definition.parameters, + optArgs); + } + + // Validate return value if defined - only in debug. + if (chromeHidden.validateCallbacks && + this.definition.returns) { + schemaUtils.validate([retval], [this.definition.returns]); + } + return retval; + }).bind(apiFunction); + }); + } + + // Setup Events + if (apiDef.events) { + apiDef.events.forEach(function(eventDef) { + if (eventDef.name in mod) { + throw new Error('Event ' + eventDef.name + + ' already defined in ' + apiDef.namespace); + } + if (!isSchemaNodeSupported(eventDef, platform, manifestVersion)) + return; + if (!isSchemaAccessAllowed(eventDef)) { + addUnprivilegedAccessGetter(mod, eventDef.name); + return; + } + + var eventName = apiDef.namespace + "." + eventDef.name; + var customEvent = customEvents[apiDef.namespace]; + var options = eventDef.options || {}; + + if (eventDef.filters && eventDef.filters.length > 0) + options.supportsFilters = true; + + if (customEvent) { + mod[eventDef.name] = new customEvent( + eventName, eventDef.parameters, eventDef.extraParameters, + options); + } else if (eventDef.anonymous) { + mod[eventDef.name] = new chrome.Event(); + } else { + mod[eventDef.name] = new chrome.Event( + eventName, eventDef.parameters, options); + } + }); + } + + function addProperties(m, parentDef) { + var properties = parentDef.properties; + if (!properties) + return; + + utils.forEach(properties, function(propertyName, propertyDef) { + if (propertyName in m) + return; // TODO(kalman): be strict like functions/events somehow. + if (!isSchemaNodeSupported(propertyDef, platform, manifestVersion)) + return; + if (!isSchemaAccessAllowed(propertyDef)) { + addUnprivilegedAccessGetter(m, propertyName); + return; + } + + var value = propertyDef.value; + if (value) { + // Values may just have raw types as defined in the JSON, such + // as "WINDOW_ID_NONE": { "value": -1 }. We handle this here. + // TODO(kalman): enforce that things with a "value" property can't + // define their own types. + var type = propertyDef.type || typeof(value); + if (type === 'integer' || type === 'number') { + value = parseInt(value); + } else if (type === 'boolean') { + value = value === "true"; + } else if (propertyDef["$ref"]) { + var constructor = customTypes[propertyDef["$ref"]]; + if (!constructor) + throw new Error("No custom binding for " + propertyDef["$ref"]); + var args = value; + // For an object propertyDef, |value| is an array of constructor + // arguments, but we want to pass the arguments directly (i.e. + // not as an array), so we have to fake calling |new| on the + // constructor. + value = { __proto__: constructor.prototype }; + constructor.apply(value, args); + // Recursively add properties. + addProperties(value, propertyDef); + } else if (type === 'object') { + // Recursively add properties. + addProperties(value, propertyDef); + } else if (type !== 'string') { + throw new Error("NOT IMPLEMENTED (extension_api.json error): " + + "Cannot parse values for type \"" + type + "\""); + } + m[propertyName] = value; + } + }); + } + + addProperties(mod, apiDef); + }); + + // Run the non-declarative custom hooks after all the schemas have been + // generated, in case hooks depend on other APIs being available. + apiDefinitions.forEach(function(apiDef) { + if (!isSchemaNodeSupported(apiDef, platform, manifestVersion)) + return; + + var hook = customHooks[apiDef.namespace]; + if (!hook) + return; + + // Pass through the public API of schema_generated_bindings, to be used + // by custom bindings JS files. Create a new one so that bindings can't + // interfere with each other. + hook({ + apiFunctions: new NamespacedAPIFunctions(apiDef.namespace, + apiFunctions), + apiDefinitions: apiDefinitions, + }, extensionId, contextType); + }); + + if (chrome.test) + chrome.test.getApiDefinitions = GetExtensionAPIDefinition; + }); diff --git a/chrome/renderer/resources/extensions/schema_utils.js b/chrome/renderer/resources/extensions/schema_utils.js index 31531f9..8cd0212 100644 --- a/chrome/renderer/resources/extensions/schema_utils.js +++ b/chrome/renderer/resources/extensions/schema_utils.js @@ -5,7 +5,6 @@ // Routines used to validate and normalize arguments. var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); -var chrome = requireNative('chrome').GetChrome(); // TODO(benwells): unit test this file. // JSONSchemaValidator is not loaded in unit tests. diff --git a/chrome/renderer/resources/extensions/send_request.js b/chrome/renderer/resources/extensions/send_request.js index 1e5746f..d689a5b 100644 --- a/chrome/renderer/resources/extensions/send_request.js +++ b/chrome/renderer/resources/extensions/send_request.js @@ -3,7 +3,6 @@ // found in the LICENSE file. var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); -var DCHECK = requireNative('logging').DCHECK; var json = require('json'); var lastError = require('lastError'); var natives = requireNative('sendRequest'); @@ -15,7 +14,6 @@ chromeHidden.handleResponse = function(requestId, name, success, responseList, error) { try { var request = requests[requestId]; - DCHECK(request != null); if (success) { lastError.clear(); } else { @@ -34,7 +32,7 @@ chromeHidden.handleResponse = function(requestId, name, if (request.callback) { // Validate callback in debug only -- and only when the // caller has provided a callback. Implementations of api - // calls may not return data if they observe the caller + // calls my not return data if they observe the caller // has not provided a callback. if (chromeHidden.validateCallbacks && !error) { try { diff --git a/chrome/renderer/resources/extensions/storage_custom_bindings.js b/chrome/renderer/resources/extensions/storage_custom_bindings.js index 869a555..d230099 100644 --- a/chrome/renderer/resources/extensions/storage_custom_bindings.js +++ b/chrome/renderer/resources/extensions/storage_custom_bindings.js @@ -2,15 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the storage API. - -var binding = require('binding').Binding.create('storage'); +// Custom bindings for the storage API. +var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); var normalizeArgumentsAndValidate = require('schemaUtils').normalizeArgumentsAndValidate var sendRequest = require('sendRequest').sendRequest; -binding.registerCustomType('storage.StorageArea', function() { +chromeHidden.registerCustomType('storage.StorageArea', function() { function extendSchema(schema) { var extendedSchema = schema.slice(); extendedSchema.unshift({'type': 'string'}); @@ -22,7 +21,7 @@ binding.registerCustomType('storage.StorageArea', function() { // storage.sync.get('foo') -> (binds to) -> // storage.get('sync', 'foo'). // - // TODO(kalman): Put as a method on CustombindingObject and re-use (or + // TODO(kalman): Put as a method on CustomBindingsObject and re-use (or // even generate) for other APIs that need to do this. Same for other // callers of registerCustomType(). var self = this; @@ -44,5 +43,3 @@ binding.registerCustomType('storage.StorageArea', function() { return StorageArea; }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js b/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js index bcb1219..03c6caa 100644 --- a/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js +++ b/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js @@ -2,15 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the syncFileSystem API. - -var binding = require('binding').Binding.create('syncFileSystem'); +// Custom bindings for the syncFileSystem API. var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); var fileSystemNatives = requireNative('file_system_natives'); var syncFileSystemNatives = requireNative('sync_file_system'); -binding.registerCustomHook(function(bindingsAPI) { +chromeHidden.registerCustomHook('syncFileSystem', function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; // Functions which take in an [instanceOf=FileEntry]. @@ -69,5 +67,3 @@ chromeHidden.Event.registerArgumentMassager( } dispatch([fileInfo]); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/system_indicator_custom_bindings.js b/chrome/renderer/resources/extensions/system_indicator_custom_bindings.js index 0551a83..0d58de1 100644 --- a/chrome/renderer/resources/extensions/system_indicator_custom_bindings.js +++ b/chrome/renderer/resources/extensions/system_indicator_custom_bindings.js @@ -2,16 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the systemIndicator API. -// TODO(dewittj) Refactor custom binding to reduce redundancy between the +// Custom bindings for the systemIndicator API. +// TODO(dewittj) Refactor custom bindings to reduce redundancy between the // extension action APIs. -var binding = require('binding').Binding.create('systemIndicator'); - var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); var setIcon = require('setIcon').setIcon; -binding.registerCustomHook(function(bindingsAPI) { +chromeHidden.registerCustomHook('systemIndicator', function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setHandleRequest('setIcon', function(details, callback) { @@ -20,4 +18,3 @@ binding.registerCustomHook(function(bindingsAPI) { }); }); -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/tab_capture_custom_bindings.js b/chrome/renderer/resources/extensions/tab_capture_custom_bindings.js index a75d36d..f458a2f 100644 --- a/chrome/renderer/resources/extensions/tab_capture_custom_bindings.js +++ b/chrome/renderer/resources/extensions/tab_capture_custom_bindings.js @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the Tab Capture API. +// Custom bindings for the Tab Capture API. +var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); -var binding = require('binding').Binding.create('tabCapture'); - -binding.registerCustomHook(function(bindingsAPI, extensionId) { +chromeHidden.registerCustomHook('tabCapture', + function(bindingsAPI, extensionId) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setCustomCallback('capture', @@ -33,5 +33,3 @@ binding.registerCustomHook(function(bindingsAPI, extensionId) { request.callback = null; }); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/tabs_custom_bindings.js b/chrome/renderer/resources/extensions/tabs_custom_bindings.js index 0d7c405..90e5912 100644 --- a/chrome/renderer/resources/extensions/tabs_custom_bindings.js +++ b/chrome/renderer/resources/extensions/tabs_custom_bindings.js @@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the tabs API. - -var binding = require('binding').Binding.create('tabs'); +// Custom bindings for the tabs API. var tabsNatives = requireNative('tabs'); var OpenChannelToTab = tabsNatives.OpenChannelToTab; @@ -12,9 +10,8 @@ var sendRequestIsDisabled = requireNative('process').IsSendRequestDisabled(); var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); -binding.registerCustomHook(function(bindingsAPI, extensionId) { +chromeHidden.registerCustomHook('tabs', function(bindingsAPI, extensionId) { var apiFunctions = bindingsAPI.apiFunctions; - var tabs = bindingsAPI.compiledApi; apiFunctions.setHandleRequest('connect', function(tabId, connectInfo) { var name = ''; @@ -29,15 +26,13 @@ binding.registerCustomHook(function(bindingsAPI, extensionId) { function(tabId, request, responseCallback) { if (sendRequestIsDisabled) throw new Error(sendRequestIsDisabled); - var port = tabs.connect(tabId, {name: chromeHidden.kRequestChannel}); + var port = chrome.tabs.connect(tabId, {name: chromeHidden.kRequestChannel}); chromeHidden.Port.sendMessageImpl(port, request, responseCallback); }); apiFunctions.setHandleRequest('sendMessage', function(tabId, message, responseCallback) { - var port = tabs.connect(tabId, {name: chromeHidden.kMessageChannel}); + var port = chrome.tabs.connect(tabId, {name: chromeHidden.kMessageChannel}); chromeHidden.Port.sendMessageImpl(port, message, responseCallback); }); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/tts_custom_bindings.js b/chrome/renderer/resources/extensions/tts_custom_bindings.js index 5c74666..634ee38 100644 --- a/chrome/renderer/resources/extensions/tts_custom_bindings.js +++ b/chrome/renderer/resources/extensions/tts_custom_bindings.js @@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the tts API. - -var binding = require('binding').Binding.create('tts'); +// Custom bindings for the tts API. var ttsNatives = requireNative('tts'); var GetNextTTSEventId = ttsNatives.GetNextTTSEventId; @@ -13,9 +11,8 @@ var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); var sendRequest = require('sendRequest').sendRequest; var lazyBG = requireNative('lazy_background_page'); -binding.registerCustomHook(function(api) { +chromeHidden.registerCustomHook('tts', function(api) { var apiFunctions = api.apiFunctions; - var tts = api.compiledApi; chromeHidden.tts = { handlers: {} @@ -42,7 +39,7 @@ binding.registerCustomHook(function(api) { // add a listener to chrome.tts.onEvent will fail. // See http://crbug.com/122474. try { - tts.onEvent.addListener(ttsEventListener); + chrome.tts.onEvent.addListener(ttsEventListener); } catch (e) {} apiFunctions.setHandleRequest('speak', function() { @@ -59,5 +56,3 @@ binding.registerCustomHook(function(api) { return id; }); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/tts_engine_custom_bindings.js b/chrome/renderer/resources/extensions/tts_engine_custom_bindings.js index 1d19cea..f16f143 100644 --- a/chrome/renderer/resources/extensions/tts_engine_custom_bindings.js +++ b/chrome/renderer/resources/extensions/tts_engine_custom_bindings.js @@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the ttsEngine API. - -var binding = require('binding').Binding.create('ttsEngine'); +// Custom bindings for the ttsEngine API. var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); @@ -18,5 +16,3 @@ chromeHidden.Event.registerArgumentMassager('ttsEngine.onSpeak', }; dispatch([text, options, sendTtsEvent]); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/types_custom_bindings.js b/chrome/renderer/resources/extensions/types_custom_bindings.js index 1c386f4..4af67b4d 100644 --- a/chrome/renderer/resources/extensions/types_custom_bindings.js +++ b/chrome/renderer/resources/extensions/types_custom_bindings.js @@ -2,15 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the types API. +// Custom bindings for the types API. -var binding = require('binding').Binding.create('types'); - -var chrome = requireNative('chrome').GetChrome(); +var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); var sendRequest = require('sendRequest').sendRequest; var validate = require('schemaUtils').validate; -binding.registerCustomType('types.ChromeSetting', function() { +chromeHidden.registerCustomType('types.ChromeSetting', function() { function extendSchema(schema) { var extendedSchema = schema.slice(); @@ -47,5 +45,3 @@ binding.registerCustomType('types.ChromeSetting', function() { return ChromeSetting; }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/utils.js b/chrome/renderer/resources/extensions/utils.js index ed35e15..beb9a51 100644 --- a/chrome/renderer/resources/extensions/utils.js +++ b/chrome/renderer/resources/extensions/utils.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -var chrome = requireNative('chrome').GetChrome(); - function forEach(dict, f) { for (var key in dict) { if (dict.hasOwnProperty(key)) @@ -27,16 +25,5 @@ function lookup(array_of_dictionaries, field, value) { } } -// Specify |currentApi| if this should return an API for $refs in the current -// namespace. -function loadRefDependency(ref, currentApi) { - var parts = ref.split("."); - if (parts.length > 1) - return chrome[parts.slice(0, parts.length - 1).join(".")]; - else - return currentApi; -} - exports.forEach = forEach; -exports.loadRefDependency = loadRefDependency; exports.lookup = lookup; diff --git a/chrome/renderer/resources/extensions/web_request_custom_bindings.js b/chrome/renderer/resources/extensions/web_request_custom_bindings.js index 135da99..9a458de 100644 --- a/chrome/renderer/resources/extensions/web_request_custom_bindings.js +++ b/chrome/renderer/resources/extensions/web_request_custom_bindings.js @@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the webRequest API. - -var binding = require('binding').Binding.create('webRequest'); +// Custom bindings for the webRequest API. var webRequestNatives = requireNative('web_request'); var GetUniqueSubEventName = webRequestNatives.GetUniqueSubEventName; @@ -12,7 +10,6 @@ var GetUniqueSubEventName = webRequestNatives.GetUniqueSubEventName; var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); var sendRequest = require('sendRequest').sendRequest; var validate = require('schemaUtils').validate; -var webRequestInternal = require('webRequestInternal').binding; // WebRequestEvent object. This is used for special webRequest events with // extra parameters. Each invocation of addListener creates a new named @@ -69,7 +66,7 @@ WebRequestEvent.prototype.addListener = // Note: this could fail to validate, in which case we would not add the // subEvent listener. validate(Array.prototype.slice.call(arguments, 1), this.extraArgSchemas_); - webRequestInternal.addEventListener( + chromeHidden.internalAPIs.webRequestInternal.addEventListener( cb, opt_filter, opt_extraInfo, this.eventName_, subEventName); var subEvent = new chrome.Event(subEventName, this.argSchemas_); @@ -80,10 +77,10 @@ WebRequestEvent.prototype.addListener = var requestId = arguments[0].requestId; try { var result = cb.apply(null, arguments); - webRequestInternal.eventHandled( + chromeHidden.internalAPIs.webRequestInternal.eventHandled( eventName, subEventName, requestId, result); } catch (e) { - webRequestInternal.eventHandled( + chromeHidden.internalAPIs.webRequestInternal.eventHandled( eventName, subEventName, requestId); throw e; } @@ -94,7 +91,7 @@ WebRequestEvent.prototype.addListener = var details = arguments[0]; var requestId = details.requestId; var handledCallback = function(response) { - webRequestInternal.eventHandled( + chromeHidden.internalAPIs.webRequestInternal.eventHandled( eventName, subEventName, requestId, response); }; cb.apply(null, [details, handledCallback]); @@ -152,9 +149,9 @@ WebRequestEvent.prototype.getRules = function(ruleIdentifiers, cb) { this.eventForRules_.getRules(ruleIdentifiers, cb); } -binding.registerCustomEvent(WebRequestEvent); +chromeHidden.registerCustomEvent('webRequest', WebRequestEvent); -binding.registerCustomHook(function(api) { +chromeHidden.registerCustomHook('webRequest', function(api) { var apiFunctions = api.apiFunctions; apiFunctions.setHandleRequest('handlerBehaviorChanged', function() { @@ -163,5 +160,3 @@ binding.registerCustomHook(function(api) { {forIOThread: true}); }); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/web_request_internal_custom_bindings.js b/chrome/renderer/resources/extensions/web_request_internal_custom_bindings.js index 584be5f..a33599c 100644 --- a/chrome/renderer/resources/extensions/web_request_internal_custom_bindings.js +++ b/chrome/renderer/resources/extensions/web_request_internal_custom_bindings.js @@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the webRequestInternal API. - -var binding = require('binding').Binding.create('webRequestInternal'); +// Custom bindings for the webRequestInternal API. +var chromeHidden = requireNative('chrome_hidden').GetChromeHidden(); var sendRequest = require('sendRequest').sendRequest; -binding.registerCustomHook(function(api) { +chromeHidden.registerCustomHook('webRequestInternal', function(api) { var apiFunctions = api.apiFunctions; apiFunctions.setHandleRequest('addEventListener', function() { @@ -23,5 +22,3 @@ binding.registerCustomHook(function(api) { {forIOThread: true}); }); }); - -exports.binding = binding.generate(); diff --git a/chrome/renderer/resources/extensions/web_view.js b/chrome/renderer/resources/extensions/web_view.js index 2fcf058..43c6dc4 100644 --- a/chrome/renderer/resources/extensions/web_view.js +++ b/chrome/renderer/resources/extensions/web_view.js @@ -7,9 +7,7 @@ // The actual tag is implemented via the browser plugin. The internals of this // are hidden via Shadow DOM. -var watchForTag = require('tagWatcher').watchForTag; - -var chrome = requireNative('chrome').GetChrome(); +var watchForTag = require("tagWatcher").watchForTag; var WEB_VIEW_ATTRIBUTES = ['name', 'src', 'partition', 'autosize', 'minheight', 'minwidth', 'maxheight', 'maxwidth']; diff --git a/chrome/renderer/resources/extensions/web_view_experimental.js b/chrome/renderer/resources/extensions/web_view_experimental.js index fd7226e..c5fa217 100644 --- a/chrome/renderer/resources/extensions/web_view_experimental.js +++ b/chrome/renderer/resources/extensions/web_view_experimental.js @@ -11,7 +11,7 @@ // permission API would only be available for channels CHANNEL_DEV and // CHANNEL_CANARY. -var WebView = require('webView').WebView; +var WebView = require('webview').WebView; /** @type {string} */ var REQUEST_TYPE_MEDIA = 'media'; diff --git a/chrome/renderer/resources/extensions/webstore_custom_bindings.js b/chrome/renderer/resources/extensions/webstore_custom_bindings.js index 8ef9935..19c8f0f 100644 --- a/chrome/renderer/resources/extensions/webstore_custom_bindings.js +++ b/chrome/renderer/resources/extensions/webstore_custom_bindings.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Custom binding for the webstore API. +// Custom bindings for the webstore API. var webstoreNatives = requireNative('webstore'); @@ -49,14 +49,14 @@ var chromeWebstore = { } }; -// Called by webstore_binding.cc. +// Called by webstore_bindings.cc. var chromeHiddenWebstore = { onInstallResponse: function(installId, success, error) { installer.onInstallResponse(installId, success, error); } }; -// These must match the names in InstallWebstorebinding in +// These must match the names in InstallWebstoreBindings in // chrome/renderer/extensions/dispatcher.cc. exports.chromeWebstore = chromeWebstore; exports.chromeHiddenWebstore = chromeHiddenWebstore; diff --git a/chrome/renderer/resources/renderer_resources.grd b/chrome/renderer/resources/renderer_resources.grd index 8a95160..593a799 100644 --- a/chrome/renderer/resources/renderer_resources.grd +++ b/chrome/renderer/resources/renderer_resources.grd @@ -26,12 +26,14 @@ without changes to the corresponding grd file. fb9 --> <include name="IDR_DISABLED_PLUGIN_HTML" file="disabled_plugin.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_ERROR_APP_HTML" file="error_app.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_EVENT_BINDINGS_JS" file="extensions\event.js" type="BINDATA" /> + <include name="IDR_EXTENSION_APITEST_JS" file="extensions\apitest.js" type="BINDATA" /> <include name="IDR_GREASEMONKEY_API_JS" file="extensions\greasemonkey_api.js" type="BINDATA" /> <include name="IDR_SEARCHBOX_API" file="extensions\searchbox_api.js" type="BINDATA" /> <include name="IDR_JSON_JS" file="extensions\json.js" type="BINDATA" /> <include name="IDR_JSON_SCHEMA_JS" file="extensions\json_schema.js" type="BINDATA" /> <include name="IDR_MISCELLANEOUS_BINDINGS_JS" file="extensions\miscellaneous_bindings.js" type="BINDATA" /> <include name="IDR_NET_ERROR_HTML" file="neterror.html" flattenhtml="true" type="BINDATA" /> + <include name="IDR_SCHEMA_GENERATED_BINDINGS_JS" file="extensions\schema_generated_bindings.js" type="BINDATA" /> <!-- Libraries. --> <include name="IDR_TAG_WATCHER_JS" file="extensions\tag_watcher.js" type="BINDATA" /> @@ -71,13 +73,11 @@ without changes to the corresponding grd file. fb9 --> <include name="IDR_PAGE_ACTION_CUSTOM_BINDINGS_JS" file="extensions\page_action_custom_bindings.js" type="BINDATA" /> <include name="IDR_PAGE_CAPTURE_CUSTOM_BINDINGS_JS" file="extensions\page_capture_custom_bindings.js" type="BINDATA" /> <include name="IDR_RUNTIME_CUSTOM_BINDINGS_JS" file="extensions\runtime_custom_bindings.js" type="BINDATA" /> - <include name="IDR_BINDING_JS" file="extensions\binding.js" type="BINDATA" /> <include name="IDR_STORAGE_CUSTOM_BINDINGS_JS" file="extensions\storage_custom_bindings.js" type="BINDATA" /> <include name="IDR_SYNC_FILE_SYSTEM_CUSTOM_BINDINGS_JS" file="extensions\sync_file_system_custom_bindings.js" type="BINDATA" /> <include name="IDR_SYSTEM_INDICATOR_CUSTOM_BINDINGS_JS" file="extensions\system_indicator_custom_bindings.js" type="BINDATA" /> <include name="IDR_TAB_CAPTURE_CUSTOM_BINDINGS_JS" file="extensions\tab_capture_custom_bindings.js" type="BINDATA" /> <include name="IDR_TABS_CUSTOM_BINDINGS_JS" file="extensions\tabs_custom_bindings.js" type="BINDATA" /> - <include name="IDR_TEST_CUSTOM_BINDINGS_JS" file="extensions\test_custom_bindings.js" type="BINDATA" /> <include name="IDR_TTS_CUSTOM_BINDINGS_JS" file="extensions\tts_custom_bindings.js" type="BINDATA" /> <include name="IDR_TTS_ENGINE_CUSTOM_BINDINGS_JS" file="extensions\tts_engine_custom_bindings.js" type="BINDATA" /> <include name="IDR_TYPES_CUSTOM_BINDINGS_JS" file="extensions\types_custom_bindings.js" type="BINDATA" /> diff --git a/chrome/test/base/module_system_test.cc b/chrome/test/base/module_system_test.cc index 9aa764b..9eef4da 100644 --- a/chrome/test/base/module_system_test.cc +++ b/chrome/test/base/module_system_test.cc @@ -7,7 +7,7 @@ #include "base/callback.h" #include "base/memory/scoped_ptr.h" #include "base/string_piece.h" -#include "chrome/renderer/extensions/object_backed_native_handler.h" +#include "chrome/renderer/extensions/native_handler.h" #include "ui/base/resource/resource_bundle.h" #include <map> @@ -15,13 +15,12 @@ using extensions::ModuleSystem; using extensions::NativeHandler; -using extensions::ObjectBackedNativeHandler; // Native JS functions for doing asserts. -class AssertNatives : public ObjectBackedNativeHandler { +class AssertNatives : public NativeHandler { public: - explicit AssertNatives(v8::Handle<v8::Context> context) - : ObjectBackedNativeHandler(context), + explicit AssertNatives(v8::Isolate* isolate) + : NativeHandler(isolate), assertion_made_(false), failed_(false) { RouteFunction("AssertTrue", base::Bind(&AssertNatives::AssertTrue, @@ -89,7 +88,7 @@ ModuleSystemTest::ModuleSystemTest() source_map_(new StringSourceMap()), should_assertions_be_made_(true) { context_->Enter(); - assert_natives_ = new AssertNatives(context_); + assert_natives_ = new AssertNatives(context_->GetIsolate()); module_system_.reset(new ModuleSystem(context_, source_map_.get())); module_system_->RegisterNativeHandler("assert", scoped_ptr<NativeHandler>( assert_natives_)); @@ -100,7 +99,7 @@ ModuleSystemTest::ModuleSystemTest() ModuleSystemTest::~ModuleSystemTest() { module_system_.reset(); context_->Exit(); - context_.Dispose(); + context_.Dispose(context_->GetIsolate()); } void ModuleSystemTest::RegisterModule(const std::string& name, |