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