OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/extension_webrequest_api.h" | 5 #include "chrome/browser/extensions/extension_webrequest_api.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/json/json_writer.h" | 9 #include "base/json/json_writer.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
11 #include "base/string_number_conversions.h" | 11 #include "base/string_number_conversions.h" |
12 #include "base/values.h" | 12 #include "base/values.h" |
13 #include "chrome/browser/extensions/extension_event_router_forwarder.h" | 13 #include "chrome/browser/extensions/extension_event_router_forwarder.h" |
14 #include "chrome/browser/extensions/extension_tab_id_map.h" | 14 #include "chrome/browser/extensions/extension_tab_id_map.h" |
15 #include "chrome/browser/extensions/extension_webrequest_api_constants.h" | 15 #include "chrome/browser/extensions/extension_webrequest_api_constants.h" |
16 #include "chrome/browser/profiles/profile.h" | 16 #include "chrome/browser/profiles/profile.h" |
17 #include "chrome/common/extensions/extension.h" | 17 #include "chrome/common/extensions/extension.h" |
18 #include "chrome/common/extensions/extension_extent.h" | 18 #include "chrome/common/extensions/extension_extent.h" |
19 #include "chrome/common/extensions/url_pattern.h" | 19 #include "chrome/common/extensions/url_pattern.h" |
20 #include "chrome/common/url_constants.h" | |
20 #include "content/browser/browser_thread.h" | 21 #include "content/browser/browser_thread.h" |
21 #include "content/browser/renderer_host/resource_dispatcher_host.h" | 22 #include "content/browser/renderer_host/resource_dispatcher_host.h" |
22 #include "content/browser/renderer_host/resource_dispatcher_host_request_info.h" | 23 #include "content/browser/renderer_host/resource_dispatcher_host_request_info.h" |
23 #include "net/base/net_errors.h" | 24 #include "net/base/net_errors.h" |
24 #include "net/url_request/url_request.h" | 25 #include "net/url_request/url_request.h" |
25 #include "googleurl/src/gurl.h" | 26 #include "googleurl/src/gurl.h" |
26 | 27 |
27 namespace keys = extension_webrequest_api_constants; | 28 namespace keys = extension_webrequest_api_constants; |
28 | 29 |
29 namespace { | 30 namespace { |
30 | 31 |
31 // List of all the webRequest events. | 32 // List of all the webRequest events. |
32 static const char *kWebRequestEvents[] = { | 33 static const char *kWebRequestEvents[] = { |
willchan no longer on Chromium
2011/03/26 01:46:49
Where's OnRequestDeleted?
Nit: FYI, these should
Matt Perry
2011/03/28 22:51:01
These are only the extension-visible events. Exten
willchan no longer on Chromium
2011/03/29 20:46:27
OK, I defer to you here. Just noting that this mea
| |
33 keys::kOnBeforeRedirect, | 34 keys::kOnBeforeRedirect, |
34 keys::kOnBeforeRequest, | 35 keys::kOnBeforeRequest, |
36 keys::kOnBeforeSendHeaders, | |
35 keys::kOnCompleted, | 37 keys::kOnCompleted, |
36 keys::kOnErrorOccurred, | 38 keys::kOnErrorOccurred, |
37 keys::kOnHeadersReceived, | 39 keys::kOnHeadersReceived, |
38 keys::kOnRequestSent | 40 keys::kOnRequestSent |
39 }; | 41 }; |
40 | 42 |
41 static const char* kResourceTypeStrings[] = { | 43 static const char* kResourceTypeStrings[] = { |
42 "main_frame", | 44 "main_frame", |
43 "sub_frame", | 45 "sub_frame", |
44 "stylesheet", | 46 "stylesheet", |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
148 // Internal representation of the extraInfoSpec parameter on webRequest events, | 150 // Internal representation of the extraInfoSpec parameter on webRequest events, |
149 // used to specify extra information to be included with network events. | 151 // used to specify extra information to be included with network events. |
150 struct ExtensionWebRequestEventRouter::ExtraInfoSpec { | 152 struct ExtensionWebRequestEventRouter::ExtraInfoSpec { |
151 enum Flags { | 153 enum Flags { |
152 REQUEST_LINE = 1<<0, | 154 REQUEST_LINE = 1<<0, |
153 REQUEST_HEADERS = 1<<1, | 155 REQUEST_HEADERS = 1<<1, |
154 STATUS_LINE = 1<<2, | 156 STATUS_LINE = 1<<2, |
155 RESPONSE_HEADERS = 1<<3, | 157 RESPONSE_HEADERS = 1<<3, |
156 REDIRECT_REQUEST_LINE = 1<<4, | 158 REDIRECT_REQUEST_LINE = 1<<4, |
157 REDIRECT_REQUEST_HEADERS = 1<<5, | 159 REDIRECT_REQUEST_HEADERS = 1<<5, |
158 BLOCKING = 1<<5, | 160 BLOCKING = 1<<6, |
159 }; | 161 }; |
160 | 162 |
161 static bool InitFromValue(const ListValue& value, int* extra_info_spec); | 163 static bool InitFromValue(const ListValue& value, int* extra_info_spec); |
162 }; | 164 }; |
163 | 165 |
164 // Represents a single unique listener to an event, along with whatever filter | 166 // Represents a single unique listener to an event, along with whatever filter |
165 // parameters and extra_info_spec were specified at the time the listener was | 167 // parameters and extra_info_spec were specified at the time the listener was |
166 // added. | 168 // added. |
167 struct ExtensionWebRequestEventRouter::EventListener { | 169 struct ExtensionWebRequestEventRouter::EventListener { |
168 std::string extension_id; | 170 std::string extension_id; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
273 ExtensionWebRequestEventRouter* ExtensionWebRequestEventRouter::GetInstance() { | 275 ExtensionWebRequestEventRouter* ExtensionWebRequestEventRouter::GetInstance() { |
274 return Singleton<ExtensionWebRequestEventRouter>::get(); | 276 return Singleton<ExtensionWebRequestEventRouter>::get(); |
275 } | 277 } |
276 | 278 |
277 ExtensionWebRequestEventRouter::ExtensionWebRequestEventRouter() { | 279 ExtensionWebRequestEventRouter::ExtensionWebRequestEventRouter() { |
278 } | 280 } |
279 | 281 |
280 ExtensionWebRequestEventRouter::~ExtensionWebRequestEventRouter() { | 282 ExtensionWebRequestEventRouter::~ExtensionWebRequestEventRouter() { |
281 } | 283 } |
282 | 284 |
283 bool ExtensionWebRequestEventRouter::OnBeforeRequest( | 285 int ExtensionWebRequestEventRouter::OnBeforeRequest( |
284 ProfileId profile_id, | 286 ProfileId profile_id, |
285 ExtensionEventRouterForwarder* event_router, | 287 ExtensionEventRouterForwarder* event_router, |
286 net::URLRequest* request, | 288 net::URLRequest* request, |
287 net::CompletionCallback* callback) { | 289 net::CompletionCallback* callback) { |
288 // TODO(jochen): Figure out what to do with events from the system context. | 290 // TODO(jochen): Figure out what to do with events from the system context. |
289 if (profile_id == Profile::kInvalidProfileId) | 291 if (profile_id == Profile::kInvalidProfileId) |
290 return false; | 292 return net::OK; |
291 | 293 |
292 int tab_id = -1; | 294 int tab_id = -1; |
293 int window_id = -1; | 295 int window_id = -1; |
294 ResourceType::Type resource_type = ResourceType::LAST_TYPE; | 296 ResourceType::Type resource_type = ResourceType::LAST_TYPE; |
295 ExtractRequestInfo(request, &tab_id, &window_id, &resource_type); | 297 ExtractRequestInfo(request, &tab_id, &window_id, &resource_type); |
296 | 298 |
297 std::vector<const EventListener*> listeners = | 299 std::vector<const EventListener*> listeners = |
298 GetMatchingListeners(profile_id, keys::kOnBeforeRequest, request->url(), | 300 GetMatchingListeners(profile_id, keys::kOnBeforeRequest, request->url(), |
299 tab_id, window_id, resource_type); | 301 tab_id, window_id, resource_type); |
300 if (listeners.empty()) | 302 if (listeners.empty()) |
301 return false; | 303 return net::OK; |
304 | |
305 // If this is an HTTP request, keep track of it. HTTP-specific events only | |
306 // have the request ID, so we'll need to look up the URLRequest from that. | |
307 if (request->url().SchemeIs(chrome::kHttpScheme) || | |
308 request->url().SchemeIs(chrome::kHttpsScheme)) { | |
309 http_requests_[request->identifier()] = request; | |
willchan no longer on Chromium
2011/03/26 01:46:49
As discussed previously, this may include more tha
Matt Perry
2011/03/28 22:51:01
OK. I think it doesn't affect anything if these ar
willchan no longer on Chromium
2011/03/29 20:46:27
No there isn't. I suspect that eventually you'll w
| |
310 } | |
302 | 311 |
303 ListValue args; | 312 ListValue args; |
304 DictionaryValue* dict = new DictionaryValue(); | 313 DictionaryValue* dict = new DictionaryValue(); |
305 dict->SetString(keys::kRequestIdKey, | 314 dict->SetString(keys::kRequestIdKey, |
306 base::Uint64ToString(request->identifier())); | 315 base::Uint64ToString(request->identifier())); |
307 dict->SetString(keys::kUrlKey, request->url().spec()); | 316 dict->SetString(keys::kUrlKey, request->url().spec()); |
308 dict->SetString(keys::kMethodKey, request->method()); | 317 dict->SetString(keys::kMethodKey, request->method()); |
309 dict->SetInteger(keys::kTabIdKey, tab_id); | 318 dict->SetInteger(keys::kTabIdKey, tab_id); |
310 dict->SetString(keys::kTypeKey, ResourceTypeToString(resource_type)); | 319 dict->SetString(keys::kTypeKey, ResourceTypeToString(resource_type)); |
311 args.Append(dict); | 320 args.Append(dict); |
312 | 321 |
322 if (DispatchEvent(profile_id, event_router, request, callback, listeners, | |
323 args)) | |
324 return net::ERR_IO_PENDING; | |
325 return net::OK; | |
326 } | |
327 | |
328 int ExtensionWebRequestEventRouter::OnBeforeSendHeaders( | |
329 ProfileId profile_id, | |
330 ExtensionEventRouterForwarder* event_router, | |
331 uint64 request_id, | |
332 net::HttpRequestHeaders* headers, | |
333 net::CompletionCallback* callback) { | |
334 // TODO(jochen): Figure out what to do with events from the system context. | |
335 if (profile_id == Profile::kInvalidProfileId) | |
336 return net::OK; | |
337 | |
338 HttpRequestMap::iterator iter = http_requests_.find(request_id); | |
339 if (iter == http_requests_.end()) | |
340 return net::OK; | |
341 | |
342 net::URLRequest* request = iter->second; | |
343 http_requests_.erase(iter); | |
344 | |
345 std::vector<const EventListener*> listeners = | |
346 GetMatchingListeners(profile_id, keys::kOnBeforeSendHeaders, request); | |
347 if (listeners.empty()) | |
348 return net::OK; | |
349 | |
350 ListValue args; | |
351 DictionaryValue* dict = new DictionaryValue(); | |
352 dict->SetString(keys::kRequestIdKey, | |
353 base::Uint64ToString(request->identifier())); | |
354 dict->SetString(keys::kUrlKey, request->url().spec()); | |
355 dict->SetDouble(keys::kTimeStampKey, base::Time::Now().ToDoubleT() * 1000); | |
356 // TODO(mpcomplete): request headers. | |
357 args.Append(dict); | |
358 | |
359 if (DispatchEvent(profile_id, event_router, request, callback, listeners, | |
360 args)) | |
361 return net::ERR_IO_PENDING; | |
362 return net::OK; | |
363 } | |
364 | |
365 void ExtensionWebRequestEventRouter::OnURLRequestDestroyed( | |
366 ProfileId profile_id, net::URLRequest* request) { | |
367 http_requests_.erase(request->identifier()); | |
willchan no longer on Chromium
2011/03/26 01:46:49
Doesn't erase() cause crashes if the key doesn't e
Matt Perry
2011/03/28 22:51:01
No, that's not an error.
willchan no longer on Chromium
2011/03/29 20:46:27
Learn something new everyday.
| |
368 } | |
369 | |
370 bool ExtensionWebRequestEventRouter::DispatchEvent( | |
371 ProfileId profile_id, | |
372 ExtensionEventRouterForwarder* event_router, | |
373 net::URLRequest* request, | |
374 net::CompletionCallback* callback, | |
375 const std::vector<const EventListener*>& listeners, | |
376 const ListValue& args) { | |
313 std::string json_args; | 377 std::string json_args; |
314 base::JSONWriter::Write(&args, false, &json_args); | 378 base::JSONWriter::Write(&args, false, &json_args); |
315 | 379 |
316 // TODO(mpcomplete): Consider consolidating common (extension_id,json_args) | 380 // TODO(mpcomplete): Consider consolidating common (extension_id,json_args) |
317 // pairs into a single message sent to a list of sub_event_names. | 381 // pairs into a single message sent to a list of sub_event_names. |
318 int num_handlers_blocking = 0; | 382 int num_handlers_blocking = 0; |
319 for (std::vector<const EventListener*>::iterator it = listeners.begin(); | 383 for (std::vector<const EventListener*>::const_iterator it = listeners.begin(); |
320 it != listeners.end(); ++it) { | 384 it != listeners.end(); ++it) { |
321 event_router->DispatchEventToExtension( | 385 event_router->DispatchEventToExtension( |
322 (*it)->extension_id, (*it)->sub_event_name, json_args, | 386 (*it)->extension_id, (*it)->sub_event_name, json_args, |
323 profile_id, true, GURL()); | 387 profile_id, true, GURL()); |
324 if ((*it)->extra_info_spec & ExtraInfoSpec::BLOCKING) { | 388 if (callback && (*it)->extra_info_spec & ExtraInfoSpec::BLOCKING) { |
325 (*it)->blocked_requests.insert(request->identifier()); | 389 (*it)->blocked_requests.insert(request->identifier()); |
326 ++num_handlers_blocking; | 390 ++num_handlers_blocking; |
327 } | 391 } |
328 } | 392 } |
329 | 393 |
330 if (num_handlers_blocking > 0) { | 394 if (num_handlers_blocking > 0) { |
331 CHECK(blocked_requests_.find(request->identifier()) == | 395 CHECK(blocked_requests_.find(request->identifier()) == |
332 blocked_requests_.end()); | 396 blocked_requests_.end()); |
333 blocked_requests_[request->identifier()].num_handlers_blocking = | 397 blocked_requests_[request->identifier()].num_handlers_blocking = |
334 num_handlers_blocking; | 398 num_handlers_blocking; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
435 if (!it->filter.types.empty() && | 499 if (!it->filter.types.empty() && |
436 std::find(it->filter.types.begin(), it->filter.types.end(), | 500 std::find(it->filter.types.begin(), it->filter.types.end(), |
437 resource_type) == it->filter.types.end()) | 501 resource_type) == it->filter.types.end()) |
438 continue; | 502 continue; |
439 | 503 |
440 matching_listeners.push_back(&(*it)); | 504 matching_listeners.push_back(&(*it)); |
441 } | 505 } |
442 return matching_listeners; | 506 return matching_listeners; |
443 } | 507 } |
444 | 508 |
509 std::vector<const ExtensionWebRequestEventRouter::EventListener*> | |
510 ExtensionWebRequestEventRouter::GetMatchingListeners( | |
511 ProfileId profile_id, | |
512 const std::string& event_name, | |
513 net::URLRequest* request) { | |
514 int tab_id = -1; | |
515 int window_id = -1; | |
516 ResourceType::Type resource_type = ResourceType::LAST_TYPE; | |
517 ExtractRequestInfo(request, &tab_id, &window_id, &resource_type); | |
518 | |
519 return GetMatchingListeners( | |
520 profile_id, event_name, request->url(), tab_id, window_id, resource_type); | |
521 } | |
522 | |
445 void ExtensionWebRequestEventRouter::DecrementBlockCount(uint64 request_id, | 523 void ExtensionWebRequestEventRouter::DecrementBlockCount(uint64 request_id, |
446 bool cancel) { | 524 bool cancel) { |
447 // It's possible that this request was already cancelled by a previous event | 525 // It's possible that this request was already cancelled by a previous event |
448 // handler. If so, ignore this response. | 526 // handler. If so, ignore this response. |
449 if (blocked_requests_.find(request_id) == blocked_requests_.end()) | 527 if (blocked_requests_.find(request_id) == blocked_requests_.end()) |
450 return; | 528 return; |
451 | 529 |
452 BlockedRequest& blocked_request = blocked_requests_[request_id]; | 530 BlockedRequest& blocked_request = blocked_requests_[request_id]; |
453 int num_handlers_blocking = --blocked_request.num_handlers_blocking; | 531 int num_handlers_blocking = --blocked_request.num_handlers_blocking; |
454 CHECK_GE(num_handlers_blocking, 0); | 532 CHECK_GE(num_handlers_blocking, 0); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
522 | 600 |
523 BrowserThread::PostTask( | 601 BrowserThread::PostTask( |
524 BrowserThread::IO, FROM_HERE, | 602 BrowserThread::IO, FROM_HERE, |
525 NewRunnableFunction( | 603 NewRunnableFunction( |
526 &EventHandledOnIOThread, | 604 &EventHandledOnIOThread, |
527 profile()->GetRuntimeId(), extension_id(), | 605 profile()->GetRuntimeId(), extension_id(), |
528 event_name, sub_event_name, request_id, cancel)); | 606 event_name, sub_event_name, request_id, cancel)); |
529 | 607 |
530 return true; | 608 return true; |
531 } | 609 } |
OLD | NEW |