15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api/web_request/web_request_api.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind_helpers.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/lazy_instance.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_message_filter.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/browser/render_frame_host.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/resource_request_info.h"
247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/user_metrics.h"
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api/activity_log/web_request_constants.h"
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api/declarative_webrequest/request_stage.h"
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api/declarative_webrequest/webrequest_constants.h"
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api/declarative_webrequest/webrequest_rules_registry.h"
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api/extensions_api_client.h"
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api/web_request/upload_data_presenter.h"
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api/web_request/web_request_api_constants.h"
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api/web_request/web_request_api_helpers.h"
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api/web_request/web_request_event_router_delegate.h"
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/api/web_request/web_request_time_tracker.h"
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h"
36e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "extensions/browser/extension_message_filter.h"
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_prefs.h"
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_registry.h"
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/extensions_browser_client.h"
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/guest_view/web_view/web_view_constants.h"
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/info_map.h"
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/runtime_data.h"
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/warning_service.h"
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/warning_set.h"
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/common/api/web_request.h"
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/error_utils.h"
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/event_filtering_info.h"
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/features/feature.h"
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/permissions/permissions_data.h"
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/url_pattern.h"
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/strings/grit/extensions_strings.h"
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/auth.h"
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/upload_data_stream.h"
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/http/http_util.h"
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request.h"
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::DictionaryValue;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::ListValue;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::StringValue;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserMessageFilter;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::ResourceRequestInfo;
70116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing content::ResourceType;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using extensions::ErrorUtils;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension;
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using extensions::InfoMap;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Feature;
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using extensions::RulesRegistryService;
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing extensions::Warning;
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing extensions::WarningService;
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing extensions::WarningSet;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace activitylog = activity_log_web_request_constants;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace helpers = extension_web_request_api_helpers;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace keys = extension_web_request_api_constants;
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace web_request = extensions::core_api::web_request;
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace declarative_keys = extensions::declarative_webrequest_constants;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
88116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst char kWebRequestEventPrefix[] = "webRequest.";
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// List of all the webRequest events.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kWebRequestEvents[] = {
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  keys::kOnBeforeRedirectEvent,
933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  web_request::OnBeforeRequest::kEventName,
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  keys::kOnBeforeSendHeadersEvent,
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  keys::kOnCompletedEvent,
963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  web_request::OnErrorOccurred::kEventName,
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  keys::kOnSendHeadersEvent,
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  keys::kOnAuthRequiredEvent,
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  keys::kOnResponseStartedEvent,
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  keys::kOnHeadersReceivedEvent,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst size_t kWebRequestEventsLength = arraysize(kWebRequestEvents);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char* GetRequestStageAsString(
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ExtensionWebRequestEventRouter::EventTypes type) {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (type) {
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kInvalidEvent:
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "Invalid";
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnBeforeRequest:
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return keys::kOnBeforeRequest;
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnBeforeSendHeaders:
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return keys::kOnBeforeSendHeaders;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnSendHeaders:
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return keys::kOnSendHeaders;
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnHeadersReceived:
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return keys::kOnHeadersReceived;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnBeforeRedirect:
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return keys::kOnBeforeRedirect;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnAuthRequired:
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return keys::kOnAuthRequired;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnResponseStarted:
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return keys::kOnResponseStarted;
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnErrorOccurred:
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return keys::kOnErrorOccurred;
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnCompleted:
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return keys::kOnCompleted;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTREACHED();
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return "Not reached";
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int GetFrameId(bool is_main_frame, int frame_id) {
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return is_main_frame ? 0 : frame_id;
135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsWebRequestEvent(const std::string& event_name) {
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string web_request_event_name(event_name);
139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (StartsWithASCII(
140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          web_request_event_name, webview::kWebViewEventPrefix, true)) {
141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    web_request_event_name.replace(
142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        0, strlen(webview::kWebViewEventPrefix), kWebRequestEventPrefix);
143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return std::find(
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      kWebRequestEvents,
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      kWebRequestEvents + kWebRequestEventsLength,
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      web_request_event_name) != (kWebRequestEvents + kWebRequestEventsLength);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns whether |request| has been triggered by an extension in
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |extension_info_map|.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsRequestFromExtension(const net::URLRequest* request,
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            const InfoMap* extension_info_map) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |extension_info_map| is NULL for system-level requests.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension_info_map)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If this request was not created by the ResourceDispatcher, |info| is NULL.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All requests from extensions are created by the ResourceDispatcher.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!info)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return extension_info_map->process_map().Contains(info->GetChildID());
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ExtractRequestRoutingInfo(net::URLRequest* request,
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               int* render_process_host_id,
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               int* routing_id) {
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!request->GetUserData(NULL))
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *render_process_host_id = info->GetChildID();
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *routing_id = info->GetRouteID();
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Given a |request|, this function determines whether it originated from
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// a <webview> guest process or not. If it is from a <webview> guest process,
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// then |web_view_info| is returned with information about the instance ID
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// that uniquely identifies the <webview> and its embedder.
1826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool GetWebViewInfo(
1836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    net::URLRequest* request,
1846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    extensions::WebViewRendererState::WebViewInfo* web_view_info) {
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int render_process_host_id = -1;
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int routing_id = -1;
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ExtractRequestRoutingInfo(request, &render_process_host_id, &routing_id);
1886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return extensions::WebViewRendererState::GetInstance()->
189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      GetInfo(render_process_host_id, routing_id, web_view_info);
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtractRequestInfoDetails(net::URLRequest* request,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               bool* is_main_frame,
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               int* frame_id,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               bool* parent_is_main_frame,
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               int* parent_frame_id,
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               int* render_process_host_id,
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               int* routing_id,
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               ResourceType* resource_type) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!request->GetUserData(NULL))
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  *frame_id = info->GetRenderFrameID();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *is_main_frame = info->IsMainFrame();
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  *parent_frame_id = info->GetParentRenderFrameID();
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *parent_is_main_frame = info->ParentIsMainFrame();
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *render_process_host_id = info->GetChildID();
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *routing_id = info->GetRouteID();
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Restrict the resource type to the values we care about.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (helpers::IsRelevantResourceType(info->GetResourceType()))
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *resource_type = info->GetResourceType();
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    *resource_type = content::RESOURCE_TYPE_LAST_TYPE;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Extracts the body from |request| and writes the data into |out|.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtractRequestInfoBody(const net::URLRequest* request,
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            base::DictionaryValue* out) {
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const net::UploadDataStream* upload_data = request->get_upload();
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!upload_data ||
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (request->method() != "POST" && request->method() != "PUT"))
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Need to exit without "out->Set(keys::kRequestBodyKey, ...);" .
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* requestBody = new base::DictionaryValue();
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->Set(keys::kRequestBodyKey, requestBody);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the data presenters, ordered by how specific they are.
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extensions::ParsedDataPresenter parsed_data_presenter(*request);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extensions::RawDataPresenter raw_data_presenter;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extensions::UploadDataPresenter* const presenters[] = {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    &parsed_data_presenter,    // 1: any parseable forms? (Specific to forms.)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    &raw_data_presenter        // 2: any data at all? (Non-specific.)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Keys for the results of the corresponding presenters.
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* const kKeys[] = {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    keys::kRequestBodyFormDataKey,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    keys::kRequestBodyRawKey
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ScopedVector<net::UploadElementReader>& readers =
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      upload_data->element_readers();
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool some_succeeded = false;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; !some_succeeded && i < arraysize(presenters); ++i) {
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ScopedVector<net::UploadElementReader>::const_iterator reader;
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (reader = readers.begin(); reader != readers.end(); ++reader)
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      presenters[i]->FeedNext(**reader);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (presenters[i]->Succeeded()) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      requestBody->Set(kKeys[i], presenters[i]->Result().release());
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      some_succeeded = true;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!some_succeeded)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    requestBody->SetString(keys::kRequestBodyErrorKey, "Unknown error.");
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts a HttpHeaders dictionary to a |name|, |value| pair. Returns
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// true if successful.
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool FromHeaderDictionary(const base::DictionaryValue* header_value,
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          std::string* name,
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          std::string* value) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!header_value->GetString(keys::kHeaderNameKey, name))
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We require either a "value" or a "binaryValue" entry.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!(header_value->HasKey(keys::kHeaderValueKey) ^
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        header_value->HasKey(keys::kHeaderBinaryValueKey)))
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (header_value->HasKey(keys::kHeaderValueKey)) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!header_value->GetString(keys::kHeaderValueKey, value)) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (header_value->HasKey(keys::kHeaderBinaryValueKey)) {
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::ListValue* list = NULL;
277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!header_value->HasKey(keys::kHeaderBinaryValueKey)) {
278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      *value = "";
279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    } else if (!header_value->GetList(keys::kHeaderBinaryValueKey, &list) ||
280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)               !helpers::CharListToString(list, value)) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a list of HttpHeaders (see the extension API JSON). If |headers| is
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NULL, the list is empty. Ownership is passed to the caller.
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::ListValue* GetResponseHeadersList(
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const net::HttpResponseHeaders* headers) {
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* headers_value = new base::ListValue();
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (headers) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* iter = NULL;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string value;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (headers->EnumerateHeaderLines(&iter, &name, &value))
2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      headers_value->Append(helpers::CreateHeaderDictionary(name, value));
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return headers_value;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::ListValue* GetRequestHeadersList(const net::HttpRequestHeaders& headers) {
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* headers_value = new base::ListValue();
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext(); )
3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    headers_value->Append(
3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        helpers::CreateHeaderDictionary(it.name(), it.value()));
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return headers_value;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Creates a base::StringValue with the status line of |headers|. If |headers|
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// is NULL, an empty string is returned.  Ownership is passed to the caller.
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::StringValue* GetStatusLine(net::HttpResponseHeaders* headers) {
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return new base::StringValue(
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      headers ? headers->GetStatusLine() : std::string());
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void RemoveEventListenerOnUI(
3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void* browser_context_id,
31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const std::string& event_name,
32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int process_id,
32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const std::string& extension_id) {
322effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  content::BrowserContext* browser_context =
3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      reinterpret_cast<content::BrowserContext*>(browser_context_id);
3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext(
3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      browser_context))
32890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
32990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  extensions::EventRouter* event_router =
3311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      extensions::EventRouter::Get(browser_context);
33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!event_router)
33390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
33490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  content::RenderProcessHost* process =
33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      content::RenderProcessHost::FromID(process_id);
33790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!process)
33890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
33990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
34090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  event_router->RemoveEventListener(event_name, process, extension_id);
34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Sends an event to subscribers of chrome.declarativeWebRequest.onMessage or
344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// to subscribers of webview.onMessage if the action is being operated upon
345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// a <webview> guest renderer.
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |extension_id| identifies the extension that sends and receives the event.
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// |is_web_view_guest| indicates whether the action is for a <webview>.
348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// |web_view_info| is a struct containing information about the <webview>
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// embedder.
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |event_argument| is passed to the event listener.
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SendOnMessageEventOnUI(
3521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context_id,
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& extension_id,
354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bool is_web_view_guest,
3556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const extensions::WebViewRendererState::WebViewInfo& web_view_info,
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> event_argument) {
357effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  content::BrowserContext* browser_context =
3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      reinterpret_cast<content::BrowserContext*>(browser_context_id);
3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext(
3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      browser_context))
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::ListValue> event_args(new base::ListValue);
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  event_args->Append(event_argument.release());
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  extensions::EventRouter* event_router =
3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      extensions::EventRouter::Get(browser_context);
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  extensions::EventFilteringInfo event_filtering_info;
372f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
373f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::string event_name;
374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // The instance ID uniquely identifies a <webview> instance within an embedder
375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // process. We use a filter here so that only event listeners for a particular
376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // <webview> will fire.
377f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (is_web_view_guest) {
378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    event_filtering_info.SetInstanceID(web_view_info.instance_id);
379f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    event_name = webview::kEventMessage;
380f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
381f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    event_name = declarative_keys::kOnMessage;
382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<extensions::Event> event(new extensions::Event(
385f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      event_name,
3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      event_args.Pass(), browser_context, GURL(),
387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      extensions::EventRouter::USER_GESTURE_UNKNOWN,
388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      event_filtering_info));
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  event_router->DispatchEventToExtension(extension_id, event.Pass());
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void RemoveEventListenerOnIOThread(
393f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    content::BrowserContext* browser_context,
394f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& extension_id,
395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& sub_event_name) {
396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      browser_context, extension_id, sub_event_name);
398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
399f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace extensions {
403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
404f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)WebRequestAPI::WebRequestAPI(content::BrowserContext* context)
405f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : browser_context_(context) {
4060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EventRouter* event_router = EventRouter::Get(browser_context_);
407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (size_t i = 0; i < arraysize(kWebRequestEvents); ++i) {
408f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Observe the webRequest event.
409f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    std::string event_name = kWebRequestEvents[i];
410f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    event_router->RegisterObserver(this, event_name);
411f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
412f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Also observe the corresponding webview event.
413116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    event_name.replace(
414116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        0, sizeof(kWebRequestEventPrefix) - 1, webview::kWebViewEventPrefix);
415f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    event_router->RegisterObserver(this, event_name);
416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
417f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
418f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
419f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)WebRequestAPI::~WebRequestAPI() {
4200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EventRouter::Get(browser_context_)->UnregisterObserver(this);
421f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
422f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
423a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static base::LazyInstance<BrowserContextKeyedAPIFactory<WebRequestAPI> >
424f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    g_factory = LAZY_INSTANCE_INITIALIZER;
425f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
426f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// static
427a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserContextKeyedAPIFactory<WebRequestAPI>*
428a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)WebRequestAPI::GetFactoryInstance() {
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return g_factory.Pointer();
430f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
431f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
432f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void WebRequestAPI::OnListenerRemoved(const EventListenerInfo& details) {
433effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
434f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Note that details.event_name includes the sub-event details (e.g. "/123").
435f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  BrowserThread::PostTask(BrowserThread::IO,
436f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          FROM_HERE,
437f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          base::Bind(&RemoveEventListenerOnIOThread,
438f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     details.browser_context,
439f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     details.extension_id,
440f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     details.event_name));
441f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
442f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
443f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace extensions
444f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Represents a single unique listener to an event, along with whatever filter
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// parameters and extra_info_spec were specified at the time the listener was
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// added.
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// NOTE(benjhayden) New APIs should not use this sub_event_name trick! It does
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// not play well with event pages. See downloads.onDeterminingFilename and
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ExtensionDownloadsEventRouter for an alternative approach.
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ExtensionWebRequestEventRouter::EventListener {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string extension_id;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string extension_name;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string sub_event_name;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RequestFilter filter;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec;
45790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int embedder_process_id;
458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int webview_instance_id;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtr<IPC::Sender> ipc_sender;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable std::set<uint64> blocked_requests;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Comparator to work with std::set.
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator<(const EventListener& that) const {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extension_id < that.extension_id)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extension_id == that.extension_id &&
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sub_event_name < that.sub_event_name)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventListener() : extra_info_spec(0) {}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Contains info about requests that are blocked waiting for a response from
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// an extension.
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ExtensionWebRequestEventRouter::BlockedRequest {
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The request that is being blocked.
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::URLRequest* request;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Whether the request originates from an incognito tab.
4827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  bool is_incognito;
4837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The event that we're currently blocked on.
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventTypes event;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The number of event handlers that we are awaiting a response from.
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_handlers_blocking;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pointer to NetLog to report significant changes to the request for
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // debugging.
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const net::BoundNetLog* net_log;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The callback to call when we get a response from all event handlers.
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::CompletionCallback callback;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If non-empty, this contains the new URL that the request will redirect to.
498effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Only valid for OnBeforeRequest and OnHeadersReceived.
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL* new_url;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The request headers that will be issued along with this request. Only valid
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for OnBeforeSendHeaders.
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::HttpRequestHeaders* request_headers;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The response headers that were received from the server. Only valid for
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnHeadersReceived.
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<const net::HttpResponseHeaders> original_response_headers;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Location where to override response headers. Only valid for
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnHeadersReceived.
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<net::HttpResponseHeaders>* override_response_headers;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If non-empty, this contains the auth credentials that may be filled in.
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only valid for OnAuthRequired.
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::AuthCredentials* auth_credentials;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The callback to invoke for auth. If |auth_callback.is_null()| is false,
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |callback| must be NULL.
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only valid for OnAuthRequired.
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::NetworkDelegate::AuthCallback auth_callback;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Time the request was paused. Used for logging purposes.
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time blocking_time;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Changes requested by extensions.
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helpers::EventResponseDeltas response_deltas;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Provider of meta data about extensions, only used and non-NULL for events
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that are delayed until the rules registry is ready.
530f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  InfoMap* extension_info_map;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlockedRequest()
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : request(NULL),
5347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        is_incognito(false),
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        event(kInvalidEvent),
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_handlers_blocking(0),
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_log(NULL),
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new_url(NULL),
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        request_headers(NULL),
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        override_response_headers(NULL),
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        auth_credentials(NULL),
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extension_info_map(NULL) {}
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionWebRequestEventRouter::RequestFilter::InitFromValue(
5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::DictionaryValue& value, std::string* error) {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!value.HasKey("urls"))
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (base::DictionaryValue::Iterator it(value); !it.IsAtEnd(); it.Advance()) {
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (it.key() == "urls") {
5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const base::ListValue* urls_value = NULL;
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!it.value().GetAsList(&urls_value))
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < urls_value->GetSize(); ++i) {
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string url;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        URLPattern pattern(
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS |
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            URLPattern::SCHEME_FTP | URLPattern::SCHEME_FILE |
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            URLPattern::SCHEME_EXTENSION);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!urls_value->GetString(i, &url) ||
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            pattern.Parse(url) != URLPattern::PARSE_SUCCESS) {
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          *error = ErrorUtils::FormatErrorMessage(
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              keys::kInvalidRequestFilterUrl, url);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        urls.AddPattern(pattern);
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (it.key() == "types") {
5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const base::ListValue* types_value = NULL;
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!it.value().GetAsList(&types_value))
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < types_value->GetSize(); ++i) {
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string type_str;
5755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ResourceType type;
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!types_value->GetString(i, &type_str) ||
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            !helpers::ParseResourceType(type_str, &type))
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        types.push_back(type);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (it.key() == "tabId") {
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!it.value().GetAsInteger(&tab_id))
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (it.key() == "windowId") {
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!it.value().GetAsInteger(&window_id))
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionWebRequestEventRouter::ExtraInfoSpec::InitFromValue(
5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::ListValue& value, int* extra_info_spec) {
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *extra_info_spec = 0;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < value.GetSize(); ++i) {
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string str;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!value.GetString(i, &str))
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (str == "requestHeaders")
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *extra_info_spec |= REQUEST_HEADERS;
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (str == "responseHeaders")
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *extra_info_spec |= RESPONSE_HEADERS;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (str == "blocking")
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *extra_info_spec |= BLOCKING;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (str == "asyncBlocking")
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *extra_info_spec |= ASYNC_BLOCKING;
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (str == "requestBody")
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *extra_info_spec |= REQUEST_BODY;
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // BLOCKING and ASYNC_BLOCKING are mutually exclusive.
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*extra_info_spec & BLOCKING) && (*extra_info_spec & ASYNC_BLOCKING))
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebRequestEventRouter::EventResponse::EventResponse(
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id, const base::Time& extension_install_time)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : extension_id(extension_id),
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_install_time(extension_install_time),
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cancel(false) {
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebRequestEventRouter::EventResponse::~EventResponse() {
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebRequestEventRouter::RequestFilter::RequestFilter()
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : tab_id(-1), window_id(-1) {
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebRequestEventRouter::RequestFilter::~RequestFilter() {
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ExtensionWebRequestEventRouter
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebRequestEventRouter* ExtensionWebRequestEventRouter::GetInstance() {
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Singleton<ExtensionWebRequestEventRouter>::get();
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebRequestEventRouter::ExtensionWebRequestEventRouter()
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : request_time_tracker_(new ExtensionWebRequestTimeTracker) {
6521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  web_request_event_router_delegate_.reset(
6531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      extensions::ExtensionsAPIClient::Get()->
6541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          CreateWebRequestEventRouterDelegate());
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebRequestEventRouter::~ExtensionWebRequestEventRouter() {
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::RegisterRulesRegistry(
6611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
6621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const extensions::RulesRegistry::WebViewKey& webview_key,
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<extensions::WebRequestRulesRegistry> rules_registry) {
6641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  RulesRegistryKey key(browser_context, webview_key);
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rules_registry.get())
666f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    rules_registries_[key] = rules_registry;
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
668f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    rules_registries_.erase(key);
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ExtensionWebRequestEventRouter::ExtractRequestInfo(
6721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    net::URLRequest* request, base::DictionaryValue* out) {
6731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool is_main_frame = false;
6741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int frame_id = -1;
6751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool parent_is_main_frame = false;
6761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int parent_frame_id = -1;
6771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int frame_id_for_extension = -1;
6781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int parent_frame_id_for_extension = -1;
6791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int render_process_host_id = -1;
6801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int routing_id = -1;
6811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ResourceType resource_type = content::RESOURCE_TYPE_LAST_TYPE;
6821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ExtractRequestInfoDetails(request, &is_main_frame, &frame_id,
6831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            &parent_is_main_frame, &parent_frame_id,
6841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            &render_process_host_id, &routing_id,
6851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            &resource_type);
6861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  frame_id_for_extension = GetFrameId(is_main_frame, frame_id);
6871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  parent_frame_id_for_extension = GetFrameId(parent_is_main_frame,
6881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             parent_frame_id);
6891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  out->SetString(keys::kRequestIdKey,
6911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Uint64ToString(request->identifier()));
6921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  out->SetString(keys::kUrlKey, request->url().spec());
6931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  out->SetString(keys::kMethodKey, request->method());
6941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  out->SetInteger(keys::kFrameIdKey, frame_id_for_extension);
6951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  out->SetInteger(keys::kParentFrameIdKey, parent_frame_id_for_extension);
6961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  out->SetString(keys::kTypeKey, helpers::ResourceTypeToString(resource_type));
6971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  out->SetDouble(keys::kTimeStampKey, base::Time::Now().ToDoubleT() * 1000);
6981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (web_request_event_router_delegate_) {
6991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    web_request_event_router_delegate_->ExtractExtraRequestDetails(
7001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        request, out);
7011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
7021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
7031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionWebRequestEventRouter::OnBeforeRequest(
7051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
706f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    InfoMap* extension_info_map,
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::CompletionCallback& callback,
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL* new_url) {
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We hide events from the system context as well as sensitive requests.
7111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!browser_context ||
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebRequestPermissions::HideRequest(extension_info_map, request))
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsPageLoad(request))
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyPageLoad();
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_time_tracker_->LogRequestStartTime(request->identifier(),
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             base::Time::Now(),
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             request->url(),
7211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             browser_context);
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether to initialized blocked_requests_.
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool initialize_blocked_requests = false;
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  initialize_blocked_requests |=
7271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ProcessDeclarativeRules(browser_context, extension_info_map,
7283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                              web_request::OnBeforeRequest::kEventName, request,
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              extensions::ON_BEFORE_REQUEST, NULL);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const EventListener*> listeners =
7331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      GetMatchingListeners(browser_context, extension_info_map,
7343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                           web_request::OnBeforeRequest::kEventName, request,
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           &extra_info_spec);
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!listeners.empty() &&
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !GetAndSetSignaled(request->identifier(), kOnBeforeRequest)) {
7385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ListValue args;
7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* dict = new base::DictionaryValue();
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtractRequestInfo(request, dict);
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extra_info_spec & ExtraInfoSpec::REQUEST_BODY)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExtractRequestInfoBody(request, dict);
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    args.Append(dict);
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    initialize_blocked_requests |=
7461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        DispatchEvent(browser_context, request, listeners, args);
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!initialize_blocked_requests)
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;  // Nobody saw a reason for modifying the request.
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].event = kOnBeforeRequest;
7537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  blocked_requests_[request->identifier()].is_incognito |=
7541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      IsIncognitoBrowserContext(browser_context);
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  blocked_requests_[request->identifier()].request = request;
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].callback = callback;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].new_url = new_url;
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].net_log = &request->net_log();
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (blocked_requests_[request->identifier()].num_handlers_blocking == 0) {
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If there are no blocking handlers, only the declarative rules tried
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to modify the request and we can respond synchronously.
7631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return ExecuteDeltas(browser_context, request->identifier(),
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         false /* call_callback*/);
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_IO_PENDING;
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionWebRequestEventRouter::OnBeforeSendHeaders(
7711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
772f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    InfoMap* extension_info_map,
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::CompletionCallback& callback,
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::HttpRequestHeaders* headers) {
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We hide events from the system context as well as sensitive requests.
7771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!browser_context ||
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebRequestPermissions::HideRequest(extension_info_map, request))
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool initialize_blocked_requests = false;
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  initialize_blocked_requests |=
7841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ProcessDeclarativeRules(browser_context, extension_info_map,
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              keys::kOnBeforeSendHeadersEvent, request,
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              extensions::ON_BEFORE_SEND_HEADERS, NULL);
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const EventListener*> listeners =
7901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      GetMatchingListeners(browser_context, extension_info_map,
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           keys::kOnBeforeSendHeadersEvent, request,
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &extra_info_spec);
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!listeners.empty() &&
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !GetAndSetSignaled(request->identifier(), kOnBeforeSendHeaders)) {
7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ListValue args;
7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* dict = new base::DictionaryValue();
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtractRequestInfo(request, dict);
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS)
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dict->Set(keys::kRequestHeadersKey, GetRequestHeadersList(*headers));
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    args.Append(dict);
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    initialize_blocked_requests |=
8031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        DispatchEvent(browser_context, request, listeners, args);
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!initialize_blocked_requests)
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;  // Nobody saw a reason for modifying the request.
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].event = kOnBeforeSendHeaders;
8107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  blocked_requests_[request->identifier()].is_incognito |=
8111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      IsIncognitoBrowserContext(browser_context);
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  blocked_requests_[request->identifier()].request = request;
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].callback = callback;
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].request_headers = headers;
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].net_log = &request->net_log();
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (blocked_requests_[request->identifier()].num_handlers_blocking == 0) {
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If there are no blocking handlers, only the declarative rules tried
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to modify the request and we can respond synchronously.
8201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return ExecuteDeltas(browser_context, request->identifier(),
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         false /* call_callback*/);
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_IO_PENDING;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::OnSendHeaders(
8281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
829f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    InfoMap* extension_info_map,
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::HttpRequestHeaders& headers) {
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We hide events from the system context as well as sensitive requests.
8331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!browser_context ||
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebRequestPermissions::HideRequest(extension_info_map, request))
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetAndSetSignaled(request->identifier(), kOnSendHeaders))
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearSignaled(request->identifier(), kOnBeforeRedirect);
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const EventListener*> listeners =
8441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      GetMatchingListeners(browser_context, extension_info_map,
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           keys::kOnSendHeadersEvent, request,
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           &extra_info_spec);
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listeners.empty())
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue args;
8515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue();
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtractRequestInfo(request, dict);
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS)
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->Set(keys::kRequestHeadersKey, GetRequestHeadersList(headers));
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args.Append(dict);
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DispatchEvent(browser_context, request, listeners, args);
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionWebRequestEventRouter::OnHeadersReceived(
8611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
862f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    InfoMap* extension_info_map,
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::CompletionCallback& callback,
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::HttpResponseHeaders* original_response_headers,
866effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
867effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    GURL* allowed_unsafe_redirect_url) {
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We hide events from the system context as well as sensitive requests.
8691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!browser_context ||
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebRequestPermissions::HideRequest(extension_info_map, request))
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool initialize_blocked_requests = false;
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  initialize_blocked_requests |=
8761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ProcessDeclarativeRules(browser_context, extension_info_map,
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              keys::kOnHeadersReceivedEvent, request,
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              extensions::ON_HEADERS_RECEIVED,
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              original_response_headers);
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const EventListener*> listeners =
8831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      GetMatchingListeners(browser_context, extension_info_map,
8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           keys::kOnHeadersReceivedEvent, request,
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &extra_info_spec);
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!listeners.empty() &&
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !GetAndSetSignaled(request->identifier(), kOnHeadersReceived)) {
8895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ListValue args;
8905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* dict = new base::DictionaryValue();
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtractRequestInfo(request, dict);
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->SetString(keys::kStatusLineKey,
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        original_response_headers->GetStatusLine());
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dict->Set(keys::kResponseHeadersKey,
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GetResponseHeadersList(original_response_headers));
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    args.Append(dict);
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    initialize_blocked_requests |=
9011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        DispatchEvent(browser_context, request, listeners, args);
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!initialize_blocked_requests)
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;  // Nobody saw a reason for modifying the request.
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].event = kOnHeadersReceived;
9087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  blocked_requests_[request->identifier()].is_incognito |=
9091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      IsIncognitoBrowserContext(browser_context);
9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  blocked_requests_[request->identifier()].request = request;
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].callback = callback;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].net_log = &request->net_log();
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].override_response_headers =
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      override_response_headers;
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].original_response_headers =
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      original_response_headers;
917effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  blocked_requests_[request->identifier()].new_url =
918effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      allowed_unsafe_redirect_url;
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (blocked_requests_[request->identifier()].num_handlers_blocking == 0) {
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If there are no blocking handlers, only the declarative rules tried
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to modify the request and we can respond synchronously.
9231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return ExecuteDeltas(browser_context, request->identifier(),
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         false /* call_callback*/);
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_IO_PENDING;
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)net::NetworkDelegate::AuthRequiredResponse
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebRequestEventRouter::OnAuthRequired(
9321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
933f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    InfoMap* extension_info_map,
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::AuthChallengeInfo& auth_info,
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::NetworkDelegate::AuthCallback& callback,
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::AuthCredentials* credentials) {
9381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // No browser_context means that this is for authentication challenges in the
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // system context. Skip in that case. Also skip sensitive requests.
9401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!browser_context ||
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebRequestPermissions::HideRequest(extension_info_map, request))
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const EventListener*> listeners =
9461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      GetMatchingListeners(browser_context, extension_info_map,
9472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           keys::kOnAuthRequiredEvent, request,
9482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           &extra_info_spec);
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listeners.empty())
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue args;
9535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue();
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtractRequestInfo(request, dict);
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetBoolean(keys::kIsProxyKey, auth_info.is_proxy);
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!auth_info.scheme.empty())
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->SetString(keys::kSchemeKey, auth_info.scheme);
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!auth_info.realm.empty())
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->SetString(keys::kRealmKey, auth_info.realm);
9605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* challenger = new base::DictionaryValue();
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  challenger->SetString(keys::kHostKey, auth_info.challenger.host());
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  challenger->SetInteger(keys::kPortKey, auth_info.challenger.port());
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->Set(keys::kChallengerKey, challenger);
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers()));
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->Set(keys::kResponseHeadersKey,
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetResponseHeadersList(request->response_headers()));
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args.Append(dict);
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (DispatchEvent(browser_context, request, listeners, args)) {
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_[request->identifier()].event = kOnAuthRequired;
9737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    blocked_requests_[request->identifier()].is_incognito |=
9741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        IsIncognitoBrowserContext(browser_context);
9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    blocked_requests_[request->identifier()].request = request;
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_[request->identifier()].auth_callback = callback;
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_[request->identifier()].auth_credentials = credentials;
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_[request->identifier()].net_log = &request->net_log();
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_IO_PENDING;
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::OnBeforeRedirect(
9851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
986f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    InfoMap* extension_info_map,
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& new_location) {
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We hide events from the system context as well as sensitive requests.
9901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!browser_context ||
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebRequestPermissions::HideRequest(extension_info_map, request))
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetAndSetSignaled(request->identifier(), kOnBeforeRedirect))
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearSignaled(request->identifier(), kOnBeforeRequest);
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearSignaled(request->identifier(), kOnBeforeSendHeaders);
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearSignaled(request->identifier(), kOnSendHeaders);
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearSignaled(request->identifier(), kOnHeadersReceived);
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const EventListener*> listeners =
10041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      GetMatchingListeners(browser_context, extension_info_map,
10052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           keys::kOnBeforeRedirectEvent, request,
10062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           &extra_info_spec);
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listeners.empty())
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int http_status_code = request->GetResponseCode();
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string response_ip = request->GetSocketAddress().host();
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue args;
10155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue();
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtractRequestInfo(request, dict);
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetString(keys::kRedirectUrlKey, new_location.spec());
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetInteger(keys::kStatusCodeKey, http_status_code);
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!response_ip.empty())
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->SetString(keys::kIpKey, response_ip);
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetBoolean(keys::kFromCache, request->was_cached());
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers()));
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->Set(keys::kResponseHeadersKey,
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetResponseHeadersList(request->response_headers()));
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args.Append(dict);
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DispatchEvent(browser_context, request, listeners, args);
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::OnResponseStarted(
10331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
1034f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    InfoMap* extension_info_map,
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request) {
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We hide events from the system context as well as sensitive requests.
10371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!browser_context ||
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebRequestPermissions::HideRequest(extension_info_map, request))
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnResponseStarted is even triggered, when the request was cancelled.
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request->status().status() != net::URLRequestStatus::SUCCESS)
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const EventListener*> listeners =
10471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      GetMatchingListeners(browser_context, extension_info_map,
10482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           keys::kOnResponseStartedEvent, request,
10492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           &extra_info_spec);
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listeners.empty())
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // UrlRequestFileJobs do not send headers, so we simulate their behavior.
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int response_code = 200;
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request->response_headers())
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_code = request->response_headers()->response_code();
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string response_ip = request->GetSocketAddress().host();
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue args;
10615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue();
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtractRequestInfo(request, dict);
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!response_ip.empty())
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->SetString(keys::kIpKey, response_ip);
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetBoolean(keys::kFromCache, request->was_cached());
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetInteger(keys::kStatusCodeKey, response_code);
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers()));
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->Set(keys::kResponseHeadersKey,
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetResponseHeadersList(request->response_headers()));
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args.Append(dict);
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DispatchEvent(browser_context, request, listeners, args);
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ExtensionWebRequestEventRouter::OnCompleted(void* browser_context,
1078f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                 InfoMap* extension_info_map,
1079f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                 net::URLRequest* request) {
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We hide events from the system context as well as sensitive requests.
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // However, if the request first became sensitive after redirecting we have
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // already signaled it and thus we have to signal the end of it. This is
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // risk-free because the handler cannot modify the request now.
10841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!browser_context ||
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (WebRequestPermissions::HideRequest(extension_info_map, request) &&
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       !WasSignaled(*request)))
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_time_tracker_->LogRequestEndTime(request->identifier(),
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           base::Time::Now());
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request->status().status() == net::URLRequestStatus::SUCCESS);
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!GetAndSetSignaled(request->identifier(), kOnCompleted));
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearPendingCallbacks(request);
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const EventListener*> listeners =
11001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      GetMatchingListeners(browser_context, extension_info_map,
11012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           keys::kOnCompletedEvent, request, &extra_info_spec);
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listeners.empty())
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // UrlRequestFileJobs do not send headers, so we simulate their behavior.
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int response_code = 200;
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request->response_headers())
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_code = request->response_headers()->response_code();
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string response_ip = request->GetSocketAddress().host();
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue args;
11135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue();
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtractRequestInfo(request, dict);
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetInteger(keys::kStatusCodeKey, response_code);
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!response_ip.empty())
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->SetString(keys::kIpKey, response_ip);
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetBoolean(keys::kFromCache, request->was_cached());
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers()));
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->Set(keys::kResponseHeadersKey,
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetResponseHeadersList(request->response_headers()));
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args.Append(dict);
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DispatchEvent(browser_context, request, listeners, args);
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::OnErrorOccurred(
11301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
1131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    InfoMap* extension_info_map,
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool started) {
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We hide events from the system context as well as sensitive requests.
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // However, if the request first became sensitive after redirecting we have
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // already signaled it and thus we have to signal the end of it. This is
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // risk-free because the handler cannot modify the request now.
11381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!browser_context ||
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (WebRequestPermissions::HideRequest(extension_info_map, request) &&
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       !WasSignaled(*request)))
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_time_tracker_->LogRequestEndTime(request->identifier(),
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           base::Time::Now());
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request->status().status() == net::URLRequestStatus::FAILED ||
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         request->status().status() == net::URLRequestStatus::CANCELED);
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!GetAndSetSignaled(request->identifier(), kOnErrorOccurred));
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearPendingCallbacks(request);
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const EventListener*> listeners =
11551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      GetMatchingListeners(browser_context, extension_info_map,
11563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                           web_request::OnErrorOccurred::kEventName, request,
11572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           &extra_info_spec);
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listeners.empty())
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue args;
11625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue();
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtractRequestInfo(request, dict);
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (started) {
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string response_ip = request->GetSocketAddress().host();
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!response_ip.empty())
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dict->SetString(keys::kIpKey, response_ip);
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetBoolean(keys::kFromCache, request->was_cached());
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetString(keys::kErrorKey,
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  net::ErrorToString(request->status().error()));
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args.Append(dict);
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DispatchEvent(browser_context, request, listeners, args);
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::OnURLRequestDestroyed(
11781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context, net::URLRequest* request) {
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearPendingCallbacks(request);
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signaled_requests_.erase(request->identifier());
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_time_tracker_->LogRequestEndTime(request->identifier(),
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           base::Time::Now());
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::ClearPendingCallbacks(
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request) {
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_.erase(request->identifier());
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionWebRequestEventRouter::DispatchEvent(
11931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<const EventListener*>& listeners,
11965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::ListValue& args) {
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(mpcomplete): Consider consolidating common (extension_id,json_args)
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pairs into a single message sent to a list of sub_event_names.
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_handlers_blocking = 0;
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<const EventListener*>::const_iterator it = listeners.begin();
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != listeners.end(); ++it) {
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Filter out the optional keys that this listener didn't request.
12035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::ListValue> args_filtered(args.DeepCopy());
12045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* dict = NULL;
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(args_filtered->GetDictionary(0, &dict) && dict);
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!((*it)->extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS))
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dict->Remove(keys::kRequestHeadersKey, NULL);
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!((*it)->extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS))
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dict->Remove(keys::kResponseHeadersKey, NULL);
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions::EventRouter::DispatchEvent(
12121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        (*it)->ipc_sender.get(), browser_context,
12132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (*it)->extension_id, (*it)->sub_event_name,
1214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        args_filtered.Pass(),
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extensions::EventRouter::USER_GESTURE_UNKNOWN,
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extensions::EventFilteringInfo());
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*it)->extra_info_spec &
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) {
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (*it)->blocked_requests.insert(request->identifier());
12201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // If this is the first delegate blocking the request, go ahead and log
12211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // it.
12221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (num_handlers_blocking == 0) {
12231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        std::string delegate_info =
12241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            l10n_util::GetStringFUTF8(IDS_LOAD_STATE_PARAMETER_EXTENSION,
12255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      base::UTF8ToUTF16((*it)->extension_name));
1226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // LobAndReport allows extensions that block requests to be displayed in
1227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // the load status bar.
1228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        request->LogAndReportBlockedBy(delegate_info.c_str());
12291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      }
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++num_handlers_blocking;
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_handlers_blocking > 0) {
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_[request->identifier()].request = request;
12367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    blocked_requests_[request->identifier()].is_incognito |=
12371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        IsIncognitoBrowserContext(browser_context);
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_[request->identifier()].num_handlers_blocking +=
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_handlers_blocking;
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_[request->identifier()].blocking_time = base::Time::Now();
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::OnEventHandled(
12491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id,
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& event_name,
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& sub_event_name,
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint64 request_id,
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EventResponse* response) {
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventListener listener;
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.extension_id = extension_id;
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.sub_event_name = sub_event_name;
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The listener may have been removed (e.g. due to the process going away)
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // before we got here.
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<EventListener>::iterator found =
12621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      listeners_[browser_context][event_name].find(listener);
12631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (found != listeners_[browser_context][event_name].end())
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    found->blocked_requests.erase(request_id);
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DecrementBlockCount(
12671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      browser_context, extension_id, event_name, request_id, response);
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionWebRequestEventRouter::AddEventListener(
12711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id,
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_name,
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& event_name,
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& sub_event_name,
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const RequestFilter& filter,
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int extra_info_spec,
127890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int embedder_process_id,
1279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int webview_instance_id,
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::WeakPtr<IPC::Sender> ipc_sender) {
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsWebRequestEvent(event_name))
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventListener listener;
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.extension_id = extension_id;
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.extension_name = extension_name;
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.sub_event_name = sub_event_name;
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.filter = filter;
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.extra_info_spec = extra_info_spec;
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.ipc_sender = ipc_sender;
129190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  listener.embedder_process_id = embedder_process_id;
1292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  listener.webview_instance_id = webview_instance_id;
12935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (listener.webview_instance_id) {
12945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    content::RecordAction(
12955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::UserMetricsAction("WebView.WebRequest.AddListener"));
12965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (listeners_[browser_context][event_name].count(listener) != 0u) {
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This is likely an abuse of the API by a malicious extension.
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  listeners_[browser_context][event_name].insert(listener);
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::RemoveEventListener(
13071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id,
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& sub_event_name) {
1310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string event_name =
1311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      extensions::EventRouter::GetBaseEventName(sub_event_name);
1312f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(IsWebRequestEvent(event_name));
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventListener listener;
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.extension_id = extension_id;
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.sub_event_name = sub_event_name;
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's possible for AddEventListener to fail asynchronously. In that case,
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the renderer believes the listener exists, while the browser does not.
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ignore a RemoveEventListener in that case.
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<EventListener>::iterator found =
13221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      listeners_[browser_context][event_name].find(listener);
13231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (found == listeners_[browser_context][event_name].end())
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK_EQ(listeners_[browser_context][event_name].count(listener), 1u) <<
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "extension=" << extension_id << " event=" << event_name;
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unblock any request that this event listener may have been blocking.
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<uint64>::iterator it = found->blocked_requests.begin();
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != found->blocked_requests.end(); ++it) {
13321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DecrementBlockCount(browser_context, extension_id, event_name, *it, NULL);
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  listeners_[browser_context][event_name].erase(listener);
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helpers::ClearCacheOnNavigation();
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
134090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ExtensionWebRequestEventRouter::RemoveWebViewEventListeners(
13411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
134290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& extension_id,
134390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int embedder_process_id,
1344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int webview_instance_id) {
134590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Iterate over all listeners of all WebRequest events to delete
134690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // any listeners that belong to the provided <webview>.
13471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ListenerMapForBrowserContext& map_for_browser_context =
13481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      listeners_[browser_context];
13491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (ListenerMapForBrowserContext::iterator event_iter =
13501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       map_for_browser_context.begin();
13511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       event_iter != map_for_browser_context.end(); ++event_iter) {
135290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    std::vector<EventListener> listeners_to_delete;
135390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    std::set<EventListener>& listeners = event_iter->second;
135490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (std::set<EventListener>::iterator listener_iter = listeners.begin();
135590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         listener_iter != listeners.end(); ++listener_iter) {
135690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const EventListener& listener = *listener_iter;
135790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (listener.embedder_process_id == embedder_process_id &&
1358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          listener.webview_instance_id == webview_instance_id)
135990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        listeners_to_delete.push_back(listener);
136090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
136190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (size_t i = 0; i < listeners_to_delete.size(); ++i) {
136290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      EventListener& listener = listeners_to_delete[i];
136390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      content::BrowserThread::PostTask(
136490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          content::BrowserThread::UI,
136590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          FROM_HERE,
136690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          base::Bind(&RemoveEventListenerOnUI,
13671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     browser_context,
136890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     listener.sub_event_name,
136990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     embedder_process_id,
137090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     extension_id));
137190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
137290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
137390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
137490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ExtensionWebRequestEventRouter::OnOTRBrowserContextCreated(
13761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* original_browser_context, void* otr_browser_context) {
13771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  cross_browser_context_map_[original_browser_context] =
13781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      std::make_pair(false, otr_browser_context);
13791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  cross_browser_context_map_[otr_browser_context] =
13801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      std::make_pair(true, original_browser_context);
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ExtensionWebRequestEventRouter::OnOTRBrowserContextDestroyed(
13841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* original_browser_context, void* otr_browser_context) {
13851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  cross_browser_context_map_.erase(otr_browser_context);
13861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  cross_browser_context_map_.erase(original_browser_context);
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::AddCallbackForPageLoad(
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& callback) {
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callbacks_for_page_load_.push_back(callback);
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionWebRequestEventRouter::IsPageLoad(
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request) const {
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_main_frame = false;
13975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int frame_id = -1;
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool parent_is_main_frame = false;
13995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int parent_frame_id = -1;
14002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int render_process_host_id = -1;
14012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int routing_id = -1;
14025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ResourceType resource_type = content::RESOURCE_TYPE_LAST_TYPE;
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtractRequestInfoDetails(request, &is_main_frame, &frame_id,
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &parent_is_main_frame, &parent_frame_id,
14061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            &render_process_host_id,
14072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            &routing_id, &resource_type);
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return resource_type == content::RESOURCE_TYPE_MAIN_FRAME;
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::NotifyPageLoad() {
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (CallbacksForPageLoad::const_iterator i =
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           callbacks_for_page_load_.begin();
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != callbacks_for_page_load_.end(); ++i) {
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i->Run();
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callbacks_for_page_load_.clear();
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid* ExtensionWebRequestEventRouter::GetCrossBrowserContext(
14221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context) const {
14231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CrossBrowserContextMap::const_iterator cross_browser_context =
14241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      cross_browser_context_map_.find(browser_context);
14251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (cross_browser_context == cross_browser_context_map_.end())
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
14271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return cross_browser_context->second.second;
14287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
14297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
14301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ExtensionWebRequestEventRouter::IsIncognitoBrowserContext(
14311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context) const {
14321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CrossBrowserContextMap::const_iterator cross_browser_context =
14331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      cross_browser_context_map_.find(browser_context);
14341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (cross_browser_context == cross_browser_context_map_.end())
14357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
14361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return cross_browser_context->second.first;
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionWebRequestEventRouter::WasSignaled(
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::URLRequest& request) const {
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignaledRequestMap::const_iterator flag =
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      signaled_requests_.find(request.identifier());
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (flag != signaled_requests_.end()) && (flag->second != 0);
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::GetMatchingListenersImpl(
14471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
14481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    net::URLRequest* request,
1449f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    InfoMap* extension_info_map,
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool crosses_incognito,
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& event_name,
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
14532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int render_process_host_id,
14542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int routing_id,
14555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ResourceType resource_type,
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_async_request,
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_request_from_extension,
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int* extra_info_spec,
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<const ExtensionWebRequestEventRouter::EventListener*>*
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        matching_listeners) {
146190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string web_request_event_name(event_name);
14626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  extensions::WebViewRendererState::WebViewInfo web_view_info;
14636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  bool is_web_view_guest = extensions::WebViewRendererState::GetInstance()->
1464116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      GetInfo(render_process_host_id, routing_id, &web_view_info);
1465116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (is_web_view_guest) {
1466116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    web_request_event_name.replace(
1467116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        0, sizeof(kWebRequestEventPrefix) - 1, webview::kWebViewEventPrefix);
1468116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
146990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
147090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::set<EventListener>& listeners =
14711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      listeners_[browser_context][web_request_event_name];
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<EventListener>::iterator it = listeners.begin();
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != listeners.end(); ++it) {
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!it->ipc_sender.get()) {
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The IPC sender has been deleted. This listener will be removed soon
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // via a call to RemoveEventListener. For now, just skip it.
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (is_web_view_guest &&
1481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        (it->embedder_process_id != web_view_info.embedder_process_id ||
1482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         it->webview_instance_id != web_view_info.instance_id))
14832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
14842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!it->filter.urls.is_empty() && !it->filter.urls.MatchesURL(url))
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
14871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (web_request_event_router_delegate_ &&
14881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        web_request_event_router_delegate_->OnGetMatchingListenersImplCheck(
14891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            it->filter.tab_id, it->filter.window_id, request))
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!it->filter.types.empty() &&
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::find(it->filter.types.begin(), it->filter.types.end(),
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  resource_type) == it->filter.types.end())
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!is_web_view_guest && !WebRequestPermissions::CanExtensionAccessURL(
1497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            extension_info_map, it->extension_id, url, crosses_incognito,
1498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            WebRequestPermissions::REQUIRE_HOST_PERMISSION))
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool blocking_listener =
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (it->extra_info_spec &
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) != 0;
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We do not want to notify extensions about XHR requests that are
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // triggered by themselves. This is a workaround to prevent deadlocks
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // in case of synchronous XHR requests that block the extension renderer
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and therefore prevent the extension from processing the request
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // handler. This is only a problem for blocking listeners.
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // http://crbug.com/105656
15115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool synchronous_xhr_from_extension =
15125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        !is_async_request && is_request_from_extension &&
15135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        resource_type == content::RESOURCE_TYPE_XHR;
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Only send webRequest events for URLs the extension has access to.
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (blocking_listener && synchronous_xhr_from_extension)
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    matching_listeners->push_back(&(*it));
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *extra_info_spec |= it->extra_info_spec;
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::vector<const ExtensionWebRequestEventRouter::EventListener*>
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebRequestEventRouter::GetMatchingListeners(
15261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
1527f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    InfoMap* extension_info_map,
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& event_name,
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int* extra_info_spec) {
15311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(mpcomplete): handle browser_context == NULL (should collect all
15321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // listeners).
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *extra_info_spec = 0;
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_main_frame = false;
15365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int frame_id = -1;
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool parent_is_main_frame = false;
15385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int parent_frame_id = -1;
15392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int render_process_host_id = -1;
15402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int routing_id = -1;
15415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ResourceType resource_type = content::RESOURCE_TYPE_LAST_TYPE;
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GURL& url = request->url();
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtractRequestInfoDetails(request, &is_main_frame, &frame_id,
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &parent_is_main_frame, &parent_frame_id,
15461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            &render_process_host_id,
15472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            &routing_id, &resource_type);
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const ExtensionWebRequestEventRouter::EventListener*>
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      matching_listeners;
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_request_from_extension =
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IsRequestFromExtension(request, extension_info_map);
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We are conservative here and assume requests are asynchronous in case
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we don't have an info object. We don't want to risk a deadlock.
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_async_request = !info || info->IsAsync();
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetMatchingListenersImpl(
15611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      browser_context, request, extension_info_map, false, event_name,
15621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      url, render_process_host_id, routing_id, resource_type,
15632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      is_async_request, is_request_from_extension, extra_info_spec,
15642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &matching_listeners);
15651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void* cross_browser_context = GetCrossBrowserContext(browser_context);
15661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (cross_browser_context) {
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetMatchingListenersImpl(
15681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        cross_browser_context, request, extension_info_map, true, event_name,
15691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        url, render_process_host_id, routing_id, resource_type,
15702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        is_async_request, is_request_from_extension, extra_info_spec,
15712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &matching_listeners);
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return matching_listeners;
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)helpers::EventResponseDelta* CalculateDelta(
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionWebRequestEventRouter::BlockedRequest* blocked_request,
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionWebRequestEventRouter::EventResponse* response) {
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (blocked_request->event) {
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnBeforeRequest:
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return helpers::CalculateOnBeforeRequestDelta(
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response->extension_id, response->extension_install_time,
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response->cancel, response->new_url);
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnBeforeSendHeaders: {
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::HttpRequestHeaders* old_headers = blocked_request->request_headers;
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::HttpRequestHeaders* new_headers = response->request_headers.get();
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return helpers::CalculateOnBeforeSendHeadersDelta(
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response->extension_id, response->extension_install_time,
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response->cancel, old_headers, new_headers);
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnHeadersReceived: {
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const net::HttpResponseHeaders* old_headers =
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          blocked_request->original_response_headers.get();
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      helpers::ResponseHeaders* new_headers =
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response->response_headers.get();
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return helpers::CalculateOnHeadersReceivedDelta(
1600effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          response->extension_id,
1601effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          response->extension_install_time,
1602effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          response->cancel,
1603effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          response->new_url,
1604effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          old_headers,
1605effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          new_headers);
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnAuthRequired:
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return helpers::CalculateOnAuthRequiredDelta(
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response->extension_id, response->extension_install_time,
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response->cancel, &response->auth_credentials);
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::Value* SerializeResponseHeaders(const helpers::ResponseHeaders& headers) {
16195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::ListValue> serialized_headers(new base::ListValue());
1620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (helpers::ResponseHeaders::const_iterator i = headers.begin();
1621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       i != headers.end(); ++i) {
16221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    serialized_headers->Append(
16231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        helpers::CreateHeaderDictionary(i->first, i->second));
1624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return serialized_headers.release();
1626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Convert a RequestCookieModifications/ResponseCookieModifications object to a
16295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// base::ListValue which summarizes the changes made.  This is templated since
16305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// the two types (request/response) are different but contain essentially the
16315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// same fields.
1632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)template<typename CookieType>
16335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::ListValue* SummarizeCookieModifications(
1634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::vector<linked_ptr<CookieType> >& modifications) {
16355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::ListValue> cookie_modifications(new base::ListValue());
1636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (typename std::vector<linked_ptr<CookieType> >::const_iterator i =
1637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           modifications.begin();
1638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       i != modifications.end(); ++i) {
16395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::DictionaryValue> summary(new base::DictionaryValue());
1640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const CookieType& mod = *i->get();
1641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    switch (mod.type) {
1642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case helpers::ADD:
1643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        summary->SetString(activitylog::kCookieModificationTypeKey,
1644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           activitylog::kCookieModificationAdd);
1645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
1646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case helpers::EDIT:
1647c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        summary->SetString(activitylog::kCookieModificationTypeKey,
1648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           activitylog::kCookieModificationEdit);
1649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
1650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case helpers::REMOVE:
1651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        summary->SetString(activitylog::kCookieModificationTypeKey,
1652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           activitylog::kCookieModificationRemove);
1653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
1654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (mod.filter) {
1656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (mod.filter->name)
1657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        summary->SetString(activitylog::kCookieFilterNameKey,
1658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           *mod.modification->name);
1659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (mod.filter->domain)
1660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        summary->SetString(activitylog::kCookieFilterDomainKey,
1661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           *mod.modification->name);
1662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (mod.modification) {
1664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (mod.modification->name)
1665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        summary->SetString(activitylog::kCookieModDomainKey,
1666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           *mod.modification->name);
1667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (mod.modification->domain)
1668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        summary->SetString(activitylog::kCookieModDomainKey,
1669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           *mod.modification->name);
1670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cookie_modifications->Append(summary.release());
1672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return cookie_modifications.release();
1674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Converts an EventResponseDelta object to a dictionary value suitable for the
16777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// activity log.
16785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<base::DictionaryValue> SummarizeResponseDelta(
1679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& event_name,
1680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const helpers::EventResponseDelta& delta) {
16815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> details(new base::DictionaryValue());
1682c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (delta.cancel) {
1683c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    details->SetBoolean(activitylog::kCancelKey, true);
1684c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1685c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!delta.new_url.is_empty()) {
1686c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      details->SetString(activitylog::kNewUrlKey, delta.new_url.spec());
1687c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1688c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::ListValue> modified_headers(new base::ListValue());
1690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  net::HttpRequestHeaders::Iterator iter(delta.modified_request_headers);
1691c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (iter.GetNext()) {
16921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    modified_headers->Append(
16931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        helpers::CreateHeaderDictionary(iter.name(), iter.value()));
1694c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1695c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!modified_headers->empty()) {
1696c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    details->Set(activitylog::kModifiedRequestHeadersKey,
1697c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 modified_headers.release());
1698c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1699c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::ListValue> deleted_headers(new base::ListValue());
1701c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  deleted_headers->AppendStrings(delta.deleted_request_headers);
1702c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!deleted_headers->empty()) {
1703c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    details->Set(activitylog::kDeletedRequestHeadersKey,
1704c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 deleted_headers.release());
1705c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1706c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!delta.added_response_headers.empty()) {
1708c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    details->Set(activitylog::kAddedRequestHeadersKey,
1709c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 SerializeResponseHeaders(delta.added_response_headers));
1710c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1711c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!delta.deleted_response_headers.empty()) {
1712c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    details->Set(activitylog::kDeletedResponseHeadersKey,
1713c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 SerializeResponseHeaders(delta.deleted_response_headers));
1714c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1715c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (delta.auth_credentials) {
1716c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    details->SetString(activitylog::kAuthCredentialsKey,
17175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       base::UTF16ToUTF8(
17185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           delta.auth_credentials->username()) + ":*");
1719c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1720c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1721c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!delta.response_cookie_modifications.empty()) {
1722c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    details->Set(
1723c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        activitylog::kResponseCookieModificationsKey,
1724c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        SummarizeCookieModifications(delta.response_cookie_modifications));
1725c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return details.Pass();
1728c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1729c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace
17311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
17321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ExtensionWebRequestEventRouter::LogExtensionActivity(
17331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context_id,
17341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    bool is_incognito,
17351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::string& extension_id,
17361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const GURL& url,
17371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::string& api_call,
17381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<base::DictionaryValue> details) {
1739c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
17401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    BrowserThread::PostTask(
17411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        BrowserThread::UI,
17421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        FROM_HERE,
17431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::Bind(&ExtensionWebRequestEventRouter::LogExtensionActivity,
17441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    base::Unretained(this),
17451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    browser_context_id,
17461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    is_incognito,
17471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    extension_id,
17481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    url,
17491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    api_call,
17501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    base::Passed(&details)));
1751c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
17521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (web_request_event_router_delegate_) {
17531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      web_request_event_router_delegate_->LogExtensionActivity(
17541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          reinterpret_cast<content::BrowserContext*>(browser_context_id),
17551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          is_incognito, extension_id, url, api_call, details.Pass());
17561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
1757c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1758c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1759c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::DecrementBlockCount(
17611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id,
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& event_name,
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint64 request_id,
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EventResponse* response) {
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<EventResponse> response_scoped(response);
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's possible that this request was deleted, or cancelled by a previous
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // event handler. If so, ignore this response.
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (blocked_requests_.find(request_id) == blocked_requests_.end())
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlockedRequest& blocked_request = blocked_requests_[request_id];
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_handlers_blocking = --blocked_request.num_handlers_blocking;
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_GE(num_handlers_blocking, 0);
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response) {
1778c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    helpers::EventResponseDelta* delta =
1779c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        CalculateDelta(&blocked_request, response);
1780c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    LogExtensionActivity(browser_context,
178258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                         blocked_request.is_incognito,
178358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                         extension_id,
178458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                         blocked_request.request->url(),
178558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                         event_name,
178658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                         SummarizeResponseDelta(event_name, *delta));
1787c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_request.response_deltas.push_back(
1789c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        linked_ptr<helpers::EventResponseDelta>(delta));
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta block_time =
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::Now() - blocked_request.blocking_time;
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension_id.empty()) {
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_time_tracker_->IncrementExtensionBlockTime(
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extension_id, request_id, block_time);
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |extension_id| is empty for requests blocked on startup waiting for the
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // declarative rules to be read from disk.
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_TIMES("Extensions.NetworkDelayStartup", block_time);
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_handlers_blocking == 0) {
1804a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    blocked_request.request->LogUnblocked();
18051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ExecuteDeltas(browser_context, request_id, true);
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
18071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Update the URLRequest to make sure it's tagged with an extension that's
18081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // still blocking it.  This may end up being the same extension as before.
18091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::set<EventListener>& listeners =
18101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        listeners_[browser_context][event_name];
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::set<EventListener>::iterator it = listeners.begin();
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         it != listeners.end(); ++it) {
18141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (it->blocked_requests.count(request_id) == 0)
18151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        continue;
18161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      std::string delegate_info =
18171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          l10n_util::GetStringFUTF8(IDS_LOAD_STATE_PARAMETER_EXTENSION,
18185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    base::UTF8ToUTF16(it->extension_name));
1819a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      blocked_request.request->LogAndReportBlockedBy(delegate_info.c_str());
18201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      break;
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionWebRequestEventRouter::SendMessages(
18261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
18272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const BlockedRequest& blocked_request) {
18282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const helpers::EventResponseDeltas& deltas = blocked_request.response_deltas;
18292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (helpers::EventResponseDeltas::const_iterator delta = deltas.begin();
18302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       delta != deltas.end(); ++delta) {
18312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::set<std::string>& messages = (*delta)->messages_to_extension;
18322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (std::set<std::string>::const_iterator message = messages.begin();
18332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         message != messages.end(); ++message) {
18342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<base::DictionaryValue> argument(new base::DictionaryValue);
18352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ExtractRequestInfo(blocked_request.request, argument.get());
18366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      extensions::WebViewRendererState::WebViewInfo web_view_info;
1837cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      bool is_web_view_guest = GetWebViewInfo(blocked_request.request,
1838cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                              &web_view_info);
18392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      argument->SetString(keys::kMessageKey, *message);
18402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      argument->SetString(keys::kStageKey,
18412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          GetRequestStageAsString(blocked_request.event));
18422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      BrowserThread::PostTask(
18442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          BrowserThread::UI,
18452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          FROM_HERE,
18462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&SendOnMessageEventOnUI,
18471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     browser_context,
18482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     (*delta)->extension_id,
1849cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     is_web_view_guest,
1850cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     web_view_info,
18512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     base::Passed(&argument)));
18522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
18532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
18542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
18552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionWebRequestEventRouter::ExecuteDeltas(
18571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint64 request_id,
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool call_callback) {
18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlockedRequest& blocked_request = blocked_requests_[request_id];
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(blocked_request.num_handlers_blocking == 0);
18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helpers::EventResponseDeltas& deltas = blocked_request.response_deltas;
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta block_time =
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::Now() - blocked_request.blocking_time;
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_time_tracker_->IncrementTotalBlockTime(request_id, block_time);
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool credentials_set = false;
18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  deltas.sort(&helpers::InDecreasingExtensionInstallationTimeOrder);
18701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  WarningSet warnings;
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool canceled = false;
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helpers::MergeCancelOfResponses(
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocked_request.response_deltas,
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &canceled,
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocked_request.net_log);
18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (blocked_request.event == kOnBeforeRequest) {
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(!blocked_request.callback.is_null());
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helpers::MergeOnBeforeRequestResponses(
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.response_deltas,
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.new_url,
18832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &warnings,
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.net_log);
18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (blocked_request.event == kOnBeforeSendHeaders) {
18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(!blocked_request.callback.is_null());
18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helpers::MergeOnBeforeSendHeadersResponses(
18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.response_deltas,
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.request_headers,
18902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &warnings,
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.net_log);
18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (blocked_request.event == kOnHeadersReceived) {
18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(!blocked_request.callback.is_null());
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helpers::MergeOnHeadersReceivedResponses(
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.response_deltas,
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.original_response_headers.get(),
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.override_response_headers,
1898effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        blocked_request.new_url,
18992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &warnings,
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.net_log);
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (blocked_request.event == kOnAuthRequired) {
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(blocked_request.callback.is_null());
19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(!blocked_request.auth_callback.is_null());
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    credentials_set = helpers::MergeOnAuthRequiredResponses(
19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       blocked_request.response_deltas,
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       blocked_request.auth_credentials,
19072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       &warnings,
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       blocked_request.net_log);
19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SendMessages(browser_context, blocked_request);
19142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!warnings.empty()) {
19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(
19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserThread::UI,
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
19191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::Bind(&WarningService::NotifyWarningsOnUI,
19201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   browser_context, warnings));
19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (canceled) {
19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_time_tracker_->SetRequestCanceled(request_id);
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (blocked_request.new_url &&
19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             !blocked_request.new_url->is_empty()) {
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_time_tracker_->SetRequestRedirected(request_id);
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This triggers onErrorOccurred if canceled is true.
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = canceled ? net::ERR_BLOCKED_BY_CLIENT : net::OK;
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!blocked_request.callback.is_null()) {
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::CompletionCallback callback = blocked_request.callback;
19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ensure that request is removed before callback because the callback
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // might trigger the next event.
19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_.erase(request_id);
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (call_callback)
19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.Run(rv);
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (!blocked_request.auth_callback.is_null()) {
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::NetworkDelegate::AuthRequiredResponse response =
19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (canceled) {
19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response = net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_CANCEL_AUTH;
19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (credentials_set) {
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response = net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_SET_AUTH;
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::NetworkDelegate::AuthCallback callback = blocked_request.auth_callback;
19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_.erase(request_id);
19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (call_callback)
19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.Run(response);
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_.erase(request_id);
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionWebRequestEventRouter::ProcessDeclarativeRules(
19591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
1960f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    InfoMap* extension_info_map,
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& event_name,
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions::RequestStage request_stage,
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::HttpResponseHeaders* original_response_headers) {
19656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  extensions::WebViewRendererState::WebViewInfo web_view_info;
1966cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool is_web_view_guest = GetWebViewInfo(request, &web_view_info);
1967f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
19681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  extensions::RulesRegistry::WebViewKey webview_key(
1969cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      is_web_view_guest ? web_view_info.embedder_process_id : 0,
1970cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      is_web_view_guest ? web_view_info.instance_id : 0);
19711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  RulesRegistryKey rules_key(browser_context, webview_key);
19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If this check fails, check that the active stages are up-to-date in
19731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // extensions/browser/api/declarative_webrequest/request_stage.h .
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request_stage & extensions::kActiveStages);
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Rules of the current |browser_context| may apply but we need to check also
19771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // whether there are applicable rules from extensions whose background page
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // spans from regular to incognito mode.
19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First parameter identifies the registry, the second indicates whether the
19811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // registry belongs to the cross browser_context.
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::pair<extensions::WebRequestRulesRegistry*, bool>
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RelevantRegistry;
19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::vector<RelevantRegistry> RelevantRegistries;
19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RelevantRegistries relevant_registries;
19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1987f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (rules_registries_.find(rules_key) != rules_registries_.end()) {
19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    relevant_registries.push_back(
1989f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        std::make_pair(rules_registries_[rules_key].get(), false));
19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void* cross_browser_context = GetCrossBrowserContext(browser_context);
19931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  RulesRegistryKey cross_browser_context_rules_key(
19941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      cross_browser_context, webview_key);
19951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (cross_browser_context &&
19961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      rules_registries_.find(cross_browser_context_rules_key) !=
1997f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          rules_registries_.end()) {
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    relevant_registries.push_back(
19991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        std::make_pair(
20001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            rules_registries_[cross_browser_context_rules_key].get(), true));
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The following block is experimentally enabled and its impact on load time
20042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // logged with UMA Extensions.NetworkDelayRegistryLoad. crbug.com/175961
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (RelevantRegistries::iterator i = relevant_registries.begin();
20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != relevant_registries.end(); ++i) {
20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions::WebRequestRulesRegistry* rules_registry = i->first;
200890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!rules_registry->ready().is_signaled()) {
20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The rules registry is still loading. Block this request until it
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // finishes.
201190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      rules_registry->ready().Post(
201290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          FROM_HERE,
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&ExtensionWebRequestEventRouter::OnRulesRegistryReady,
201490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     AsWeakPtr(),
20151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     browser_context,
201690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     event_name,
201790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     request->identifier(),
20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     request_stage));
20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocked_requests_[request->identifier()].num_handlers_blocking++;
20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocked_requests_[request->identifier()].request = request;
20217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      blocked_requests_[request->identifier()].is_incognito |=
20221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          IsIncognitoBrowserContext(browser_context);
20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocked_requests_[request->identifier()].blocking_time =
20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Time::Now();
20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocked_requests_[request->identifier()].original_response_headers =
20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          original_response_headers;
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocked_requests_[request->identifier()].extension_info_map =
20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          extension_info_map;
20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time start = base::Time::Now();
20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool deltas_created = false;
20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (RelevantRegistries::iterator i = relevant_registries.begin();
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != relevant_registries.end(); ++i) {
20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions::WebRequestRulesRegistry* rules_registry =
20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        i->first;
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helpers::EventResponseDeltas result =
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rules_registry->CreateDeltas(
20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            extension_info_map,
20432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            extensions::WebRequestData(
20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                request, request_stage, original_response_headers),
20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            i->second);
20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!result.empty()) {
20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      helpers::EventResponseDeltas& deltas =
20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          blocked_requests_[request->identifier()].response_deltas;
20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      deltas.insert(deltas.end(), result.begin(), result.end());
20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      deltas_created = true;
20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta elapsed_time = start - base::Time::Now();
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_TIMES("Extensions.DeclarativeWebRequestNetworkDelay",
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      elapsed_time);
20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return deltas_created;
20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::OnRulesRegistryReady(
20631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void* browser_context,
20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& event_name,
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint64 request_id,
20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions::RequestStage request_stage) {
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's possible that this request was deleted, or cancelled by a previous
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // event handler. If so, ignore this response.
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (blocked_requests_.find(request_id) == blocked_requests_.end())
20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlockedRequest& blocked_request = blocked_requests_[request_id];
20732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta block_time =
20742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Time::Now() - blocked_request.blocking_time;
20752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UMA_HISTOGRAM_TIMES("Extensions.NetworkDelayRegistryLoad", block_time);
20762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ProcessDeclarativeRules(browser_context,
2078868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          blocked_request.extension_info_map,
2079868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          event_name,
2080868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          blocked_request.request,
2081868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          request_stage,
2082868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          blocked_request.original_response_headers.get());
20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset to NULL so that nobody relies on this being set.
20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_request.extension_info_map = NULL;
20851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DecrementBlockCount(
20861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      browser_context, std::string(), event_name, request_id, NULL);
20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionWebRequestEventRouter::GetAndSetSignaled(uint64 request_id,
20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       EventTypes event_type) {
20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignaledRequestMap::iterator iter = signaled_requests_.find(request_id);
20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == signaled_requests_.end()) {
20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    signaled_requests_[request_id] = event_type;
20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool was_signaled_before = (iter->second & event_type) != 0;
20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  iter->second |= event_type;
20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return was_signaled_before;
20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::ClearSignaled(uint64 request_id,
21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   EventTypes event_type) {
21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignaledRequestMap::iterator iter = signaled_requests_.find(request_id);
21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == signaled_requests_.end())
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  iter->second &= ~event_type;
21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Special QuotaLimitHeuristic for WebRequestHandlerBehaviorChangedFunction.
21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Each call of webRequest.handlerBehaviorChanged() clears the in-memory cache
21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of WebKit at the time of the next page load (top level navigation event).
21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This quota heuristic is intended to limit the number of times the cache is
21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cleared by an extension.
21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// As we want to account for the number of times the cache is really cleared
21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (opposed to the number of times webRequest.handlerBehaviorChanged() is
21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// called), we cannot decide whether a call of
21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// webRequest.handlerBehaviorChanged() should trigger a quota violation at the
21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// time it is called. Instead we only decrement the bucket counter at the time
21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// when the cache is cleared (when page loads happen).
2122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class ClearCacheQuotaHeuristic : public extensions::QuotaLimitHeuristic {
21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearCacheQuotaHeuristic(const Config& config, BucketMapper* map)
21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : QuotaLimitHeuristic(
21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            config,
21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            map,
21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES"),
21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        callback_registered_(false),
21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        weak_ptr_factory_(this) {}
21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ClearCacheQuotaHeuristic() {}
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Apply(Bucket* bucket,
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const base::TimeTicks& event_time) OVERRIDE;
21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callback that is triggered by the ExtensionWebRequestEventRouter on a page
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // load.
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't need to take care of the life time of |bucket|: It is owned by the
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // BucketMapper of our base class in |QuotaLimitHeuristic::bucket_mapper_|. As
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // long as |this| exists, the respective BucketMapper and its bucket will
21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // exist as well.
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnPageLoad(Bucket* bucket);
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flag to prevent that we register more than one call back in-between
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // clearing the cache.
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool callback_registered_;
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<ClearCacheQuotaHeuristic> weak_ptr_factory_;
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ClearCacheQuotaHeuristic);
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ClearCacheQuotaHeuristic::Apply(Bucket* bucket,
21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const base::TimeTicks& event_time) {
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event_time > bucket->expiration())
21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bucket->Reset(config(), event_time);
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Call bucket->DeductToken() on a new page load, this is when
21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // webRequest.handlerBehaviorChanged() clears the cache.
21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!callback_registered_) {
21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionWebRequestEventRouter::GetInstance()->AddCallbackForPageLoad(
21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&ClearCacheQuotaHeuristic::OnPageLoad,
21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(),
21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   bucket));
21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_registered_ = true;
21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We only check whether tokens are left here. Deducting a token happens in
21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnPageLoad().
21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bucket->has_tokens();
21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClearCacheQuotaHeuristic::OnPageLoad(Bucket* bucket) {
21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_registered_ = false;
21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bucket->DeductToken();
21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool WebRequestInternalAddEventListenerFunction::RunSync() {
21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Argument 0 is the callback, which we don't use here.
21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionWebRequestEventRouter::RequestFilter filter;
21825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* value = NULL;
21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  error_.clear();
21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &value));
21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Failure + an empty error string means a fatal error.
21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(filter.InitFromValue(*value, &error_) ||
21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              !error_.empty());
21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!error_.empty())
21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasOptionalArgument(2)) {
21935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ListValue* value = NULL;
21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXTENSION_FUNCTION_VALIDATE(args_->GetList(2, &value));
21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXTENSION_FUNCTION_VALIDATE(
21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ExtensionWebRequestEventRouter::ExtraInfoSpec::InitFromValue(
21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *value, &extra_info_spec));
21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string event_name;
22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(args_->GetString(3, &event_name));
22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string sub_event_name;
22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(args_->GetString(4, &sub_event_name));
22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int webview_instance_id = 0;
2207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(5, &webview_instance_id));
220890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2209e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  base::WeakPtr<extensions::ExtensionMessageFilter> ipc_sender =
2210e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      ipc_sender_weak();
221190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int embedder_process_id =
221290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      ipc_sender.get() ? ipc_sender->render_process_id() : -1;
221390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Extension* extension =
22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_info_map()->extensions().GetByID(extension_id());
22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string extension_name = extension ? extension->name() : extension_id();
22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool is_web_view_guest = webview_instance_id != 0;
22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We check automatically whether the extension has the 'webRequest'
22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // permission. For blocking calls we require the additional permission
22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 'webRequestBlocking'.
222246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if ((!is_web_view_guest &&
222346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       extra_info_spec &
222446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)           (ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING |
222546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING)) &&
222646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      !extension->permissions_data()->HasAPIPermission(
222746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          extensions::APIPermission::kWebRequestBlocking)) {
22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = keys::kBlockingPermissionRequired;
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We allow to subscribe to patterns that are broader than the host
22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // permissions. E.g., we could subscribe to http://www.example.com/*
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // while having host permissions for http://www.example.com/foo/* and
22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://www.example.com/bar/*.
22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For this reason we do only a coarse check here to warn the extension
22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // developer if he does something obviously wrong.
2238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!is_web_view_guest &&
223946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      extension->permissions_data()->GetEffectiveHostPermissions().is_empty()) {
22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = keys::kHostPermissionsRequired;
22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success =
22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          profile_id(), extension_id(), extension_name,
224790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          event_name, sub_event_name, filter, extra_info_spec,
2248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          embedder_process_id, webview_instance_id, ipc_sender_weak());
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(success);
22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helpers::ClearCacheOnNavigation();
22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  BrowserThread::PostTask(BrowserThread::UI,
22545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          FROM_HERE,
22555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          base::Bind(&helpers::NotifyWebRequestAPIUsed,
22565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     profile_id(),
22575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     make_scoped_refptr(extension)));
22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2262a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid WebRequestInternalEventHandledFunction::RespondWithError(
2263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string& event_name,
2264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string& sub_event_name,
2265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    uint64 request_id,
2266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_ptr<ExtensionWebRequestEventRouter::EventResponse> response,
2267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string& error) {
2268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  error_ = error;
2269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled(
2270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      profile_id(),
2271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      extension_id(),
2272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      event_name,
2273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      sub_event_name,
2274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      request_id,
2275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      response.release());
2276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
2277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
22785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool WebRequestInternalEventHandledFunction::RunSync() {
22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string event_name;
22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &event_name));
22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string sub_event_name;
22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &sub_event_name));
22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string request_id_str;
22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &request_id_str));
22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64 request_id;
22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(base::StringToUint64(request_id_str,
22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   &request_id));
22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ExtensionWebRequestEventRouter::EventResponse> response;
22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasOptionalArgument(3)) {
22935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* value = NULL;
22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(3, &value));
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!value->empty()) {
22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time install_time =
22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          extension_info_map()->GetInstallTime(extension_id());
22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response.reset(new ExtensionWebRequestEventRouter::EventResponse(
23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          extension_id(), install_time));
23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (value->HasKey("cancel")) {
23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Don't allow cancel mixed with other keys.
2305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (value->size() != 1) {
2306effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        RespondWithError(event_name,
2307effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         sub_event_name,
2308effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         request_id,
2309effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         response.Pass(),
2310effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         keys::kInvalidBlockingResponse);
23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool cancel = false;
23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXTENSION_FUNCTION_VALIDATE(value->GetBoolean("cancel", &cancel));
23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response->cancel = cancel;
23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (value->HasKey("redirectUrl")) {
23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string new_url_str;
23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXTENSION_FUNCTION_VALIDATE(value->GetString("redirectUrl",
23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   &new_url_str));
23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response->new_url = GURL(new_url_str);
23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!response->new_url.is_valid()) {
2325effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        RespondWithError(event_name,
2326effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         sub_event_name,
2327effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         request_id,
2328effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         response.Pass(),
2329effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         ErrorUtils::FormatErrorMessage(
2330effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                             keys::kInvalidRedirectUrl, new_url_str));
23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const bool hasRequestHeaders = value->HasKey("requestHeaders");
2336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const bool hasResponseHeaders = value->HasKey("responseHeaders");
2337a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (hasRequestHeaders || hasResponseHeaders) {
2338a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (hasRequestHeaders && hasResponseHeaders) {
2339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // Allow only one of the keys, not both.
2340effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        RespondWithError(event_name,
2341effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         sub_event_name,
2342effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         request_id,
2343effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         response.Pass(),
2344effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                         keys::kInvalidHeaderKeyCombination);
2345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        return false;
2346a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
2347a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2348a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::ListValue* headers_value = NULL;
2349effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      scoped_ptr<net::HttpRequestHeaders> request_headers;
2350effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      scoped_ptr<helpers::ResponseHeaders> response_headers;
2351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (hasRequestHeaders) {
2352effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        request_headers.reset(new net::HttpRequestHeaders());
2353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        EXTENSION_FUNCTION_VALIDATE(value->GetList(keys::kRequestHeadersKey,
2354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                   &headers_value));
2355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      } else {
2356effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        response_headers.reset(new helpers::ResponseHeaders());
2357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        EXTENSION_FUNCTION_VALIDATE(value->GetList(keys::kResponseHeadersKey,
2358a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                   &headers_value));
23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      for (size_t i = 0; i < headers_value->GetSize(); ++i) {
23625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::DictionaryValue* header_value = NULL;
23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string name;
23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string value;
23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXTENSION_FUNCTION_VALIDATE(
2366a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            headers_value->GetDictionary(i, &header_value));
2367a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        if (!FromHeaderDictionary(header_value, &name, &value)) {
2368a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          std::string serialized_header;
2369a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          base::JSONWriter::Write(header_value, &serialized_header);
2370effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          RespondWithError(event_name,
2371effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                           sub_event_name,
2372effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                           request_id,
2373effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                           response.Pass(),
2374effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                           ErrorUtils::FormatErrorMessage(keys::kInvalidHeader,
2375effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                                          serialized_header));
2376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          return false;
2377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        }
23781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (!net::HttpUtil::IsValidHeaderName(name)) {
2379effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          RespondWithError(event_name,
2380effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                           sub_event_name,
2381effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                           request_id,
2382effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                           response.Pass(),
2383effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                           keys::kInvalidHeaderName);
2384a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          return false;
2385a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        }
23861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if (!net::HttpUtil::IsValidHeaderValue(value)) {
2387effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          RespondWithError(event_name,
2388effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                           sub_event_name,
2389effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                           request_id,
2390effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                           response.Pass(),
2391effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                           ErrorUtils::FormatErrorMessage(
2392effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                               keys::kInvalidHeaderValue, name));
2393a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          return false;
2394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        }
2395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        if (hasRequestHeaders)
2396effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          request_headers->SetHeader(name, value);
2397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        else
2398effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          response_headers->push_back(helpers::ResponseHeader(name, value));
23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2400effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (hasRequestHeaders)
2401effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        response->request_headers.reset(request_headers.release());
2402effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      else
2403effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        response->response_headers.reset(response_headers.release());
24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (value->HasKey(keys::kAuthCredentialsKey)) {
24075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::DictionaryValue* credentials_value = NULL;
24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXTENSION_FUNCTION_VALIDATE(value->GetDictionary(
24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          keys::kAuthCredentialsKey,
24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &credentials_value));
2411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::string16 username;
2412a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::string16 password;
24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXTENSION_FUNCTION_VALIDATE(
24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          credentials_value->GetString(keys::kUsernameKey, &username));
24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXTENSION_FUNCTION_VALIDATE(
24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          credentials_value->GetString(keys::kPasswordKey, &password));
24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response->auth_credentials.reset(
24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new net::AuthCredentials(username, password));
24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled(
24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_id(), extension_id(), event_name, sub_event_name, request_id,
24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response.release());
24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRequestHandlerBehaviorChangedFunction::GetQuotaLimitHeuristics(
2430f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    extensions::QuotaLimitHeuristics* heuristics) const {
2431f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  extensions::QuotaLimitHeuristic::Config config = {
2432f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // See web_request.json for current value.
2433f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      web_request::MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES,
2434f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::TimeDelta::FromMinutes(10)};
2435f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  extensions::QuotaLimitHeuristic::BucketMapper* bucket_mapper =
2436f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new extensions::QuotaLimitHeuristic::SingletonBucketMapper();
24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearCacheQuotaHeuristic* heuristic =
24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ClearCacheQuotaHeuristic(config, bucket_mapper);
24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  heuristics->push_back(heuristic);
24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRequestHandlerBehaviorChangedFunction::OnQuotaExceeded(
24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& violation_error) {
24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Post warning message.
24451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  WarningSet warnings;
24462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  warnings.insert(
24471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      Warning::CreateRepeatedCacheFlushesWarning(extension_id()));
24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::UI,
24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
24511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&WarningService::NotifyWarningsOnUI, profile_id(), warnings));
24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Continue gracefully.
2454010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RunSync();
24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool WebRequestHandlerBehaviorChangedFunction::RunSync() {
24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helpers::ClearCacheOnNavigation();
24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2461