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

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

Issue 11571014: Lazy load chrome.* APIs (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: windows interactive_ui_tests fix Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/renderer/extensions/dispatcher.h ('k') | chrome/renderer/extensions/event_bindings.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/renderer/extensions/dispatcher.cc
diff --git a/chrome/renderer/extensions/dispatcher.cc b/chrome/renderer/extensions/dispatcher.cc
index 930cb5d568e4bfc8812c9d484c4820e8c8efeaf5..de9691f836ee623adfd5c8cd363eca8fb2129cc9 100644
--- a/chrome/renderer/extensions/dispatcher.cc
+++ b/chrome/renderer/extensions/dispatcher.cc
@@ -8,12 +8,14 @@
#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"
#include "chrome/common/extensions/api/extension_api.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"
@@ -23,6 +25,7 @@
#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"
@@ -38,7 +41,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/native_handler.h"
+#include "chrome/renderer/extensions/object_backed_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"
@@ -89,24 +92,97 @@ static const char kEventDispatchFunction[] = "Event.dispatchEvent";
static const char kOnSuspendEvent[] = "runtime.onSuspend";
static const char kOnSuspendCanceledEvent[] = "runtime.onSuspendCanceled";
-class ChromeHiddenNativeHandler : public NativeHandler {
+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 {
public:
- explicit ChromeHiddenNativeHandler(v8::Isolate* isolate)
- : NativeHandler(isolate) {
+ 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) {
RouteFunction("GetChromeHidden",
base::Bind(&ChromeHiddenNativeHandler::GetChromeHidden,
base::Unretained(this)));
}
v8::Handle<v8::Value> GetChromeHidden(const v8::Arguments& args) {
- return ChromeV8Context::GetOrCreateChromeHidden(v8::Context::GetCurrent());
+ return ChromeV8Context::GetOrCreateChromeHidden(v8_context());
}
};
-class PrintNativeHandler : public NativeHandler {
+class ChromeNativeHandler : public ObjectBackedNativeHandler {
public:
- explicit PrintNativeHandler(v8::Isolate* isolate)
- : NativeHandler(isolate) {
+ 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());
+ }
+};
+
+class PrintNativeHandler : public ObjectBackedNativeHandler {
+ public:
+ explicit PrintNativeHandler(v8::Handle<v8::Context> context)
+ : ObjectBackedNativeHandler(context) {
RouteFunction("Print",
base::Bind(&PrintNativeHandler::Print,
base::Unretained(this)));
@@ -138,7 +214,8 @@ class LazyBackgroundPageNativeHandler : public ChromeV8Extension {
}
v8::Handle<v8::Value> IncrementKeepaliveCount(const v8::Arguments& args) {
- ChromeV8Context* context = dispatcher()->v8_context_set().GetCurrent();
+ ChromeV8Context* context =
+ dispatcher()->v8_context_set().GetByV8Context(v8_context());
if (!context)
return v8::Undefined();
RenderView* render_view = context->GetRenderView();
@@ -150,7 +227,8 @@ class LazyBackgroundPageNativeHandler : public ChromeV8Extension {
}
v8::Handle<v8::Value> DecrementKeepaliveCount(const v8::Arguments& args) {
- ChromeV8Context* context = dispatcher()->v8_context_set().GetCurrent();
+ ChromeV8Context* context =
+ dispatcher()->v8_context_set().GetByV8Context(v8_context());
if (!context)
return v8::Undefined();
RenderView* render_view = context->GetRenderView();
@@ -238,13 +316,12 @@ class ProcessInfoNativeHandler : public ChromeV8Extension {
bool send_request_disabled_;
};
-class LoggingNativeHandler : public NativeHandler {
+class LoggingNativeHandler : public ObjectBackedNativeHandler {
public:
- explicit LoggingNativeHandler(v8::Isolate* isolate)
- : NativeHandler(isolate) {
+ explicit LoggingNativeHandler(v8::Handle<v8::Context> context)
+ : ObjectBackedNativeHandler(context) {
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) {
@@ -270,7 +347,6 @@ class LoggingNativeHandler : public NativeHandler {
}
}
DCHECK(check_value) << error_message;
- LOG(WARNING) << error_message;
return v8::Undefined();
}
@@ -302,20 +378,6 @@ 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()
@@ -336,7 +398,7 @@ Dispatcher::Dispatcher()
}
user_script_slave_.reset(new UserScriptSlave(&extensions_));
- request_sender_.reset(new RequestSender(this, &v8_context_set_));
+ request_sender_.reset(new RequestSender(this));
PopulateSourceMap();
PopulateLazyBindingsMap();
}
@@ -560,58 +622,128 @@ 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->IsUndefined() && value->IsObject())
not at google - send to devlin 2013/03/01 00:36:06 I think that IsObject implies !undefined so the fi
cduvall 2013/03/01 00:43:52 Done.
+ 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::Get(this)));
+ scoped_ptr<NativeHandler>(
+ EventBindings::Create(this, context->v8_context())));
module_system->RegisterNativeHandler("miscellaneous_bindings",
- scoped_ptr<NativeHandler>(MiscellaneousBindings::Get(this)));
+ scoped_ptr<NativeHandler>(
+ MiscellaneousBindings::Get(this, context->v8_context())));
module_system->RegisterNativeHandler("apiDefinitions",
- scoped_ptr<NativeHandler>(new ApiDefinitionsNatives(this)));
+ scoped_ptr<NativeHandler>(new ApiDefinitionsNatives(this, context)));
module_system->RegisterNativeHandler("sendRequest",
scoped_ptr<NativeHandler>(
- new SendRequestNatives(this, request_sender_.get())));
+ new SendRequestNatives(this, request_sender_.get(), context)));
module_system->RegisterNativeHandler("setIcon",
scoped_ptr<NativeHandler>(
- new SetIconNatives(this, request_sender_.get())));
+ new SetIconNatives(this, request_sender_.get(), context)));
module_system->RegisterNativeHandler("contentWatcherNative",
content_watcher_->MakeNatives());
// Natives used by multiple APIs.
module_system->RegisterNativeHandler("file_system_natives",
- scoped_ptr<NativeHandler>(new FileSystemNatives()));
+ scoped_ptr<NativeHandler>(new FileSystemNatives(context->v8_context())));
// Custom bindings.
module_system->RegisterNativeHandler("app",
scoped_ptr<NativeHandler>(new AppBindings(this, context)));
module_system->RegisterNativeHandler("app_runtime",
- scoped_ptr<NativeHandler>(new AppRuntimeCustomBindings()));
+ scoped_ptr<NativeHandler>(
+ new AppRuntimeCustomBindings(this, context->v8_context())));
module_system->RegisterNativeHandler("app_window",
- scoped_ptr<NativeHandler>(new AppWindowCustomBindings(this)));
+ scoped_ptr<NativeHandler>(
+ new AppWindowCustomBindings(this, context->v8_context())));
module_system->RegisterNativeHandler("context_menus",
scoped_ptr<NativeHandler>(new ContextMenusCustomBindings()));
module_system->RegisterNativeHandler("extension",
scoped_ptr<NativeHandler>(
- new ExtensionCustomBindings(this)));
+ new ExtensionCustomBindings(this, context->v8_context())));
module_system->RegisterNativeHandler("sync_file_system",
scoped_ptr<NativeHandler>(new SyncFileSystemCustomBindings()));
module_system->RegisterNativeHandler("file_browser_handler",
- scoped_ptr<NativeHandler>(new FileBrowserHandlerCustomBindings()));
+ scoped_ptr<NativeHandler>(new FileBrowserHandlerCustomBindings(
+ context->v8_context())));
module_system->RegisterNativeHandler("file_browser_private",
- scoped_ptr<NativeHandler>(new FileBrowserPrivateCustomBindings()));
+ scoped_ptr<NativeHandler>(new FileBrowserPrivateCustomBindings(
+ context->v8_context())));
module_system->RegisterNativeHandler("i18n",
- scoped_ptr<NativeHandler>(new I18NCustomBindings()));
+ scoped_ptr<NativeHandler>(
+ new I18NCustomBindings(this, context->v8_context())));
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()));
+ scoped_ptr<NativeHandler>(
+ new PageCaptureCustomBindings(this, context->v8_context())));
module_system->RegisterNativeHandler("runtime",
- scoped_ptr<NativeHandler>(new RuntimeCustomBindings(context)));
+ scoped_ptr<NativeHandler>(new RuntimeCustomBindings(this, context)));
module_system->RegisterNativeHandler("tabs",
- scoped_ptr<NativeHandler>(new TabsCustomBindings()));
+ scoped_ptr<NativeHandler>(
+ new TabsCustomBindings(this, context->v8_context())));
module_system->RegisterNativeHandler("tts",
scoped_ptr<NativeHandler>(new TTSCustomBindings()));
module_system->RegisterNativeHandler("web_request",
@@ -624,11 +756,9 @@ 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("apitest", IDR_EXTENSION_APITEST_JS);
+ source_map_.RegisterSource("test", IDR_TEST_CUSTOM_BINDINGS_JS);
// Libraries.
source_map_.RegisterSource("contentWatcher", IDR_CONTENT_WATCHER_JS);
@@ -695,10 +825,11 @@ 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);
- source_map_.RegisterSource("webview", IDR_WEB_VIEW_JS);
+ source_map_.RegisterSource("web_view", IDR_WEB_VIEW_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);
@@ -771,15 +902,21 @@ void Dispatcher::DidCreateScriptContext(
RegisterNativeHandlers(module_system.get(), context);
- v8::Isolate* isolate = v8_context->GetIsolate();
+ module_system->RegisterNativeHandler("chrome",
+ scoped_ptr<NativeHandler>(new ChromeNativeHandler(v8_context)));
module_system->RegisterNativeHandler("chrome_hidden",
- scoped_ptr<NativeHandler>(new ChromeHiddenNativeHandler(isolate)));
+ scoped_ptr<NativeHandler>(new ChromeHiddenNativeHandler(v8_context)));
module_system->RegisterNativeHandler("print",
- scoped_ptr<NativeHandler>(new PrintNativeHandler(isolate)));
+ scoped_ptr<NativeHandler>(new PrintNativeHandler(v8_context)));
module_system->RegisterNativeHandler("lazy_background_page",
scoped_ptr<NativeHandler>(new LazyBackgroundPageNativeHandler(this)));
module_system->RegisterNativeHandler("logging",
- scoped_ptr<NativeHandler>(new LoggingNativeHandler(isolate)));
+ 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)));
int manifest_version = extension ? extension->manifest_version() : 1;
bool send_request_disabled =
@@ -803,25 +940,20 @@ 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.
- 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);
- }
-
+ RegisterSchemaGeneratedBindings(module_system.get(),
+ context,
+ v8_context);
break;
}
}
@@ -832,7 +964,7 @@ void Dispatcher::DidCreateScriptContext(
if (context_type == Feature::BLESSED_EXTENSION_CONTEXT) {
bool has_permission = extension->HasAPIPermission(APIPermission::kWebView);
- module_system->Require(has_permission ? "webview" : "denyWebview");
+ module_system->Require(has_permission ? "web_view" : "denyWebview");
}
context->set_module_system(module_system.Pass());
@@ -873,6 +1005,8 @@ 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();
@@ -1109,9 +1243,8 @@ void Dispatcher::OnExtensionResponse(int request_id,
request_sender_->HandleResponse(request_id, success, response, error);
}
-bool Dispatcher::CheckCurrentContextAccessToExtensionAPI(
- const std::string& function_name) const {
- ChromeV8Context* context = v8_context_set().GetCurrent();
+bool Dispatcher::CheckContextAccessToExtensionAPI(
+ const std::string& function_name, ChromeV8Context* context) const {
if (!context) {
DLOG(ERROR) << "Not in a v8::Context";
return false;
« no previous file with comments | « chrome/renderer/extensions/dispatcher.h ('k') | chrome/renderer/extensions/event_bindings.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698