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