172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// found in the LICENSE file. 472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/extensions/extension_webrequest_api.h" 672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <algorithm> 872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/json/json_writer.h" 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/metrics/histogram.h" 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/string_number_conversions.h" 1272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/values.h" 13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/extensions/extension_event_router_forwarder.h" 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_tab_id_map.h" 1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/extensions/extension_webrequest_api_constants.h" 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/profiles/profile.h" 1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/common/extensions/extension.h" 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/extensions/extension_error_utils.h" 1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/common/extensions/extension_extent.h" 2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/common/extensions/url_pattern.h" 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/url_constants.h" 22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h" 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/renderer_host/resource_dispatcher_host.h" 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/renderer_host/resource_dispatcher_host_request_info.h" 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/net_errors.h" 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/url_request/url_request.h" 2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "googleurl/src/gurl.h" 2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsennamespace keys = extension_webrequest_api_constants; 3072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsennamespace { 3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// List of all the webRequest events. 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const char* const kWebRequestEvents[] = { 3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen keys::kOnBeforeRedirect, 3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen keys::kOnBeforeRequest, 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen keys::kOnBeforeSendHeaders, 3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen keys::kOnCompleted, 3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen keys::kOnErrorOccurred, 4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen keys::kOnHeadersReceived, 4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen keys::kOnRequestSent 4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}; 4372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const char* kResourceTypeStrings[] = { 4572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "main_frame", 4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "sub_frame", 4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "stylesheet", 4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "script", 4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "image", 5072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "object", 5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "other", 5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}; 5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic ResourceType::Type kResourceTypeValues[] = { 55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResourceType::MAIN_FRAME, 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResourceType::SUB_FRAME, 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResourceType::STYLESHEET, 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResourceType::SCRIPT, 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResourceType::IMAGE, 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResourceType::OBJECT, 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResourceType::LAST_TYPE, // represents "other" 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenCOMPILE_ASSERT( 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen arraysize(kResourceTypeStrings) == arraysize(kResourceTypeValues), 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen keep_resource_types_in_sync); 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#define ARRAYEND(array) (array + arraysize(array)) 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic bool IsWebRequestEvent(const std::string& event_name) { 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return std::find(kWebRequestEvents, ARRAYEND(kWebRequestEvents), 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen event_name) != ARRAYEND(kWebRequestEvents); 7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const char* ResourceTypeToString(ResourceType::Type type) { 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResourceType::Type* iter = 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::find(kResourceTypeValues, ARRAYEND(kResourceTypeValues), type); 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (iter == ARRAYEND(kResourceTypeValues)) 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return "other"; 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return kResourceTypeStrings[iter - kResourceTypeValues]; 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic bool ParseResourceType(const std::string& type_str, 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResourceType::Type* type) { 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const char** iter = 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::find(kResourceTypeStrings, ARRAYEND(kResourceTypeStrings), type_str); 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (iter == ARRAYEND(kResourceTypeStrings)) 89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *type = kResourceTypeValues[iter - kResourceTypeStrings]; 91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic void ExtractRequestInfo(net::URLRequest* request, 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int* tab_id, 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int* window_id, 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResourceType::Type* resource_type) { 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!request->GetUserData(NULL)) 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResourceDispatcherHostRequestInfo* info = 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResourceDispatcherHost::InfoForRequest(request); 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExtensionTabIdMap::GetInstance()->GetTabAndWindowId( 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen info->child_id(), info->route_id(), tab_id, window_id); 105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Restrict the resource type to the values we care about. 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResourceType::Type* iter = 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::find(kResourceTypeValues, ARRAYEND(kResourceTypeValues), 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen info->resource_type()); 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *resource_type = (iter != ARRAYEND(kResourceTypeValues)) ? 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *iter : ResourceType::LAST_TYPE; 11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic void AddEventListenerOnIOThread( 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileId profile_id, 11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& extension_id, 11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& event_name, 11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& sub_event_name, 11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const ExtensionWebRequestEventRouter::RequestFilter& filter, 12072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int extra_info_spec) { 12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen profile_id, extension_id, event_name, sub_event_name, filter, 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen extra_info_spec); 12472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 12572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic void EventHandledOnIOThread( 127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileId profile_id, 128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& extension_id, 129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& event_name, 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& sub_event_name, 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen uint64 request_id, 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool cancel, 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const GURL& new_url) { 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled( 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen profile_id, extension_id, event_name, sub_event_name, request_id, 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cancel, new_url); 13772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 13872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} // namespace 14072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 14172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Internal representation of the webRequest.RequestFilter type, used to 14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// filter what network events an extension cares about. 14372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstruct ExtensionWebRequestEventRouter::RequestFilter { 14472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ExtensionExtent urls; 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<ResourceType::Type> types; 14672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int tab_id; 14772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int window_id; 14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RequestFilter() : tab_id(-1), window_id(-1) {} 15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool InitFromValue(const DictionaryValue& value); 15172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}; 15272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 15372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Internal representation of the extraInfoSpec parameter on webRequest events, 15472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// used to specify extra information to be included with network events. 15572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstruct ExtensionWebRequestEventRouter::ExtraInfoSpec { 15672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen enum Flags { 15772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen REQUEST_LINE = 1<<0, 15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen REQUEST_HEADERS = 1<<1, 15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen STATUS_LINE = 1<<2, 16072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen RESPONSE_HEADERS = 1<<3, 16172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen REDIRECT_REQUEST_LINE = 1<<4, 16272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen REDIRECT_REQUEST_HEADERS = 1<<5, 163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BLOCKING = 1<<6, 16472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }; 16572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 16672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen static bool InitFromValue(const ListValue& value, int* extra_info_spec); 16772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}; 16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 16972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Represents a single unique listener to an event, along with whatever filter 17072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// parameters and extra_info_spec were specified at the time the listener was 17172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// added. 17272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstruct ExtensionWebRequestEventRouter::EventListener { 17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string extension_id; 17472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string sub_event_name; 17572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen RequestFilter filter; 17672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int extra_info_spec; 177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen mutable std::set<uint64> blocked_requests; 17872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 17972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Comparator to work with std::set. 18072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool operator<(const EventListener& that) const { 18172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (extension_id < that.extension_id) 18272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return true; 18372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (extension_id == that.extension_id && 18472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen sub_event_name < that.sub_event_name) 18572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return true; 18672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 18772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 18872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}; 18972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Contains info about requests that are blocked waiting for a response from 191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// an extension. 192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstruct ExtensionWebRequestEventRouter::BlockedRequest { 193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The number of event handlers that we are awaiting a response from. 194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int num_handlers_blocking; 195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The callback to call when we get a response from all event handlers. 197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::CompletionCallback* callback; 198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If non-empty, this contains the new URL that the request will redirect to. 200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GURL* new_url; 201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Time the request was issued. Used for logging purposes. 203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::Time request_time; 204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BlockedRequest() : num_handlers_blocking(0), callback(NULL), new_url(NULL) {} 206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 20872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool ExtensionWebRequestEventRouter::RequestFilter::InitFromValue( 20972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const DictionaryValue& value) { 21072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (DictionaryValue::key_iterator key = value.begin_keys(); 21172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen key != value.end_keys(); ++key) { 21272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (*key == "urls") { 21372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ListValue* urls_value = NULL; 21472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!value.GetList("urls", &urls_value)) 21572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 21672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (size_t i = 0; i < urls_value->GetSize(); ++i) { 21772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string url; 21872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen URLPattern pattern(URLPattern::SCHEME_ALL); 21972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!urls_value->GetString(i, &url) || 220dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen pattern.Parse(url, URLPattern::PARSE_STRICT) != 221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen URLPattern::PARSE_SUCCESS) 22272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 22372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen urls.AddPattern(pattern); 22472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 22572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else if (*key == "types") { 22672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ListValue* types_value = NULL; 227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!value.GetList("types", &types_value)) 22872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 22972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (size_t i = 0; i < types_value->GetSize(); ++i) { 230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string type_str; 231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResourceType::Type type; 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!types_value->GetString(i, &type_str) || 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen !ParseResourceType(type_str, &type)) 23472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 23572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen types.push_back(type); 23672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 23772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else if (*key == "tabId") { 23872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!value.GetInteger("tabId", &tab_id)) 23972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 24072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else if (*key == "windowId") { 24172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!value.GetInteger("windowId", &window_id)) 24272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 24372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 24472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 24572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 24672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 24772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return true; 24872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 24972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 25072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static 25172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool ExtensionWebRequestEventRouter::ExtraInfoSpec::InitFromValue( 25272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const ListValue& value, int* extra_info_spec) { 25372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *extra_info_spec = 0; 25472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (size_t i = 0; i < value.GetSize(); ++i) { 25572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string str; 25672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!value.GetString(i, &str)) 25772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 25872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 25972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // TODO(mpcomplete): not all of these are valid for every event. 26072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (str == "requestLine") 26172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *extra_info_spec |= REQUEST_LINE; 26272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen else if (str == "requestHeaders") 26372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *extra_info_spec |= REQUEST_HEADERS; 26472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen else if (str == "statusLine") 26572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *extra_info_spec |= STATUS_LINE; 26672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen else if (str == "responseHeaders") 26772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *extra_info_spec |= RESPONSE_HEADERS; 26872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen else if (str == "redirectRequestLine") 26972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *extra_info_spec |= REDIRECT_REQUEST_LINE; 27072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen else if (str == "redirectRequestHeaders") 27172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *extra_info_spec |= REDIRECT_REQUEST_HEADERS; 272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen else if (str == "blocking") 273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *extra_info_spec |= BLOCKING; 27472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen else 27572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 27672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 27772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return true; 27872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 27972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 28072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static 28172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenExtensionWebRequestEventRouter* ExtensionWebRequestEventRouter::GetInstance() { 28272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return Singleton<ExtensionWebRequestEventRouter>::get(); 28372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 28472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 28572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenExtensionWebRequestEventRouter::ExtensionWebRequestEventRouter() { 28672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 28772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 28872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenExtensionWebRequestEventRouter::~ExtensionWebRequestEventRouter() { 28972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 29072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint ExtensionWebRequestEventRouter::OnBeforeRequest( 292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileId profile_id, 293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExtensionEventRouterForwarder* event_router, 294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::URLRequest* request, 295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::CompletionCallback* callback, 296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GURL* new_url) { 297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(jochen): Figure out what to do with events from the system context. 298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (profile_id == Profile::kInvalidProfileId) 299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return net::OK; 300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int tab_id = -1; 302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int window_id = -1; 303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResourceType::Type resource_type = ResourceType::LAST_TYPE; 304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExtractRequestInfo(request, &tab_id, &window_id, &resource_type); 305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<const EventListener*> listeners = 307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetMatchingListeners(profile_id, keys::kOnBeforeRequest, request->url(), 308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_id, window_id, resource_type); 309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (listeners.empty()) 310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return net::OK; 311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If this is an HTTP request, keep track of it. HTTP-specific events only 313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // have the request ID, so we'll need to look up the URLRequest from that. 314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (request->url().SchemeIs(chrome::kHttpScheme) || 315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen request->url().SchemeIs(chrome::kHttpsScheme)) { 316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen http_requests_[request->identifier()] = request; 317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ListValue args; 320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DictionaryValue* dict = new DictionaryValue(); 321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dict->SetString(keys::kRequestIdKey, 322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::Uint64ToString(request->identifier())); 323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dict->SetString(keys::kUrlKey, request->url().spec()); 324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dict->SetString(keys::kMethodKey, request->method()); 325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dict->SetInteger(keys::kTabIdKey, tab_id); 326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dict->SetString(keys::kTypeKey, ResourceTypeToString(resource_type)); 327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dict->SetDouble(keys::kTimeStampKey, 328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen request->request_time().ToDoubleT() * 1000); 329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen args.Append(dict); 330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (DispatchEvent(profile_id, event_router, request, callback, listeners, 332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen args)) { 333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen blocked_requests_[request->identifier()].new_url = new_url; 334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return net::ERR_IO_PENDING; 335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return net::OK; 33772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 33872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint ExtensionWebRequestEventRouter::OnBeforeSendHeaders( 340dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ProfileId profile_id, 341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExtensionEventRouterForwarder* event_router, 342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen uint64 request_id, 343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::CompletionCallback* callback, 344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::HttpRequestHeaders* headers) { 345dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // TODO(jochen): Figure out what to do with events from the system context. 346dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (profile_id == Profile::kInvalidProfileId) 347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return net::OK; 348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 349ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen HttpRequestMap::iterator iter = http_requests_.find(request_id); 350ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (iter == http_requests_.end()) 351ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return net::OK; 352ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 353ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::URLRequest* request = iter->second; 354ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen http_requests_.erase(iter); 355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 35672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::vector<const EventListener*> listeners = 357ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetMatchingListeners(profile_id, keys::kOnBeforeSendHeaders, request); 35872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (listeners.empty()) 359ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return net::OK; 36072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 36172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ListValue args; 36272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DictionaryValue* dict = new DictionaryValue(); 363ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dict->SetString(keys::kRequestIdKey, 364ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::Uint64ToString(request->identifier())); 365ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dict->SetString(keys::kUrlKey, request->url().spec()); 366ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dict->SetDouble(keys::kTimeStampKey, 367ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen request->request_time().ToDoubleT() * 1000); 368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(mpcomplete): request headers. 36972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen args.Append(dict); 37072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 371ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (DispatchEvent(profile_id, event_router, request, callback, listeners, 372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen args)) 373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return net::ERR_IO_PENDING; 374ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return net::OK; 375ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 376ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 377ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionWebRequestEventRouter::OnURLRequestDestroyed( 378ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileId profile_id, net::URLRequest* request) { 379ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen http_requests_.erase(request->identifier()); 380ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen blocked_requests_.erase(request->identifier()); 381ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 382ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 383ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ExtensionWebRequestEventRouter::DispatchEvent( 384ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileId profile_id, 385ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExtensionEventRouterForwarder* event_router, 386ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::URLRequest* request, 387ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::CompletionCallback* callback, 388ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::vector<const EventListener*>& listeners, 389ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const ListValue& args) { 39072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string json_args; 39172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::JSONWriter::Write(&args, false, &json_args); 39272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 393ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(mpcomplete): Consider consolidating common (extension_id,json_args) 394ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // pairs into a single message sent to a list of sub_event_names. 395ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int num_handlers_blocking = 0; 396ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (std::vector<const EventListener*>::const_iterator it = listeners.begin(); 39772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen it != listeners.end(); ++it) { 39872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen event_router->DispatchEventToExtension( 399dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen (*it)->extension_id, (*it)->sub_event_name, json_args, 400dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen profile_id, true, GURL()); 401ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (callback && (*it)->extra_info_spec & ExtraInfoSpec::BLOCKING) { 402ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (*it)->blocked_requests.insert(request->identifier()); 403ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ++num_handlers_blocking; 404ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 405ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 406ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 407ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (num_handlers_blocking > 0) { 408ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CHECK(blocked_requests_.find(request->identifier()) == 409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen blocked_requests_.end()); 410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen blocked_requests_[request->identifier()].num_handlers_blocking = 411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen num_handlers_blocking; 412ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen blocked_requests_[request->identifier()].callback = callback; 413ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen blocked_requests_[request->identifier()].request_time = 414ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen request->request_time(); 415ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 416ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 41772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 418ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 420ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 421ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 422ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionWebRequestEventRouter::OnEventHandled( 423ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileId profile_id, 424ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& extension_id, 425ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& event_name, 426ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& sub_event_name, 427ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen uint64 request_id, 428ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool cancel, 429ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const GURL& new_url) { 430ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EventListener listener; 431ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen listener.extension_id = extension_id; 432ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen listener.sub_event_name = sub_event_name; 433ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 434ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The listener may have been removed (e.g. due to the process going away) 435ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // before we got here. 436ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::set<EventListener>::iterator found = 437ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen listeners_[profile_id][event_name].find(listener); 438ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (found != listeners_[profile_id][event_name].end()) 439ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen found->blocked_requests.erase(request_id); 440ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 441ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DecrementBlockCount(request_id, cancel, new_url); 44272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 44372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 44472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ExtensionWebRequestEventRouter::AddEventListener( 445ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileId profile_id, 44672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& extension_id, 44772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& event_name, 44872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& sub_event_name, 44972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const RequestFilter& filter, 45072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int extra_info_spec) { 45172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!IsWebRequestEvent(event_name)) 45272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 45372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 45472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EventListener listener; 45572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen listener.extension_id = extension_id; 45672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen listener.sub_event_name = sub_event_name; 45772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen listener.filter = filter; 45872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen listener.extra_info_spec = extra_info_spec; 45972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 460ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CHECK_EQ(listeners_[profile_id][event_name].count(listener), 0u) << 46172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "extension=" << extension_id << " event=" << event_name; 462ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen listeners_[profile_id][event_name].insert(listener); 46372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 46472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 46572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ExtensionWebRequestEventRouter::RemoveEventListener( 466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileId profile_id, 46772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& extension_id, 46872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& sub_event_name) { 46972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen size_t slash_sep = sub_event_name.find('/'); 47072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string event_name = sub_event_name.substr(0, slash_sep); 47172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 47272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!IsWebRequestEvent(event_name)) 47372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 47472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 47572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EventListener listener; 47672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen listener.extension_id = extension_id; 47772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen listener.sub_event_name = sub_event_name; 47872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 479ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CHECK_EQ(listeners_[profile_id][event_name].count(listener), 1u) << 48072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "extension=" << extension_id << " event=" << event_name; 481ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 482ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Unblock any request that this event listener may have been blocking. 483ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::set<EventListener>::iterator found = 484ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen listeners_[profile_id][event_name].find(listener); 485ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (std::set<uint64>::iterator it = found->blocked_requests.begin(); 486ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen it != found->blocked_requests.end(); ++it) { 487ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DecrementBlockCount(*it, false, GURL()); 488ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 489ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 490ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen listeners_[profile_id][event_name].erase(listener); 49172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 49272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 49372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstd::vector<const ExtensionWebRequestEventRouter::EventListener*> 49472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenExtensionWebRequestEventRouter::GetMatchingListeners( 495ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileId profile_id, 496ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& event_name, 497ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const GURL& url, 498ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int tab_id, 499ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int window_id, 500ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResourceType::Type resource_type) { 501ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(mpcomplete): handle profile_id == invalid (should collect all 502ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // listeners). 50372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::vector<const EventListener*> matching_listeners; 504ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::set<EventListener>& listeners = listeners_[profile_id][event_name]; 50572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (std::set<EventListener>::iterator it = listeners.begin(); 50672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen it != listeners.end(); ++it) { 507ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!it->filter.urls.is_empty() && !it->filter.urls.ContainsURL(url)) 508ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen continue; 509ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (it->filter.tab_id != -1 && tab_id != it->filter.tab_id) 510ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen continue; 511ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (it->filter.window_id != -1 && window_id != it->filter.window_id) 512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen continue; 513ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!it->filter.types.empty() && 514ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::find(it->filter.types.begin(), it->filter.types.end(), 515ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen resource_type) == it->filter.types.end()) 516ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen continue; 517ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 518ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen matching_listeners.push_back(&(*it)); 51972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 52072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return matching_listeners; 52172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 52272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 523ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstd::vector<const ExtensionWebRequestEventRouter::EventListener*> 524ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenExtensionWebRequestEventRouter::GetMatchingListeners( 525ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProfileId profile_id, 526ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& event_name, 527ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::URLRequest* request) { 528ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int tab_id = -1; 529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int window_id = -1; 530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ResourceType::Type resource_type = ResourceType::LAST_TYPE; 531ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ExtractRequestInfo(request, &tab_id, &window_id, &resource_type); 532ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 533ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return GetMatchingListeners( 534ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen profile_id, event_name, request->url(), tab_id, window_id, resource_type); 535ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 536ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 537ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ExtensionWebRequestEventRouter::DecrementBlockCount(uint64 request_id, 538ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool cancel, 539ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const GURL& new_url) { 540ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // It's possible that this request was deleted, or cancelled by a previous 541ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // event handler. If so, ignore this response. 542ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (blocked_requests_.find(request_id) == blocked_requests_.end()) 543ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 544ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 545ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BlockedRequest& blocked_request = blocked_requests_[request_id]; 546ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int num_handlers_blocking = --blocked_request.num_handlers_blocking; 547ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CHECK_GE(num_handlers_blocking, 0); 548ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 549ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (num_handlers_blocking == 0 || cancel || !new_url.is_empty()) { 550ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen HISTOGRAM_TIMES("Extensions.NetworkDelay", 551ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::Time::Now() - blocked_request.request_time); 552ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 553ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CHECK(blocked_request.callback); 554ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!new_url.is_empty()) { 555ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CHECK(new_url.is_valid()); 556ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *blocked_request.new_url = new_url; 557ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen blocked_request.callback->Run(cancel ? net::ERR_EMPTY_RESPONSE : net::OK); 559ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen blocked_requests_.erase(request_id); 560ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 561ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 562ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 56372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool WebRequestAddEventListener::RunImpl() { 56472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Argument 0 is the callback, which we don't use here. 56572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 56672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ExtensionWebRequestEventRouter::RequestFilter filter; 56772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (HasOptionalArgument(1)) { 56872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DictionaryValue* value = NULL; 56972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &value)); 57072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EXTENSION_FUNCTION_VALIDATE(filter.InitFromValue(*value)); 57172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 57272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 57372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int extra_info_spec = 0; 57472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (HasOptionalArgument(2)) { 57572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ListValue* value = NULL; 57672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EXTENSION_FUNCTION_VALIDATE(args_->GetList(2, &value)); 57772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EXTENSION_FUNCTION_VALIDATE( 57872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ExtensionWebRequestEventRouter::ExtraInfoSpec::InitFromValue( 57972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *value, &extra_info_spec)); 58072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 58172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 58272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string event_name; 58372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EXTENSION_FUNCTION_VALIDATE(args_->GetString(3, &event_name)); 58472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 58572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string sub_event_name; 58672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EXTENSION_FUNCTION_VALIDATE(args_->GetString(4, &sub_event_name)); 58772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 58872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BrowserThread::PostTask( 58972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BrowserThread::IO, FROM_HERE, 59072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NewRunnableFunction( 59172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &AddEventListenerOnIOThread, 592ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen profile()->GetRuntimeId(), extension_id(), 593ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen event_name, sub_event_name, filter, extra_info_spec)); 594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 595ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 596ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 597ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 598ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool WebRequestEventHandled::RunImpl() { 599ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string event_name; 600ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &event_name)); 601ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 602ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string sub_event_name; 603ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &sub_event_name)); 604ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 605ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string request_id_str; 606ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &request_id_str)); 607ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(mpcomplete): string-to-uint64? 608ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 request_id; 609ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXTENSION_FUNCTION_VALIDATE(base::StringToInt64(request_id_str, &request_id)); 610ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 611ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool cancel = false; 612ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GURL new_url; 613ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (HasOptionalArgument(3)) { 614ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DictionaryValue* value = NULL; 615ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(3, &value)); 616ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 617ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (value->HasKey("cancel")) 618ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXTENSION_FUNCTION_VALIDATE(value->GetBoolean("cancel", &cancel)); 619ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 620ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string new_url_str; 621ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (value->HasKey("redirectUrl")) { 622ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EXTENSION_FUNCTION_VALIDATE(value->GetString("redirectUrl", 623ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &new_url_str)); 624ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new_url = GURL(new_url_str); 625ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!new_url.is_valid()) { 626ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen error_ = ExtensionErrorUtils::FormatErrorMessage( 627ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen keys::kInvalidRedirectUrl, new_url_str); 628ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 629ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 630ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 631ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 632ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 633ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserThread::PostTask( 634ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserThread::IO, FROM_HERE, 635ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NewRunnableFunction( 636ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &EventHandledOnIOThread, 637ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen profile()->GetRuntimeId(), extension_id(), 638ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen event_name, sub_event_name, request_id, cancel, new_url)); 63972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 64072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return true; 64172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 642