diff options
author | kalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-29 16:51:28 +0000 |
---|---|---|
committer | kalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-29 16:51:28 +0000 |
commit | 7415e329ce844348328e54a99d36f31dc72d890c (patch) | |
tree | 40ea05abf21ef027f66c97f38c71925a3fbeacfb /chrome | |
parent | db64549243ff94833254385cbdd236ecf2d431c5 (diff) | |
download | chromium_src-7415e329ce844348328e54a99d36f31dc72d890c.zip chromium_src-7415e329ce844348328e54a99d36f31dc72d890c.tar.gz chromium_src-7415e329ce844348328e54a99d36f31dc72d890c.tar.bz2 |
Merge 241969 "Add a BLESSED_WEB_PAGE extension JS context type t..."
> Add a BLESSED_WEB_PAGE extension JS context type to describe the context in
> which hosted apps run. Currently they're running in BLESSED_EXTENSION which is
> dangerous not to mention wrong. WEB_PAGE is also wrong because additional APIs
> are available to hosted apps.
>
> The immediate need for this change is so that websites with hosted apps can
> still use chrome.runtime.connect/sendMessage if they're connectable. As they're
> currently classed as extension contexts the security checks are done as though
> the messages originate from an extension. This CL doesn't quite fix the bug but
> is half way there.
>
> BUG=326250
> R=koz@chromium.org,jochen@chromium.org
>
> Review URL: https://codereview.chromium.org/112293003
TBR=kalman@chromium.org
Review URL: https://codereview.chromium.org/149523003
git-svn-id: svn://svn.chromium.org/chrome/branches/1750/src@247702 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/extensions/extension_function_dispatcher.cc | 3 | ||||
-rw-r--r-- | chrome/common/extensions/api/_api_features.json | 12 | ||||
-rw-r--r-- | chrome/common/extensions/features/simple_feature.cc | 3 | ||||
-rw-r--r-- | chrome/common/extensions/features/simple_feature_unittest.cc | 5 | ||||
-rw-r--r-- | chrome/renderer/chrome_content_renderer_client.cc | 21 | ||||
-rw-r--r-- | chrome/renderer/extensions/chrome_v8_context.cc | 1 | ||||
-rw-r--r-- | chrome/renderer/extensions/dispatcher.cc | 27 | ||||
-rw-r--r-- | chrome/renderer/extensions/dispatcher.h | 2 |
8 files changed, 55 insertions, 19 deletions
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc index 1365e4a..f648657 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.cc +++ b/chrome/browser/extensions/extension_function_dispatcher.cc @@ -427,6 +427,9 @@ bool AllowHostedAppAPICall(const Extension& extension, if (!extension.web_extent().MatchesURL(source_url)) return false; + // Note: Not BLESSED_WEB_PAGE_CONTEXT here because these component hosted app + // entities have traditionally been treated as blessed extensions, for better + // or worse. Feature::Availability availability = ExtensionAPI::GetSharedInstance()->IsAvailable( function_name, &extension, Feature::BLESSED_EXTENSION_CONTEXT, diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json index 62db5f7..eb87ca2 100644 --- a/chrome/common/extensions/api/_api_features.json +++ b/chrome/common/extensions/api/_api_features.json @@ -22,7 +22,11 @@ "channel": "stable", "extension_types": ["hosted_app", "extension", "legacy_packaged_app"], "contexts": [ - "blessed_extension", "unblessed_extension", "content_script", "web_page" + "blessed_extension", + "unblessed_extension", + "content_script", + "web_page", + "blessed_web_page" ], "matches": [ "http://*/*", "https://*/*", "chrome-extension://*/*", "file://*/*" @@ -237,9 +241,7 @@ "internal": true, "channel": "stable", "extension_types": ["platform_app", "extension"], - "contexts": [ - "blessed_extension", "unblessed_extension", "content_script", "web_page" - ], + "contexts": "all", "matches": ["<all_urls>"] }, "experimental.accessibility": { @@ -709,7 +711,7 @@ // Hosted apps can use the webstore API from within a blessed context. "channel": "stable", "extension_types": ["hosted_app"], - "contexts": ["blessed_extension", "web_page"], + "contexts": ["blessed_web_page", "web_page"], // Any webpage can use the webstore API. "matches": ["http://*/*", "https://*/*"] }, diff --git a/chrome/common/extensions/features/simple_feature.cc b/chrome/common/extensions/features/simple_feature.cc index b971ed6..01431ce 100644 --- a/chrome/common/extensions/features/simple_feature.cc +++ b/chrome/common/extensions/features/simple_feature.cc @@ -35,6 +35,7 @@ struct Mappings { contexts["unblessed_extension"] = Feature::UNBLESSED_EXTENSION_CONTEXT; contexts["content_script"] = Feature::CONTENT_SCRIPT_CONTEXT; contexts["web_page"] = Feature::WEB_PAGE_CONTEXT; + contexts["blessed_web_page"] = Feature::BLESSED_WEB_PAGE_CONTEXT; locations["component"] = Feature::COMPONENT_LOCATION; @@ -197,6 +198,8 @@ std::string GetDisplayName(Feature::Context context) { return "content script"; case Feature::WEB_PAGE_CONTEXT: return "web page"; + case Feature::BLESSED_WEB_PAGE_CONTEXT: + return "hosted app"; } NOTREACHED(); return ""; diff --git a/chrome/common/extensions/features/simple_feature_unittest.cc b/chrome/common/extensions/features/simple_feature_unittest.cc index b2ea868..38ba4af 100644 --- a/chrome/common/extensions/features/simple_feature_unittest.cc +++ b/chrome/common/extensions/features/simple_feature_unittest.cc @@ -430,10 +430,11 @@ TEST_F(ExtensionSimpleFeatureTest, ParseContexts) { contexts->Append(new base::StringValue("unblessed_extension")); contexts->Append(new base::StringValue("content_script")); contexts->Append(new base::StringValue("web_page")); + contexts->Append(new base::StringValue("blessed_web_page")); value->Set("contexts", contexts); scoped_ptr<SimpleFeature> feature(new SimpleFeature()); feature->Parse(value.get()); - EXPECT_EQ(4u, feature->GetContexts()->size()); + EXPECT_EQ(5u, feature->GetContexts()->size()); EXPECT_TRUE( feature->GetContexts()->count(Feature::BLESSED_EXTENSION_CONTEXT)); EXPECT_TRUE( @@ -442,6 +443,8 @@ TEST_F(ExtensionSimpleFeatureTest, ParseContexts) { feature->GetContexts()->count(Feature::CONTENT_SCRIPT_CONTEXT)); EXPECT_TRUE( feature->GetContexts()->count(Feature::WEB_PAGE_CONTEXT)); + EXPECT_TRUE( + feature->GetContexts()->count(Feature::BLESSED_WEB_PAGE_CONTEXT)); value->SetString("contexts", "all"); scoped_ptr<SimpleFeature> feature2(new SimpleFeature()); diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 2fa016e..72e04f0 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc @@ -991,11 +991,22 @@ bool ChromeContentRendererClient::RunIdleHandlerWhenWidgetsHidden() { bool ChromeContentRendererClient::AllowPopup() { extensions::ChromeV8Context* current_context = extension_dispatcher_->v8_context_set().GetCurrent(); - return current_context && current_context->extension() && - (current_context->context_type() == - extensions::Feature::BLESSED_EXTENSION_CONTEXT || - current_context->context_type() == - extensions::Feature::CONTENT_SCRIPT_CONTEXT); + if (!current_context || !current_context->extension()) + return false; + // See http://crbug.com/117446 for the subtlety of this check. + switch (current_context->context_type()) { + case extensions::Feature::UNSPECIFIED_CONTEXT: + case extensions::Feature::WEB_PAGE_CONTEXT: + case extensions::Feature::UNBLESSED_EXTENSION_CONTEXT: + return false; + case extensions::Feature::BLESSED_EXTENSION_CONTEXT: + case extensions::Feature::CONTENT_SCRIPT_CONTEXT: + return true; + case extensions::Feature::BLESSED_WEB_PAGE_CONTEXT: + return !current_context->web_frame()->parent(); + } + NOTREACHED(); + return false; } bool ChromeContentRendererClient::ShouldFork(WebFrame* frame, diff --git a/chrome/renderer/extensions/chrome_v8_context.cc b/chrome/renderer/extensions/chrome_v8_context.cc index bdeebd1..e6e8d18 100644 --- a/chrome/renderer/extensions/chrome_v8_context.cc +++ b/chrome/renderer/extensions/chrome_v8_context.cc @@ -123,6 +123,7 @@ std::string ChromeV8Context::GetContextTypeDescription() { case Feature::UNBLESSED_EXTENSION_CONTEXT: return "UNBLESSED_EXTENSION"; case Feature::CONTENT_SCRIPT_CONTEXT: return "CONTENT_SCRIPT"; case Feature::WEB_PAGE_CONTEXT: return "WEB_PAGE"; + case Feature::BLESSED_WEB_PAGE_CONTEXT: return "BLESSED_WEB_PAGE"; } NOTREACHED(); return std::string(); diff --git a/chrome/renderer/extensions/dispatcher.cc b/chrome/renderer/extensions/dispatcher.cc index 3a21e8e..bc3aad0 100644 --- a/chrome/renderer/extensions/dispatcher.cc +++ b/chrome/renderer/extensions/dispatcher.cc @@ -732,6 +732,7 @@ void Dispatcher::AddOrRemoveBindingsForContext(ChromeV8Context* context) { } case Feature::BLESSED_EXTENSION_CONTEXT: + case Feature::BLESSED_WEB_PAGE_CONTEXT: case Feature::UNBLESSED_EXTENSION_CONTEXT: case Feature::CONTENT_SCRIPT_CONTEXT: { // Extension context; iterate through all the APIs and bind the available @@ -1113,7 +1114,8 @@ void Dispatcher::DidCreateScriptContext( } Feature::Context context_type = ClassifyJavaScriptContext( - extension_id, extension_group, + extension, + extension_group, UserScriptSlave::GetDataSourceURLForFrame(frame), frame->document().securityOrigin()); @@ -1528,13 +1530,13 @@ bool Dispatcher::IsSandboxedPage(const GURL& url) const { } Feature::Context Dispatcher::ClassifyJavaScriptContext( - const std::string& extension_id, + const Extension* extension, int extension_group, const GURL& url, const blink::WebSecurityOrigin& origin) { DCHECK_GE(extension_group, 0); if (extension_group == EXTENSION_GROUP_CONTENT_SCRIPTS) { - return extensions_.Contains(extension_id) ? + return extension ? // TODO(kalman): when does this happen? Feature::CONTENT_SCRIPT_CONTEXT : Feature::UNSPECIFIED_CONTEXT; } @@ -1549,14 +1551,25 @@ Feature::Context Dispatcher::ClassifyJavaScriptContext( if (IsSandboxedPage(url)) return Feature::WEB_PAGE_CONTEXT; - if (IsExtensionActive(extension_id)) - return Feature::BLESSED_EXTENSION_CONTEXT; + if (extension && IsExtensionActive(extension->id())) { + // |extension| is active in this process, but it could be either a true + // extension process or within the extent of a hosted app. In the latter + // case this would usually be considered a (blessed) web page context, + // unless the extension in question is a component extension, in which case + // we cheat and call it blessed. + return (extension->is_hosted_app() && + extension->location() != Manifest::COMPONENT) ? + Feature::BLESSED_WEB_PAGE_CONTEXT : Feature::BLESSED_EXTENSION_CONTEXT; + } // TODO(kalman): This isUnique() check is wrong, it should be performed as // part of IsSandboxedPage(). if (!origin.isUnique() && extensions_.ExtensionBindingsAllowed(url)) { - return extensions_.Contains(extension_id) ? - Feature::UNBLESSED_EXTENSION_CONTEXT : Feature::UNSPECIFIED_CONTEXT; + if (!extension) // TODO(kalman): when does this happen? + return Feature::UNSPECIFIED_CONTEXT; + return extension->is_hosted_app() ? + Feature::BLESSED_WEB_PAGE_CONTEXT : + Feature::UNBLESSED_EXTENSION_CONTEXT; } if (url.is_valid()) diff --git a/chrome/renderer/extensions/dispatcher.h b/chrome/renderer/extensions/dispatcher.h index c0cf115..a111805 100644 --- a/chrome/renderer/extensions/dispatcher.h +++ b/chrome/renderer/extensions/dispatcher.h @@ -243,7 +243,7 @@ class Dispatcher : public content::RenderProcessObserver { // Returns the Feature::Context type of context for a JavaScript context. Feature::Context ClassifyJavaScriptContext( - const std::string& extension_id, + const Extension* extension, int extension_group, const GURL& url, const blink::WebSecurityOrigin& origin); |