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

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: apitest.js 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
Index: chrome/renderer/extensions/dispatcher.cc
diff --git a/chrome/renderer/extensions/dispatcher.cc b/chrome/renderer/extensions/dispatcher.cc
index 94a90d6dd15e027f56171962a0c3e7041b9f7f32..7ac92d89cce73224511cff96a3ffc59a55506314 100644
--- a/chrome/renderer/extensions/dispatcher.cc
+++ b/chrome/renderer/extensions/dispatcher.cc
@@ -8,6 +8,7 @@
#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"
@@ -23,6 +24,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 +40,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,10 +91,74 @@ static const char kEventDispatchFunction[] = "Event.dispatchEvent";
static const char kOnUnloadEvent[] = "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:
+ SchemaRegistryNativeHandler(V8SchemaRegistry* registry, v8::Isolate* isolate)
+ : ObjectBackedNativeHandler(isolate),
+ 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:
+ V8ContextNativeHandler(ChromeV8Context* context, v8::Isolate* isolate)
+ : ObjectBackedNativeHandler(isolate),
+ context_(context) {
+ RouteFunction("GetAvailability",
+ base::Bind(&V8ContextNativeHandler::GetAvailability,
+ base::Unretained(this)));
+ }
+
+ private:
+ v8::Handle<v8::Value> GetAvailability(const v8::Arguments& args) {
+ if (args.Length() < 1)
+ return v8::Undefined();
not at google - send to devlin 2013/02/13 01:45:49 CHECK?
cduvall 2013/02/15 00:40:28 Done.
+
+ std::string api_name = *v8::String::AsciiValue(args[0]->ToString());
+ v8::Handle<v8::Object> ret = v8::Object::New();
+ const std::set<std::string>& available_apis =
+ context_->GetAvailableExtensionAPIs();
+
+ if (available_apis.find(api_name) == available_apis.end()) {
+ ret->Set(v8::String::New("is_available"), v8::Boolean::New(false));
+ ret->Set(v8::String::New("message"), v8::String::New("SORRY!"));
+ } else {
+ ret->Set(v8::String::New("is_available"), v8::Boolean::New(true));
+ }
not at google - send to devlin 2013/02/13 01:45:49 Heh - ok so let's add a GetAvailability method to
cduvall 2013/02/15 00:40:28 Done.
+ return ret;
+ }
+
+ ChromeV8Context* context_;
+};
+
+class ChromeHiddenNativeHandler : public ObjectBackedNativeHandler {
public:
explicit ChromeHiddenNativeHandler(v8::Isolate* isolate)
- : NativeHandler(isolate) {
+ : ObjectBackedNativeHandler(isolate) {
RouteFunction("GetChromeHidden",
base::Bind(&ChromeHiddenNativeHandler::GetChromeHidden,
base::Unretained(this)));
@@ -103,10 +169,23 @@ class ChromeHiddenNativeHandler : public NativeHandler {
}
};
-class PrintNativeHandler : public NativeHandler {
+class ChromeNativeHandler : public ObjectBackedNativeHandler {
+ public:
+ explicit ChromeNativeHandler(v8::Isolate* isolate)
+ : ObjectBackedNativeHandler(isolate) {
+ RouteFunction("GetChrome",
+ base::Bind(&ChromeNativeHandler::GetChrome, base::Unretained(this)));
+ }
+
+ v8::Handle<v8::Value> GetChrome(const v8::Arguments& args) {
+ return GetOrCreateChrome(v8::Context::GetCurrent());
+ }
+};
+
+class PrintNativeHandler : public ObjectBackedNativeHandler {
public:
explicit PrintNativeHandler(v8::Isolate* isolate)
- : NativeHandler(isolate) {
+ : ObjectBackedNativeHandler(isolate) {
RouteFunction("Print",
base::Bind(&PrintNativeHandler::Print,
base::Unretained(this)));
@@ -238,10 +317,10 @@ class ProcessInfoNativeHandler : public ChromeV8Extension {
bool send_request_disabled_;
};
-class LoggingNativeHandler : public NativeHandler {
+class LoggingNativeHandler : public ObjectBackedNativeHandler {
public:
explicit LoggingNativeHandler(v8::Isolate* isolate)
- : NativeHandler(isolate) {
+ : ObjectBackedNativeHandler(isolate) {
RouteFunction("DCHECK",
base::Bind(&LoggingNativeHandler::Dcheck,
base::Unretained(this)));
@@ -302,20 +381,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()
@@ -560,6 +625,68 @@ bool Dispatcher::AllowScriptExtension(WebFrame* frame,
return true;
}
+v8::Handle<v8::Object> Dispatcher::GetOrCreateObject(
+ v8::Handle<v8::Object> object,
+ const std::string& field) {
+ 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::Object> existing =
+ v8::Handle<v8::Object>::Cast(object->Get(key));
+ if (!existing->IsUndefined())
not at google - send to devlin 2013/02/13 01:45:49 koz@ can't remember which of the many existence ch
koz (OOO until 15th September) 2013/02/14 06:21:13 Just existing.IsEmpty() to make sure the handle is
cduvall 2013/02/15 00:40:28 Done.
+ return existing;
+ else
+ object->Delete(key);
+ }
+
+ v8::Handle<v8::Object> new_object = v8::Object::New();
+ object->Set(key, new_object);
+ return 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,
+ v8_schema_registry(),
+ 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",
@@ -624,10 +751,8 @@ 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_schema", IDR_JSON_SCHEMA_JS);
- source_map_.RegisterSource("apitest", IDR_EXTENSION_APITEST_JS);
+ source_map_.RegisterSource("test", IDR_EXTENSION_APITEST_JS);
// Libraries.
source_map_.RegisterSource("contentWatcher", IDR_CONTENT_WATCHER_JS);
@@ -691,10 +816,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);
@@ -760,7 +886,7 @@ void Dispatcher::DidCreateScriptContext(
new ChromeV8Context(v8_context, frame, extension, context_type);
v8_context_set_.Add(context);
- scoped_ptr<ModuleSystem> module_system(new ModuleSystem(v8_context,
+ scoped_ptr<ModuleSystem> module_system(new ModuleSystem(context,
&source_map_));
// Enable natives in startup.
ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system.get());
@@ -768,6 +894,8 @@ void Dispatcher::DidCreateScriptContext(
RegisterNativeHandlers(module_system.get(), context);
v8::Isolate* isolate = v8_context->GetIsolate();
+ module_system->RegisterNativeHandler("chrome",
+ scoped_ptr<NativeHandler>(new ChromeNativeHandler(isolate)));
module_system->RegisterNativeHandler("chrome_hidden",
scoped_ptr<NativeHandler>(new ChromeHiddenNativeHandler(isolate)));
module_system->RegisterNativeHandler("print",
@@ -776,6 +904,11 @@ void Dispatcher::DidCreateScriptContext(
scoped_ptr<NativeHandler>(new LazyBackgroundPageNativeHandler(this)));
module_system->RegisterNativeHandler("logging",
scoped_ptr<NativeHandler>(new LoggingNativeHandler(isolate)));
+ module_system->RegisterNativeHandler("schema_registry",
+ scoped_ptr<NativeHandler>(
+ new SchemaRegistryNativeHandler(v8_schema_registry(), isolate)));
+ module_system->RegisterNativeHandler("v8_context",
+ scoped_ptr<NativeHandler>(new V8ContextNativeHandler(context, isolate)));
int manifest_version = extension ? extension->manifest_version() : 1;
bool send_request_disabled =
@@ -799,27 +932,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: {
- module_system->Require("miscellaneous_bindings");
- module_system->Require("schema_generated_bindings");
- module_system->Require("apitest");
+ if (extension && !extension->is_platform_app())
+ module_system->Require("miscellaneous_bindings");
// 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;
}
}
+ // TODO(cduvall): Hack for loading JSON into chromeHidden (event.js).
not at google - send to devlin 2013/02/13 01:45:49 what JSON?
cduvall 2013/02/15 00:40:28 Clarified the comment.
+ // This is for ExtensionApiTest.Messaging.
+ module_system->Require("event_bindings");
// Inject custom JS into the platform app context.
if (IsWithinPlatformApp(frame))
@@ -827,7 +958,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());

Powered by Google App Engine
This is Rietveld 408576698