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