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