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