Index: chrome/browser/extensions/api/web_request/web_request_api.cc |
diff --git a/chrome/browser/extensions/api/web_request/web_request_api.cc b/chrome/browser/extensions/api/web_request/web_request_api.cc |
index 10f1d581887ab328fd3bc0dbb4124f670d89b67c..7c2f278321dc8eb4887b0322a8fb6847a315f6e0 100644 |
--- a/chrome/browser/extensions/api/web_request/web_request_api.cc |
+++ b/chrome/browser/extensions/api/web_request/web_request_api.cc |
@@ -455,8 +455,12 @@ ExtensionWebRequestEventRouter::~ExtensionWebRequestEventRouter() { |
} |
void ExtensionWebRequestEventRouter::RegisterRulesRegistry( |
+ void* profile, |
scoped_refptr<extensions::WebRequestRulesRegistry> rules_registry) { |
- rules_registry_ = rules_registry; |
+ if (rules_registry.get()) |
+ rules_registries_[profile] = rules_registry; |
+ else |
+ rules_registries_.erase(profile); |
} |
int ExtensionWebRequestEventRouter::OnBeforeRequest( |
@@ -466,7 +470,7 @@ int ExtensionWebRequestEventRouter::OnBeforeRequest( |
const net::CompletionCallback& callback, |
GURL* new_url) { |
// We hide events from the system context as well as sensitive requests. |
- if (!profile || helpers::HideRequest(request)) |
+ if (!profile || WebRequestPermissions::HideRequest(request)) |
return net::OK; |
if (IsPageLoad(request)) |
@@ -525,7 +529,7 @@ int ExtensionWebRequestEventRouter::OnBeforeSendHeaders( |
const net::CompletionCallback& callback, |
net::HttpRequestHeaders* headers) { |
// We hide events from the system context as well as sensitive requests. |
- if (!profile || helpers::HideRequest(request)) |
+ if (!profile || WebRequestPermissions::HideRequest(request)) |
return net::OK; |
bool initialize_blocked_requests = false; |
@@ -577,7 +581,7 @@ void ExtensionWebRequestEventRouter::OnSendHeaders( |
net::URLRequest* request, |
const net::HttpRequestHeaders& headers) { |
// We hide events from the system context as well as sensitive requests. |
- if (!profile || helpers::HideRequest(request)) |
+ if (!profile || WebRequestPermissions::HideRequest(request)) |
return; |
if (GetAndSetSignaled(request->identifier(), kOnSendHeaders)) |
@@ -610,7 +614,7 @@ int ExtensionWebRequestEventRouter::OnHeadersReceived( |
net::HttpResponseHeaders* original_response_headers, |
scoped_refptr<net::HttpResponseHeaders>* override_response_headers) { |
// We hide events from the system context as well as sensitive requests. |
- if (!profile || helpers::HideRequest(request)) |
+ if (!profile || WebRequestPermissions::HideRequest(request)) |
return net::OK; |
bool initialize_blocked_requests = false; |
@@ -675,7 +679,7 @@ ExtensionWebRequestEventRouter::OnAuthRequired( |
net::AuthCredentials* credentials) { |
// No profile means that this is for authentication challenges in the |
// system context. Skip in that case. Also skip sensitive requests. |
- if (!profile || helpers::HideRequest(request)) |
+ if (!profile || WebRequestPermissions::HideRequest(request)) |
return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION; |
int extra_info_spec = 0; |
@@ -720,7 +724,7 @@ void ExtensionWebRequestEventRouter::OnBeforeRedirect( |
net::URLRequest* request, |
const GURL& new_location) { |
// We hide events from the system context as well as sensitive requests. |
- if (!profile || helpers::HideRequest(request)) |
+ if (!profile || WebRequestPermissions::HideRequest(request)) |
return; |
if (GetAndSetSignaled(request->identifier(), kOnBeforeRedirect)) |
@@ -765,7 +769,7 @@ void ExtensionWebRequestEventRouter::OnResponseStarted( |
ExtensionInfoMap* extension_info_map, |
net::URLRequest* request) { |
// We hide events from the system context as well as sensitive requests. |
- if (!profile || helpers::HideRequest(request)) |
+ if (!profile || WebRequestPermissions::HideRequest(request)) |
return; |
// OnResponseStarted is even triggered, when the request was cancelled. |
@@ -808,7 +812,7 @@ void ExtensionWebRequestEventRouter::OnCompleted( |
ExtensionInfoMap* extension_info_map, |
net::URLRequest* request) { |
// We hide events from the system context as well as sensitive requests. |
- if (!profile || helpers::HideRequest(request)) |
+ if (!profile || WebRequestPermissions::HideRequest(request)) |
return; |
request_time_tracker_->LogRequestEndTime(request->identifier(), |
@@ -857,7 +861,7 @@ void ExtensionWebRequestEventRouter::OnErrorOccurred( |
net::URLRequest* request, |
bool started) { |
// We hide events from the system context as well as sensitive requests. |
- if (!profile || helpers::HideRequest(request)) |
+ if (!profile || WebRequestPermissions::HideRequest(request)) |
return; |
request_time_tracker_->LogRequestEndTime(request->identifier(), |
@@ -1087,6 +1091,14 @@ void ExtensionWebRequestEventRouter::NotifyPageLoad() { |
callbacks_for_page_load_.clear(); |
} |
+void* ExtensionWebRequestEventRouter::GetCrossProfile(void* profile) const { |
+ CrossProfileMap::const_iterator cross_profile = |
+ cross_profile_map_.find(profile); |
+ if (cross_profile == cross_profile_map_.end()) |
+ return NULL; |
+ return cross_profile->second; |
+} |
+ |
void ExtensionWebRequestEventRouter::GetMatchingListenersImpl( |
void* profile, |
ExtensionInfoMap* extension_info_map, |
@@ -1120,36 +1132,26 @@ void ExtensionWebRequestEventRouter::GetMatchingListenersImpl( |
resource_type) == it->filter.types.end()) |
continue; |
- // 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; |
- |
- 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 (!helpers::CanExtensionAccessURL(extension, url) || |
- (blocking_listener && possibly_synchronous_xhr_from_extension)) { |
- continue; |
- } |
- } |
+ if (!WebRequestPermissions::CanExtensionAccessURL( |
+ extension_info_map, it->extension_id, url, crosses_incognito, true)) |
+ 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 (blocking_listener && possibly_synchronous_xhr_from_extension) |
+ continue; |
matching_listeners->push_back(&(*it)); |
*extra_info_spec |= it->extra_info_spec; |
@@ -1189,13 +1191,12 @@ ExtensionWebRequestEventRouter::GetMatchingListeners( |
profile, extension_info_map, false, event_name, url, |
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()) { |
+ void* cross_profile = GetCrossProfile(profile); |
+ if (cross_profile) { |
GetMatchingListenersImpl( |
- cross_profile->second, extension_info_map, true, event_name, url, |
- tab_id, window_id, resource_type, is_request_from_extension, |
- extra_info_spec, &matching_listeners); |
+ cross_profile, extension_info_map, true, event_name, url, tab_id, |
+ window_id, resource_type, is_request_from_extension, extra_info_spec, |
+ &matching_listeners); |
} |
return matching_listeners; |
@@ -1401,51 +1402,83 @@ bool ExtensionWebRequestEventRouter::ProcessDeclarativeRules( |
net::URLRequest* request, |
extensions::RequestStages request_stage, |
net::HttpResponseHeaders* original_response_headers) { |
- if (!rules_registry_.get()) |
- return false; |
+ // Rules of the current |profile| may apply but we need to check also whether |
+ // there are applicable rules from extensions whose background page |
+ // spans from regular to incognito mode. |
+ |
+ // First parameter identifies the registry, the second indicates whether the |
+ // registry belongs to the cross profile. |
+ typedef std::pair<extensions::WebRequestRulesRegistry*, bool> |
+ RelevantRegistry; |
+ typedef std::vector<RelevantRegistry> RelevantRegistries; |
+ RelevantRegistries relevant_registries; |
+ |
+ if (rules_registries_.find(profile) != rules_registries_.end()) { |
+ relevant_registries.push_back( |
+ std::make_pair(rules_registries_[profile].get(), false)); |
+ } |
+ |
+ void* cross_profile = GetCrossProfile(profile); |
+ if (cross_profile && |
+ rules_registries_.find(cross_profile) != rules_registries_.end()) { |
+ relevant_registries.push_back( |
+ std::make_pair(rules_registries_[cross_profile].get(), true)); |
+ } |
// TODO(mpcomplete): Eventually we'll want to turn this on, but for now, |
// we won't block startup for declarative webrequest. I want to measure |
// its effect first. |
#if defined(BLOCK_STARTUP_ON_DECLARATIVE_RULES) |
- if (!rules_registry_->IsReady()) { |
- // The rules registry is still loading. Block this request until it |
- // finishes. |
- rules_registry_->AddReadyCallback( |
- base::Bind(&ExtensionWebRequestEventRouter::OnRulesRegistryReady, |
- AsWeakPtr(), profile, event_name, request->identifier(), |
- request_stage)); |
- blocked_requests_[request->identifier()].num_handlers_blocking++; |
- blocked_requests_[request->identifier()].request = request; |
- blocked_requests_[request->identifier()].blocking_time = base::Time::Now(); |
- blocked_requests_[request->identifier()].original_response_headers = |
- original_response_headers; |
- blocked_requests_[request->identifier()].extension_info_map = |
- extension_info_map; |
- return true; |
+ for (RelevantRegistries::iterator i = relevant_registries.begin(); |
+ i != relevant_registries.end(); ++i) { |
+ extensions::WebRequestRulesRegistry* rules_registry = i->first; |
+ if (!rules_registry->IsReady()) { |
+ // The rules registry is still loading. Block this request until it |
+ // finishes. |
+ rules_registry->AddReadyCallback( |
+ base::Bind(&ExtensionWebRequestEventRouter::OnRulesRegistryReady, |
+ AsWeakPtr(), profile, event_name, request->identifier(), |
+ request_stage)); |
+ blocked_requests_[request->identifier()].num_handlers_blocking++; |
+ blocked_requests_[request->identifier()].request = request; |
+ blocked_requests_[request->identifier()].blocking_time = |
+ base::Time::Now(); |
+ blocked_requests_[request->identifier()].original_response_headers = |
+ original_response_headers; |
+ blocked_requests_[request->identifier()].extension_info_map = |
+ extension_info_map; |
+ return true; |
+ } |
} |
#endif |
base::Time start = base::Time::Now(); |
- extensions::WebRequestRule::OptionalRequestData optional_request_data; |
- optional_request_data.original_response_headers = |
- original_response_headers; |
- helpers::EventResponseDeltas result = |
- rules_registry_->CreateDeltas(extension_info_map, request, |
- request_stage, optional_request_data); |
+ bool deltas_created = false; |
+ for (RelevantRegistries::iterator i = relevant_registries.begin(); |
+ i != relevant_registries.end(); ++i) { |
+ extensions::WebRequestRulesRegistry* rules_registry = |
+ i->first; |
+ extensions::WebRequestRule::OptionalRequestData optional_request_data; |
+ optional_request_data.original_response_headers = |
+ original_response_headers; |
+ helpers::EventResponseDeltas result = |
+ rules_registry->CreateDeltas(extension_info_map, request, |
+ i->second, request_stage, optional_request_data); |
+ |
+ if (!result.empty()) { |
+ helpers::EventResponseDeltas& deltas = |
+ blocked_requests_[request->identifier()].response_deltas; |
+ deltas.insert(deltas.end(), result.begin(), result.end()); |
+ deltas_created = true; |
+ } |
+ } |
base::TimeDelta elapsed_time = start - base::Time::Now(); |
UMA_HISTOGRAM_TIMES("Extensions.DeclarativeWebRequestNetworkDelay", |
elapsed_time); |
- if (result.empty()) |
- return false; |
- |
- helpers::EventResponseDeltas& deltas = |
- blocked_requests_[request->identifier()].response_deltas; |
- deltas.insert(deltas.end(), result.begin(), result.end()); |
- return true; |
+ return deltas_created; |
} |
void ExtensionWebRequestEventRouter::OnRulesRegistryReady( |