diff options
author | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-17 18:39:26 +0000 |
---|---|---|
committer | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-17 18:39:26 +0000 |
commit | 35d5280876154e0dab2f472314e49dce2ced217b (patch) | |
tree | 397419e377486ebc7c6c776622970b2106846c68 | |
parent | 71739aad68e647b360158e72cf4aeddf5f2490d0 (diff) | |
download | chromium_src-35d5280876154e0dab2f472314e49dce2ced217b.zip chromium_src-35d5280876154e0dab2f472314e49dce2ced217b.tar.gz chromium_src-35d5280876154e0dab2f472314e49dce2ced217b.tar.bz2 |
Restrict webRequest events to extensions with host permissions
for the URL of the request being made.
This has the side effect of allowing extensions to see network requests made to their extension (chrome-extension://my-extension-id/*).
BUG=92485,92395
TEST=no
Review URL: http://codereview.chromium.org/8274014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@105859 0039d316-1c4b-4281-b951-d872f2087c98
8 files changed, 78 insertions, 21 deletions
diff --git a/chrome/browser/extensions/extension_webrequest_api.cc b/chrome/browser/extensions/extension_webrequest_api.cc index 0874731..e969c7a6 100644 --- a/chrome/browser/extensions/extension_webrequest_api.cc +++ b/chrome/browser/extensions/extension_webrequest_api.cc @@ -155,15 +155,23 @@ bool IsWebRequestEvent(const std::string& event_name) { event_name) != ARRAYEND(kWebRequestEvents); } -bool allow_extension_scheme = false; +// Returns true if the scheme is one we want to allow extensions to have access +// to. Extensions still need specific permissions for a given URL, which is +// covered by CanExtensionAccessURL. bool HasWebRequestScheme(const GURL& url) { - if (allow_extension_scheme && url.SchemeIs(chrome::kExtensionScheme)) - return true; return (url.SchemeIs(chrome::kAboutScheme) || url.SchemeIs(chrome::kFileScheme) || url.SchemeIs(chrome::kFtpScheme) || url.SchemeIs(chrome::kHttpScheme) || - url.SchemeIs(chrome::kHttpsScheme)); + url.SchemeIs(chrome::kHttpsScheme) || + url.SchemeIs(chrome::kExtensionScheme)); +} + +bool CanExtensionAccessURL(const Extension* extension, const GURL& url) { + // about: URLs are not covered in host permissions, but are allowed anyway. + return (url.SchemeIs(chrome::kAboutScheme) || + extension->HasHostPermission(url) || + url.GetOrigin() == extension->url()); } const char* ResourceTypeToString(ResourceType::Type type) { @@ -465,11 +473,6 @@ ExtensionWebRequestEventRouter::RequestFilter::~RequestFilter() { // // static -void ExtensionWebRequestEventRouter::SetAllowChromeExtensionScheme() { - allow_extension_scheme = true; -} - -// static ExtensionWebRequestEventRouter* ExtensionWebRequestEventRouter::GetInstance() { return Singleton<ExtensionWebRequestEventRouter>::get(); } @@ -1063,15 +1066,20 @@ void ExtensionWebRequestEventRouter::GetMatchingListenersImpl( resource_type) == it->filter.types.end()) continue; - // Check if this event crosses incognito boundaries when it shouldn't. // extension_info_map can be NULL if this is a system-level request. if (extension_info_map) { const Extension* extension = extension_info_map->extensions().GetByID(it->extension_id); + + // Check if this event crosses incognito boundaries when it shouldn't. if (!extension || (crosses_incognito && !extension_info_map->CanCrossIncognito(extension))) continue; + + // Only send webRequest events for URLs the extension has access to. + if (!CanExtensionAccessURL(extension, url)) + continue; } matching_listeners->push_back(&(*it)); diff --git a/chrome/browser/extensions/extension_webrequest_api.h b/chrome/browser/extensions/extension_webrequest_api.h index 5196818..3de36cb 100644 --- a/chrome/browser/extensions/extension_webrequest_api.h +++ b/chrome/browser/extensions/extension_webrequest_api.h @@ -150,9 +150,6 @@ class ExtensionWebRequestEventRouter { typedef std::list<linked_ptr<EventResponseDelta> > EventResponseDeltas; - // Used in testing to allow chrome-extension URLs to be intercepted. - static void SetAllowChromeExtensionScheme(); - static ExtensionWebRequestEventRouter* GetInstance(); // Dispatches the OnBeforeRequest event to any extensions whose filters match diff --git a/chrome/browser/extensions/extension_webrequest_apitest.cc b/chrome/browser/extensions/extension_webrequest_apitest.cc index 204468b..c12f2da 100644 --- a/chrome/browser/extensions/extension_webrequest_apitest.cc +++ b/chrome/browser/extensions/extension_webrequest_apitest.cc @@ -44,7 +44,6 @@ class ExtensionWebRequestApiTest : public ExtensionApiTest { public: virtual void SetUpInProcessBrowserTestFixture() { ExtensionApiTest::SetUpInProcessBrowserTestFixture(); - ExtensionWebRequestEventRouter::SetAllowChromeExtensionScheme(); host_resolver()->AddRule("*", "127.0.0.1"); ASSERT_TRUE(StartTestServer()); } diff --git a/chrome/common/extensions/docs/experimental.webRequest.html b/chrome/common/extensions/docs/experimental.webRequest.html index 5108d69..63b8d93 100644 --- a/chrome/common/extensions/docs/experimental.webRequest.html +++ b/chrome/common/extensions/docs/experimental.webRequest.html @@ -385,12 +385,15 @@ information on how to use experimental APIs, see the <h2 id="manifest">Manifest</h2> <p>You must declare the "experimental" permission in the <a href="manifest.html">extension manifest</a> to use the webRequest settings -API. For example:</p> +API, along with <a href="manifest.html#permissions">host permissions</a> +for any hosts whose network requests you want to access. +For example:</p> <pre>{ "name": "My extension", ... <b>"permissions": [ - "experimental" + "experimental", + "*://*.google.com" ]</b>, ... }</pre> diff --git a/chrome/common/extensions/docs/static/experimental.webRequest.html b/chrome/common/extensions/docs/static/experimental.webRequest.html index 374c518..b70f111 100644 --- a/chrome/common/extensions/docs/static/experimental.webRequest.html +++ b/chrome/common/extensions/docs/static/experimental.webRequest.html @@ -11,12 +11,15 @@ information on how to use experimental APIs, see the <h2 id="manifest">Manifest</h2> <p>You must declare the "experimental" permission in the <a href="manifest.html">extension manifest</a> to use the webRequest settings -API. For example:</p> +API, along with <a href="manifest.html#permissions">host permissions</a> +for any hosts whose network requests you want to access. +For example:</p> <pre>{ "name": "My extension", ... <b>"permissions": [ - "experimental" + "experimental", + "*://*.google.com" ]</b>, ... }</pre> diff --git a/chrome/test/data/extensions/api_test/webrequest/framework.js b/chrome/test/data/extensions/api_test/webrequest/framework.js index 939e63e..57c34f8 100644 --- a/chrome/test/data/extensions/api_test/webrequest/framework.js +++ b/chrome/test/data/extensions/api_test/webrequest/framework.js @@ -24,10 +24,11 @@ function runTests(tests) { // Returns an URL from the test server, fixing up the port. Must be called // from within a test case passed to runTests. -function getServerURL(path) { +function getServerURL(path, opt_host) { if (!testServerPort) throw new Error("Called getServerURL outside of runTests."); - return "http://" + testServer + ":" + testServerPort + "/" + path; + var host = opt_host || testServer; + return "http://" + host + ":" + testServerPort + "/" + path; } // Helper to advance to the next test only when the tab has finished loading. diff --git a/chrome/test/data/extensions/api_test/webrequest/manifest.json b/chrome/test/data/extensions/api_test/webrequest/manifest.json index 118a17e8..68d573c 100644 --- a/chrome/test/data/extensions/api_test/webrequest/manifest.json +++ b/chrome/test/data/extensions/api_test/webrequest/manifest.json @@ -2,5 +2,5 @@ "name": "webRequest", "version": "1.0", "description": "Tests the webRequest API.", - "permissions": ["experimental", "tabs", "http://*/*"] + "permissions": ["experimental", "tabs", "http://*.a.com/*"] } diff --git a/chrome/test/data/extensions/api_test/webrequest/test_simple.html b/chrome/test/data/extensions/api_test/webrequest/test_simple.html index 97cc1b0..b026730 100644 --- a/chrome/test/data/extensions/api_test/webrequest/test_simple.html +++ b/chrome/test/data/extensions/api_test/webrequest/test_simple.html @@ -10,6 +10,12 @@ function getURLHttpSimpleLoadRedirect() { return getServerURL('server-redirect?'+getURLHttpSimpleLoad()); } +// A URL from b.com, which we don't have permission to access. +function getURLNotVisible() { + return getServerURL('files/extensions/api_test/webrequest/simpleLoad/b.html', + 'b.com'); +} + runTests([ // Navigates to a blank page. function simpleLoad() { @@ -181,5 +187,45 @@ runTests([ ["onBeforeRequest", "onErrorOccurred"] ]); navigateAndWait(getURL("does_not_exist.html")); }, + + // Navigates to a page that we don't have access to, then a blank page. + // We should not see the first navigation. + function simpleLoadNonVisible() { + expect( + [ // events + { label: "a-onBeforeRequest", + event: "onBeforeRequest", + details: { + url: getURL("simpleLoad/a.html"), + frameUrl: getURL("simpleLoad/a.html") + } + }, + { label: "a-onResponseStarted", + event: "onResponseStarted", + details: { + url: getURL("simpleLoad/a.html"), + statusCode: 200, + fromCache: false, + statusLine: "HTTP/1.1 200 OK", + // Request to chrome-extension:// url has no IP. + } + }, + { label: "a-onCompleted", + event: "onCompleted", + details: { + url: getURL("simpleLoad/a.html"), + statusCode: 200, + fromCache: false, + statusLine: "HTTP/1.1 200 OK", + // Request to chrome-extension:// url has no IP. + } + }, + ], + [ // event order + ["a-onBeforeRequest", "a-onResponseStarted", "a-onCompleted"] ]); + navigateAndWait(getURLNotVisible(), function() { + navigateAndWait(getURL("simpleLoad/a.html")); + }); + }, ]); </script> |