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