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