Home | History | Annotate | Download | only in web_request
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "extensions/browser/api/web_request/web_request_api.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/bind.h"
     10 #include "base/bind_helpers.h"
     11 #include "base/json/json_writer.h"
     12 #include "base/lazy_instance.h"
     13 #include "base/metrics/histogram.h"
     14 #include "base/strings/string_number_conversions.h"
     15 #include "base/strings/string_util.h"
     16 #include "base/strings/utf_string_conversions.h"
     17 #include "base/time/time.h"
     18 #include "base/values.h"
     19 #include "content/public/browser/browser_message_filter.h"
     20 #include "content/public/browser/browser_thread.h"
     21 #include "content/public/browser/render_frame_host.h"
     22 #include "content/public/browser/render_process_host.h"
     23 #include "content/public/browser/resource_request_info.h"
     24 #include "content/public/browser/user_metrics.h"
     25 #include "extensions/browser/api/activity_log/web_request_constants.h"
     26 #include "extensions/browser/api/declarative_webrequest/request_stage.h"
     27 #include "extensions/browser/api/declarative_webrequest/webrequest_constants.h"
     28 #include "extensions/browser/api/declarative_webrequest/webrequest_rules_registry.h"
     29 #include "extensions/browser/api/extensions_api_client.h"
     30 #include "extensions/browser/api/web_request/upload_data_presenter.h"
     31 #include "extensions/browser/api/web_request/web_request_api_constants.h"
     32 #include "extensions/browser/api/web_request/web_request_api_helpers.h"
     33 #include "extensions/browser/api/web_request/web_request_event_router_delegate.h"
     34 #include "extensions/browser/api/web_request/web_request_time_tracker.h"
     35 #include "extensions/browser/event_router.h"
     36 #include "extensions/browser/extension_message_filter.h"
     37 #include "extensions/browser/extension_prefs.h"
     38 #include "extensions/browser/extension_registry.h"
     39 #include "extensions/browser/extension_system.h"
     40 #include "extensions/browser/extensions_browser_client.h"
     41 #include "extensions/browser/guest_view/web_view/web_view_constants.h"
     42 #include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
     43 #include "extensions/browser/info_map.h"
     44 #include "extensions/browser/runtime_data.h"
     45 #include "extensions/browser/warning_service.h"
     46 #include "extensions/browser/warning_set.h"
     47 #include "extensions/common/api/web_request.h"
     48 #include "extensions/common/error_utils.h"
     49 #include "extensions/common/event_filtering_info.h"
     50 #include "extensions/common/extension.h"
     51 #include "extensions/common/features/feature.h"
     52 #include "extensions/common/permissions/permissions_data.h"
     53 #include "extensions/common/url_pattern.h"
     54 #include "extensions/strings/grit/extensions_strings.h"
     55 #include "net/base/auth.h"
     56 #include "net/base/net_errors.h"
     57 #include "net/base/upload_data_stream.h"
     58 #include "net/http/http_response_headers.h"
     59 #include "net/http/http_util.h"
     60 #include "net/url_request/url_request.h"
     61 #include "ui/base/l10n/l10n_util.h"
     62 #include "url/gurl.h"
     63 
     64 using base::DictionaryValue;
     65 using base::ListValue;
     66 using base::StringValue;
     67 using content::BrowserMessageFilter;
     68 using content::BrowserThread;
     69 using content::ResourceRequestInfo;
     70 using content::ResourceType;
     71 using extensions::ErrorUtils;
     72 using extensions::Extension;
     73 using extensions::InfoMap;
     74 using extensions::Feature;
     75 using extensions::RulesRegistryService;
     76 using extensions::Warning;
     77 using extensions::WarningService;
     78 using extensions::WarningSet;
     79 
     80 namespace activitylog = activity_log_web_request_constants;
     81 namespace helpers = extension_web_request_api_helpers;
     82 namespace keys = extension_web_request_api_constants;
     83 namespace web_request = extensions::core_api::web_request;
     84 namespace declarative_keys = extensions::declarative_webrequest_constants;
     85 
     86 namespace {
     87 
     88 const char kWebRequestEventPrefix[] = "webRequest.";
     89 
     90 // List of all the webRequest events.
     91 const char* const kWebRequestEvents[] = {
     92   keys::kOnBeforeRedirectEvent,
     93   web_request::OnBeforeRequest::kEventName,
     94   keys::kOnBeforeSendHeadersEvent,
     95   keys::kOnCompletedEvent,
     96   web_request::OnErrorOccurred::kEventName,
     97   keys::kOnSendHeadersEvent,
     98   keys::kOnAuthRequiredEvent,
     99   keys::kOnResponseStartedEvent,
    100   keys::kOnHeadersReceivedEvent,
    101 };
    102 
    103 const size_t kWebRequestEventsLength = arraysize(kWebRequestEvents);
    104 
    105 const char* GetRequestStageAsString(
    106     ExtensionWebRequestEventRouter::EventTypes type) {
    107   switch (type) {
    108     case ExtensionWebRequestEventRouter::kInvalidEvent:
    109       return "Invalid";
    110     case ExtensionWebRequestEventRouter::kOnBeforeRequest:
    111       return keys::kOnBeforeRequest;
    112     case ExtensionWebRequestEventRouter::kOnBeforeSendHeaders:
    113       return keys::kOnBeforeSendHeaders;
    114     case ExtensionWebRequestEventRouter::kOnSendHeaders:
    115       return keys::kOnSendHeaders;
    116     case ExtensionWebRequestEventRouter::kOnHeadersReceived:
    117       return keys::kOnHeadersReceived;
    118     case ExtensionWebRequestEventRouter::kOnBeforeRedirect:
    119       return keys::kOnBeforeRedirect;
    120     case ExtensionWebRequestEventRouter::kOnAuthRequired:
    121       return keys::kOnAuthRequired;
    122     case ExtensionWebRequestEventRouter::kOnResponseStarted:
    123       return keys::kOnResponseStarted;
    124     case ExtensionWebRequestEventRouter::kOnErrorOccurred:
    125       return keys::kOnErrorOccurred;
    126     case ExtensionWebRequestEventRouter::kOnCompleted:
    127       return keys::kOnCompleted;
    128   }
    129   NOTREACHED();
    130   return "Not reached";
    131 }
    132 
    133 int GetFrameId(bool is_main_frame, int frame_id) {
    134   return is_main_frame ? 0 : frame_id;
    135 }
    136 
    137 bool IsWebRequestEvent(const std::string& event_name) {
    138   std::string web_request_event_name(event_name);
    139   if (StartsWithASCII(
    140           web_request_event_name, webview::kWebViewEventPrefix, true)) {
    141     web_request_event_name.replace(
    142         0, strlen(webview::kWebViewEventPrefix), kWebRequestEventPrefix);
    143   }
    144   return std::find(
    145       kWebRequestEvents,
    146       kWebRequestEvents + kWebRequestEventsLength,
    147       web_request_event_name) != (kWebRequestEvents + kWebRequestEventsLength);
    148 }
    149 
    150 // Returns whether |request| has been triggered by an extension in
    151 // |extension_info_map|.
    152 bool IsRequestFromExtension(const net::URLRequest* request,
    153                             const InfoMap* extension_info_map) {
    154   // |extension_info_map| is NULL for system-level requests.
    155   if (!extension_info_map)
    156     return false;
    157 
    158   const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
    159 
    160   // If this request was not created by the ResourceDispatcher, |info| is NULL.
    161   // All requests from extensions are created by the ResourceDispatcher.
    162   if (!info)
    163     return false;
    164 
    165   return extension_info_map->process_map().Contains(info->GetChildID());
    166 }
    167 
    168 void ExtractRequestRoutingInfo(net::URLRequest* request,
    169                                int* render_process_host_id,
    170                                int* routing_id) {
    171   if (!request->GetUserData(NULL))
    172     return;
    173   const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
    174   *render_process_host_id = info->GetChildID();
    175   *routing_id = info->GetRouteID();
    176 }
    177 
    178 // Given a |request|, this function determines whether it originated from
    179 // a <webview> guest process or not. If it is from a <webview> guest process,
    180 // then |web_view_info| is returned with information about the instance ID
    181 // that uniquely identifies the <webview> and its embedder.
    182 bool GetWebViewInfo(
    183     net::URLRequest* request,
    184     extensions::WebViewRendererState::WebViewInfo* web_view_info) {
    185   int render_process_host_id = -1;
    186   int routing_id = -1;
    187   ExtractRequestRoutingInfo(request, &render_process_host_id, &routing_id);
    188   return extensions::WebViewRendererState::GetInstance()->
    189       GetInfo(render_process_host_id, routing_id, web_view_info);
    190 }
    191 
    192 void ExtractRequestInfoDetails(net::URLRequest* request,
    193                                bool* is_main_frame,
    194                                int* frame_id,
    195                                bool* parent_is_main_frame,
    196                                int* parent_frame_id,
    197                                int* render_process_host_id,
    198                                int* routing_id,
    199                                ResourceType* resource_type) {
    200   if (!request->GetUserData(NULL))
    201     return;
    202 
    203   const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
    204   *frame_id = info->GetRenderFrameID();
    205   *is_main_frame = info->IsMainFrame();
    206   *parent_frame_id = info->GetParentRenderFrameID();
    207   *parent_is_main_frame = info->ParentIsMainFrame();
    208   *render_process_host_id = info->GetChildID();
    209   *routing_id = info->GetRouteID();
    210 
    211   // Restrict the resource type to the values we care about.
    212   if (helpers::IsRelevantResourceType(info->GetResourceType()))
    213     *resource_type = info->GetResourceType();
    214   else
    215     *resource_type = content::RESOURCE_TYPE_LAST_TYPE;
    216 }
    217 
    218 // Extracts the body from |request| and writes the data into |out|.
    219 void ExtractRequestInfoBody(const net::URLRequest* request,
    220                             base::DictionaryValue* out) {
    221   const net::UploadDataStream* upload_data = request->get_upload();
    222   if (!upload_data ||
    223       (request->method() != "POST" && request->method() != "PUT"))
    224     return;  // Need to exit without "out->Set(keys::kRequestBodyKey, ...);" .
    225 
    226   base::DictionaryValue* requestBody = new base::DictionaryValue();
    227   out->Set(keys::kRequestBodyKey, requestBody);
    228 
    229   // Get the data presenters, ordered by how specific they are.
    230   extensions::ParsedDataPresenter parsed_data_presenter(*request);
    231   extensions::RawDataPresenter raw_data_presenter;
    232   extensions::UploadDataPresenter* const presenters[] = {
    233     &parsed_data_presenter,    // 1: any parseable forms? (Specific to forms.)
    234     &raw_data_presenter        // 2: any data at all? (Non-specific.)
    235   };
    236   // Keys for the results of the corresponding presenters.
    237   static const char* const kKeys[] = {
    238     keys::kRequestBodyFormDataKey,
    239     keys::kRequestBodyRawKey
    240   };
    241 
    242   const ScopedVector<net::UploadElementReader>& readers =
    243       upload_data->element_readers();
    244   bool some_succeeded = false;
    245   for (size_t i = 0; !some_succeeded && i < arraysize(presenters); ++i) {
    246     ScopedVector<net::UploadElementReader>::const_iterator reader;
    247     for (reader = readers.begin(); reader != readers.end(); ++reader)
    248       presenters[i]->FeedNext(**reader);
    249     if (presenters[i]->Succeeded()) {
    250       requestBody->Set(kKeys[i], presenters[i]->Result().release());
    251       some_succeeded = true;
    252     }
    253   }
    254   if (!some_succeeded)
    255     requestBody->SetString(keys::kRequestBodyErrorKey, "Unknown error.");
    256 }
    257 
    258 // Converts a HttpHeaders dictionary to a |name|, |value| pair. Returns
    259 // true if successful.
    260 bool FromHeaderDictionary(const base::DictionaryValue* header_value,
    261                           std::string* name,
    262                           std::string* value) {
    263   if (!header_value->GetString(keys::kHeaderNameKey, name))
    264     return false;
    265 
    266   // We require either a "value" or a "binaryValue" entry.
    267   if (!(header_value->HasKey(keys::kHeaderValueKey) ^
    268         header_value->HasKey(keys::kHeaderBinaryValueKey)))
    269     return false;
    270 
    271   if (header_value->HasKey(keys::kHeaderValueKey)) {
    272     if (!header_value->GetString(keys::kHeaderValueKey, value)) {
    273       return false;
    274     }
    275   } else if (header_value->HasKey(keys::kHeaderBinaryValueKey)) {
    276     const base::ListValue* list = NULL;
    277     if (!header_value->HasKey(keys::kHeaderBinaryValueKey)) {
    278       *value = "";
    279     } else if (!header_value->GetList(keys::kHeaderBinaryValueKey, &list) ||
    280                !helpers::CharListToString(list, value)) {
    281       return false;
    282     }
    283   }
    284   return true;
    285 }
    286 
    287 // Creates a list of HttpHeaders (see the extension API JSON). If |headers| is
    288 // NULL, the list is empty. Ownership is passed to the caller.
    289 base::ListValue* GetResponseHeadersList(
    290     const net::HttpResponseHeaders* headers) {
    291   base::ListValue* headers_value = new base::ListValue();
    292   if (headers) {
    293     void* iter = NULL;
    294     std::string name;
    295     std::string value;
    296     while (headers->EnumerateHeaderLines(&iter, &name, &value))
    297       headers_value->Append(helpers::CreateHeaderDictionary(name, value));
    298   }
    299   return headers_value;
    300 }
    301 
    302 base::ListValue* GetRequestHeadersList(const net::HttpRequestHeaders& headers) {
    303   base::ListValue* headers_value = new base::ListValue();
    304   for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext(); )
    305     headers_value->Append(
    306         helpers::CreateHeaderDictionary(it.name(), it.value()));
    307   return headers_value;
    308 }
    309 
    310 // Creates a base::StringValue with the status line of |headers|. If |headers|
    311 // is NULL, an empty string is returned.  Ownership is passed to the caller.
    312 base::StringValue* GetStatusLine(net::HttpResponseHeaders* headers) {
    313   return new base::StringValue(
    314       headers ? headers->GetStatusLine() : std::string());
    315 }
    316 
    317 void RemoveEventListenerOnUI(
    318   void* browser_context_id,
    319   const std::string& event_name,
    320   int process_id,
    321   const std::string& extension_id) {
    322   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    323 
    324   content::BrowserContext* browser_context =
    325       reinterpret_cast<content::BrowserContext*>(browser_context_id);
    326   if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext(
    327       browser_context))
    328     return;
    329 
    330   extensions::EventRouter* event_router =
    331       extensions::EventRouter::Get(browser_context);
    332   if (!event_router)
    333     return;
    334 
    335   content::RenderProcessHost* process =
    336       content::RenderProcessHost::FromID(process_id);
    337   if (!process)
    338     return;
    339 
    340   event_router->RemoveEventListener(event_name, process, extension_id);
    341 }
    342 
    343 // Sends an event to subscribers of chrome.declarativeWebRequest.onMessage or
    344 // to subscribers of webview.onMessage if the action is being operated upon
    345 // a <webview> guest renderer.
    346 // |extension_id| identifies the extension that sends and receives the event.
    347 // |is_web_view_guest| indicates whether the action is for a <webview>.
    348 // |web_view_info| is a struct containing information about the <webview>
    349 // embedder.
    350 // |event_argument| is passed to the event listener.
    351 void SendOnMessageEventOnUI(
    352     void* browser_context_id,
    353     const std::string& extension_id,
    354     bool is_web_view_guest,
    355     const extensions::WebViewRendererState::WebViewInfo& web_view_info,
    356     scoped_ptr<base::DictionaryValue> event_argument) {
    357   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    358 
    359   content::BrowserContext* browser_context =
    360       reinterpret_cast<content::BrowserContext*>(browser_context_id);
    361   if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext(
    362       browser_context))
    363     return;
    364 
    365   scoped_ptr<base::ListValue> event_args(new base::ListValue);
    366   event_args->Append(event_argument.release());
    367 
    368   extensions::EventRouter* event_router =
    369       extensions::EventRouter::Get(browser_context);
    370 
    371   extensions::EventFilteringInfo event_filtering_info;
    372 
    373   std::string event_name;
    374   // The instance ID uniquely identifies a <webview> instance within an embedder
    375   // process. We use a filter here so that only event listeners for a particular
    376   // <webview> will fire.
    377   if (is_web_view_guest) {
    378     event_filtering_info.SetInstanceID(web_view_info.instance_id);
    379     event_name = webview::kEventMessage;
    380   } else {
    381     event_name = declarative_keys::kOnMessage;
    382   }
    383 
    384   scoped_ptr<extensions::Event> event(new extensions::Event(
    385       event_name,
    386       event_args.Pass(), browser_context, GURL(),
    387       extensions::EventRouter::USER_GESTURE_UNKNOWN,
    388       event_filtering_info));
    389   event_router->DispatchEventToExtension(extension_id, event.Pass());
    390 }
    391 
    392 void RemoveEventListenerOnIOThread(
    393     content::BrowserContext* browser_context,
    394     const std::string& extension_id,
    395     const std::string& sub_event_name) {
    396   ExtensionWebRequestEventRouter::GetInstance()->RemoveEventListener(
    397       browser_context, extension_id, sub_event_name);
    398 }
    399 
    400 }  // namespace
    401 
    402 namespace extensions {
    403 
    404 WebRequestAPI::WebRequestAPI(content::BrowserContext* context)
    405     : browser_context_(context) {
    406   EventRouter* event_router = EventRouter::Get(browser_context_);
    407   for (size_t i = 0; i < arraysize(kWebRequestEvents); ++i) {
    408     // Observe the webRequest event.
    409     std::string event_name = kWebRequestEvents[i];
    410     event_router->RegisterObserver(this, event_name);
    411 
    412     // Also observe the corresponding webview event.
    413     event_name.replace(
    414         0, sizeof(kWebRequestEventPrefix) - 1, webview::kWebViewEventPrefix);
    415     event_router->RegisterObserver(this, event_name);
    416   }
    417 }
    418 
    419 WebRequestAPI::~WebRequestAPI() {
    420   EventRouter::Get(browser_context_)->UnregisterObserver(this);
    421 }
    422 
    423 static base::LazyInstance<BrowserContextKeyedAPIFactory<WebRequestAPI> >
    424     g_factory = LAZY_INSTANCE_INITIALIZER;
    425 
    426 // static
    427 BrowserContextKeyedAPIFactory<WebRequestAPI>*
    428 WebRequestAPI::GetFactoryInstance() {
    429   return g_factory.Pointer();
    430 }
    431 
    432 void WebRequestAPI::OnListenerRemoved(const EventListenerInfo& details) {
    433   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    434   // Note that details.event_name includes the sub-event details (e.g. "/123").
    435   BrowserThread::PostTask(BrowserThread::IO,
    436                           FROM_HERE,
    437                           base::Bind(&RemoveEventListenerOnIOThread,
    438                                      details.browser_context,
    439                                      details.extension_id,
    440                                      details.event_name));
    441 }
    442 
    443 }  // namespace extensions
    444 
    445 // Represents a single unique listener to an event, along with whatever filter
    446 // parameters and extra_info_spec were specified at the time the listener was
    447 // added.
    448 // NOTE(benjhayden) New APIs should not use this sub_event_name trick! It does
    449 // not play well with event pages. See downloads.onDeterminingFilename and
    450 // ExtensionDownloadsEventRouter for an alternative approach.
    451 struct ExtensionWebRequestEventRouter::EventListener {
    452   std::string extension_id;
    453   std::string extension_name;
    454   std::string sub_event_name;
    455   RequestFilter filter;
    456   int extra_info_spec;
    457   int embedder_process_id;
    458   int webview_instance_id;
    459   base::WeakPtr<IPC::Sender> ipc_sender;
    460   mutable std::set<uint64> blocked_requests;
    461 
    462   // Comparator to work with std::set.
    463   bool operator<(const EventListener& that) const {
    464     if (extension_id < that.extension_id)
    465       return true;
    466     if (extension_id == that.extension_id &&
    467         sub_event_name < that.sub_event_name)
    468       return true;
    469     return false;
    470   }
    471 
    472   EventListener() : extra_info_spec(0) {}
    473 };
    474 
    475 // Contains info about requests that are blocked waiting for a response from
    476 // an extension.
    477 struct ExtensionWebRequestEventRouter::BlockedRequest {
    478   // The request that is being blocked.
    479   net::URLRequest* request;
    480 
    481   // Whether the request originates from an incognito tab.
    482   bool is_incognito;
    483 
    484   // The event that we're currently blocked on.
    485   EventTypes event;
    486 
    487   // The number of event handlers that we are awaiting a response from.
    488   int num_handlers_blocking;
    489 
    490   // Pointer to NetLog to report significant changes to the request for
    491   // debugging.
    492   const net::BoundNetLog* net_log;
    493 
    494   // The callback to call when we get a response from all event handlers.
    495   net::CompletionCallback callback;
    496 
    497   // If non-empty, this contains the new URL that the request will redirect to.
    498   // Only valid for OnBeforeRequest and OnHeadersReceived.
    499   GURL* new_url;
    500 
    501   // The request headers that will be issued along with this request. Only valid
    502   // for OnBeforeSendHeaders.
    503   net::HttpRequestHeaders* request_headers;
    504 
    505   // The response headers that were received from the server. Only valid for
    506   // OnHeadersReceived.
    507   scoped_refptr<const net::HttpResponseHeaders> original_response_headers;
    508 
    509   // Location where to override response headers. Only valid for
    510   // OnHeadersReceived.
    511   scoped_refptr<net::HttpResponseHeaders>* override_response_headers;
    512 
    513   // If non-empty, this contains the auth credentials that may be filled in.
    514   // Only valid for OnAuthRequired.
    515   net::AuthCredentials* auth_credentials;
    516 
    517   // The callback to invoke for auth. If |auth_callback.is_null()| is false,
    518   // |callback| must be NULL.
    519   // Only valid for OnAuthRequired.
    520   net::NetworkDelegate::AuthCallback auth_callback;
    521 
    522   // Time the request was paused. Used for logging purposes.
    523   base::Time blocking_time;
    524 
    525   // Changes requested by extensions.
    526   helpers::EventResponseDeltas response_deltas;
    527 
    528   // Provider of meta data about extensions, only used and non-NULL for events
    529   // that are delayed until the rules registry is ready.
    530   InfoMap* extension_info_map;
    531 
    532   BlockedRequest()
    533       : request(NULL),
    534         is_incognito(false),
    535         event(kInvalidEvent),
    536         num_handlers_blocking(0),
    537         net_log(NULL),
    538         new_url(NULL),
    539         request_headers(NULL),
    540         override_response_headers(NULL),
    541         auth_credentials(NULL),
    542         extension_info_map(NULL) {}
    543 };
    544 
    545 bool ExtensionWebRequestEventRouter::RequestFilter::InitFromValue(
    546     const base::DictionaryValue& value, std::string* error) {
    547   if (!value.HasKey("urls"))
    548     return false;
    549 
    550   for (base::DictionaryValue::Iterator it(value); !it.IsAtEnd(); it.Advance()) {
    551     if (it.key() == "urls") {
    552       const base::ListValue* urls_value = NULL;
    553       if (!it.value().GetAsList(&urls_value))
    554         return false;
    555       for (size_t i = 0; i < urls_value->GetSize(); ++i) {
    556         std::string url;
    557         URLPattern pattern(
    558             URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS |
    559             URLPattern::SCHEME_FTP | URLPattern::SCHEME_FILE |
    560             URLPattern::SCHEME_EXTENSION);
    561         if (!urls_value->GetString(i, &url) ||
    562             pattern.Parse(url) != URLPattern::PARSE_SUCCESS) {
    563           *error = ErrorUtils::FormatErrorMessage(
    564               keys::kInvalidRequestFilterUrl, url);
    565           return false;
    566         }
    567         urls.AddPattern(pattern);
    568       }
    569     } else if (it.key() == "types") {
    570       const base::ListValue* types_value = NULL;
    571       if (!it.value().GetAsList(&types_value))
    572         return false;
    573       for (size_t i = 0; i < types_value->GetSize(); ++i) {
    574         std::string type_str;
    575         ResourceType type;
    576         if (!types_value->GetString(i, &type_str) ||
    577             !helpers::ParseResourceType(type_str, &type))
    578           return false;
    579         types.push_back(type);
    580       }
    581     } else if (it.key() == "tabId") {
    582       if (!it.value().GetAsInteger(&tab_id))
    583         return false;
    584     } else if (it.key() == "windowId") {
    585       if (!it.value().GetAsInteger(&window_id))
    586         return false;
    587     } else {
    588       return false;
    589     }
    590   }
    591   return true;
    592 }
    593 
    594 // static
    595 bool ExtensionWebRequestEventRouter::ExtraInfoSpec::InitFromValue(
    596     const base::ListValue& value, int* extra_info_spec) {
    597   *extra_info_spec = 0;
    598   for (size_t i = 0; i < value.GetSize(); ++i) {
    599     std::string str;
    600     if (!value.GetString(i, &str))
    601       return false;
    602 
    603     if (str == "requestHeaders")
    604       *extra_info_spec |= REQUEST_HEADERS;
    605     else if (str == "responseHeaders")
    606       *extra_info_spec |= RESPONSE_HEADERS;
    607     else if (str == "blocking")
    608       *extra_info_spec |= BLOCKING;
    609     else if (str == "asyncBlocking")
    610       *extra_info_spec |= ASYNC_BLOCKING;
    611     else if (str == "requestBody")
    612       *extra_info_spec |= REQUEST_BODY;
    613     else
    614       return false;
    615 
    616     // BLOCKING and ASYNC_BLOCKING are mutually exclusive.
    617     if ((*extra_info_spec & BLOCKING) && (*extra_info_spec & ASYNC_BLOCKING))
    618       return false;
    619   }
    620   return true;
    621 }
    622 
    623 
    624 ExtensionWebRequestEventRouter::EventResponse::EventResponse(
    625     const std::string& extension_id, const base::Time& extension_install_time)
    626     : extension_id(extension_id),
    627       extension_install_time(extension_install_time),
    628       cancel(false) {
    629 }
    630 
    631 ExtensionWebRequestEventRouter::EventResponse::~EventResponse() {
    632 }
    633 
    634 ExtensionWebRequestEventRouter::RequestFilter::RequestFilter()
    635     : tab_id(-1), window_id(-1) {
    636 }
    637 
    638 ExtensionWebRequestEventRouter::RequestFilter::~RequestFilter() {
    639 }
    640 
    641 //
    642 // ExtensionWebRequestEventRouter
    643 //
    644 
    645 // static
    646 ExtensionWebRequestEventRouter* ExtensionWebRequestEventRouter::GetInstance() {
    647   return Singleton<ExtensionWebRequestEventRouter>::get();
    648 }
    649 
    650 ExtensionWebRequestEventRouter::ExtensionWebRequestEventRouter()
    651     : request_time_tracker_(new ExtensionWebRequestTimeTracker) {
    652   web_request_event_router_delegate_.reset(
    653       extensions::ExtensionsAPIClient::Get()->
    654           CreateWebRequestEventRouterDelegate());
    655 }
    656 
    657 ExtensionWebRequestEventRouter::~ExtensionWebRequestEventRouter() {
    658 }
    659 
    660 void ExtensionWebRequestEventRouter::RegisterRulesRegistry(
    661     void* browser_context,
    662     const extensions::RulesRegistry::WebViewKey& webview_key,
    663     scoped_refptr<extensions::WebRequestRulesRegistry> rules_registry) {
    664   RulesRegistryKey key(browser_context, webview_key);
    665   if (rules_registry.get())
    666     rules_registries_[key] = rules_registry;
    667   else
    668     rules_registries_.erase(key);
    669 }
    670 
    671 void ExtensionWebRequestEventRouter::ExtractRequestInfo(
    672     net::URLRequest* request, base::DictionaryValue* out) {
    673   bool is_main_frame = false;
    674   int frame_id = -1;
    675   bool parent_is_main_frame = false;
    676   int parent_frame_id = -1;
    677   int frame_id_for_extension = -1;
    678   int parent_frame_id_for_extension = -1;
    679   int render_process_host_id = -1;
    680   int routing_id = -1;
    681   ResourceType resource_type = content::RESOURCE_TYPE_LAST_TYPE;
    682   ExtractRequestInfoDetails(request, &is_main_frame, &frame_id,
    683                             &parent_is_main_frame, &parent_frame_id,
    684                             &render_process_host_id, &routing_id,
    685                             &resource_type);
    686   frame_id_for_extension = GetFrameId(is_main_frame, frame_id);
    687   parent_frame_id_for_extension = GetFrameId(parent_is_main_frame,
    688                                              parent_frame_id);
    689 
    690   out->SetString(keys::kRequestIdKey,
    691                  base::Uint64ToString(request->identifier()));
    692   out->SetString(keys::kUrlKey, request->url().spec());
    693   out->SetString(keys::kMethodKey, request->method());
    694   out->SetInteger(keys::kFrameIdKey, frame_id_for_extension);
    695   out->SetInteger(keys::kParentFrameIdKey, parent_frame_id_for_extension);
    696   out->SetString(keys::kTypeKey, helpers::ResourceTypeToString(resource_type));
    697   out->SetDouble(keys::kTimeStampKey, base::Time::Now().ToDoubleT() * 1000);
    698   if (web_request_event_router_delegate_) {
    699     web_request_event_router_delegate_->ExtractExtraRequestDetails(
    700         request, out);
    701   }
    702 }
    703 
    704 int ExtensionWebRequestEventRouter::OnBeforeRequest(
    705     void* browser_context,
    706     InfoMap* extension_info_map,
    707     net::URLRequest* request,
    708     const net::CompletionCallback& callback,
    709     GURL* new_url) {
    710   // We hide events from the system context as well as sensitive requests.
    711   if (!browser_context ||
    712       WebRequestPermissions::HideRequest(extension_info_map, request))
    713     return net::OK;
    714 
    715   if (IsPageLoad(request))
    716     NotifyPageLoad();
    717 
    718   request_time_tracker_->LogRequestStartTime(request->identifier(),
    719                                              base::Time::Now(),
    720                                              request->url(),
    721                                              browser_context);
    722 
    723   // Whether to initialized blocked_requests_.
    724   bool initialize_blocked_requests = false;
    725 
    726   initialize_blocked_requests |=
    727       ProcessDeclarativeRules(browser_context, extension_info_map,
    728                               web_request::OnBeforeRequest::kEventName, request,
    729                               extensions::ON_BEFORE_REQUEST, NULL);
    730 
    731   int extra_info_spec = 0;
    732   std::vector<const EventListener*> listeners =
    733       GetMatchingListeners(browser_context, extension_info_map,
    734                            web_request::OnBeforeRequest::kEventName, request,
    735                            &extra_info_spec);
    736   if (!listeners.empty() &&
    737       !GetAndSetSignaled(request->identifier(), kOnBeforeRequest)) {
    738     base::ListValue args;
    739     base::DictionaryValue* dict = new base::DictionaryValue();
    740     ExtractRequestInfo(request, dict);
    741     if (extra_info_spec & ExtraInfoSpec::REQUEST_BODY)
    742       ExtractRequestInfoBody(request, dict);
    743     args.Append(dict);
    744 
    745     initialize_blocked_requests |=
    746         DispatchEvent(browser_context, request, listeners, args);
    747   }
    748 
    749   if (!initialize_blocked_requests)
    750     return net::OK;  // Nobody saw a reason for modifying the request.
    751 
    752   blocked_requests_[request->identifier()].event = kOnBeforeRequest;
    753   blocked_requests_[request->identifier()].is_incognito |=
    754       IsIncognitoBrowserContext(browser_context);
    755   blocked_requests_[request->identifier()].request = request;
    756   blocked_requests_[request->identifier()].callback = callback;
    757   blocked_requests_[request->identifier()].new_url = new_url;
    758   blocked_requests_[request->identifier()].net_log = &request->net_log();
    759 
    760   if (blocked_requests_[request->identifier()].num_handlers_blocking == 0) {
    761     // If there are no blocking handlers, only the declarative rules tried
    762     // to modify the request and we can respond synchronously.
    763     return ExecuteDeltas(browser_context, request->identifier(),
    764                          false /* call_callback*/);
    765   } else {
    766     return net::ERR_IO_PENDING;
    767   }
    768 }
    769 
    770 int ExtensionWebRequestEventRouter::OnBeforeSendHeaders(
    771     void* browser_context,
    772     InfoMap* extension_info_map,
    773     net::URLRequest* request,
    774     const net::CompletionCallback& callback,
    775     net::HttpRequestHeaders* headers) {
    776   // We hide events from the system context as well as sensitive requests.
    777   if (!browser_context ||
    778       WebRequestPermissions::HideRequest(extension_info_map, request))
    779     return net::OK;
    780 
    781   bool initialize_blocked_requests = false;
    782 
    783   initialize_blocked_requests |=
    784       ProcessDeclarativeRules(browser_context, extension_info_map,
    785                               keys::kOnBeforeSendHeadersEvent, request,
    786                               extensions::ON_BEFORE_SEND_HEADERS, NULL);
    787 
    788   int extra_info_spec = 0;
    789   std::vector<const EventListener*> listeners =
    790       GetMatchingListeners(browser_context, extension_info_map,
    791                            keys::kOnBeforeSendHeadersEvent, request,
    792                            &extra_info_spec);
    793   if (!listeners.empty() &&
    794       !GetAndSetSignaled(request->identifier(), kOnBeforeSendHeaders)) {
    795     base::ListValue args;
    796     base::DictionaryValue* dict = new base::DictionaryValue();
    797     ExtractRequestInfo(request, dict);
    798     if (extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS)
    799       dict->Set(keys::kRequestHeadersKey, GetRequestHeadersList(*headers));
    800     args.Append(dict);
    801 
    802     initialize_blocked_requests |=
    803         DispatchEvent(browser_context, request, listeners, args);
    804   }
    805 
    806   if (!initialize_blocked_requests)
    807     return net::OK;  // Nobody saw a reason for modifying the request.
    808 
    809   blocked_requests_[request->identifier()].event = kOnBeforeSendHeaders;
    810   blocked_requests_[request->identifier()].is_incognito |=
    811       IsIncognitoBrowserContext(browser_context);
    812   blocked_requests_[request->identifier()].request = request;
    813   blocked_requests_[request->identifier()].callback = callback;
    814   blocked_requests_[request->identifier()].request_headers = headers;
    815   blocked_requests_[request->identifier()].net_log = &request->net_log();
    816 
    817   if (blocked_requests_[request->identifier()].num_handlers_blocking == 0) {
    818     // If there are no blocking handlers, only the declarative rules tried
    819     // to modify the request and we can respond synchronously.
    820     return ExecuteDeltas(browser_context, request->identifier(),
    821                          false /* call_callback*/);
    822   } else {
    823     return net::ERR_IO_PENDING;
    824   }
    825 }
    826 
    827 void ExtensionWebRequestEventRouter::OnSendHeaders(
    828     void* browser_context,
    829     InfoMap* extension_info_map,
    830     net::URLRequest* request,
    831     const net::HttpRequestHeaders& headers) {
    832   // We hide events from the system context as well as sensitive requests.
    833   if (!browser_context ||
    834       WebRequestPermissions::HideRequest(extension_info_map, request))
    835     return;
    836 
    837   if (GetAndSetSignaled(request->identifier(), kOnSendHeaders))
    838     return;
    839 
    840   ClearSignaled(request->identifier(), kOnBeforeRedirect);
    841 
    842   int extra_info_spec = 0;
    843   std::vector<const EventListener*> listeners =
    844       GetMatchingListeners(browser_context, extension_info_map,
    845                            keys::kOnSendHeadersEvent, request,
    846                            &extra_info_spec);
    847   if (listeners.empty())
    848     return;
    849 
    850   base::ListValue args;
    851   base::DictionaryValue* dict = new base::DictionaryValue();
    852   ExtractRequestInfo(request, dict);
    853   if (extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS)
    854     dict->Set(keys::kRequestHeadersKey, GetRequestHeadersList(headers));
    855   args.Append(dict);
    856 
    857   DispatchEvent(browser_context, request, listeners, args);
    858 }
    859 
    860 int ExtensionWebRequestEventRouter::OnHeadersReceived(
    861     void* browser_context,
    862     InfoMap* extension_info_map,
    863     net::URLRequest* request,
    864     const net::CompletionCallback& callback,
    865     const net::HttpResponseHeaders* original_response_headers,
    866     scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
    867     GURL* allowed_unsafe_redirect_url) {
    868   // We hide events from the system context as well as sensitive requests.
    869   if (!browser_context ||
    870       WebRequestPermissions::HideRequest(extension_info_map, request))
    871     return net::OK;
    872 
    873   bool initialize_blocked_requests = false;
    874 
    875   initialize_blocked_requests |=
    876       ProcessDeclarativeRules(browser_context, extension_info_map,
    877                               keys::kOnHeadersReceivedEvent, request,
    878                               extensions::ON_HEADERS_RECEIVED,
    879                               original_response_headers);
    880 
    881   int extra_info_spec = 0;
    882   std::vector<const EventListener*> listeners =
    883       GetMatchingListeners(browser_context, extension_info_map,
    884                            keys::kOnHeadersReceivedEvent, request,
    885                            &extra_info_spec);
    886 
    887   if (!listeners.empty() &&
    888       !GetAndSetSignaled(request->identifier(), kOnHeadersReceived)) {
    889     base::ListValue args;
    890     base::DictionaryValue* dict = new base::DictionaryValue();
    891     ExtractRequestInfo(request, dict);
    892     dict->SetString(keys::kStatusLineKey,
    893         original_response_headers->GetStatusLine());
    894     if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
    895       dict->Set(keys::kResponseHeadersKey,
    896           GetResponseHeadersList(original_response_headers));
    897     }
    898     args.Append(dict);
    899 
    900     initialize_blocked_requests |=
    901         DispatchEvent(browser_context, request, listeners, args);
    902   }
    903 
    904   if (!initialize_blocked_requests)
    905     return net::OK;  // Nobody saw a reason for modifying the request.
    906 
    907   blocked_requests_[request->identifier()].event = kOnHeadersReceived;
    908   blocked_requests_[request->identifier()].is_incognito |=
    909       IsIncognitoBrowserContext(browser_context);
    910   blocked_requests_[request->identifier()].request = request;
    911   blocked_requests_[request->identifier()].callback = callback;
    912   blocked_requests_[request->identifier()].net_log = &request->net_log();
    913   blocked_requests_[request->identifier()].override_response_headers =
    914       override_response_headers;
    915   blocked_requests_[request->identifier()].original_response_headers =
    916       original_response_headers;
    917   blocked_requests_[request->identifier()].new_url =
    918       allowed_unsafe_redirect_url;
    919 
    920   if (blocked_requests_[request->identifier()].num_handlers_blocking == 0) {
    921     // If there are no blocking handlers, only the declarative rules tried
    922     // to modify the request and we can respond synchronously.
    923     return ExecuteDeltas(browser_context, request->identifier(),
    924                          false /* call_callback*/);
    925   } else {
    926     return net::ERR_IO_PENDING;
    927   }
    928 }
    929 
    930 net::NetworkDelegate::AuthRequiredResponse
    931 ExtensionWebRequestEventRouter::OnAuthRequired(
    932     void* browser_context,
    933     InfoMap* extension_info_map,
    934     net::URLRequest* request,
    935     const net::AuthChallengeInfo& auth_info,
    936     const net::NetworkDelegate::AuthCallback& callback,
    937     net::AuthCredentials* credentials) {
    938   // No browser_context means that this is for authentication challenges in the
    939   // system context. Skip in that case. Also skip sensitive requests.
    940   if (!browser_context ||
    941       WebRequestPermissions::HideRequest(extension_info_map, request))
    942     return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
    943 
    944   int extra_info_spec = 0;
    945   std::vector<const EventListener*> listeners =
    946       GetMatchingListeners(browser_context, extension_info_map,
    947                            keys::kOnAuthRequiredEvent, request,
    948                            &extra_info_spec);
    949   if (listeners.empty())
    950     return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
    951 
    952   base::ListValue args;
    953   base::DictionaryValue* dict = new base::DictionaryValue();
    954   ExtractRequestInfo(request, dict);
    955   dict->SetBoolean(keys::kIsProxyKey, auth_info.is_proxy);
    956   if (!auth_info.scheme.empty())
    957     dict->SetString(keys::kSchemeKey, auth_info.scheme);
    958   if (!auth_info.realm.empty())
    959     dict->SetString(keys::kRealmKey, auth_info.realm);
    960   base::DictionaryValue* challenger = new base::DictionaryValue();
    961   challenger->SetString(keys::kHostKey, auth_info.challenger.host());
    962   challenger->SetInteger(keys::kPortKey, auth_info.challenger.port());
    963   dict->Set(keys::kChallengerKey, challenger);
    964   dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers()));
    965   if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
    966     dict->Set(keys::kResponseHeadersKey,
    967               GetResponseHeadersList(request->response_headers()));
    968   }
    969   args.Append(dict);
    970 
    971   if (DispatchEvent(browser_context, request, listeners, args)) {
    972     blocked_requests_[request->identifier()].event = kOnAuthRequired;
    973     blocked_requests_[request->identifier()].is_incognito |=
    974         IsIncognitoBrowserContext(browser_context);
    975     blocked_requests_[request->identifier()].request = request;
    976     blocked_requests_[request->identifier()].auth_callback = callback;
    977     blocked_requests_[request->identifier()].auth_credentials = credentials;
    978     blocked_requests_[request->identifier()].net_log = &request->net_log();
    979     return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_IO_PENDING;
    980   }
    981   return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
    982 }
    983 
    984 void ExtensionWebRequestEventRouter::OnBeforeRedirect(
    985     void* browser_context,
    986     InfoMap* extension_info_map,
    987     net::URLRequest* request,
    988     const GURL& new_location) {
    989   // We hide events from the system context as well as sensitive requests.
    990   if (!browser_context ||
    991       WebRequestPermissions::HideRequest(extension_info_map, request))
    992     return;
    993 
    994   if (GetAndSetSignaled(request->identifier(), kOnBeforeRedirect))
    995     return;
    996 
    997   ClearSignaled(request->identifier(), kOnBeforeRequest);
    998   ClearSignaled(request->identifier(), kOnBeforeSendHeaders);
    999   ClearSignaled(request->identifier(), kOnSendHeaders);
   1000   ClearSignaled(request->identifier(), kOnHeadersReceived);
   1001 
   1002   int extra_info_spec = 0;
   1003   std::vector<const EventListener*> listeners =
   1004       GetMatchingListeners(browser_context, extension_info_map,
   1005                            keys::kOnBeforeRedirectEvent, request,
   1006                            &extra_info_spec);
   1007   if (listeners.empty())
   1008     return;
   1009 
   1010   int http_status_code = request->GetResponseCode();
   1011 
   1012   std::string response_ip = request->GetSocketAddress().host();
   1013 
   1014   base::ListValue args;
   1015   base::DictionaryValue* dict = new base::DictionaryValue();
   1016   ExtractRequestInfo(request, dict);
   1017   dict->SetString(keys::kRedirectUrlKey, new_location.spec());
   1018   dict->SetInteger(keys::kStatusCodeKey, http_status_code);
   1019   if (!response_ip.empty())
   1020     dict->SetString(keys::kIpKey, response_ip);
   1021   dict->SetBoolean(keys::kFromCache, request->was_cached());
   1022   dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers()));
   1023   if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
   1024     dict->Set(keys::kResponseHeadersKey,
   1025               GetResponseHeadersList(request->response_headers()));
   1026   }
   1027   args.Append(dict);
   1028 
   1029   DispatchEvent(browser_context, request, listeners, args);
   1030 }
   1031 
   1032 void ExtensionWebRequestEventRouter::OnResponseStarted(
   1033     void* browser_context,
   1034     InfoMap* extension_info_map,
   1035     net::URLRequest* request) {
   1036   // We hide events from the system context as well as sensitive requests.
   1037   if (!browser_context ||
   1038       WebRequestPermissions::HideRequest(extension_info_map, request))
   1039     return;
   1040 
   1041   // OnResponseStarted is even triggered, when the request was cancelled.
   1042   if (request->status().status() != net::URLRequestStatus::SUCCESS)
   1043     return;
   1044 
   1045   int extra_info_spec = 0;
   1046   std::vector<const EventListener*> listeners =
   1047       GetMatchingListeners(browser_context, extension_info_map,
   1048                            keys::kOnResponseStartedEvent, request,
   1049                            &extra_info_spec);
   1050   if (listeners.empty())
   1051     return;
   1052 
   1053   // UrlRequestFileJobs do not send headers, so we simulate their behavior.
   1054   int response_code = 200;
   1055   if (request->response_headers())
   1056     response_code = request->response_headers()->response_code();
   1057 
   1058   std::string response_ip = request->GetSocketAddress().host();
   1059 
   1060   base::ListValue args;
   1061   base::DictionaryValue* dict = new base::DictionaryValue();
   1062   ExtractRequestInfo(request, dict);
   1063   if (!response_ip.empty())
   1064     dict->SetString(keys::kIpKey, response_ip);
   1065   dict->SetBoolean(keys::kFromCache, request->was_cached());
   1066   dict->SetInteger(keys::kStatusCodeKey, response_code);
   1067   dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers()));
   1068   if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
   1069     dict->Set(keys::kResponseHeadersKey,
   1070               GetResponseHeadersList(request->response_headers()));
   1071   }
   1072   args.Append(dict);
   1073 
   1074   DispatchEvent(browser_context, request, listeners, args);
   1075 }
   1076 
   1077 void ExtensionWebRequestEventRouter::OnCompleted(void* browser_context,
   1078                                                  InfoMap* extension_info_map,
   1079                                                  net::URLRequest* request) {
   1080   // We hide events from the system context as well as sensitive requests.
   1081   // However, if the request first became sensitive after redirecting we have
   1082   // already signaled it and thus we have to signal the end of it. This is
   1083   // risk-free because the handler cannot modify the request now.
   1084   if (!browser_context ||
   1085       (WebRequestPermissions::HideRequest(extension_info_map, request) &&
   1086        !WasSignaled(*request)))
   1087     return;
   1088 
   1089   request_time_tracker_->LogRequestEndTime(request->identifier(),
   1090                                            base::Time::Now());
   1091 
   1092   DCHECK(request->status().status() == net::URLRequestStatus::SUCCESS);
   1093 
   1094   DCHECK(!GetAndSetSignaled(request->identifier(), kOnCompleted));
   1095 
   1096   ClearPendingCallbacks(request);
   1097 
   1098   int extra_info_spec = 0;
   1099   std::vector<const EventListener*> listeners =
   1100       GetMatchingListeners(browser_context, extension_info_map,
   1101                            keys::kOnCompletedEvent, request, &extra_info_spec);
   1102   if (listeners.empty())
   1103     return;
   1104 
   1105   // UrlRequestFileJobs do not send headers, so we simulate their behavior.
   1106   int response_code = 200;
   1107   if (request->response_headers())
   1108     response_code = request->response_headers()->response_code();
   1109 
   1110   std::string response_ip = request->GetSocketAddress().host();
   1111 
   1112   base::ListValue args;
   1113   base::DictionaryValue* dict = new base::DictionaryValue();
   1114   ExtractRequestInfo(request, dict);
   1115   dict->SetInteger(keys::kStatusCodeKey, response_code);
   1116   if (!response_ip.empty())
   1117     dict->SetString(keys::kIpKey, response_ip);
   1118   dict->SetBoolean(keys::kFromCache, request->was_cached());
   1119   dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers()));
   1120   if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
   1121     dict->Set(keys::kResponseHeadersKey,
   1122               GetResponseHeadersList(request->response_headers()));
   1123   }
   1124   args.Append(dict);
   1125 
   1126   DispatchEvent(browser_context, request, listeners, args);
   1127 }
   1128 
   1129 void ExtensionWebRequestEventRouter::OnErrorOccurred(
   1130     void* browser_context,
   1131     InfoMap* extension_info_map,
   1132     net::URLRequest* request,
   1133     bool started) {
   1134   // We hide events from the system context as well as sensitive requests.
   1135   // However, if the request first became sensitive after redirecting we have
   1136   // already signaled it and thus we have to signal the end of it. This is
   1137   // risk-free because the handler cannot modify the request now.
   1138   if (!browser_context ||
   1139       (WebRequestPermissions::HideRequest(extension_info_map, request) &&
   1140        !WasSignaled(*request)))
   1141     return;
   1142 
   1143   request_time_tracker_->LogRequestEndTime(request->identifier(),
   1144                                            base::Time::Now());
   1145 
   1146   DCHECK(request->status().status() == net::URLRequestStatus::FAILED ||
   1147          request->status().status() == net::URLRequestStatus::CANCELED);
   1148 
   1149   DCHECK(!GetAndSetSignaled(request->identifier(), kOnErrorOccurred));
   1150 
   1151   ClearPendingCallbacks(request);
   1152 
   1153   int extra_info_spec = 0;
   1154   std::vector<const EventListener*> listeners =
   1155       GetMatchingListeners(browser_context, extension_info_map,
   1156                            web_request::OnErrorOccurred::kEventName, request,
   1157                            &extra_info_spec);
   1158   if (listeners.empty())
   1159     return;
   1160 
   1161   base::ListValue args;
   1162   base::DictionaryValue* dict = new base::DictionaryValue();
   1163   ExtractRequestInfo(request, dict);
   1164   if (started) {
   1165     std::string response_ip = request->GetSocketAddress().host();
   1166     if (!response_ip.empty())
   1167       dict->SetString(keys::kIpKey, response_ip);
   1168   }
   1169   dict->SetBoolean(keys::kFromCache, request->was_cached());
   1170   dict->SetString(keys::kErrorKey,
   1171                   net::ErrorToString(request->status().error()));
   1172   args.Append(dict);
   1173 
   1174   DispatchEvent(browser_context, request, listeners, args);
   1175 }
   1176 
   1177 void ExtensionWebRequestEventRouter::OnURLRequestDestroyed(
   1178     void* browser_context, net::URLRequest* request) {
   1179   ClearPendingCallbacks(request);
   1180 
   1181   signaled_requests_.erase(request->identifier());
   1182 
   1183   request_time_tracker_->LogRequestEndTime(request->identifier(),
   1184                                            base::Time::Now());
   1185 }
   1186 
   1187 void ExtensionWebRequestEventRouter::ClearPendingCallbacks(
   1188     net::URLRequest* request) {
   1189   blocked_requests_.erase(request->identifier());
   1190 }
   1191 
   1192 bool ExtensionWebRequestEventRouter::DispatchEvent(
   1193     void* browser_context,
   1194     net::URLRequest* request,
   1195     const std::vector<const EventListener*>& listeners,
   1196     const base::ListValue& args) {
   1197   // TODO(mpcomplete): Consider consolidating common (extension_id,json_args)
   1198   // pairs into a single message sent to a list of sub_event_names.
   1199   int num_handlers_blocking = 0;
   1200   for (std::vector<const EventListener*>::const_iterator it = listeners.begin();
   1201        it != listeners.end(); ++it) {
   1202     // Filter out the optional keys that this listener didn't request.
   1203     scoped_ptr<base::ListValue> args_filtered(args.DeepCopy());
   1204     base::DictionaryValue* dict = NULL;
   1205     CHECK(args_filtered->GetDictionary(0, &dict) && dict);
   1206     if (!((*it)->extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS))
   1207       dict->Remove(keys::kRequestHeadersKey, NULL);
   1208     if (!((*it)->extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS))
   1209       dict->Remove(keys::kResponseHeadersKey, NULL);
   1210 
   1211     extensions::EventRouter::DispatchEvent(
   1212         (*it)->ipc_sender.get(), browser_context,
   1213         (*it)->extension_id, (*it)->sub_event_name,
   1214         args_filtered.Pass(),
   1215         extensions::EventRouter::USER_GESTURE_UNKNOWN,
   1216         extensions::EventFilteringInfo());
   1217     if ((*it)->extra_info_spec &
   1218         (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) {
   1219       (*it)->blocked_requests.insert(request->identifier());
   1220       // If this is the first delegate blocking the request, go ahead and log
   1221       // it.
   1222       if (num_handlers_blocking == 0) {
   1223         std::string delegate_info =
   1224             l10n_util::GetStringFUTF8(IDS_LOAD_STATE_PARAMETER_EXTENSION,
   1225                                       base::UTF8ToUTF16((*it)->extension_name));
   1226         // LobAndReport allows extensions that block requests to be displayed in
   1227         // the load status bar.
   1228         request->LogAndReportBlockedBy(delegate_info.c_str());
   1229       }
   1230       ++num_handlers_blocking;
   1231     }
   1232   }
   1233 
   1234   if (num_handlers_blocking > 0) {
   1235     blocked_requests_[request->identifier()].request = request;
   1236     blocked_requests_[request->identifier()].is_incognito |=
   1237         IsIncognitoBrowserContext(browser_context);
   1238     blocked_requests_[request->identifier()].num_handlers_blocking +=
   1239         num_handlers_blocking;
   1240     blocked_requests_[request->identifier()].blocking_time = base::Time::Now();
   1241 
   1242     return true;
   1243   }
   1244 
   1245   return false;
   1246 }
   1247 
   1248 void ExtensionWebRequestEventRouter::OnEventHandled(
   1249     void* browser_context,
   1250     const std::string& extension_id,
   1251     const std::string& event_name,
   1252     const std::string& sub_event_name,
   1253     uint64 request_id,
   1254     EventResponse* response) {
   1255   EventListener listener;
   1256   listener.extension_id = extension_id;
   1257   listener.sub_event_name = sub_event_name;
   1258 
   1259   // The listener may have been removed (e.g. due to the process going away)
   1260   // before we got here.
   1261   std::set<EventListener>::iterator found =
   1262       listeners_[browser_context][event_name].find(listener);
   1263   if (found != listeners_[browser_context][event_name].end())
   1264     found->blocked_requests.erase(request_id);
   1265 
   1266   DecrementBlockCount(
   1267       browser_context, extension_id, event_name, request_id, response);
   1268 }
   1269 
   1270 bool ExtensionWebRequestEventRouter::AddEventListener(
   1271     void* browser_context,
   1272     const std::string& extension_id,
   1273     const std::string& extension_name,
   1274     const std::string& event_name,
   1275     const std::string& sub_event_name,
   1276     const RequestFilter& filter,
   1277     int extra_info_spec,
   1278     int embedder_process_id,
   1279     int webview_instance_id,
   1280     base::WeakPtr<IPC::Sender> ipc_sender) {
   1281   if (!IsWebRequestEvent(event_name))
   1282     return false;
   1283 
   1284   EventListener listener;
   1285   listener.extension_id = extension_id;
   1286   listener.extension_name = extension_name;
   1287   listener.sub_event_name = sub_event_name;
   1288   listener.filter = filter;
   1289   listener.extra_info_spec = extra_info_spec;
   1290   listener.ipc_sender = ipc_sender;
   1291   listener.embedder_process_id = embedder_process_id;
   1292   listener.webview_instance_id = webview_instance_id;
   1293   if (listener.webview_instance_id) {
   1294     content::RecordAction(
   1295         base::UserMetricsAction("WebView.WebRequest.AddListener"));
   1296   }
   1297 
   1298   if (listeners_[browser_context][event_name].count(listener) != 0u) {
   1299     // This is likely an abuse of the API by a malicious extension.
   1300     return false;
   1301   }
   1302   listeners_[browser_context][event_name].insert(listener);
   1303   return true;
   1304 }
   1305 
   1306 void ExtensionWebRequestEventRouter::RemoveEventListener(
   1307     void* browser_context,
   1308     const std::string& extension_id,
   1309     const std::string& sub_event_name) {
   1310   std::string event_name =
   1311       extensions::EventRouter::GetBaseEventName(sub_event_name);
   1312   DCHECK(IsWebRequestEvent(event_name));
   1313 
   1314   EventListener listener;
   1315   listener.extension_id = extension_id;
   1316   listener.sub_event_name = sub_event_name;
   1317 
   1318   // It's possible for AddEventListener to fail asynchronously. In that case,
   1319   // the renderer believes the listener exists, while the browser does not.
   1320   // Ignore a RemoveEventListener in that case.
   1321   std::set<EventListener>::iterator found =
   1322       listeners_[browser_context][event_name].find(listener);
   1323   if (found == listeners_[browser_context][event_name].end())
   1324     return;
   1325 
   1326   CHECK_EQ(listeners_[browser_context][event_name].count(listener), 1u) <<
   1327       "extension=" << extension_id << " event=" << event_name;
   1328 
   1329   // Unblock any request that this event listener may have been blocking.
   1330   for (std::set<uint64>::iterator it = found->blocked_requests.begin();
   1331        it != found->blocked_requests.end(); ++it) {
   1332     DecrementBlockCount(browser_context, extension_id, event_name, *it, NULL);
   1333   }
   1334 
   1335   listeners_[browser_context][event_name].erase(listener);
   1336 
   1337   helpers::ClearCacheOnNavigation();
   1338 }
   1339 
   1340 void ExtensionWebRequestEventRouter::RemoveWebViewEventListeners(
   1341     void* browser_context,
   1342     const std::string& extension_id,
   1343     int embedder_process_id,
   1344     int webview_instance_id) {
   1345   // Iterate over all listeners of all WebRequest events to delete
   1346   // any listeners that belong to the provided <webview>.
   1347   ListenerMapForBrowserContext& map_for_browser_context =
   1348       listeners_[browser_context];
   1349   for (ListenerMapForBrowserContext::iterator event_iter =
   1350        map_for_browser_context.begin();
   1351        event_iter != map_for_browser_context.end(); ++event_iter) {
   1352     std::vector<EventListener> listeners_to_delete;
   1353     std::set<EventListener>& listeners = event_iter->second;
   1354     for (std::set<EventListener>::iterator listener_iter = listeners.begin();
   1355          listener_iter != listeners.end(); ++listener_iter) {
   1356       const EventListener& listener = *listener_iter;
   1357       if (listener.embedder_process_id == embedder_process_id &&
   1358           listener.webview_instance_id == webview_instance_id)
   1359         listeners_to_delete.push_back(listener);
   1360     }
   1361     for (size_t i = 0; i < listeners_to_delete.size(); ++i) {
   1362       EventListener& listener = listeners_to_delete[i];
   1363       content::BrowserThread::PostTask(
   1364           content::BrowserThread::UI,
   1365           FROM_HERE,
   1366           base::Bind(&RemoveEventListenerOnUI,
   1367                      browser_context,
   1368                      listener.sub_event_name,
   1369                      embedder_process_id,
   1370                      extension_id));
   1371     }
   1372   }
   1373 }
   1374 
   1375 void ExtensionWebRequestEventRouter::OnOTRBrowserContextCreated(
   1376     void* original_browser_context, void* otr_browser_context) {
   1377   cross_browser_context_map_[original_browser_context] =
   1378       std::make_pair(false, otr_browser_context);
   1379   cross_browser_context_map_[otr_browser_context] =
   1380       std::make_pair(true, original_browser_context);
   1381 }
   1382 
   1383 void ExtensionWebRequestEventRouter::OnOTRBrowserContextDestroyed(
   1384     void* original_browser_context, void* otr_browser_context) {
   1385   cross_browser_context_map_.erase(otr_browser_context);
   1386   cross_browser_context_map_.erase(original_browser_context);
   1387 }
   1388 
   1389 void ExtensionWebRequestEventRouter::AddCallbackForPageLoad(
   1390     const base::Closure& callback) {
   1391   callbacks_for_page_load_.push_back(callback);
   1392 }
   1393 
   1394 bool ExtensionWebRequestEventRouter::IsPageLoad(
   1395     net::URLRequest* request) const {
   1396   bool is_main_frame = false;
   1397   int frame_id = -1;
   1398   bool parent_is_main_frame = false;
   1399   int parent_frame_id = -1;
   1400   int render_process_host_id = -1;
   1401   int routing_id = -1;
   1402   ResourceType resource_type = content::RESOURCE_TYPE_LAST_TYPE;
   1403 
   1404   ExtractRequestInfoDetails(request, &is_main_frame, &frame_id,
   1405                             &parent_is_main_frame, &parent_frame_id,
   1406                             &render_process_host_id,
   1407                             &routing_id, &resource_type);
   1408 
   1409   return resource_type == content::RESOURCE_TYPE_MAIN_FRAME;
   1410 }
   1411 
   1412 void ExtensionWebRequestEventRouter::NotifyPageLoad() {
   1413   for (CallbacksForPageLoad::const_iterator i =
   1414            callbacks_for_page_load_.begin();
   1415        i != callbacks_for_page_load_.end(); ++i) {
   1416     i->Run();
   1417   }
   1418   callbacks_for_page_load_.clear();
   1419 }
   1420 
   1421 void* ExtensionWebRequestEventRouter::GetCrossBrowserContext(
   1422     void* browser_context) const {
   1423   CrossBrowserContextMap::const_iterator cross_browser_context =
   1424       cross_browser_context_map_.find(browser_context);
   1425   if (cross_browser_context == cross_browser_context_map_.end())
   1426     return NULL;
   1427   return cross_browser_context->second.second;
   1428 }
   1429 
   1430 bool ExtensionWebRequestEventRouter::IsIncognitoBrowserContext(
   1431     void* browser_context) const {
   1432   CrossBrowserContextMap::const_iterator cross_browser_context =
   1433       cross_browser_context_map_.find(browser_context);
   1434   if (cross_browser_context == cross_browser_context_map_.end())
   1435     return false;
   1436   return cross_browser_context->second.first;
   1437 }
   1438 
   1439 bool ExtensionWebRequestEventRouter::WasSignaled(
   1440     const net::URLRequest& request) const {
   1441   SignaledRequestMap::const_iterator flag =
   1442       signaled_requests_.find(request.identifier());
   1443   return (flag != signaled_requests_.end()) && (flag->second != 0);
   1444 }
   1445 
   1446 void ExtensionWebRequestEventRouter::GetMatchingListenersImpl(
   1447     void* browser_context,
   1448     net::URLRequest* request,
   1449     InfoMap* extension_info_map,
   1450     bool crosses_incognito,
   1451     const std::string& event_name,
   1452     const GURL& url,
   1453     int render_process_host_id,
   1454     int routing_id,
   1455     ResourceType resource_type,
   1456     bool is_async_request,
   1457     bool is_request_from_extension,
   1458     int* extra_info_spec,
   1459     std::vector<const ExtensionWebRequestEventRouter::EventListener*>*
   1460         matching_listeners) {
   1461   std::string web_request_event_name(event_name);
   1462   extensions::WebViewRendererState::WebViewInfo web_view_info;
   1463   bool is_web_view_guest = extensions::WebViewRendererState::GetInstance()->
   1464       GetInfo(render_process_host_id, routing_id, &web_view_info);
   1465   if (is_web_view_guest) {
   1466     web_request_event_name.replace(
   1467         0, sizeof(kWebRequestEventPrefix) - 1, webview::kWebViewEventPrefix);
   1468   }
   1469 
   1470   std::set<EventListener>& listeners =
   1471       listeners_[browser_context][web_request_event_name];
   1472   for (std::set<EventListener>::iterator it = listeners.begin();
   1473        it != listeners.end(); ++it) {
   1474     if (!it->ipc_sender.get()) {
   1475       // The IPC sender has been deleted. This listener will be removed soon
   1476       // via a call to RemoveEventListener. For now, just skip it.
   1477       continue;
   1478     }
   1479 
   1480     if (is_web_view_guest &&
   1481         (it->embedder_process_id != web_view_info.embedder_process_id ||
   1482          it->webview_instance_id != web_view_info.instance_id))
   1483       continue;
   1484 
   1485     if (!it->filter.urls.is_empty() && !it->filter.urls.MatchesURL(url))
   1486       continue;
   1487     if (web_request_event_router_delegate_ &&
   1488         web_request_event_router_delegate_->OnGetMatchingListenersImplCheck(
   1489             it->filter.tab_id, it->filter.window_id, request))
   1490       continue;
   1491     if (!it->filter.types.empty() &&
   1492         std::find(it->filter.types.begin(), it->filter.types.end(),
   1493                   resource_type) == it->filter.types.end())
   1494       continue;
   1495 
   1496     if (!is_web_view_guest && !WebRequestPermissions::CanExtensionAccessURL(
   1497             extension_info_map, it->extension_id, url, crosses_incognito,
   1498             WebRequestPermissions::REQUIRE_HOST_PERMISSION))
   1499       continue;
   1500 
   1501     bool blocking_listener =
   1502         (it->extra_info_spec &
   1503             (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) != 0;
   1504 
   1505     // We do not want to notify extensions about XHR requests that are
   1506     // triggered by themselves. This is a workaround to prevent deadlocks
   1507     // in case of synchronous XHR requests that block the extension renderer
   1508     // and therefore prevent the extension from processing the request
   1509     // handler. This is only a problem for blocking listeners.
   1510     // http://crbug.com/105656
   1511     bool synchronous_xhr_from_extension =
   1512         !is_async_request && is_request_from_extension &&
   1513         resource_type == content::RESOURCE_TYPE_XHR;
   1514 
   1515     // Only send webRequest events for URLs the extension has access to.
   1516     if (blocking_listener && synchronous_xhr_from_extension)
   1517       continue;
   1518 
   1519     matching_listeners->push_back(&(*it));
   1520     *extra_info_spec |= it->extra_info_spec;
   1521   }
   1522 }
   1523 
   1524 std::vector<const ExtensionWebRequestEventRouter::EventListener*>
   1525 ExtensionWebRequestEventRouter::GetMatchingListeners(
   1526     void* browser_context,
   1527     InfoMap* extension_info_map,
   1528     const std::string& event_name,
   1529     net::URLRequest* request,
   1530     int* extra_info_spec) {
   1531   // TODO(mpcomplete): handle browser_context == NULL (should collect all
   1532   // listeners).
   1533   *extra_info_spec = 0;
   1534 
   1535   bool is_main_frame = false;
   1536   int frame_id = -1;
   1537   bool parent_is_main_frame = false;
   1538   int parent_frame_id = -1;
   1539   int render_process_host_id = -1;
   1540   int routing_id = -1;
   1541   ResourceType resource_type = content::RESOURCE_TYPE_LAST_TYPE;
   1542   const GURL& url = request->url();
   1543 
   1544   ExtractRequestInfoDetails(request, &is_main_frame, &frame_id,
   1545                             &parent_is_main_frame, &parent_frame_id,
   1546                             &render_process_host_id,
   1547                             &routing_id, &resource_type);
   1548 
   1549   std::vector<const ExtensionWebRequestEventRouter::EventListener*>
   1550       matching_listeners;
   1551 
   1552   bool is_request_from_extension =
   1553       IsRequestFromExtension(request, extension_info_map);
   1554 
   1555   const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
   1556   // We are conservative here and assume requests are asynchronous in case
   1557   // we don't have an info object. We don't want to risk a deadlock.
   1558   bool is_async_request = !info || info->IsAsync();
   1559 
   1560   GetMatchingListenersImpl(
   1561       browser_context, request, extension_info_map, false, event_name,
   1562       url, render_process_host_id, routing_id, resource_type,
   1563       is_async_request, is_request_from_extension, extra_info_spec,
   1564       &matching_listeners);
   1565   void* cross_browser_context = GetCrossBrowserContext(browser_context);
   1566   if (cross_browser_context) {
   1567     GetMatchingListenersImpl(
   1568         cross_browser_context, request, extension_info_map, true, event_name,
   1569         url, render_process_host_id, routing_id, resource_type,
   1570         is_async_request, is_request_from_extension, extra_info_spec,
   1571         &matching_listeners);
   1572   }
   1573 
   1574   return matching_listeners;
   1575 }
   1576 
   1577 namespace {
   1578 
   1579 helpers::EventResponseDelta* CalculateDelta(
   1580     ExtensionWebRequestEventRouter::BlockedRequest* blocked_request,
   1581     ExtensionWebRequestEventRouter::EventResponse* response) {
   1582   switch (blocked_request->event) {
   1583     case ExtensionWebRequestEventRouter::kOnBeforeRequest:
   1584       return helpers::CalculateOnBeforeRequestDelta(
   1585           response->extension_id, response->extension_install_time,
   1586           response->cancel, response->new_url);
   1587     case ExtensionWebRequestEventRouter::kOnBeforeSendHeaders: {
   1588       net::HttpRequestHeaders* old_headers = blocked_request->request_headers;
   1589       net::HttpRequestHeaders* new_headers = response->request_headers.get();
   1590       return helpers::CalculateOnBeforeSendHeadersDelta(
   1591           response->extension_id, response->extension_install_time,
   1592           response->cancel, old_headers, new_headers);
   1593     }
   1594     case ExtensionWebRequestEventRouter::kOnHeadersReceived: {
   1595       const net::HttpResponseHeaders* old_headers =
   1596           blocked_request->original_response_headers.get();
   1597       helpers::ResponseHeaders* new_headers =
   1598           response->response_headers.get();
   1599       return helpers::CalculateOnHeadersReceivedDelta(
   1600           response->extension_id,
   1601           response->extension_install_time,
   1602           response->cancel,
   1603           response->new_url,
   1604           old_headers,
   1605           new_headers);
   1606     }
   1607     case ExtensionWebRequestEventRouter::kOnAuthRequired:
   1608       return helpers::CalculateOnAuthRequiredDelta(
   1609           response->extension_id, response->extension_install_time,
   1610           response->cancel, &response->auth_credentials);
   1611     default:
   1612       NOTREACHED();
   1613       break;
   1614   }
   1615   return NULL;
   1616 }
   1617 
   1618 base::Value* SerializeResponseHeaders(const helpers::ResponseHeaders& headers) {
   1619   scoped_ptr<base::ListValue> serialized_headers(new base::ListValue());
   1620   for (helpers::ResponseHeaders::const_iterator i = headers.begin();
   1621        i != headers.end(); ++i) {
   1622     serialized_headers->Append(
   1623         helpers::CreateHeaderDictionary(i->first, i->second));
   1624   }
   1625   return serialized_headers.release();
   1626 }
   1627 
   1628 // Convert a RequestCookieModifications/ResponseCookieModifications object to a
   1629 // base::ListValue which summarizes the changes made.  This is templated since
   1630 // the two types (request/response) are different but contain essentially the
   1631 // same fields.
   1632 template<typename CookieType>
   1633 base::ListValue* SummarizeCookieModifications(
   1634     const std::vector<linked_ptr<CookieType> >& modifications) {
   1635   scoped_ptr<base::ListValue> cookie_modifications(new base::ListValue());
   1636   for (typename std::vector<linked_ptr<CookieType> >::const_iterator i =
   1637            modifications.begin();
   1638        i != modifications.end(); ++i) {
   1639     scoped_ptr<base::DictionaryValue> summary(new base::DictionaryValue());
   1640     const CookieType& mod = *i->get();
   1641     switch (mod.type) {
   1642       case helpers::ADD:
   1643         summary->SetString(activitylog::kCookieModificationTypeKey,
   1644                            activitylog::kCookieModificationAdd);
   1645         break;
   1646       case helpers::EDIT:
   1647         summary->SetString(activitylog::kCookieModificationTypeKey,
   1648                            activitylog::kCookieModificationEdit);
   1649         break;
   1650       case helpers::REMOVE:
   1651         summary->SetString(activitylog::kCookieModificationTypeKey,
   1652                            activitylog::kCookieModificationRemove);
   1653         break;
   1654     }
   1655     if (mod.filter) {
   1656       if (mod.filter->name)
   1657         summary->SetString(activitylog::kCookieFilterNameKey,
   1658                            *mod.modification->name);
   1659       if (mod.filter->domain)
   1660         summary->SetString(activitylog::kCookieFilterDomainKey,
   1661                            *mod.modification->name);
   1662     }
   1663     if (mod.modification) {
   1664       if (mod.modification->name)
   1665         summary->SetString(activitylog::kCookieModDomainKey,
   1666                            *mod.modification->name);
   1667       if (mod.modification->domain)
   1668         summary->SetString(activitylog::kCookieModDomainKey,
   1669                            *mod.modification->name);
   1670     }
   1671     cookie_modifications->Append(summary.release());
   1672   }
   1673   return cookie_modifications.release();
   1674 }
   1675 
   1676 // Converts an EventResponseDelta object to a dictionary value suitable for the
   1677 // activity log.
   1678 scoped_ptr<base::DictionaryValue> SummarizeResponseDelta(
   1679     const std::string& event_name,
   1680     const helpers::EventResponseDelta& delta) {
   1681   scoped_ptr<base::DictionaryValue> details(new base::DictionaryValue());
   1682   if (delta.cancel) {
   1683     details->SetBoolean(activitylog::kCancelKey, true);
   1684   }
   1685   if (!delta.new_url.is_empty()) {
   1686       details->SetString(activitylog::kNewUrlKey, delta.new_url.spec());
   1687   }
   1688 
   1689   scoped_ptr<base::ListValue> modified_headers(new base::ListValue());
   1690   net::HttpRequestHeaders::Iterator iter(delta.modified_request_headers);
   1691   while (iter.GetNext()) {
   1692     modified_headers->Append(
   1693         helpers::CreateHeaderDictionary(iter.name(), iter.value()));
   1694   }
   1695   if (!modified_headers->empty()) {
   1696     details->Set(activitylog::kModifiedRequestHeadersKey,
   1697                  modified_headers.release());
   1698   }
   1699 
   1700   scoped_ptr<base::ListValue> deleted_headers(new base::ListValue());
   1701   deleted_headers->AppendStrings(delta.deleted_request_headers);
   1702   if (!deleted_headers->empty()) {
   1703     details->Set(activitylog::kDeletedRequestHeadersKey,
   1704                  deleted_headers.release());
   1705   }
   1706 
   1707   if (!delta.added_response_headers.empty()) {
   1708     details->Set(activitylog::kAddedRequestHeadersKey,
   1709                  SerializeResponseHeaders(delta.added_response_headers));
   1710   }
   1711   if (!delta.deleted_response_headers.empty()) {
   1712     details->Set(activitylog::kDeletedResponseHeadersKey,
   1713                  SerializeResponseHeaders(delta.deleted_response_headers));
   1714   }
   1715   if (delta.auth_credentials) {
   1716     details->SetString(activitylog::kAuthCredentialsKey,
   1717                        base::UTF16ToUTF8(
   1718                            delta.auth_credentials->username()) + ":*");
   1719   }
   1720 
   1721   if (!delta.response_cookie_modifications.empty()) {
   1722     details->Set(
   1723         activitylog::kResponseCookieModificationsKey,
   1724         SummarizeCookieModifications(delta.response_cookie_modifications));
   1725   }
   1726 
   1727   return details.Pass();
   1728 }
   1729 
   1730 }  // namespace
   1731 
   1732 void ExtensionWebRequestEventRouter::LogExtensionActivity(
   1733     void* browser_context_id,
   1734     bool is_incognito,
   1735     const std::string& extension_id,
   1736     const GURL& url,
   1737     const std::string& api_call,
   1738     scoped_ptr<base::DictionaryValue> details) {
   1739   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
   1740     BrowserThread::PostTask(
   1741         BrowserThread::UI,
   1742         FROM_HERE,
   1743         base::Bind(&ExtensionWebRequestEventRouter::LogExtensionActivity,
   1744                     base::Unretained(this),
   1745                     browser_context_id,
   1746                     is_incognito,
   1747                     extension_id,
   1748                     url,
   1749                     api_call,
   1750                     base::Passed(&details)));
   1751   } else {
   1752     if (web_request_event_router_delegate_) {
   1753       web_request_event_router_delegate_->LogExtensionActivity(
   1754           reinterpret_cast<content::BrowserContext*>(browser_context_id),
   1755           is_incognito, extension_id, url, api_call, details.Pass());
   1756     }
   1757   }
   1758 }
   1759 
   1760 void ExtensionWebRequestEventRouter::DecrementBlockCount(
   1761     void* browser_context,
   1762     const std::string& extension_id,
   1763     const std::string& event_name,
   1764     uint64 request_id,
   1765     EventResponse* response) {
   1766   scoped_ptr<EventResponse> response_scoped(response);
   1767 
   1768   // It's possible that this request was deleted, or cancelled by a previous
   1769   // event handler. If so, ignore this response.
   1770   if (blocked_requests_.find(request_id) == blocked_requests_.end())
   1771     return;
   1772 
   1773   BlockedRequest& blocked_request = blocked_requests_[request_id];
   1774   int num_handlers_blocking = --blocked_request.num_handlers_blocking;
   1775   CHECK_GE(num_handlers_blocking, 0);
   1776 
   1777   if (response) {
   1778     helpers::EventResponseDelta* delta =
   1779         CalculateDelta(&blocked_request, response);
   1780 
   1781     LogExtensionActivity(browser_context,
   1782                          blocked_request.is_incognito,
   1783                          extension_id,
   1784                          blocked_request.request->url(),
   1785                          event_name,
   1786                          SummarizeResponseDelta(event_name, *delta));
   1787 
   1788     blocked_request.response_deltas.push_back(
   1789         linked_ptr<helpers::EventResponseDelta>(delta));
   1790   }
   1791 
   1792   base::TimeDelta block_time =
   1793       base::Time::Now() - blocked_request.blocking_time;
   1794   if (!extension_id.empty()) {
   1795     request_time_tracker_->IncrementExtensionBlockTime(
   1796         extension_id, request_id, block_time);
   1797   } else {
   1798     // |extension_id| is empty for requests blocked on startup waiting for the
   1799     // declarative rules to be read from disk.
   1800     UMA_HISTOGRAM_TIMES("Extensions.NetworkDelayStartup", block_time);
   1801   }
   1802 
   1803   if (num_handlers_blocking == 0) {
   1804     blocked_request.request->LogUnblocked();
   1805     ExecuteDeltas(browser_context, request_id, true);
   1806   } else {
   1807     // Update the URLRequest to make sure it's tagged with an extension that's
   1808     // still blocking it.  This may end up being the same extension as before.
   1809     std::set<EventListener>& listeners =
   1810         listeners_[browser_context][event_name];
   1811 
   1812     for (std::set<EventListener>::iterator it = listeners.begin();
   1813          it != listeners.end(); ++it) {
   1814       if (it->blocked_requests.count(request_id) == 0)
   1815         continue;
   1816       std::string delegate_info =
   1817           l10n_util::GetStringFUTF8(IDS_LOAD_STATE_PARAMETER_EXTENSION,
   1818                                     base::UTF8ToUTF16(it->extension_name));
   1819       blocked_request.request->LogAndReportBlockedBy(delegate_info.c_str());
   1820       break;
   1821     }
   1822   }
   1823 }
   1824 
   1825 void ExtensionWebRequestEventRouter::SendMessages(
   1826     void* browser_context,
   1827     const BlockedRequest& blocked_request) {
   1828   const helpers::EventResponseDeltas& deltas = blocked_request.response_deltas;
   1829   for (helpers::EventResponseDeltas::const_iterator delta = deltas.begin();
   1830        delta != deltas.end(); ++delta) {
   1831     const std::set<std::string>& messages = (*delta)->messages_to_extension;
   1832     for (std::set<std::string>::const_iterator message = messages.begin();
   1833          message != messages.end(); ++message) {
   1834       scoped_ptr<base::DictionaryValue> argument(new base::DictionaryValue);
   1835       ExtractRequestInfo(blocked_request.request, argument.get());
   1836       extensions::WebViewRendererState::WebViewInfo web_view_info;
   1837       bool is_web_view_guest = GetWebViewInfo(blocked_request.request,
   1838                                               &web_view_info);
   1839       argument->SetString(keys::kMessageKey, *message);
   1840       argument->SetString(keys::kStageKey,
   1841                           GetRequestStageAsString(blocked_request.event));
   1842 
   1843       BrowserThread::PostTask(
   1844           BrowserThread::UI,
   1845           FROM_HERE,
   1846           base::Bind(&SendOnMessageEventOnUI,
   1847                      browser_context,
   1848                      (*delta)->extension_id,
   1849                      is_web_view_guest,
   1850                      web_view_info,
   1851                      base::Passed(&argument)));
   1852     }
   1853   }
   1854 }
   1855 
   1856 int ExtensionWebRequestEventRouter::ExecuteDeltas(
   1857     void* browser_context,
   1858     uint64 request_id,
   1859     bool call_callback) {
   1860   BlockedRequest& blocked_request = blocked_requests_[request_id];
   1861   CHECK(blocked_request.num_handlers_blocking == 0);
   1862   helpers::EventResponseDeltas& deltas = blocked_request.response_deltas;
   1863   base::TimeDelta block_time =
   1864       base::Time::Now() - blocked_request.blocking_time;
   1865   request_time_tracker_->IncrementTotalBlockTime(request_id, block_time);
   1866 
   1867   bool credentials_set = false;
   1868 
   1869   deltas.sort(&helpers::InDecreasingExtensionInstallationTimeOrder);
   1870   WarningSet warnings;
   1871 
   1872   bool canceled = false;
   1873   helpers::MergeCancelOfResponses(
   1874       blocked_request.response_deltas,
   1875       &canceled,
   1876       blocked_request.net_log);
   1877 
   1878   if (blocked_request.event == kOnBeforeRequest) {
   1879     CHECK(!blocked_request.callback.is_null());
   1880     helpers::MergeOnBeforeRequestResponses(
   1881         blocked_request.response_deltas,
   1882         blocked_request.new_url,
   1883         &warnings,
   1884         blocked_request.net_log);
   1885   } else if (blocked_request.event == kOnBeforeSendHeaders) {
   1886     CHECK(!blocked_request.callback.is_null());
   1887     helpers::MergeOnBeforeSendHeadersResponses(
   1888         blocked_request.response_deltas,
   1889         blocked_request.request_headers,
   1890         &warnings,
   1891         blocked_request.net_log);
   1892   } else if (blocked_request.event == kOnHeadersReceived) {
   1893     CHECK(!blocked_request.callback.is_null());
   1894     helpers::MergeOnHeadersReceivedResponses(
   1895         blocked_request.response_deltas,
   1896         blocked_request.original_response_headers.get(),
   1897         blocked_request.override_response_headers,
   1898         blocked_request.new_url,
   1899         &warnings,
   1900         blocked_request.net_log);
   1901   } else if (blocked_request.event == kOnAuthRequired) {
   1902     CHECK(blocked_request.callback.is_null());
   1903     CHECK(!blocked_request.auth_callback.is_null());
   1904     credentials_set = helpers::MergeOnAuthRequiredResponses(
   1905        blocked_request.response_deltas,
   1906        blocked_request.auth_credentials,
   1907        &warnings,
   1908        blocked_request.net_log);
   1909   } else {
   1910     NOTREACHED();
   1911   }
   1912 
   1913   SendMessages(browser_context, blocked_request);
   1914 
   1915   if (!warnings.empty()) {
   1916     BrowserThread::PostTask(
   1917         BrowserThread::UI,
   1918         FROM_HERE,
   1919         base::Bind(&WarningService::NotifyWarningsOnUI,
   1920                    browser_context, warnings));
   1921   }
   1922 
   1923   if (canceled) {
   1924     request_time_tracker_->SetRequestCanceled(request_id);
   1925   } else if (blocked_request.new_url &&
   1926              !blocked_request.new_url->is_empty()) {
   1927     request_time_tracker_->SetRequestRedirected(request_id);
   1928   }
   1929 
   1930   // This triggers onErrorOccurred if canceled is true.
   1931   int rv = canceled ? net::ERR_BLOCKED_BY_CLIENT : net::OK;
   1932 
   1933   if (!blocked_request.callback.is_null()) {
   1934     net::CompletionCallback callback = blocked_request.callback;
   1935     // Ensure that request is removed before callback because the callback
   1936     // might trigger the next event.
   1937     blocked_requests_.erase(request_id);
   1938     if (call_callback)
   1939       callback.Run(rv);
   1940   } else if (!blocked_request.auth_callback.is_null()) {
   1941     net::NetworkDelegate::AuthRequiredResponse response =
   1942         net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
   1943     if (canceled) {
   1944       response = net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_CANCEL_AUTH;
   1945     } else if (credentials_set) {
   1946       response = net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_SET_AUTH;
   1947     }
   1948     net::NetworkDelegate::AuthCallback callback = blocked_request.auth_callback;
   1949     blocked_requests_.erase(request_id);
   1950     if (call_callback)
   1951       callback.Run(response);
   1952   } else {
   1953     blocked_requests_.erase(request_id);
   1954   }
   1955   return rv;
   1956 }
   1957 
   1958 bool ExtensionWebRequestEventRouter::ProcessDeclarativeRules(
   1959     void* browser_context,
   1960     InfoMap* extension_info_map,
   1961     const std::string& event_name,
   1962     net::URLRequest* request,
   1963     extensions::RequestStage request_stage,
   1964     const net::HttpResponseHeaders* original_response_headers) {
   1965   extensions::WebViewRendererState::WebViewInfo web_view_info;
   1966   bool is_web_view_guest = GetWebViewInfo(request, &web_view_info);
   1967 
   1968   extensions::RulesRegistry::WebViewKey webview_key(
   1969       is_web_view_guest ? web_view_info.embedder_process_id : 0,
   1970       is_web_view_guest ? web_view_info.instance_id : 0);
   1971   RulesRegistryKey rules_key(browser_context, webview_key);
   1972   // If this check fails, check that the active stages are up-to-date in
   1973   // extensions/browser/api/declarative_webrequest/request_stage.h .
   1974   DCHECK(request_stage & extensions::kActiveStages);
   1975 
   1976   // Rules of the current |browser_context| may apply but we need to check also
   1977   // whether there are applicable rules from extensions whose background page
   1978   // spans from regular to incognito mode.
   1979 
   1980   // First parameter identifies the registry, the second indicates whether the
   1981   // registry belongs to the cross browser_context.
   1982   typedef std::pair<extensions::WebRequestRulesRegistry*, bool>
   1983       RelevantRegistry;
   1984   typedef std::vector<RelevantRegistry> RelevantRegistries;
   1985   RelevantRegistries relevant_registries;
   1986 
   1987   if (rules_registries_.find(rules_key) != rules_registries_.end()) {
   1988     relevant_registries.push_back(
   1989         std::make_pair(rules_registries_[rules_key].get(), false));
   1990   }
   1991 
   1992   void* cross_browser_context = GetCrossBrowserContext(browser_context);
   1993   RulesRegistryKey cross_browser_context_rules_key(
   1994       cross_browser_context, webview_key);
   1995   if (cross_browser_context &&
   1996       rules_registries_.find(cross_browser_context_rules_key) !=
   1997           rules_registries_.end()) {
   1998     relevant_registries.push_back(
   1999         std::make_pair(
   2000             rules_registries_[cross_browser_context_rules_key].get(), true));
   2001   }
   2002 
   2003   // The following block is experimentally enabled and its impact on load time
   2004   // logged with UMA Extensions.NetworkDelayRegistryLoad. crbug.com/175961
   2005   for (RelevantRegistries::iterator i = relevant_registries.begin();
   2006        i != relevant_registries.end(); ++i) {
   2007     extensions::WebRequestRulesRegistry* rules_registry = i->first;
   2008     if (!rules_registry->ready().is_signaled()) {
   2009       // The rules registry is still loading. Block this request until it
   2010       // finishes.
   2011       rules_registry->ready().Post(
   2012           FROM_HERE,
   2013           base::Bind(&ExtensionWebRequestEventRouter::OnRulesRegistryReady,
   2014                      AsWeakPtr(),
   2015                      browser_context,
   2016                      event_name,
   2017                      request->identifier(),
   2018                      request_stage));
   2019       blocked_requests_[request->identifier()].num_handlers_blocking++;
   2020       blocked_requests_[request->identifier()].request = request;
   2021       blocked_requests_[request->identifier()].is_incognito |=
   2022           IsIncognitoBrowserContext(browser_context);
   2023       blocked_requests_[request->identifier()].blocking_time =
   2024           base::Time::Now();
   2025       blocked_requests_[request->identifier()].original_response_headers =
   2026           original_response_headers;
   2027       blocked_requests_[request->identifier()].extension_info_map =
   2028           extension_info_map;
   2029       return true;
   2030     }
   2031   }
   2032 
   2033   base::Time start = base::Time::Now();
   2034 
   2035   bool deltas_created = false;
   2036   for (RelevantRegistries::iterator i = relevant_registries.begin();
   2037        i != relevant_registries.end(); ++i) {
   2038     extensions::WebRequestRulesRegistry* rules_registry =
   2039         i->first;
   2040     helpers::EventResponseDeltas result =
   2041         rules_registry->CreateDeltas(
   2042             extension_info_map,
   2043             extensions::WebRequestData(
   2044                 request, request_stage, original_response_headers),
   2045             i->second);
   2046 
   2047     if (!result.empty()) {
   2048       helpers::EventResponseDeltas& deltas =
   2049           blocked_requests_[request->identifier()].response_deltas;
   2050       deltas.insert(deltas.end(), result.begin(), result.end());
   2051       deltas_created = true;
   2052     }
   2053   }
   2054 
   2055   base::TimeDelta elapsed_time = start - base::Time::Now();
   2056   UMA_HISTOGRAM_TIMES("Extensions.DeclarativeWebRequestNetworkDelay",
   2057                       elapsed_time);
   2058 
   2059   return deltas_created;
   2060 }
   2061 
   2062 void ExtensionWebRequestEventRouter::OnRulesRegistryReady(
   2063     void* browser_context,
   2064     const std::string& event_name,
   2065     uint64 request_id,
   2066     extensions::RequestStage request_stage) {
   2067   // It's possible that this request was deleted, or cancelled by a previous
   2068   // event handler. If so, ignore this response.
   2069   if (blocked_requests_.find(request_id) == blocked_requests_.end())
   2070     return;
   2071 
   2072   BlockedRequest& blocked_request = blocked_requests_[request_id];
   2073   base::TimeDelta block_time =
   2074       base::Time::Now() - blocked_request.blocking_time;
   2075   UMA_HISTOGRAM_TIMES("Extensions.NetworkDelayRegistryLoad", block_time);
   2076 
   2077   ProcessDeclarativeRules(browser_context,
   2078                           blocked_request.extension_info_map,
   2079                           event_name,
   2080                           blocked_request.request,
   2081                           request_stage,
   2082                           blocked_request.original_response_headers.get());
   2083   // Reset to NULL so that nobody relies on this being set.
   2084   blocked_request.extension_info_map = NULL;
   2085   DecrementBlockCount(
   2086       browser_context, std::string(), event_name, request_id, NULL);
   2087 }
   2088 
   2089 bool ExtensionWebRequestEventRouter::GetAndSetSignaled(uint64 request_id,
   2090                                                        EventTypes event_type) {
   2091   SignaledRequestMap::iterator iter = signaled_requests_.find(request_id);
   2092   if (iter == signaled_requests_.end()) {
   2093     signaled_requests_[request_id] = event_type;
   2094     return false;
   2095   }
   2096   bool was_signaled_before = (iter->second & event_type) != 0;
   2097   iter->second |= event_type;
   2098   return was_signaled_before;
   2099 }
   2100 
   2101 void ExtensionWebRequestEventRouter::ClearSignaled(uint64 request_id,
   2102                                                    EventTypes event_type) {
   2103   SignaledRequestMap::iterator iter = signaled_requests_.find(request_id);
   2104   if (iter == signaled_requests_.end())
   2105     return;
   2106   iter->second &= ~event_type;
   2107 }
   2108 
   2109 // Special QuotaLimitHeuristic for WebRequestHandlerBehaviorChangedFunction.
   2110 //
   2111 // Each call of webRequest.handlerBehaviorChanged() clears the in-memory cache
   2112 // of WebKit at the time of the next page load (top level navigation event).
   2113 // This quota heuristic is intended to limit the number of times the cache is
   2114 // cleared by an extension.
   2115 //
   2116 // As we want to account for the number of times the cache is really cleared
   2117 // (opposed to the number of times webRequest.handlerBehaviorChanged() is
   2118 // called), we cannot decide whether a call of
   2119 // webRequest.handlerBehaviorChanged() should trigger a quota violation at the
   2120 // time it is called. Instead we only decrement the bucket counter at the time
   2121 // when the cache is cleared (when page loads happen).
   2122 class ClearCacheQuotaHeuristic : public extensions::QuotaLimitHeuristic {
   2123  public:
   2124   ClearCacheQuotaHeuristic(const Config& config, BucketMapper* map)
   2125       : QuotaLimitHeuristic(
   2126             config,
   2127             map,
   2128             "MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES"),
   2129         callback_registered_(false),
   2130         weak_ptr_factory_(this) {}
   2131   virtual ~ClearCacheQuotaHeuristic() {}
   2132   virtual bool Apply(Bucket* bucket,
   2133                      const base::TimeTicks& event_time) OVERRIDE;
   2134 
   2135  private:
   2136   // Callback that is triggered by the ExtensionWebRequestEventRouter on a page
   2137   // load.
   2138   //
   2139   // We don't need to take care of the life time of |bucket|: It is owned by the
   2140   // BucketMapper of our base class in |QuotaLimitHeuristic::bucket_mapper_|. As
   2141   // long as |this| exists, the respective BucketMapper and its bucket will
   2142   // exist as well.
   2143   void OnPageLoad(Bucket* bucket);
   2144 
   2145   // Flag to prevent that we register more than one call back in-between
   2146   // clearing the cache.
   2147   bool callback_registered_;
   2148 
   2149   base::WeakPtrFactory<ClearCacheQuotaHeuristic> weak_ptr_factory_;
   2150 
   2151   DISALLOW_COPY_AND_ASSIGN(ClearCacheQuotaHeuristic);
   2152 };
   2153 
   2154 bool ClearCacheQuotaHeuristic::Apply(Bucket* bucket,
   2155                                      const base::TimeTicks& event_time) {
   2156   if (event_time > bucket->expiration())
   2157     bucket->Reset(config(), event_time);
   2158 
   2159   // Call bucket->DeductToken() on a new page load, this is when
   2160   // webRequest.handlerBehaviorChanged() clears the cache.
   2161   if (!callback_registered_) {
   2162     ExtensionWebRequestEventRouter::GetInstance()->AddCallbackForPageLoad(
   2163         base::Bind(&ClearCacheQuotaHeuristic::OnPageLoad,
   2164                    weak_ptr_factory_.GetWeakPtr(),
   2165                    bucket));
   2166     callback_registered_ = true;
   2167   }
   2168 
   2169   // We only check whether tokens are left here. Deducting a token happens in
   2170   // OnPageLoad().
   2171   return bucket->has_tokens();
   2172 }
   2173 
   2174 void ClearCacheQuotaHeuristic::OnPageLoad(Bucket* bucket) {
   2175   callback_registered_ = false;
   2176   bucket->DeductToken();
   2177 }
   2178 
   2179 bool WebRequestInternalAddEventListenerFunction::RunSync() {
   2180   // Argument 0 is the callback, which we don't use here.
   2181   ExtensionWebRequestEventRouter::RequestFilter filter;
   2182   base::DictionaryValue* value = NULL;
   2183   error_.clear();
   2184   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &value));
   2185   // Failure + an empty error string means a fatal error.
   2186   EXTENSION_FUNCTION_VALIDATE(filter.InitFromValue(*value, &error_) ||
   2187                               !error_.empty());
   2188   if (!error_.empty())
   2189     return false;
   2190 
   2191   int extra_info_spec = 0;
   2192   if (HasOptionalArgument(2)) {
   2193     base::ListValue* value = NULL;
   2194     EXTENSION_FUNCTION_VALIDATE(args_->GetList(2, &value));
   2195     EXTENSION_FUNCTION_VALIDATE(
   2196         ExtensionWebRequestEventRouter::ExtraInfoSpec::InitFromValue(
   2197             *value, &extra_info_spec));
   2198   }
   2199 
   2200   std::string event_name;
   2201   EXTENSION_FUNCTION_VALIDATE(args_->GetString(3, &event_name));
   2202 
   2203   std::string sub_event_name;
   2204   EXTENSION_FUNCTION_VALIDATE(args_->GetString(4, &sub_event_name));
   2205 
   2206   int webview_instance_id = 0;
   2207   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(5, &webview_instance_id));
   2208 
   2209   base::WeakPtr<extensions::ExtensionMessageFilter> ipc_sender =
   2210       ipc_sender_weak();
   2211   int embedder_process_id =
   2212       ipc_sender.get() ? ipc_sender->render_process_id() : -1;
   2213 
   2214   const Extension* extension =
   2215       extension_info_map()->extensions().GetByID(extension_id());
   2216   std::string extension_name = extension ? extension->name() : extension_id();
   2217 
   2218   bool is_web_view_guest = webview_instance_id != 0;
   2219   // We check automatically whether the extension has the 'webRequest'
   2220   // permission. For blocking calls we require the additional permission
   2221   // 'webRequestBlocking'.
   2222   if ((!is_web_view_guest &&
   2223        extra_info_spec &
   2224            (ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING |
   2225             ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING)) &&
   2226       !extension->permissions_data()->HasAPIPermission(
   2227           extensions::APIPermission::kWebRequestBlocking)) {
   2228     error_ = keys::kBlockingPermissionRequired;
   2229     return false;
   2230   }
   2231 
   2232   // We allow to subscribe to patterns that are broader than the host
   2233   // permissions. E.g., we could subscribe to http://www.example.com/*
   2234   // while having host permissions for http://www.example.com/foo/* and
   2235   // http://www.example.com/bar/*.
   2236   // For this reason we do only a coarse check here to warn the extension
   2237   // developer if he does something obviously wrong.
   2238   if (!is_web_view_guest &&
   2239       extension->permissions_data()->GetEffectiveHostPermissions().is_empty()) {
   2240     error_ = keys::kHostPermissionsRequired;
   2241     return false;
   2242   }
   2243 
   2244   bool success =
   2245       ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
   2246           profile_id(), extension_id(), extension_name,
   2247           event_name, sub_event_name, filter, extra_info_spec,
   2248           embedder_process_id, webview_instance_id, ipc_sender_weak());
   2249   EXTENSION_FUNCTION_VALIDATE(success);
   2250 
   2251   helpers::ClearCacheOnNavigation();
   2252 
   2253   BrowserThread::PostTask(BrowserThread::UI,
   2254                           FROM_HERE,
   2255                           base::Bind(&helpers::NotifyWebRequestAPIUsed,
   2256                                      profile_id(),
   2257                                      make_scoped_refptr(extension)));
   2258 
   2259   return true;
   2260 }
   2261 
   2262 void WebRequestInternalEventHandledFunction::RespondWithError(
   2263     const std::string& event_name,
   2264     const std::string& sub_event_name,
   2265     uint64 request_id,
   2266     scoped_ptr<ExtensionWebRequestEventRouter::EventResponse> response,
   2267     const std::string& error) {
   2268   error_ = error;
   2269   ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled(
   2270       profile_id(),
   2271       extension_id(),
   2272       event_name,
   2273       sub_event_name,
   2274       request_id,
   2275       response.release());
   2276 }
   2277 
   2278 bool WebRequestInternalEventHandledFunction::RunSync() {
   2279   std::string event_name;
   2280   EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &event_name));
   2281 
   2282   std::string sub_event_name;
   2283   EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &sub_event_name));
   2284 
   2285   std::string request_id_str;
   2286   EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &request_id_str));
   2287   uint64 request_id;
   2288   EXTENSION_FUNCTION_VALIDATE(base::StringToUint64(request_id_str,
   2289                                                    &request_id));
   2290 
   2291   scoped_ptr<ExtensionWebRequestEventRouter::EventResponse> response;
   2292   if (HasOptionalArgument(3)) {
   2293     base::DictionaryValue* value = NULL;
   2294     EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(3, &value));
   2295 
   2296     if (!value->empty()) {
   2297       base::Time install_time =
   2298           extension_info_map()->GetInstallTime(extension_id());
   2299       response.reset(new ExtensionWebRequestEventRouter::EventResponse(
   2300           extension_id(), install_time));
   2301     }
   2302 
   2303     if (value->HasKey("cancel")) {
   2304       // Don't allow cancel mixed with other keys.
   2305       if (value->size() != 1) {
   2306         RespondWithError(event_name,
   2307                          sub_event_name,
   2308                          request_id,
   2309                          response.Pass(),
   2310                          keys::kInvalidBlockingResponse);
   2311         return false;
   2312       }
   2313 
   2314       bool cancel = false;
   2315       EXTENSION_FUNCTION_VALIDATE(value->GetBoolean("cancel", &cancel));
   2316       response->cancel = cancel;
   2317     }
   2318 
   2319     if (value->HasKey("redirectUrl")) {
   2320       std::string new_url_str;
   2321       EXTENSION_FUNCTION_VALIDATE(value->GetString("redirectUrl",
   2322                                                    &new_url_str));
   2323       response->new_url = GURL(new_url_str);
   2324       if (!response->new_url.is_valid()) {
   2325         RespondWithError(event_name,
   2326                          sub_event_name,
   2327                          request_id,
   2328                          response.Pass(),
   2329                          ErrorUtils::FormatErrorMessage(
   2330                              keys::kInvalidRedirectUrl, new_url_str));
   2331         return false;
   2332       }
   2333     }
   2334 
   2335     const bool hasRequestHeaders = value->HasKey("requestHeaders");
   2336     const bool hasResponseHeaders = value->HasKey("responseHeaders");
   2337     if (hasRequestHeaders || hasResponseHeaders) {
   2338       if (hasRequestHeaders && hasResponseHeaders) {
   2339         // Allow only one of the keys, not both.
   2340         RespondWithError(event_name,
   2341                          sub_event_name,
   2342                          request_id,
   2343                          response.Pass(),
   2344                          keys::kInvalidHeaderKeyCombination);
   2345         return false;
   2346       }
   2347 
   2348       base::ListValue* headers_value = NULL;
   2349       scoped_ptr<net::HttpRequestHeaders> request_headers;
   2350       scoped_ptr<helpers::ResponseHeaders> response_headers;
   2351       if (hasRequestHeaders) {
   2352         request_headers.reset(new net::HttpRequestHeaders());
   2353         EXTENSION_FUNCTION_VALIDATE(value->GetList(keys::kRequestHeadersKey,
   2354                                                    &headers_value));
   2355       } else {
   2356         response_headers.reset(new helpers::ResponseHeaders());
   2357         EXTENSION_FUNCTION_VALIDATE(value->GetList(keys::kResponseHeadersKey,
   2358                                                    &headers_value));
   2359       }
   2360 
   2361       for (size_t i = 0; i < headers_value->GetSize(); ++i) {
   2362         base::DictionaryValue* header_value = NULL;
   2363         std::string name;
   2364         std::string value;
   2365         EXTENSION_FUNCTION_VALIDATE(
   2366             headers_value->GetDictionary(i, &header_value));
   2367         if (!FromHeaderDictionary(header_value, &name, &value)) {
   2368           std::string serialized_header;
   2369           base::JSONWriter::Write(header_value, &serialized_header);
   2370           RespondWithError(event_name,
   2371                            sub_event_name,
   2372                            request_id,
   2373                            response.Pass(),
   2374                            ErrorUtils::FormatErrorMessage(keys::kInvalidHeader,
   2375                                                           serialized_header));
   2376           return false;
   2377         }
   2378         if (!net::HttpUtil::IsValidHeaderName(name)) {
   2379           RespondWithError(event_name,
   2380                            sub_event_name,
   2381                            request_id,
   2382                            response.Pass(),
   2383                            keys::kInvalidHeaderName);
   2384           return false;
   2385         }
   2386         if (!net::HttpUtil::IsValidHeaderValue(value)) {
   2387           RespondWithError(event_name,
   2388                            sub_event_name,
   2389                            request_id,
   2390                            response.Pass(),
   2391                            ErrorUtils::FormatErrorMessage(
   2392                                keys::kInvalidHeaderValue, name));
   2393           return false;
   2394         }
   2395         if (hasRequestHeaders)
   2396           request_headers->SetHeader(name, value);
   2397         else
   2398           response_headers->push_back(helpers::ResponseHeader(name, value));
   2399       }
   2400       if (hasRequestHeaders)
   2401         response->request_headers.reset(request_headers.release());
   2402       else
   2403         response->response_headers.reset(response_headers.release());
   2404     }
   2405 
   2406     if (value->HasKey(keys::kAuthCredentialsKey)) {
   2407       base::DictionaryValue* credentials_value = NULL;
   2408       EXTENSION_FUNCTION_VALIDATE(value->GetDictionary(
   2409           keys::kAuthCredentialsKey,
   2410           &credentials_value));
   2411       base::string16 username;
   2412       base::string16 password;
   2413       EXTENSION_FUNCTION_VALIDATE(
   2414           credentials_value->GetString(keys::kUsernameKey, &username));
   2415       EXTENSION_FUNCTION_VALIDATE(
   2416           credentials_value->GetString(keys::kPasswordKey, &password));
   2417       response->auth_credentials.reset(
   2418           new net::AuthCredentials(username, password));
   2419     }
   2420   }
   2421 
   2422   ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled(
   2423       profile_id(), extension_id(), event_name, sub_event_name, request_id,
   2424       response.release());
   2425 
   2426   return true;
   2427 }
   2428 
   2429 void WebRequestHandlerBehaviorChangedFunction::GetQuotaLimitHeuristics(
   2430     extensions::QuotaLimitHeuristics* heuristics) const {
   2431   extensions::QuotaLimitHeuristic::Config config = {
   2432       // See web_request.json for current value.
   2433       web_request::MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES,
   2434       base::TimeDelta::FromMinutes(10)};
   2435   extensions::QuotaLimitHeuristic::BucketMapper* bucket_mapper =
   2436       new extensions::QuotaLimitHeuristic::SingletonBucketMapper();
   2437   ClearCacheQuotaHeuristic* heuristic =
   2438       new ClearCacheQuotaHeuristic(config, bucket_mapper);
   2439   heuristics->push_back(heuristic);
   2440 }
   2441 
   2442 void WebRequestHandlerBehaviorChangedFunction::OnQuotaExceeded(
   2443     const std::string& violation_error) {
   2444   // Post warning message.
   2445   WarningSet warnings;
   2446   warnings.insert(
   2447       Warning::CreateRepeatedCacheFlushesWarning(extension_id()));
   2448   BrowserThread::PostTask(
   2449       BrowserThread::UI,
   2450       FROM_HERE,
   2451       base::Bind(&WarningService::NotifyWarningsOnUI, profile_id(), warnings));
   2452 
   2453   // Continue gracefully.
   2454   RunSync();
   2455 }
   2456 
   2457 bool WebRequestHandlerBehaviorChangedFunction::RunSync() {
   2458   helpers::ClearCacheOnNavigation();
   2459   return true;
   2460 }
   2461