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