Index: chrome/renderer/extensions/dispatcher.cc |
diff --git a/chrome/renderer/extensions/dispatcher.cc b/chrome/renderer/extensions/dispatcher.cc |
index 031422824dbb78aecbc70878e09673b2ffab4f19..6c25c312706070ce221b435a5f4311107d251202 100644 |
--- a/chrome/renderer/extensions/dispatcher.cc |
+++ b/chrome/renderer/extensions/dispatcher.cc |
@@ -654,16 +654,15 @@ v8::Handle<v8::Object> Dispatcher::GetOrCreateObject( |
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)) { |
+ // If the object has a callback property, it is assumed it is an unavailable |
+ // API, so it is safe to delete. This is checked before GetOrCreateObject is |
+ // called. |
+ if (object->HasRealNamedCallbackProperty(key)) { |
+ object->Delete(key); |
+ } else if (object->HasRealNamedProperty(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); |
+ CHECK(value->IsObject()); |
+ return handle_scope.Close(v8::Handle<v8::Object>::Cast(value)); |
} |
v8::Handle<v8::Object> new_object = v8::Object::New(); |
@@ -673,13 +672,14 @@ v8::Handle<v8::Object> Dispatcher::GetOrCreateObject( |
void Dispatcher::RegisterSchemaGeneratedBindings( |
ModuleSystem* module_system, |
- ChromeV8Context* context, |
- v8::Handle<v8::Context> v8_context) { |
+ ChromeV8Context* 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 (!context->GetAvailabilityForContext(api_name).is_available()) |
+ continue; |
Feature* feature = |
BaseFeatureProvider::GetByName("api")->GetFeature(api_name); |
@@ -689,12 +689,36 @@ void Dispatcher::RegisterSchemaGeneratedBindings( |
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) |
+ v8::Handle<v8::Object> bind_object = |
+ GetOrCreateChrome(context->v8_context()); |
+ |
+ // Check if this API has an ancestor. If the API's ancestor is available and |
+ // the API is not available, don't install the bindings for this API. If |
+ // the API is available and its ancestor is not, delete the ancestor and |
+ // install the bindings for the API. This is to prevent loading the ancestor |
+ // API schema if it will not be needed. |
+ // |
+ // For example: |
+ // If app is available and app.window is not, just install app. |
+ // If app.window is available and app is not, delete app and install |
+ // app.window on a new object so app does not have to be loaded. |
+ std::string ancestor_name; |
+ bool only_ancestor_available = false; |
+ for (size_t i = 0; i < split.size() - 1; ++i) { |
+ ancestor_name += (i ? ".": "") + split[i]; |
+ if (!ancestor_name.empty() && |
+ context->GetAvailability(ancestor_name).is_available() && |
+ !context->GetAvailability(api_name).is_available()) { |
+ only_ancestor_available = true; |
+ break; |
+ } |
bind_object = GetOrCreateObject(bind_object, split[i]); |
+ } |
+ if (only_ancestor_available) |
+ continue; |
if (lazy_bindings_map_.find(api_name) != lazy_bindings_map_.end()) { |
- InstallBindings(module_system, v8_context, api_name); |
+ InstallBindings(module_system, context->v8_context(), api_name); |
} else if (!source_map_.Contains(api_name)) { |
module_system->RegisterNativeHandler( |
api_name, |
@@ -983,31 +1007,14 @@ void Dispatcher::DidCreateScriptContext( |
GetOrCreateChrome(v8_context); |
- // Loading JavaScript is expensive, so only run the full API bindings |
- // generation mechanisms in extension pages (NOT all web pages). |
- switch (context_type) { |
- case Feature::UNSPECIFIED_CONTEXT: |
- case Feature::WEB_PAGE_CONTEXT: |
- // TODO(kalman): see comment below about ExtensionAPI. |
- 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 |
- |
- // 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); |
- break; |
- } |
+ // TODO(kalman): see comment below about ExtensionAPI. |
+ InstallBindings(module_system.get(), v8_context, "app"); |
+ InstallBindings(module_system.get(), v8_context, "webstore"); |
not at google - send to devlin
2013/04/19 14:34:36
We should be able to remove these two lines since
cduvall
2013/04/24 01:34:01
Done.
|
+ if (extension && !extension->is_platform_app()) |
+ module_system->Require("miscellaneous_bindings"); |
+ module_system->Require("json"); // see paranoid comment in json.js |
not at google - send to devlin
2013/04/19 14:34:36
I'd be interested in seeing whether moving this Re
cduvall
2013/04/24 01:34:01
Deleting this Require ended up not failing any tes
not at google - send to devlin
2013/04/24 04:09:10
No tests? I would actually expect it to break one
cduvall
2013/04/25 00:12:10
Done.
|
+ |
+ RegisterSchemaGeneratedBindings(module_system.get(), context); |
bool is_within_platform_app = IsWithinPlatformApp(frame); |
// Inject custom JS into the platform app context. |