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 b6ea4b4d9e85de48778f67772da286003005188c..ad96b0a21212be702ed7ebe0cd87e3de6914237e 100644 |
--- a/chrome/browser/extensions/api/web_request/web_request_api.cc |
+++ b/chrome/browser/extensions/api/web_request/web_request_api.cc |
@@ -84,6 +84,9 @@ namespace activitylog = activity_log_web_request_constants; |
namespace { |
+const char kWebRequest[] = "webRequest"; |
+const char kWebView[] = "webview"; |
+ |
// List of all the webRequest events. |
const char* const kWebRequestEvents[] = { |
keys::kOnBeforeRedirectEvent, |
@@ -128,8 +131,11 @@ const char* GetRequestStageAsString( |
} |
bool IsWebRequestEvent(const std::string& event_name) { |
+ std::string web_request_event_name(event_name); |
+ if (web_request_event_name.find(kWebView) != std::string::npos) |
+ web_request_event_name.replace(0, sizeof(kWebView) - 1, kWebRequest); |
return std::find(kWebRequestEvents, ARRAYEND(kWebRequestEvents), |
- event_name) != ARRAYEND(kWebRequestEvents); |
+ web_request_event_name) != ARRAYEND(kWebRequestEvents); |
} |
// Returns whether |request| has been triggered by an extension in |
@@ -323,6 +329,30 @@ StringValue* GetStatusLine(net::HttpResponseHeaders* headers) { |
return new StringValue(headers ? headers->GetStatusLine() : std::string()); |
} |
+void RemoveEventListenerOnUI( |
+ void* profile_id, |
+ const std::string& event_name, |
+ int process_id, |
+ const std::string& extension_id) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ |
+ Profile* profile = reinterpret_cast<Profile*>(profile_id); |
+ if (!g_browser_process->profile_manager()->IsValidProfile(profile)) |
+ return; |
+ |
+ extensions::EventRouter* event_router = |
+ extensions::ExtensionSystem::Get(profile)->event_router(); |
+ if (!event_router) |
+ return; |
+ |
+ content::RenderProcessHost* process = |
+ content::RenderProcessHost::FromID(process_id); |
+ if (!process) |
+ return; |
+ |
+ event_router->RemoveEventListener(event_name, process, extension_id); |
+} |
+ |
// Sends an event to subscribers of chrome.declarativeWebRequest.onMessage. |
// |extension_id| identifies the extension that sends and receives the event. |
// |event_argument| is passed to the event listener. |
@@ -363,8 +393,8 @@ struct ExtensionWebRequestEventRouter::EventListener { |
std::string sub_event_name; |
RequestFilter filter; |
int extra_info_spec; |
- int target_process_id; |
- int target_route_id; |
+ int embedder_process_id; |
+ int web_view_instance_id; |
base::WeakPtr<IPC::Sender> ipc_sender; |
mutable std::set<uint64> blocked_requests; |
@@ -1124,9 +1154,10 @@ bool ExtensionWebRequestEventRouter::AddEventListener( |
const std::string& sub_event_name, |
const RequestFilter& filter, |
int extra_info_spec, |
- int target_process_id, |
- int target_route_id, |
+ int embedder_process_id, |
+ int web_view_instance_id, |
base::WeakPtr<IPC::Sender> ipc_sender) { |
+ |
if (!IsWebRequestEvent(event_name)) |
return false; |
@@ -1137,8 +1168,8 @@ bool ExtensionWebRequestEventRouter::AddEventListener( |
listener.filter = filter; |
listener.extra_info_spec = extra_info_spec; |
listener.ipc_sender = ipc_sender; |
- listener.target_process_id = target_process_id; |
- listener.target_route_id = target_route_id; |
+ listener.embedder_process_id = embedder_process_id; |
+ listener.web_view_instance_id = web_view_instance_id; |
if (listeners_[profile][event_name].count(listener) != 0u) { |
// This is likely an abuse of the API by a malicious extension. |
@@ -1184,6 +1215,39 @@ void ExtensionWebRequestEventRouter::RemoveEventListener( |
helpers::ClearCacheOnNavigation(); |
} |
+void ExtensionWebRequestEventRouter::RemoveWebViewEventListeners( |
+ void* profile, |
+ const std::string& extension_id, |
+ int embedder_process_id, |
+ int web_view_instance_id) { |
+ // Iterate over all listeners of all WebRequest events to delete |
+ // any listeners that belong to the provided <webview>. |
+ ListenerMapForProfile& map_for_profile = listeners_[profile]; |
+ for (ListenerMapForProfile::iterator event_iter = map_for_profile.begin(); |
+ event_iter != map_for_profile.end(); ++event_iter) { |
+ std::vector<EventListener> listeners_to_delete; |
+ std::set<EventListener>& listeners = event_iter->second; |
+ for (std::set<EventListener>::iterator listener_iter = listeners.begin(); |
+ listener_iter != listeners.end(); ++listener_iter) { |
+ const EventListener& listener = *listener_iter; |
+ if (listener.embedder_process_id == embedder_process_id && |
+ listener.web_view_instance_id == web_view_instance_id) |
+ listeners_to_delete.push_back(listener); |
+ } |
+ for (size_t i = 0; i < listeners_to_delete.size(); ++i) { |
+ EventListener& listener = listeners_to_delete[i]; |
+ content::BrowserThread::PostTask( |
+ content::BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&RemoveEventListenerOnUI, |
+ profile, |
+ listener.sub_event_name, |
+ embedder_process_id, |
+ extension_id)); |
+ } |
+ } |
+} |
+ |
void ExtensionWebRequestEventRouter::OnOTRProfileCreated( |
void* original_profile, void* otr_profile) { |
cross_profile_map_[original_profile] = otr_profile; |
@@ -1261,10 +1325,15 @@ void ExtensionWebRequestEventRouter::GetMatchingListenersImpl( |
int* extra_info_spec, |
std::vector<const ExtensionWebRequestEventRouter::EventListener*>* |
matching_listeners) { |
+ std::string web_request_event_name(event_name); |
ExtensionRendererState::WebViewInfo web_view_info; |
bool is_guest = ExtensionRendererState::GetInstance()-> |
GetWebViewInfo(render_process_host_id, routing_id, &web_view_info); |
- std::set<EventListener>& listeners = listeners_[profile][event_name]; |
+ if (is_guest) |
+ web_request_event_name.replace(0, sizeof(kWebRequest) - 1, kWebView); |
+ |
+ std::set<EventListener>& listeners = |
+ listeners_[profile][web_request_event_name]; |
for (std::set<EventListener>::iterator it = listeners.begin(); |
it != listeners.end(); ++it) { |
if (!it->ipc_sender.get()) { |
@@ -1273,8 +1342,9 @@ void ExtensionWebRequestEventRouter::GetMatchingListenersImpl( |
continue; |
} |
- if (is_guest && (it->target_process_id != render_process_host_id|| |
- it->target_route_id != routing_id)) |
+ if (is_guest && |
+ (it->embedder_process_id != web_view_info.embedder_process_id || |
+ it->web_view_instance_id != web_view_info.web_view_instance_id)) |
continue; |
if (!it->filter.urls.is_empty() && !it->filter.urls.MatchesURL(url)) |
@@ -1288,7 +1358,7 @@ void ExtensionWebRequestEventRouter::GetMatchingListenersImpl( |
resource_type) == it->filter.types.end()) |
continue; |
- if (!WebRequestPermissions::CanExtensionAccessURL( |
+ if (!is_guest && !WebRequestPermissions::CanExtensionAccessURL( |
extension_info_map, it->extension_id, url, crosses_incognito, |
WebRequestPermissions::REQUIRE_HOST_PERMISSION)) |
continue; |
@@ -1976,14 +2046,23 @@ bool WebRequestAddEventListener::RunImpl() { |
std::string sub_event_name; |
EXTENSION_FUNCTION_VALIDATE(args_->GetString(4, &sub_event_name)); |
+ int web_view_instance_id = 0; |
+ EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(5, &web_view_instance_id)); |
+ |
+ base::WeakPtr<ChromeRenderMessageFilter> ipc_sender = ipc_sender_weak(); |
+ |
+ int embedder_process_id = |
+ ipc_sender.get() ? ipc_sender->render_process_id() : -1; |
+ |
const Extension* extension = |
extension_info_map()->extensions().GetByID(extension_id()); |
std::string extension_name = extension ? extension->name() : extension_id(); |
+ bool is_guest = web_view_instance_id != 0; |
// We check automatically whether the extension has the 'webRequest' |
// permission. For blocking calls we require the additional permission |
// 'webRequestBlocking'. |
- if ((extra_info_spec & |
+ if ((!is_guest && extra_info_spec & |
(ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING | |
ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING)) && |
!extension->HasAPIPermission( |
@@ -1998,7 +2077,7 @@ bool WebRequestAddEventListener::RunImpl() { |
// http://www.example.com/bar/*. |
// For this reason we do only a coarse check here to warn the extension |
// developer if he does something obviously wrong. |
- if (extensions::PermissionsData::GetEffectiveHostPermissions( |
+ if (!is_guest && extensions::PermissionsData::GetEffectiveHostPermissions( |
extension).is_empty()) { |
error_ = keys::kHostPermissionsRequired; |
return false; |
@@ -2007,8 +2086,8 @@ bool WebRequestAddEventListener::RunImpl() { |
bool success = |
ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( |
profile_id(), extension_id(), extension_name, |
- event_name, sub_event_name, filter, |
- extra_info_spec, -1, -1, ipc_sender_weak()); |
+ event_name, sub_event_name, filter, extra_info_spec, |
+ embedder_process_id, web_view_instance_id, ipc_sender_weak()); |
EXTENSION_FUNCTION_VALIDATE(success); |
helpers::ClearCacheOnNavigation(); |