| 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[] = { |
| 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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 false; |
| 302 | 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; |
| 310 } |
| 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 dict->SetDouble(keys::kTimeStampKey, | 320 dict->SetDouble(keys::kTimeStampKey, |
| 312 request->request_time().ToDoubleT() * 1000); | 321 request->request_time().ToDoubleT() * 1000); |
| 313 args.Append(dict); | 322 args.Append(dict); |
| 314 | 323 |
| 324 return DispatchEvent(profile_id, event_router, request, callback, listeners, |
| 325 args); |
| 326 } |
| 327 |
| 328 bool 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 false; |
| 337 |
| 338 HttpRequestMap::iterator iter = http_requests_.find(request_id); |
| 339 if (iter == http_requests_.end()) |
| 340 return false; |
| 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 false; |
| 349 |
| 350 ListValue args; |
| 351 DictionaryValue* dict = new DictionaryValue(); |
| 352 dict->SetString(keys::kUrlKey, request->url().spec()); |
| 353 dict->SetDouble(keys::kTimeStampKey, base::Time::Now().ToDoubleT() * 1000); |
| 354 // TODO(mpcomplete): request headers. |
| 355 return DispatchEvent(profile_id, event_router, request, callback, listeners, |
| 356 args); |
| 357 } |
| 358 |
| 359 void ExtensionWebRequestEventRouter::OnURLRequestDestroyed( |
| 360 ProfileId profile_id, net::URLRequest* request) { |
| 361 http_requests_.erase(request->identifier()); |
| 362 } |
| 363 |
| 364 bool ExtensionWebRequestEventRouter::DispatchEvent( |
| 365 ProfileId profile_id, |
| 366 ExtensionEventRouterForwarder* event_router, |
| 367 net::URLRequest* request, |
| 368 net::CompletionCallback* callback, |
| 369 const std::vector<const EventListener*>& listeners, |
| 370 const ListValue& args) { |
| 315 std::string json_args; | 371 std::string json_args; |
| 316 base::JSONWriter::Write(&args, false, &json_args); | 372 base::JSONWriter::Write(&args, false, &json_args); |
| 317 | 373 |
| 318 // TODO(mpcomplete): Consider consolidating common (extension_id,json_args) | 374 // TODO(mpcomplete): Consider consolidating common (extension_id,json_args) |
| 319 // pairs into a single message sent to a list of sub_event_names. | 375 // pairs into a single message sent to a list of sub_event_names. |
| 320 int num_handlers_blocking = 0; | 376 int num_handlers_blocking = 0; |
| 321 for (std::vector<const EventListener*>::iterator it = listeners.begin(); | 377 for (std::vector<const EventListener*>::const_iterator it = listeners.begin(); |
| 322 it != listeners.end(); ++it) { | 378 it != listeners.end(); ++it) { |
| 323 event_router->DispatchEventToExtension( | 379 event_router->DispatchEventToExtension( |
| 324 (*it)->extension_id, (*it)->sub_event_name, json_args, | 380 (*it)->extension_id, (*it)->sub_event_name, json_args, |
| 325 profile_id, true, GURL()); | 381 profile_id, true, GURL()); |
| 326 if ((*it)->extra_info_spec & ExtraInfoSpec::BLOCKING) { | 382 if (callback && (*it)->extra_info_spec & ExtraInfoSpec::BLOCKING) { |
| 327 (*it)->blocked_requests.insert(request->identifier()); | 383 (*it)->blocked_requests.insert(request->identifier()); |
| 328 ++num_handlers_blocking; | 384 ++num_handlers_blocking; |
| 329 } | 385 } |
| 330 } | 386 } |
| 331 | 387 |
| 332 if (num_handlers_blocking > 0) { | 388 if (num_handlers_blocking > 0) { |
| 333 CHECK(blocked_requests_.find(request->identifier()) == | 389 CHECK(blocked_requests_.find(request->identifier()) == |
| 334 blocked_requests_.end()); | 390 blocked_requests_.end()); |
| 335 blocked_requests_[request->identifier()].num_handlers_blocking = | 391 blocked_requests_[request->identifier()].num_handlers_blocking = |
| 336 num_handlers_blocking; | 392 num_handlers_blocking; |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 if (!it->filter.types.empty() && | 493 if (!it->filter.types.empty() && |
| 438 std::find(it->filter.types.begin(), it->filter.types.end(), | 494 std::find(it->filter.types.begin(), it->filter.types.end(), |
| 439 resource_type) == it->filter.types.end()) | 495 resource_type) == it->filter.types.end()) |
| 440 continue; | 496 continue; |
| 441 | 497 |
| 442 matching_listeners.push_back(&(*it)); | 498 matching_listeners.push_back(&(*it)); |
| 443 } | 499 } |
| 444 return matching_listeners; | 500 return matching_listeners; |
| 445 } | 501 } |
| 446 | 502 |
| 503 std::vector<const ExtensionWebRequestEventRouter::EventListener*> |
| 504 ExtensionWebRequestEventRouter::GetMatchingListeners( |
| 505 ProfileId profile_id, |
| 506 const std::string& event_name, |
| 507 net::URLRequest* request) { |
| 508 int tab_id = -1; |
| 509 int window_id = -1; |
| 510 ResourceType::Type resource_type = ResourceType::LAST_TYPE; |
| 511 ExtractRequestInfo(request, &tab_id, &window_id, &resource_type); |
| 512 |
| 513 return GetMatchingListeners( |
| 514 profile_id, event_name, request->url(), tab_id, window_id, resource_type); |
| 515 } |
| 516 |
| 447 void ExtensionWebRequestEventRouter::DecrementBlockCount(uint64 request_id, | 517 void ExtensionWebRequestEventRouter::DecrementBlockCount(uint64 request_id, |
| 448 bool cancel) { | 518 bool cancel) { |
| 449 // It's possible that this request was already cancelled by a previous event | 519 // It's possible that this request was already cancelled by a previous event |
| 450 // handler. If so, ignore this response. | 520 // handler. If so, ignore this response. |
| 451 if (blocked_requests_.find(request_id) == blocked_requests_.end()) | 521 if (blocked_requests_.find(request_id) == blocked_requests_.end()) |
| 452 return; | 522 return; |
| 453 | 523 |
| 454 BlockedRequest& blocked_request = blocked_requests_[request_id]; | 524 BlockedRequest& blocked_request = blocked_requests_[request_id]; |
| 455 int num_handlers_blocking = --blocked_request.num_handlers_blocking; | 525 int num_handlers_blocking = --blocked_request.num_handlers_blocking; |
| 456 CHECK_GE(num_handlers_blocking, 0); | 526 CHECK_GE(num_handlers_blocking, 0); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 | 594 |
| 525 BrowserThread::PostTask( | 595 BrowserThread::PostTask( |
| 526 BrowserThread::IO, FROM_HERE, | 596 BrowserThread::IO, FROM_HERE, |
| 527 NewRunnableFunction( | 597 NewRunnableFunction( |
| 528 &EventHandledOnIOThread, | 598 &EventHandledOnIOThread, |
| 529 profile()->GetRuntimeId(), extension_id(), | 599 profile()->GetRuntimeId(), extension_id(), |
| 530 event_name, sub_event_name, request_id, cancel)); | 600 event_name, sub_event_name, request_id, cancel)); |
| 531 | 601 |
| 532 return true; | 602 return true; |
| 533 } | 603 } |
| OLD | NEW |