diff options
author | battre@chromium.org <battre@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-01 11:19:16 +0000 |
---|---|---|
committer | battre@chromium.org <battre@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-01 11:19:16 +0000 |
commit | 31f174dfec58dd3b5544168f3d020b5f3c6eb895 (patch) | |
tree | 789119387ea8f982606ea85a23b91c9596e7d5b4 /chrome | |
parent | 1827c69a0e70a5e7a0b257a2a36b8aa7bf1debe5 (diff) | |
download | chromium_src-31f174dfec58dd3b5544168f3d020b5f3c6eb895.zip chromium_src-31f174dfec58dd3b5544168f3d020b5f3c6eb895.tar.gz chromium_src-31f174dfec58dd3b5544168f3d020b5f3c6eb895.tar.bz2 |
Make XHRs from extensions invisible to blocking webRequest API handlers
This CL hides XmlHttpRequests from blocking webRequest API handlers that were triggered by the same extension that owns the handler. This is necessary because of a deadlock. Synchronous XHRs block the extension and prevent the handler from being executed.
BUG=105656
TEST=no
Review URL: http://codereview.chromium.org/8729028
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112450 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
3 files changed, 158 insertions, 3 deletions
diff --git a/chrome/browser/extensions/extension_webrequest_api.cc b/chrome/browser/extensions/extension_webrequest_api.cc index 3c6bcca..b9bfd0f 100644 --- a/chrome/browser/extensions/extension_webrequest_api.cc +++ b/chrome/browser/extensions/extension_webrequest_api.cc @@ -114,6 +114,25 @@ bool IsWebRequestEvent(const std::string& event_name) { event_name) != ARRAYEND(kWebRequestEvents); } +// Returns whether |request| has been triggered by an extension in +// |extension_info_map|. +bool IsRequestFromExtension(const net::URLRequest* request, + const ExtensionInfoMap* extension_info_map) { + // |extension_info_map| is NULL for system-level requests. + if (!extension_info_map) + return false; + + const ResourceDispatcherHostRequestInfo* info = + ResourceDispatcherHost::InfoForRequest(request); + + // If this request was not created by the ResourceDispatcher, |info| is NULL. + // All requests from extensions are created by the ResourceDispatcher. + if (!info) + return false; + + return extension_info_map->process_map().Contains(info->child_id()); +} + // 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. @@ -1093,6 +1112,7 @@ void ExtensionWebRequestEventRouter::GetMatchingListenersImpl( int tab_id, int window_id, ResourceType::Type resource_type, + bool is_request_from_extension, int* extra_info_spec, std::vector<const ExtensionWebRequestEventRouter::EventListener*>* matching_listeners) { @@ -1127,9 +1147,24 @@ void ExtensionWebRequestEventRouter::GetMatchingListenersImpl( !extension_info_map->CanCrossIncognito(extension))) continue; + bool blocking_listener = + (it->extra_info_spec & + (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) != 0; + + // We do not want to notify extensions about XHR requests that are + // triggered by themselves. This is a workaround to prevent deadlocks + // in case of synchronous XHR requests that block the extension renderer + // and therefore prevent the extension from processing the request + // handler. This is only a problem for blocking listeners. + // http://crbug.com/105656 + bool possibly_synchronous_xhr_from_extension = + is_request_from_extension && resource_type == ResourceType::XHR; + // Only send webRequest events for URLs the extension has access to. - if (!CanExtensionAccessURL(extension, url)) + if (!CanExtensionAccessURL(extension, url) || + (blocking_listener && possibly_synchronous_xhr_from_extension)) { continue; + } } matching_listeners->push_back(&(*it)); @@ -1163,15 +1198,20 @@ ExtensionWebRequestEventRouter::GetMatchingListeners( std::vector<const ExtensionWebRequestEventRouter::EventListener*> matching_listeners; + bool is_request_from_extension = + IsRequestFromExtension(request, extension_info_map); + GetMatchingListenersImpl( profile, extension_info_map, false, event_name, url, - tab_id, window_id, resource_type, extra_info_spec, &matching_listeners); + tab_id, window_id, resource_type, is_request_from_extension, + extra_info_spec, &matching_listeners); CrossProfileMap::const_iterator cross_profile = cross_profile_map_.find(profile); if (cross_profile != cross_profile_map_.end()) { GetMatchingListenersImpl( cross_profile->second, extension_info_map, true, event_name, url, - tab_id, window_id, resource_type, extra_info_spec, &matching_listeners); + tab_id, window_id, resource_type, is_request_from_extension, + extra_info_spec, &matching_listeners); } return matching_listeners; diff --git a/chrome/browser/extensions/extension_webrequest_api.h b/chrome/browser/extensions/extension_webrequest_api.h index ba15265..941d52d 100644 --- a/chrome/browser/extensions/extension_webrequest_api.h +++ b/chrome/browser/extensions/extension_webrequest_api.h @@ -289,6 +289,7 @@ class ExtensionWebRequestEventRouter { int tab_id, int window_id, ResourceType::Type resource_type, + bool is_request_from_extension, int* extra_info_spec, std::vector<const ExtensionWebRequestEventRouter::EventListener*>* matching_listeners); diff --git a/chrome/test/data/extensions/api_test/webrequest/test_blocking.html b/chrome/test/data/extensions/api_test/webrequest/test_blocking.html index ee849b3..608b31a 100644 --- a/chrome/test/data/extensions/api_test/webrequest/test_blocking.html +++ b/chrome/test/data/extensions/api_test/webrequest/test_blocking.html @@ -19,6 +19,9 @@ function getURLNonUTF8SetCookie() { function getURLHttpSimpleLoad() { return getServerURL('files/extensions/api_test/webrequest/simpleLoad/a.html'); } +function getURLHttpXHRData() { + return getServerURL('files/extensions/api_test/webrequest/xhr/data.json'); +} function toCharCodes(str) { var result = []; @@ -516,5 +519,116 @@ runTests([ }); }); }, + + // Checks that XHR requests from ourself are invisible to blocking handlers. + function xhrsFromOurselfAreInvisible() { + 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. + } + }, + // We do not see onBeforeRequest for the XHR request here because it is + // handled by a blocking handler. + { label: "x-onSendHeaders", + event: "onSendHeaders", + details: { + url: getURLHttpXHRData(), + tabId: 1, + type: "xmlhttprequest", + } + }, + { label: "x-onResponseStarted", + event: "onResponseStarted", + details: { + url: getURLHttpXHRData(), + statusCode: 200, + fromCache: false, + statusLine: "HTTP/1.0 200 OK", + tabId: 1, + type: "xmlhttprequest", + ip: "127.0.0.1", + // Request to chrome-extension:// url has no IP. + } + }, + { label: "x-onCompleted", + event: "onCompleted", + details: { + url: getURLHttpXHRData(), + statusCode: 200, + fromCache: false, + statusLine: "HTTP/1.0 200 OK", + tabId: 1, + type: "xmlhttprequest", + ip: "127.0.0.1", + // Request to chrome-extension:// url has no IP. + } + }, + { label: "b-onBeforeRequest", + event: "onBeforeRequest", + details: { + url: getURL("complexLoad/b.jpg"), + frameUrl: getURL("complexLoad/b.jpg") + } + }, + { label: "b-onResponseStarted", + event: "onResponseStarted", + details: { + url: getURL("complexLoad/b.jpg"), + statusCode: 200, + fromCache: false, + statusLine: "HTTP/1.1 200 OK", + // Request to chrome-extension:// url has no IP. + } + }, + { label: "b-onCompleted", + event: "onCompleted", + details: { + url: getURL("complexLoad/b.jpg"), + 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", + "x-onSendHeaders", "x-onResponseStarted", "x-onCompleted", + "b-onBeforeRequest", "b-onResponseStarted", "b-onCompleted"] + ], + {}, ["blocking"]); + // Check the page content for our modified User-Agent string. + navigateAndWait(getURL("simpleLoad/a.html"), function() { + var req = new XMLHttpRequest(); + var asynchronous = false; + req.open("GET", getURLHttpXHRData(), asynchronous); + req.send(null); + navigateAndWait(getURL("complexLoad/b.jpg")); + }); + }, ]); </script> |