Chromium Code Reviews| 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 |