Index: chrome/renderer/extensions/dispatcher.cc |
diff --git a/chrome/renderer/extensions/dispatcher.cc b/chrome/renderer/extensions/dispatcher.cc |
index 8d5aa46be680cc3f0cc83e31da6df41c0a7e41d2..bd0d241ea7fca6f43def02c988a9bc6037157e70 100644 |
--- a/chrome/renderer/extensions/dispatcher.cc |
+++ b/chrome/renderer/extensions/dispatcher.cc |
@@ -36,11 +36,12 @@ |
#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" |
#include "chrome/renderer/extensions/runtime_custom_bindings.h" |
+#include "chrome/renderer/extensions/schema_generated_native_handler.h" |
#include "chrome/renderer/extensions/send_request_natives.h" |
#include "chrome/renderer/extensions/set_icon_natives.h" |
#include "chrome/renderer/extensions/sync_file_system_custom_bindings.h" |
@@ -87,7 +88,38 @@ 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) |
+ : 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 ChromeHiddenNativeHandler : public ObjectBackedNativeHandler { |
public: |
ChromeHiddenNativeHandler() { |
RouteFunction("GetChromeHidden", |
@@ -100,7 +132,19 @@ class ChromeHiddenNativeHandler : public NativeHandler { |
} |
}; |
-class PrintNativeHandler : public NativeHandler { |
+class ChromeNativeHandler : public ObjectBackedNativeHandler { |
+ public: |
+ ChromeNativeHandler() { |
+ 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: |
PrintNativeHandler() { |
RouteFunction("Print", |
@@ -234,7 +278,7 @@ class ProcessInfoNativeHandler : public ChromeV8Extension { |
bool send_request_disabled_; |
}; |
-class LoggingNativeHandler : public NativeHandler { |
+class LoggingNativeHandler : public ObjectBackedNativeHandler { |
public: |
LoggingNativeHandler() { |
RouteFunction("DCHECK", |
@@ -297,20 +341,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() |
@@ -552,6 +582,86 @@ bool Dispatcher::AllowScriptExtension(WebFrame* frame, |
return true; |
} |
+void Dispatcher::SetUpChainedField(v8::Handle<v8::Object> object, |
+ const std::string& field, |
+ const std::string& module_name, |
+ const std::string& module_field, |
+ ModuleSystem* module_system, |
+ LazyFieldSetter setter) { |
+ size_t prev = -1, next = field.find_first_of("."); |
+ std::vector<std::string> parts; |
+ // TODO(cduvall): Clean up. |
+ while (next != std::string::npos) { |
+ parts.push_back(field.substr(prev + 1, next - prev - 1)); |
+ prev = next; |
+ next = field.find_first_of(".", prev + 1); |
+ } |
+ parts.push_back(field.substr(prev + 1)); |
+ |
+ v8::Handle<v8::Object> current = object; |
+ for (size_t i = 0; i < parts.size() - 1; i++) { |
+ v8::Handle<v8::String> key = v8::String::New(parts[i].c_str()); |
+ if (current->Has(key)) { |
+ current = v8::Handle<v8::Object>::Cast(current->Get(key)); |
+ } else { |
+ v8::Handle<v8::Object> new_object = v8::Object::New(); |
+ current->Set(key, new_object); |
+ current = new_object; |
+ } |
+ } |
+ |
+ (module_system->*setter)(current, parts.back(), module_name, module_field); |
+} |
+ |
+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; |
+ if (lazy_bindings_map_.find(api_name) != lazy_bindings_map_.end()) { |
+ InstallBindings(module_system, v8_context, api_name); |
+ // If there isn't already a custom binding for this API, we need to make |
+ // sure one exists to load the schema. Otherwise the custom binding will |
+ // need to do it itself. Either way, register it on the chrome object to be |
+ // loaded lazily. |
+ } else if (!source_map_.Contains(api_name)) { |
+ module_system->RegisterNativeHandler( |
+ api_name, |
+ scoped_ptr<NativeHandler>(new SchemaGeneratedNativeHandler( |
+ module_system, |
+ v8_schema_registry(), |
+ api_name, |
+ "bindings"))); |
+ SetUpChainedField(GetOrCreateChrome(v8_context), |
+ api_name, |
+ api_name, |
+ "bindings", |
+ module_system, |
+ &ModuleSystem::SetNativeLazyField); |
+ } else { |
+ // TODO(cduvall): Handle apitest. |
+ SetUpChainedField(GetOrCreateChrome(v8_context), |
+ api_name, |
+ api_name, |
+ "bindings", |
+ module_system, |
+ &ModuleSystem::SetLazyField); |
+ } |
+ } |
not at google - send to devlin
2013/01/25 00:44:31
I feel like this should look more like
const std:
cduvall
2013/02/12 02:13:47
Done.
|
+ module_system->SetLazyField(GetOrCreateChrome(v8_context), |
+ "Event", |
+ "event_bindings", |
not at google - send to devlin
2013/01/25 00:44:31
would it work to make schema_binding_generator req
cduvall
2013/02/12 02:13:47
Done.
|
+ "bindings"); |
+ module_system->SetLazyField(GetOrCreateChrome(v8_context), |
not at google - send to devlin
2013/01/25 00:44:31
Maybe we should fix that test thing before submitt
|
+ "test", |
+ "apitest", |
+ "bindings"); |
+} |
+ |
void Dispatcher::RegisterNativeHandlers(ModuleSystem* module_system, |
ChromeV8Context* context) { |
module_system->RegisterNativeHandler("event_bindings", |
@@ -678,6 +788,8 @@ 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("schema_binding_generator", |
+ IDR_SCHEMA_BINDING_GENERATOR_JS); |
// Platform app sources that are not API-specific.. |
source_map_.RegisterSource("tagWatcher", IDR_TAG_WATCHER_JS); |
@@ -754,6 +866,8 @@ void Dispatcher::DidCreateScriptContext( |
RegisterNativeHandlers(module_system.get(), context); |
+ module_system->RegisterNativeHandler("chrome", |
+ scoped_ptr<NativeHandler>(new ChromeNativeHandler())); |
module_system->RegisterNativeHandler("chrome_hidden", |
scoped_ptr<NativeHandler>(new ChromeHiddenNativeHandler())); |
module_system->RegisterNativeHandler("print", |
@@ -762,6 +876,9 @@ void Dispatcher::DidCreateScriptContext( |
scoped_ptr<NativeHandler>(new LazyBackgroundPageNativeHandler(this))); |
module_system->RegisterNativeHandler("logging", |
scoped_ptr<NativeHandler>(new LoggingNativeHandler())); |
+ module_system->RegisterNativeHandler("schema_registry", |
+ scoped_ptr<NativeHandler>( |
+ new SchemaRegistryNativeHandler(v8_schema_registry()))); |
int manifest_version = extension ? extension->manifest_version() : 1; |
bool send_request_disabled = |
@@ -785,24 +902,19 @@ 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"); |
+ RegisterSchemaGeneratedBindings(module_system.get(), |
+ context, |
+ v8_context); |
// 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); |
- } |
- |
break; |
} |
} |