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