| 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 910a52f742e5c67da680efe43d0a92daa3ffec85..06bfff98f7e718bfd8fa7dda93be6705a660669e 100644
|
| --- a/chrome/browser/extensions/api/web_request/web_request_api.cc
|
| +++ b/chrome/browser/extensions/api/web_request/web_request_api.cc
|
| @@ -83,6 +83,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,
|
| @@ -127,8 +130,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
|
| @@ -362,8 +368,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;
|
|
|
| @@ -1123,9 +1129,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;
|
|
|
| @@ -1136,8 +1143,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.
|
| @@ -1183,6 +1190,42 @@ 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>.
|
| + bool found_listeners = false;
|
| + 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;
|
| + const std::string& event_name = event_iter->first;
|
| + 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) {
|
| + found_listeners = true;
|
| + EventListener& listener = listeners_to_delete[i];
|
| + listeners.erase(listeners_to_delete[i]);
|
| + // Unblock any request that this event listener may have been blocking.
|
| + for (std::set<uint64>::iterator it = listener.blocked_requests.begin();
|
| + it != listener.blocked_requests.end(); ++it) {
|
| + DecrementBlockCount(profile, extension_id, event_name, *it, NULL);
|
| + }
|
| + }
|
| + }
|
| + if (found_listeners)
|
| + helpers::ClearCacheOnNavigation();
|
| +}
|
| +
|
| void ExtensionWebRequestEventRouter::OnOTRProfileCreated(
|
| void* original_profile, void* otr_profile) {
|
| cross_profile_map_[original_profile] = otr_profile;
|
| @@ -1260,10 +1303,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()) {
|
| @@ -1272,8 +1320,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))
|
| @@ -1287,7 +1336,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;
|
| @@ -1975,14 +2024,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(
|
| @@ -1997,7 +2055,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 (extension->GetEffectiveHostPermissions().is_empty()) {
|
| + if (!is_guest && extension->GetEffectiveHostPermissions().is_empty()) {
|
| error_ = keys::kHostPermissionsRequired;
|
| return false;
|
| }
|
| @@ -2005,8 +2063,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();
|
|
|