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 /chrome/renderer/extensions/dispatcher.cc | |
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
Diffstat (limited to 'chrome/renderer/extensions/dispatcher.cc')
-rw-r--r-- | chrome/renderer/extensions/dispatcher.cc | 286 |
1 files changed, 74 insertions, 212 deletions
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; |