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