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

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

Issue 15961006: Regenerate Extensions API bindings when optional permissions change (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixes Created 7 years, 6 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 095c786c57f88dcc5a7f3efce787d41d69036e2f..4afb7df9276c6fa31dcf585668577dcba16a72ac 100644
--- a/chrome/renderer/extensions/dispatcher.cc
+++ b/chrome/renderer/extensions/dispatcher.cc
@@ -718,72 +718,110 @@ v8::Handle<v8::Object> Dispatcher::GetOrCreateObject(
return handle_scope.Close(new_object);
}
-void Dispatcher::RegisterSchemaGeneratedBindings(
- ModuleSystem* module_system,
- ChromeV8Context* context) {
+void Dispatcher::AddOrRemoveBindings(ChromeV8Context* context) {
+ v8::HandleScope handle_scope;
+ v8::Context::Scope(context->v8_context());
not at google - send to devlin 2013/06/05 19:03:44 nit: new line after the scope declarations make it
cduvall 2013/06/05 23:27:59 Done.
cduvall 2013/06/06 00:01:41 Strangely, if I take out the v8::Context::Scope, a
cduvall 2013/06/06 00:33:42 Wow, looks like I'm a dummy. This line should be:
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->IsAnyFeatureAvailableToContext(api_name))
+ if (!context->IsAnyFeatureAvailableToContext(api_name)) {
+ DeregisterBinding(api_name, context);
continue;
+ }
Feature* feature =
BaseFeatureProvider::GetByName("api")->GetFeature(api_name);
if (feature && feature->IsInternal())
continue;
- std::vector<std::string> split;
- base::SplitString(api_name, '.', &split);
-
- 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;
+ RegisterBinding(api_name, context);
+ }
+}
- if (lazy_bindings_map_.find(api_name) != lazy_bindings_map_.end()) {
- InstallBindings(module_system, context->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::DeregisterBinding(const std::string& api_name,
+ ChromeV8Context* context) {
+ v8::HandleScope handle_scope;
not at google - send to devlin 2013/06/05 19:03:44 handle scope shouldn't be necessary here, callers
cduvall 2013/06/05 23:27:59 Done.
+ std::string bind_name;
+ v8::Handle<v8::Object> bind_object =
+ GetOrCreateBindObjectIfAvailable(api_name, &bind_name, context);
+ v8::Handle<v8::String> v8_bind_name = v8::String::New(bind_name.c_str());
+ if (bind_object->HasRealNamedProperty(v8_bind_name))
+ bind_object->Delete(v8_bind_name);
+}
+
+v8::Handle<v8::Object> Dispatcher::GetOrCreateBindObjectIfAvailable(
+ const std::string& api_name,
+ std::string* bind_name,
+ ChromeV8Context* context) {
+ v8::HandleScope handle_scope;
not at google - send to devlin 2013/06/05 19:03:44 handle scope shouldn't be necessary here, callers
cduvall 2013/06/05 23:27:59 Done.
+ std::vector<std::string> split;
+ base::SplitString(api_name, '.', &split);
+
+ v8::Handle<v8::Object> bind_object;
+
+ // 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;
}
+ if (bind_object.IsEmpty())
+ bind_object = GetOrCreateChrome(context->v8_context());
+ bind_object = GetOrCreateObject(bind_object, split[i]);
+ }
+ if (only_ancestor_available)
+ return handle_scope.Close(v8::Handle<v8::Object>());
+ if (bind_name)
+ *bind_name = split.back();
+
+ return handle_scope.Close(bind_object.IsEmpty() ?
+ GetOrCreateChrome(context->v8_context()) : bind_object);
+}
+
+void Dispatcher::RegisterBinding(const std::string& api_name,
+ ChromeV8Context* context) {
+ std::string bind_name;
+ v8::Handle<v8::Object> bind_object =
+ GetOrCreateBindObjectIfAvailable(api_name, &bind_name, context);
+ if (bind_object.IsEmpty())
+ return;
+
+ ModuleSystem* module_system = context->module_system();
+ CHECK(module_system);
not at google - send to devlin 2013/06/05 19:03:44 myeh, no point CHECKing here. maybe a DCHECK if yo
cduvall 2013/06/05 23:27:59 Done.
+ if (lazy_bindings_map_.find(api_name) != lazy_bindings_map_.end()) {
+ InstallBindings(module_system, context->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,
+ bind_name,
+ api_name,
+ "binding");
+ } else {
+ module_system->SetLazyField(bind_object,
+ bind_name,
+ api_name,
+ "binding");
}
}
@@ -1019,35 +1057,38 @@ void Dispatcher::DidCreateScriptContext(
scoped_ptr<ModuleSystem> module_system(new ModuleSystem(context,
&source_map_));
+ context->set_module_system(module_system.Pass());
not at google - send to devlin 2013/06/05 19:03:44 to prevent callers from using the module system ac
cduvall 2013/06/05 23:27:59 Done.
+
// Enable natives in startup.
- ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system.get());
+ ModuleSystem::NativesEnabledScope natives_enabled_scope(
+ context->module_system());
- RegisterNativeHandlers(module_system.get(), context);
+ RegisterNativeHandlers(context->module_system(), context);
- module_system->RegisterNativeHandler("chrome",
+ context->module_system()->RegisterNativeHandler("chrome",
scoped_ptr<NativeHandler>(new ChromeNativeHandler(context)));
- module_system->RegisterNativeHandler("chrome_hidden",
+ context->module_system()->RegisterNativeHandler("chrome_hidden",
scoped_ptr<NativeHandler>(new ChromeHiddenNativeHandler(context)));
- module_system->RegisterNativeHandler("print",
+ context->module_system()->RegisterNativeHandler("print",
scoped_ptr<NativeHandler>(new PrintNativeHandler(context)));
- module_system->RegisterNativeHandler("lazy_background_page",
+ context->module_system()->RegisterNativeHandler("lazy_background_page",
scoped_ptr<NativeHandler>(
new LazyBackgroundPageNativeHandler(this, context)));
- module_system->RegisterNativeHandler("logging",
+ context->module_system()->RegisterNativeHandler("logging",
scoped_ptr<NativeHandler>(new LoggingNativeHandler(context)));
- module_system->RegisterNativeHandler("schema_registry",
+ context->module_system()->RegisterNativeHandler("schema_registry",
scoped_ptr<NativeHandler>(
new SchemaRegistryNativeHandler(v8_schema_registry(), context)));
- module_system->RegisterNativeHandler("v8_context",
+ context->module_system()->RegisterNativeHandler("v8_context",
scoped_ptr<NativeHandler>(new V8ContextNativeHandler(context, this)));
- module_system->RegisterNativeHandler("test_features",
+ context->module_system()->RegisterNativeHandler("test_features",
scoped_ptr<NativeHandler>(new TestFeaturesNativeHandler(context)));
int manifest_version = extension ? extension->manifest_version() : 1;
bool send_request_disabled =
(extension && Manifest::IsUnpackedLocation(extension->location()) &&
BackgroundInfo::HasLazyBackgroundPage(extension));
- module_system->RegisterNativeHandler("process",
+ context->module_system()->RegisterNativeHandler("process",
scoped_ptr<NativeHandler>(new ProcessInfoNativeHandler(
this, context, context->GetExtensionID(),
context->GetContextTypeDescription(),
@@ -1062,26 +1103,29 @@ void Dispatcher::DidCreateScriptContext(
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");
+ InstallBindings(context->module_system(), v8_context, "app");
+ InstallBindings(context->module_system(), v8_context, "webstore");
break;
case Feature::BLESSED_EXTENSION_CONTEXT:
case Feature::UNBLESSED_EXTENSION_CONTEXT:
case Feature::CONTENT_SCRIPT_CONTEXT:
- module_system->Require("json"); // see paranoid comment in json.js
+ if (extension && !extension->is_platform_app())
+ context->module_system()->Require("miscellaneous_bindings");
+ // See paranoid comment in json.js.
+ context->module_system()->Require("json");
// 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);
+ AddOrRemoveBindings(context);
break;
}
bool is_within_platform_app = IsWithinPlatformApp(frame);
// Inject custom JS into the platform app context.
if (is_within_platform_app)
- module_system->Require("platformApp");
+ context->module_system()->Require("platformApp");
// Only platform apps support the <webview> tag, because the "webView" and
// "denyWebView" modules will affect the performance of DOM modifications
@@ -1091,11 +1135,11 @@ void Dispatcher::DidCreateScriptContext(
// 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");
+ context->module_system()->Require("webView");
if (Feature::GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV)
- module_system->Require("webViewExperimental");
+ context->module_system()->Require("webViewExperimental");
} else {
- module_system->Require("denyWebView");
+ context->module_system()->Require("denyWebView");
}
}
@@ -1106,17 +1150,15 @@ void Dispatcher::DidCreateScriptContext(
if (extension->HasAPIPermission(APIPermission::kAdView)) {
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableAdviewSrcAttribute)) {
- module_system->Require("adViewCustom");
+ context->module_system()->Require("adViewCustom");
}
- module_system->Require("adView");
+ context->module_system()->Require("adView");
} else {
- module_system->Require("denyAdView");
+ context->module_system()->Require("denyAdView");
}
}
}
- context->set_module_system(module_system.Pass());
-
VLOG(1) << "Num tracked contexts: " << v8_context_set_.size();
}
@@ -1279,6 +1321,10 @@ void Dispatcher::OnUpdatePermissions(int reason_id,
PermissionsData::SetActivePermissions(extension, new_active);
AddOrRemoveOriginPermissions(reason, extension, explicit_hosts);
+ v8_context_set().ForEach(
+ extension_id,
+ NULL,
+ base::Bind(&Dispatcher::AddOrRemoveBindings, base::Unretained(this)));
}
void Dispatcher::OnUpdateTabSpecificPermissions(

Powered by Google App Engine
This is Rietveld 408576698