summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-17 18:39:26 +0000
committermpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-17 18:39:26 +0000
commit35d5280876154e0dab2f472314e49dce2ced217b (patch)
tree397419e377486ebc7c6c776622970b2106846c68
parent71739aad68e647b360158e72cf4aeddf5f2490d0 (diff)
downloadchromium_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
-rw-r--r--chrome/browser/extensions/extension_webrequest_api.cc28
-rw-r--r--chrome/browser/extensions/extension_webrequest_api.h3
-rw-r--r--chrome/browser/extensions/extension_webrequest_apitest.cc1
-rw-r--r--chrome/common/extensions/docs/experimental.webRequest.html7
-rw-r--r--chrome/common/extensions/docs/static/experimental.webRequest.html7
-rw-r--r--chrome/test/data/extensions/api_test/webrequest/framework.js5
-rw-r--r--chrome/test/data/extensions/api_test/webrequest/manifest.json2
-rw-r--r--chrome/test/data/extensions/api_test/webrequest/test_simple.html46
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>