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