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