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