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