diff options
Diffstat (limited to 'chrome')
8 files changed, 99 insertions, 22 deletions
diff --git a/chrome/browser/extensions/api/guest_view/guest_view_internal_api.cc b/chrome/browser/extensions/api/guest_view/guest_view_internal_api.cc index 0e898a4..caaadbb 100644 --- a/chrome/browser/extensions/api/guest_view/guest_view_internal_api.cc +++ b/chrome/browser/extensions/api/guest_view/guest_view_internal_api.cc @@ -40,9 +40,15 @@ bool GuestViewInternalCreateGuestFunction::RunAsync() { error_ = "Guest views can only be embedded in web content"; return false; } + // If the guest is an <extensionoptions> to be embedded in a WebUI, then + // there is no extension, and extension() will be null. Use an empty string + // instead. + std::string embedder_extension_id; + if (extension()) + embedder_extension_id = extension_id(); guest_view_manager->CreateGuest(view_type, - extension_id(), + embedder_extension_id, embedder_web_contents, *create_params, callback); diff --git a/chrome/browser/extensions/extension_webui_apitest.cc b/chrome/browser/extensions/extension_webui_apitest.cc index dcd40d3..156c6c0 100644 --- a/chrome/browser/extensions/extension_webui_apitest.cc +++ b/chrome/browser/extensions/extension_webui_apitest.cc @@ -18,6 +18,8 @@ #include "extensions/browser/event_router.h" #include "extensions/common/api/test.h" #include "extensions/common/extension.h" +#include "extensions/common/feature_switch.h" +#include "extensions/common/switches.h" #include "testing/gtest/include/gtest/gtest.h" namespace extensions { @@ -108,6 +110,18 @@ class ExtensionWebUITest : public ExtensionApiTest { base::Bind(&FindFrame, frame_url, &frame_host)); return frame_host; } + + virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { + FeatureSwitch::ScopedOverride enable_options( + FeatureSwitch::embedded_extension_options(), true); + // Need to add a command line flag as well as a FeatureSwitch because the + // FeatureSwitch is not copied over to the renderer process from the + // browser process. + command_line->AppendSwitch(switches::kEnableEmbeddedExtensionOptions); + ExtensionApiTest::SetUpCommandLine(command_line); + } + + scoped_ptr<FeatureSwitch::ScopedOverride> enable_options_; }; IN_PROC_BROWSER_TEST_F(ExtensionWebUITest, SanityCheckAvailableAPIs) { @@ -167,6 +181,23 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebUITest, RuntimeLastError) { EXPECT_EQ("true", listener->message()); } +IN_PROC_BROWSER_TEST_F(ExtensionWebUITest, CanEmbedExtensionOptions) { + scoped_ptr<ExtensionTestMessageListener> listener( + new ExtensionTestMessageListener("ready", true)); + + const Extension* extension = InstallExtension( + test_data_dir_.AppendASCII("extension_options").AppendASCII("embed_self"), + 1); + ASSERT_TRUE(extension); + + ASSERT_TRUE(RunTestOnExtensions("can_embed_extension_options.js")); + + ASSERT_TRUE(listener->WaitUntilSatisfied()); + listener->Reply(extension->id()); + listener.reset(new ExtensionTestMessageListener("guest loaded", false)); + ASSERT_TRUE(listener->WaitUntilSatisfied()); +} + } // namespace } // namespace extensions diff --git a/chrome/browser/guest_view/extension_options/extension_options_guest.cc b/chrome/browser/guest_view/extension_options/extension_options_guest.cc index 6d89f6f..f7ca290 100644 --- a/chrome/browser/guest_view/extension_options/extension_options_guest.cc +++ b/chrome/browser/guest_view/extension_options/extension_options_guest.cc @@ -64,7 +64,9 @@ void ExtensionOptionsGuest::CreateWebContents( return; } - if (extension_id != embedder_extension_id) { + if (extensions::Extension::IdIsValid(embedder_extension_id) && + extension_id != embedder_extension_id) { + // Extensions cannot embed other extensions' options pages. callback.Run(NULL); return; } diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc index 34902aa..fab449d 100644 --- a/chrome/browser/ui/webui/extensions/extensions_ui.cc +++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc @@ -84,6 +84,10 @@ ExtensionsUI::ExtensionsUI(content::WebUI* web_ui) : WebUIController(web_ui) { web_ui->AddMessageHandler(new MetricsHandler()); + // Need to allow <object> elements so that the <extensionoptions> browser + // plugin can be loaded within chrome://extensions. + source->OverrideContentSecurityPolicyObjectSrc("object-src 'self';"); + content::WebUIDataSource::Add(profile, source); } diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json index 7051eb5..d0ebe4f 100644 --- a/chrome/common/extensions/api/_api_features.json +++ b/chrome/common/extensions/api/_api_features.json @@ -375,11 +375,16 @@ "extension.sendRequest": { "contexts": ["blessed_extension", "unblessed_extension", "content_script"] }, - "extensionOptionsInternal": { + "extensionOptionsInternal": [{ "internal": true, "contexts": ["blessed_extension"], "dependencies": ["permission:embeddedExtensionOptions"] - }, + }, { + "internal": true, + "channel": "trunk", + "contexts": ["webui"], + "matches": ["chrome://extensions-frame/*", "chrome://extensions/*"] + }], // This is not a real API, only here for documentation purposes. // See http://crbug.com/275944 for background. "extensionsManifestTypes": { @@ -453,6 +458,11 @@ "internal": true, "dependencies": ["permission:webview"], "contexts": ["unblessed_extension"] + }, { + "internal": true, + "channel": "trunk", + "contexts": ["webui"], + "matches": ["chrome://extensions-frame/*", "chrome://extensions/*"] }], "hangoutsPrivate": { "channel": "stable", diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index a5094ce..9eb68b5 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc @@ -245,6 +245,14 @@ bool ShouldUseJavaScriptSettingForPlugin(const WebPluginInfo& plugin) { return false; } +void IsGuestViewApiAvailableToScriptContext( + bool* api_is_available, + extensions::ScriptContext* context) { + if (context->GetAvailability("guestViewInternal").is_available()) { + *api_is_available = true; + } +} + } // namespace ChromeContentRendererClient::ChromeContentRendererClient() { @@ -520,20 +528,13 @@ bool ChromeContentRendererClient::OverrideCreatePlugin( WebPlugin** plugin) { std::string orig_mime_type = params.mimeType.utf8(); if (orig_mime_type == content::kBrowserPluginMimeType) { - WebDocument document = frame->document(); - const Extension* extension = - GetExtensionByOrigin(document.securityOrigin()); - if (extension) { - const extensions::APIPermission::ID perms[] = { - extensions::APIPermission::kAppView, - extensions::APIPermission::kEmbeddedExtensionOptions, - extensions::APIPermission::kWebView, - }; - for (size_t i = 0; i < arraysize(perms); ++i) { - if (extension->permissions_data()->HasAPIPermission(perms[i])) - return false; - } - } + bool guest_view_api_available = false; + extension_dispatcher_->script_context_set().ForEach( + render_frame->GetRenderView(), + base::Bind(&IsGuestViewApiAvailableToScriptContext, + &guest_view_api_available)); + if (guest_view_api_available) + return false; } ChromeViewHostMsg_GetPluginInfo_Output output; diff --git a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc index 960b675..47600fb 100644 --- a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc +++ b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc @@ -289,6 +289,7 @@ void ChromeExtensionsDispatcherDelegate::RequireAdditionalModules( // The API will be automatically set up when first used. if (context_type == extensions::Feature::BLESSED_EXTENSION_CONTEXT || context_type == extensions::Feature::UNBLESSED_EXTENSION_CONTEXT) { + // TODO(fsamuel): Use context->GetAvailability("webViewInternal"). if (extension->permissions_data()->HasAPIPermission( extensions::APIPermission::kWebView)) { module_system->Require("webView"); @@ -313,6 +314,7 @@ void ChromeExtensionsDispatcherDelegate::RequireAdditionalModules( } if (context_type == extensions::Feature::BLESSED_EXTENSION_CONTEXT) { + // TODO(fsamuel): Use context->GetAvailability("appViewInternal"). if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableAppView) && extension->permissions_data()->HasAPIPermission( extensions::APIPermission::kAppView)) { @@ -322,10 +324,8 @@ void ChromeExtensionsDispatcherDelegate::RequireAdditionalModules( } } - if (context_type == extensions::Feature::BLESSED_EXTENSION_CONTEXT && - extensions::FeatureSwitch::embedded_extension_options()->IsEnabled() && - extension->permissions_data()->HasAPIPermission( - extensions::APIPermission::kEmbeddedExtensionOptions)) { + if (extensions::FeatureSwitch::embedded_extension_options()->IsEnabled() && + context->GetAvailability("extensionOptionsInternal").is_available()) { module_system->Require("extensionOptions"); } } diff --git a/chrome/test/data/extensions/webui/can_embed_extension_options.js b/chrome/test/data/extensions/webui/can_embed_extension_options.js new file mode 100644 index 0000000..57f538d --- /dev/null +++ b/chrome/test/data/extensions/webui/can_embed_extension_options.js @@ -0,0 +1,23 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// out/Debug/browser_tests +// --gtest_filter=ExtensionWebUITest.CanEmbedExtensionOptions +if (!chrome || !chrome.test || !chrome.test.sendMessage) { + console.error('chrome.test.sendMessage is unavailable on ' + + document.location.href); + domAutomationController.send(false); + return; +} + +chrome.test.sendMessage('ready', function(reply) { + var extensionoptions = document.createElement('extensionoptions'); + extensionoptions.addEventListener('load', function() { + chrome.test.sendMessage('guest loaded'); + }); + extensionoptions.setAttribute('extension', reply); + document.body.appendChild(extensionoptions); +}); + +domAutomationController.send(true); |