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