// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/api/web_request/web_request_api.h"

#include <algorithm>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/json/json_writer.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/extensions/activity_log/activity_action_constants.h"
#include "chrome/browser/extensions/activity_log/activity_actions.h"
#include "chrome/browser/extensions/activity_log/activity_log.h"
#include "chrome/browser/extensions/activity_log/web_request_constants.h"
#include "chrome/browser/extensions/api/declarative_webrequest/request_stage.h"
#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h"
#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h"
#include "chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.h"
#include "chrome/browser/extensions/api/web_request/upload_data_presenter.h"
#include "chrome/browser/extensions/api/web_request/web_request_api_constants.h"
#include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h"
#include "chrome/browser/extensions/api/web_request/web_request_time_tracker.h"
#include "chrome/browser/extensions/event_router.h"
#include "chrome/browser/extensions/extension_info_map.h"
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extension_renderer_state.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/extension_warning_service.h"
#include "chrome/browser/extensions/extension_warning_set.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/renderer_host/chrome_render_message_filter.h"
#include "chrome/common/extensions/api/web_request.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension_messages.h"
#include "chrome/common/extensions/permissions/permissions_data.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/user_metrics.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/event_filtering_info.h"
#include "extensions/common/features/feature.h"
#include "extensions/common/url_pattern.h"
#include "grit/generated_resources.h"
#include "net/base/auth.h"
#include "net/base/net_errors.h"
#include "net/base/upload_data_stream.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"

using base::DictionaryValue;
using base::ListValue;
using base::StringValue;
using chrome::VersionInfo;
using content::BrowserMessageFilter;
using content::BrowserThread;
using content::ResourceRequestInfo;
using extensions::ErrorUtils;
using extensions::Extension;
using extensions::ExtensionWarning;
using extensions::ExtensionWarningService;
using extensions::ExtensionWarningSet;
using extensions::Feature;
using extensions::web_navigation_api_helpers::GetFrameId;

namespace helpers = extension_web_request_api_helpers;
namespace keys = extension_web_request_api_constants;
namespace web_request = extensions::api::web_request;
namespace declarative_keys = extensions::declarative_webrequest_constants;
namespace activitylog = activity_log_web_request_constants;

namespace {

const char kWebRequest[] = "webRequest";
const char kWebView[] = "webview";

// List of all the webRequest events.
const char* const kWebRequestEvents[] = {
  keys::kOnBeforeRedirectEvent,
  web_request::OnBeforeRequest::kEventName,
  keys::kOnBeforeSendHeadersEvent,
  keys::kOnCompletedEvent,
  web_request::OnErrorOccurred::kEventName,
  keys::kOnSendHeadersEvent,
  keys::kOnAuthRequiredEvent,
  keys::kOnResponseStartedEvent,
  keys::kOnHeadersReceivedEvent,
};

#define ARRAYEND(array) (array + arraysize(array))

const char* GetRequestStageAsString(
    ExtensionWebRequestEventRouter::EventTypes type) {
  switch (type) {
    case ExtensionWebRequestEventRouter::kInvalidEvent:
      return "Invalid";
    case ExtensionWebRequestEventRouter::kOnBeforeRequest:
      return keys::kOnBeforeRequest;
    case ExtensionWebRequestEventRouter::kOnBeforeSendHeaders:
      return keys::kOnBeforeSendHeaders;
    case ExtensionWebRequestEventRouter::kOnSendHeaders:
      return keys::kOnSendHeaders;
    case ExtensionWebRequestEventRouter::kOnHeadersReceived:
      return keys::kOnHeadersReceived;
    case ExtensionWebRequestEventRouter::kOnBeforeRedirect:
      return keys::kOnBeforeRedirect;
    case ExtensionWebRequestEventRouter::kOnAuthRequired:
      return keys::kOnAuthRequired;
    case ExtensionWebRequestEventRouter::kOnResponseStarted:
      return keys::kOnResponseStarted;
    case ExtensionWebRequestEventRouter::kOnErrorOccurred:
      return keys::kOnErrorOccurred;
    case ExtensionWebRequestEventRouter::kOnCompleted:
      return keys::kOnCompleted;
  }
  NOTREACHED();
  return "Not reached";
}

bool IsWebRequestEvent(const std::string& event_name) {
  std::string web_request_event_name(event_name);
  if (web_request_event_name.find(kWebView) != std::string::npos)
    web_request_event_name.replace(0, sizeof(kWebView) - 1, kWebRequest);
  return std::find(kWebRequestEvents, ARRAYEND(kWebRequestEvents),
                   web_request_event_name) != ARRAYEND(kWebRequestEvents);
}

// Returns whether |request| has been triggered by an extension in
// |extension_info_map|.
bool IsRequestFromExtension(const net::URLRequest* request,
                            const ExtensionInfoMap* extension_info_map) {
  // |extension_info_map| is NULL for system-level requests.
  if (!extension_info_map)
    return false;

  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);

  // If this request was not created by the ResourceDispatcher, |info| is NULL.
  // All requests from extensions are created by the ResourceDispatcher.
  if (!info)
    return false;

  return extension_info_map->process_map().Contains(info->GetChildID());
}

void ExtractRequestInfoDetails(net::URLRequest* request,
                               bool* is_main_frame,
                               int64* frame_id,
                               bool* parent_is_main_frame,
                               int64* parent_frame_id,
                               int* tab_id,
                               int* window_id,
                               int* render_process_host_id,
                               int* routing_id,
                               ResourceType::Type* resource_type) {
  if (!request->GetUserData(NULL))
    return;

  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
  ExtensionRendererState::GetInstance()->GetTabAndWindowId(
      info->GetChildID(), info->GetRouteID(), tab_id, window_id);
  *frame_id = info->GetFrameID();
  *is_main_frame = info->IsMainFrame();
  *parent_frame_id = info->GetParentFrameID();
  *parent_is_main_frame = info->ParentIsMainFrame();
  *render_process_host_id = info->GetChildID();
  *routing_id = info->GetRouteID();

  // Restrict the resource type to the values we care about.
  if (helpers::IsRelevantResourceType(info->GetResourceType()))
    *resource_type = info->GetResourceType();
  else
    *resource_type = ResourceType::LAST_TYPE;
}

// Extracts from |request| information for the keys requestId, url, method,
// frameId, tabId, type, and timeStamp and writes these into |out| to be passed
// on to extensions.
void ExtractRequestInfo(net::URLRequest* request, DictionaryValue* out) {
  bool is_main_frame = false;
  int64 frame_id = -1;
  bool parent_is_main_frame = false;
  int64 parent_frame_id = -1;
  int frame_id_for_extension = -1;
  int parent_frame_id_for_extension = -1;
  int tab_id = -1;
  int window_id = -1;
  int render_process_host_id = -1;
  int routing_id = -1;
  ResourceType::Type resource_type = ResourceType::LAST_TYPE;
  ExtractRequestInfoDetails(request, &is_main_frame, &frame_id,
                            &parent_is_main_frame, &parent_frame_id, &tab_id,
                            &window_id, &render_process_host_id, &routing_id,
                            &resource_type);
  frame_id_for_extension = GetFrameId(is_main_frame, frame_id);
  parent_frame_id_for_extension = GetFrameId(parent_is_main_frame,
                                             parent_frame_id);

  out->SetString(keys::kRequestIdKey,
                 base::Uint64ToString(request->identifier()));
  out->SetString(keys::kUrlKey, request->url().spec());
  out->SetString(keys::kMethodKey, request->method());
  out->SetInteger(keys::kFrameIdKey, frame_id_for_extension);
  out->SetInteger(keys::kParentFrameIdKey, parent_frame_id_for_extension);
  out->SetInteger(keys::kTabIdKey, tab_id);
  out->SetString(keys::kTypeKey, helpers::ResourceTypeToString(resource_type));
  out->SetDouble(keys::kTimeStampKey, base::Time::Now().ToDoubleT() * 1000);
}

// Extracts the body from |request| and writes the data into |out|.
void ExtractRequestInfoBody(const net::URLRequest* request,
                            DictionaryValue* out) {
  const net::UploadDataStream* upload_data = request->get_upload();
  if (!upload_data ||
      (request->method() != "POST" && request->method() != "PUT"))
    return;  // Need to exit without "out->Set(keys::kRequestBodyKey, ...);" .

  DictionaryValue* requestBody = new DictionaryValue();
  out->Set(keys::kRequestBodyKey, requestBody);

  // Get the data presenters, ordered by how specific they are.
  extensions::ParsedDataPresenter parsed_data_presenter(*request);
  extensions::RawDataPresenter raw_data_presenter;
  extensions::UploadDataPresenter* const presenters[] = {
    &parsed_data_presenter,    // 1: any parseable forms? (Specific to forms.)
    &raw_data_presenter        // 2: any data at all? (Non-specific.)
  };
  // Keys for the results of the corresponding presenters.
  static const char* const kKeys[] = {
    keys::kRequestBodyFormDataKey,
    keys::kRequestBodyRawKey
  };

  const ScopedVector<net::UploadElementReader>& readers =
      upload_data->element_readers();
  bool some_succeeded = false;
  for (size_t i = 0; !some_succeeded && i < arraysize(presenters); ++i) {
    ScopedVector<net::UploadElementReader>::const_iterator reader;
    for (reader = readers.begin(); reader != readers.end(); ++reader)
      presenters[i]->FeedNext(**reader);
    if (presenters[i]->Succeeded()) {
      requestBody->Set(kKeys[i], presenters[i]->Result().release());
      some_succeeded = true;
    }
  }
  if (!some_succeeded)
    requestBody->SetString(keys::kRequestBodyErrorKey, "Unknown error.");
}

// Converts a HttpHeaders dictionary to a |name|, |value| pair. Returns
// true if successful.
bool FromHeaderDictionary(const DictionaryValue* header_value,
                          std::string* name,
                          std::string* value) {
  if (!header_value->GetString(keys::kHeaderNameKey, name))
    return false;

  // We require either a "value" or a "binaryValue" entry.
  if (!(header_value->HasKey(keys::kHeaderValueKey) ^
        header_value->HasKey(keys::kHeaderBinaryValueKey)))
    return false;

  if (header_value->HasKey(keys::kHeaderValueKey)) {
    if (!header_value->GetString(keys::kHeaderValueKey, value)) {
      return false;
    }
  } else if (header_value->HasKey(keys::kHeaderBinaryValueKey)) {
    const ListValue* list = NULL;
    if (!header_value->GetList(keys::kHeaderBinaryValueKey, &list) ||
        !helpers::CharListToString(list, value)) {
      return false;
    }
  }
  return true;
}

// Converts the |name|, |value| pair of a http header to a HttpHeaders
// dictionary. Ownership is passed to the caller.
DictionaryValue* ToHeaderDictionary(const std::string& name,
                                    const std::string& value) {
  DictionaryValue* header = new DictionaryValue();
  header->SetString(keys::kHeaderNameKey, name);
  if (IsStringUTF8(value)) {
    header->SetString(keys::kHeaderValueKey, value);
  } else {
    header->Set(keys::kHeaderBinaryValueKey,
                helpers::StringToCharList(value));
  }
  return header;
}

// Creates a list of HttpHeaders (see the extension API JSON). If |headers| is
// NULL, the list is empty. Ownership is passed to the caller.
ListValue* GetResponseHeadersList(const net::HttpResponseHeaders* headers) {
  ListValue* headers_value = new ListValue();
  if (headers) {
    void* iter = NULL;
    std::string name;
    std::string value;
    while (headers->EnumerateHeaderLines(&iter, &name, &value))
      headers_value->Append(ToHeaderDictionary(name, value));
  }
  return headers_value;
}

ListValue* GetRequestHeadersList(const net::HttpRequestHeaders& headers) {
  ListValue* headers_value = new ListValue();
  for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext(); )
    headers_value->Append(ToHeaderDictionary(it.name(), it.value()));
  return headers_value;
}

// Creates a StringValue with the status line of |headers|. If |headers| is
// NULL, an empty string is returned.  Ownership is passed to the caller.
StringValue* GetStatusLine(net::HttpResponseHeaders* headers) {
  return new StringValue(headers ? headers->GetStatusLine() : std::string());
}

void RemoveEventListenerOnUI(
  void* profile_id,
  const std::string& event_name,
  int process_id,
  const std::string& extension_id) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  Profile* profile = reinterpret_cast<Profile*>(profile_id);
  if (!g_browser_process->profile_manager()->IsValidProfile(profile))
    return;

  extensions::EventRouter* event_router =
      extensions::ExtensionSystem::Get(profile)->event_router();
  if (!event_router)
    return;

  content::RenderProcessHost* process =
      content::RenderProcessHost::FromID(process_id);
  if (!process)
    return;

  event_router->RemoveEventListener(event_name, process, extension_id);
}

// Sends an event to subscribers of chrome.declarativeWebRequest.onMessage.
// |extension_id| identifies the extension that sends and receives the event.
// |event_argument| is passed to the event listener.
void SendOnMessageEventOnUI(
    void* profile_id,
    const std::string& extension_id,
    scoped_ptr<base::DictionaryValue> event_argument) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  Profile* profile = reinterpret_cast<Profile*>(profile_id);
  if (!g_browser_process->profile_manager()->IsValidProfile(profile))
    return;

  scoped_ptr<base::ListValue> event_args(new ListValue);
  event_args->Append(event_argument.release());

  extensions::EventRouter* event_router =
      extensions::ExtensionSystem::Get(profile)->event_router();

  scoped_ptr<extensions::Event> event(new extensions::Event(
      declarative_keys::kOnMessage, event_args.Pass(), profile,
      GURL(), extensions::EventRouter::USER_GESTURE_UNKNOWN,
      extensions::EventFilteringInfo()));
  event_router->DispatchEventToExtension(extension_id, event.Pass());
}

}  // namespace

// Represents a single unique listener to an event, along with whatever filter
// parameters and extra_info_spec were specified at the time the listener was
// added.
// NOTE(benjhayden) New APIs should not use this sub_event_name trick! It does
// not play well with event pages. See downloads.onDeterminingFilename and
// ExtensionDownloadsEventRouter for an alternative approach.
struct ExtensionWebRequestEventRouter::EventListener {
  std::string extension_id;
  std::string extension_name;
  std::string sub_event_name;
  RequestFilter filter;
  int extra_info_spec;
  int embedder_process_id;
  int embedder_routing_id;
  int webview_instance_id;
  base::WeakPtr<IPC::Sender> ipc_sender;
  mutable std::set<uint64> blocked_requests;

  // Comparator to work with std::set.
  bool operator<(const EventListener& that) const {
    if (extension_id < that.extension_id)
      return true;
    if (extension_id == that.extension_id &&
        sub_event_name < that.sub_event_name)
      return true;
    return false;
  }

  EventListener() : extra_info_spec(0) {}
};

// Contains info about requests that are blocked waiting for a response from
// an extension.
struct ExtensionWebRequestEventRouter::BlockedRequest {
  // The request that is being blocked.
  net::URLRequest* request;

  // Whether the request originates from an incognito tab.
  bool is_incognito;

  // The event that we're currently blocked on.
  EventTypes event;

  // The number of event handlers that we are awaiting a response from.
  int num_handlers_blocking;

  // Pointer to NetLog to report significant changes to the request for
  // debugging.
  const net::BoundNetLog* net_log;

  // The callback to call when we get a response from all event handlers.
  net::CompletionCallback callback;

  // If non-empty, this contains the new URL that the request will redirect to.
  // Only valid for OnBeforeRequest.
  GURL* new_url;

  // The request headers that will be issued along with this request. Only valid
  // for OnBeforeSendHeaders.
  net::HttpRequestHeaders* request_headers;

  // The response headers that were received from the server. Only valid for
  // OnHeadersReceived.
  scoped_refptr<const net::HttpResponseHeaders> original_response_headers;

  // Location where to override response headers. Only valid for
  // OnHeadersReceived.
  scoped_refptr<net::HttpResponseHeaders>* override_response_headers;

  // If non-empty, this contains the auth credentials that may be filled in.
  // Only valid for OnAuthRequired.
  net::AuthCredentials* auth_credentials;

  // The callback to invoke for auth. If |auth_callback.is_null()| is false,
  // |callback| must be NULL.
  // Only valid for OnAuthRequired.
  net::NetworkDelegate::AuthCallback auth_callback;

  // Time the request was paused. Used for logging purposes.
  base::Time blocking_time;

  // Changes requested by extensions.
  helpers::EventResponseDeltas response_deltas;

  // Provider of meta data about extensions, only used and non-NULL for events
  // that are delayed until the rules registry is ready.
  ExtensionInfoMap* extension_info_map;

  BlockedRequest()
      : request(NULL),
        is_incognito(false),
        event(kInvalidEvent),
        num_handlers_blocking(0),
        net_log(NULL),
        new_url(NULL),
        request_headers(NULL),
        override_response_headers(NULL),
        auth_credentials(NULL),
        extension_info_map(NULL) {}
};

bool ExtensionWebRequestEventRouter::RequestFilter::InitFromValue(
    const DictionaryValue& value, std::string* error) {
  if (!value.HasKey("urls"))
    return false;

  for (DictionaryValue::Iterator it(value); !it.IsAtEnd(); it.Advance()) {
    if (it.key() == "urls") {
      const ListValue* urls_value = NULL;
      if (!it.value().GetAsList(&urls_value))
        return false;
      for (size_t i = 0; i < urls_value->GetSize(); ++i) {
        std::string url;
        URLPattern pattern(
            URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS |
            URLPattern::SCHEME_FTP | URLPattern::SCHEME_FILE |
            URLPattern::SCHEME_EXTENSION);
        if (!urls_value->GetString(i, &url) ||
            pattern.Parse(url) != URLPattern::PARSE_SUCCESS) {
          *error = ErrorUtils::FormatErrorMessage(
              keys::kInvalidRequestFilterUrl, url);
          return false;
        }
        urls.AddPattern(pattern);
      }
    } else if (it.key() == "types") {
      const ListValue* types_value = NULL;
      if (!it.value().GetAsList(&types_value))
        return false;
      for (size_t i = 0; i < types_value->GetSize(); ++i) {
        std::string type_str;
        ResourceType::Type type;
        if (!types_value->GetString(i, &type_str) ||
            !helpers::ParseResourceType(type_str, &type))
          return false;
        types.push_back(type);
      }
    } else if (it.key() == "tabId") {
      if (!it.value().GetAsInteger(&tab_id))
        return false;
    } else if (it.key() == "windowId") {
      if (!it.value().GetAsInteger(&window_id))
        return false;
    } else {
      return false;
    }
  }
  return true;
}

// static
bool ExtensionWebRequestEventRouter::ExtraInfoSpec::InitFromValue(
    const ListValue& value, int* extra_info_spec) {
  *extra_info_spec = 0;
  for (size_t i = 0; i < value.GetSize(); ++i) {
    std::string str;
    if (!value.GetString(i, &str))
      return false;

    if (str == "requestHeaders")
      *extra_info_spec |= REQUEST_HEADERS;
    else if (str == "responseHeaders")
      *extra_info_spec |= RESPONSE_HEADERS;
    else if (str == "blocking")
      *extra_info_spec |= BLOCKING;
    else if (str == "asyncBlocking")
      *extra_info_spec |= ASYNC_BLOCKING;
    else if (str == "requestBody")
      *extra_info_spec |= REQUEST_BODY;
    else
      return false;

    // BLOCKING and ASYNC_BLOCKING are mutually exclusive.
    if ((*extra_info_spec & BLOCKING) && (*extra_info_spec & ASYNC_BLOCKING))
      return false;
  }
  return true;
}


ExtensionWebRequestEventRouter::EventResponse::EventResponse(
    const std::string& extension_id, const base::Time& extension_install_time)
    : extension_id(extension_id),
      extension_install_time(extension_install_time),
      cancel(false) {
}

ExtensionWebRequestEventRouter::EventResponse::~EventResponse() {
}


ExtensionWebRequestEventRouter::RequestFilter::RequestFilter()
    : tab_id(-1), window_id(-1) {
}

ExtensionWebRequestEventRouter::RequestFilter::~RequestFilter() {
}

//
// ExtensionWebRequestEventRouter
//

// static
ExtensionWebRequestEventRouter* ExtensionWebRequestEventRouter::GetInstance() {
  return Singleton<ExtensionWebRequestEventRouter>::get();
}

ExtensionWebRequestEventRouter::ExtensionWebRequestEventRouter()
    : request_time_tracker_(new ExtensionWebRequestTimeTracker) {
}

ExtensionWebRequestEventRouter::~ExtensionWebRequestEventRouter() {
}

void ExtensionWebRequestEventRouter::RegisterRulesRegistry(
    void* profile,
    scoped_refptr<extensions::WebRequestRulesRegistry> rules_registry) {
  if (rules_registry.get())
    rules_registries_[profile] = rules_registry;
  else
    rules_registries_.erase(profile);
}

int ExtensionWebRequestEventRouter::OnBeforeRequest(
    void* profile,
    ExtensionInfoMap* extension_info_map,
    net::URLRequest* request,
    const net::CompletionCallback& callback,
    GURL* new_url) {
  // We hide events from the system context as well as sensitive requests.
  if (!profile ||
      WebRequestPermissions::HideRequest(extension_info_map, request))
    return net::OK;

  if (IsPageLoad(request))
    NotifyPageLoad();

  request_time_tracker_->LogRequestStartTime(request->identifier(),
                                             base::Time::Now(),
                                             request->url(),
                                             profile);

  // Whether to initialized blocked_requests_.
  bool initialize_blocked_requests = false;

  initialize_blocked_requests |=
      ProcessDeclarativeRules(profile, extension_info_map,
                              web_request::OnBeforeRequest::kEventName, request,
                              extensions::ON_BEFORE_REQUEST, NULL);

  int extra_info_spec = 0;
  std::vector<const EventListener*> listeners =
      GetMatchingListeners(profile, extension_info_map,
                           web_request::OnBeforeRequest::kEventName, request,
                           &extra_info_spec);
  if (!listeners.empty() &&
      !GetAndSetSignaled(request->identifier(), kOnBeforeRequest)) {
    ListValue args;
    DictionaryValue* dict = new DictionaryValue();
    ExtractRequestInfo(request, dict);
    if (extra_info_spec & ExtraInfoSpec::REQUEST_BODY)
      ExtractRequestInfoBody(request, dict);
    args.Append(dict);

    initialize_blocked_requests |=
        DispatchEvent(profile, request, listeners, args);
  }

  if (!initialize_blocked_requests)
    return net::OK;  // Nobody saw a reason for modifying the request.

  blocked_requests_[request->identifier()].event = kOnBeforeRequest;
  blocked_requests_[request->identifier()].is_incognito |=
      IsIncognitoProfile(profile);
  blocked_requests_[request->identifier()].request = request;
  blocked_requests_[request->identifier()].callback = callback;
  blocked_requests_[request->identifier()].new_url = new_url;
  blocked_requests_[request->identifier()].net_log = &request->net_log();

  if (blocked_requests_[request->identifier()].num_handlers_blocking == 0) {
    // If there are no blocking handlers, only the declarative rules tried
    // to modify the request and we can respond synchronously.
    return ExecuteDeltas(profile, request->identifier(),
                         false /* call_callback*/);
  } else {
    return net::ERR_IO_PENDING;
  }
}

int ExtensionWebRequestEventRouter::OnBeforeSendHeaders(
    void* profile,
    ExtensionInfoMap* extension_info_map,
    net::URLRequest* request,
    const net::CompletionCallback& callback,
    net::HttpRequestHeaders* headers) {
  // We hide events from the system context as well as sensitive requests.
  if (!profile ||
      WebRequestPermissions::HideRequest(extension_info_map, request))
    return net::OK;

  bool initialize_blocked_requests = false;

  initialize_blocked_requests |=
      ProcessDeclarativeRules(profile, extension_info_map,
                              keys::kOnBeforeSendHeadersEvent, request,
                              extensions::ON_BEFORE_SEND_HEADERS, NULL);

  int extra_info_spec = 0;
  std::vector<const EventListener*> listeners =
      GetMatchingListeners(profile, extension_info_map,
                           keys::kOnBeforeSendHeadersEvent, request,
                           &extra_info_spec);
  if (!listeners.empty() &&
      !GetAndSetSignaled(request->identifier(), kOnBeforeSendHeaders)) {
    ListValue args;
    DictionaryValue* dict = new DictionaryValue();
    ExtractRequestInfo(request, dict);
    if (extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS)
      dict->Set(keys::kRequestHeadersKey, GetRequestHeadersList(*headers));
    args.Append(dict);

    initialize_blocked_requests |=
        DispatchEvent(profile, request, listeners, args);
  }

  if (!initialize_blocked_requests)
    return net::OK;  // Nobody saw a reason for modifying the request.

  blocked_requests_[request->identifier()].event = kOnBeforeSendHeaders;
  blocked_requests_[request->identifier()].is_incognito |=
      IsIncognitoProfile(profile);
  blocked_requests_[request->identifier()].request = request;
  blocked_requests_[request->identifier()].callback = callback;
  blocked_requests_[request->identifier()].request_headers = headers;
  blocked_requests_[request->identifier()].net_log = &request->net_log();

  if (blocked_requests_[request->identifier()].num_handlers_blocking == 0) {
    // If there are no blocking handlers, only the declarative rules tried
    // to modify the request and we can respond synchronously.
    return ExecuteDeltas(profile, request->identifier(),
                         false /* call_callback*/);
  } else {
    return net::ERR_IO_PENDING;
  }
}

void ExtensionWebRequestEventRouter::OnSendHeaders(
    void* profile,
    ExtensionInfoMap* extension_info_map,
    net::URLRequest* request,
    const net::HttpRequestHeaders& headers) {
  // We hide events from the system context as well as sensitive requests.
  if (!profile ||
      WebRequestPermissions::HideRequest(extension_info_map, request))
    return;

  if (GetAndSetSignaled(request->identifier(), kOnSendHeaders))
    return;

  ClearSignaled(request->identifier(), kOnBeforeRedirect);

  int extra_info_spec = 0;
  std::vector<const EventListener*> listeners =
      GetMatchingListeners(profile, extension_info_map,
                           keys::kOnSendHeadersEvent, request,
                           &extra_info_spec);
  if (listeners.empty())
    return;

  ListValue args;
  DictionaryValue* dict = new DictionaryValue();
  ExtractRequestInfo(request, dict);
  if (extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS)
    dict->Set(keys::kRequestHeadersKey, GetRequestHeadersList(headers));
  args.Append(dict);

  DispatchEvent(profile, request, listeners, args);
}

int ExtensionWebRequestEventRouter::OnHeadersReceived(
    void* profile,
    ExtensionInfoMap* extension_info_map,
    net::URLRequest* request,
    const net::CompletionCallback& callback,
    const net::HttpResponseHeaders* original_response_headers,
    scoped_refptr<net::HttpResponseHeaders>* override_response_headers) {
  // We hide events from the system context as well as sensitive requests.
  if (!profile ||
      WebRequestPermissions::HideRequest(extension_info_map, request))
    return net::OK;

  bool initialize_blocked_requests = false;

  initialize_blocked_requests |=
      ProcessDeclarativeRules(profile, extension_info_map,
                              keys::kOnHeadersReceivedEvent, request,
                              extensions::ON_HEADERS_RECEIVED,
                              original_response_headers);

  int extra_info_spec = 0;
  std::vector<const EventListener*> listeners =
      GetMatchingListeners(profile, extension_info_map,
                           keys::kOnHeadersReceivedEvent, request,
                           &extra_info_spec);

  if (!listeners.empty() &&
      !GetAndSetSignaled(request->identifier(), kOnHeadersReceived)) {
    ListValue args;
    DictionaryValue* dict = new DictionaryValue();
    ExtractRequestInfo(request, dict);
    dict->SetString(keys::kStatusLineKey,
        original_response_headers->GetStatusLine());
    if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
      dict->Set(keys::kResponseHeadersKey,
          GetResponseHeadersList(original_response_headers));
    }
    args.Append(dict);

    initialize_blocked_requests |=
        DispatchEvent(profile, request, listeners, args);
  }

  if (!initialize_blocked_requests)
    return net::OK;  // Nobody saw a reason for modifying the request.

  blocked_requests_[request->identifier()].event = kOnHeadersReceived;
  blocked_requests_[request->identifier()].is_incognito |=
      IsIncognitoProfile(profile);
  blocked_requests_[request->identifier()].request = request;
  blocked_requests_[request->identifier()].callback = callback;
  blocked_requests_[request->identifier()].net_log = &request->net_log();
  blocked_requests_[request->identifier()].override_response_headers =
      override_response_headers;
  blocked_requests_[request->identifier()].original_response_headers =
      original_response_headers;

  if (blocked_requests_[request->identifier()].num_handlers_blocking == 0) {
    // If there are no blocking handlers, only the declarative rules tried
    // to modify the request and we can respond synchronously.
    return ExecuteDeltas(profile, request->identifier(),
                         false /* call_callback*/);
  } else {
    return net::ERR_IO_PENDING;
  }
}

net::NetworkDelegate::AuthRequiredResponse
ExtensionWebRequestEventRouter::OnAuthRequired(
    void* profile,
    ExtensionInfoMap* extension_info_map,
    net::URLRequest* request,
    const net::AuthChallengeInfo& auth_info,
    const net::NetworkDelegate::AuthCallback& callback,
    net::AuthCredentials* credentials) {
  // No profile means that this is for authentication challenges in the
  // system context. Skip in that case. Also skip sensitive requests.
  if (!profile ||
      WebRequestPermissions::HideRequest(extension_info_map, request))
    return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;

  int extra_info_spec = 0;
  std::vector<const EventListener*> listeners =
      GetMatchingListeners(profile, extension_info_map,
                           keys::kOnAuthRequiredEvent, request,
                           &extra_info_spec);
  if (listeners.empty())
    return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;

  ListValue args;
  DictionaryValue* dict = new DictionaryValue();
  ExtractRequestInfo(request, dict);
  dict->SetBoolean(keys::kIsProxyKey, auth_info.is_proxy);
  if (!auth_info.scheme.empty())
    dict->SetString(keys::kSchemeKey, auth_info.scheme);
  if (!auth_info.realm.empty())
    dict->SetString(keys::kRealmKey, auth_info.realm);
  DictionaryValue* challenger = new DictionaryValue();
  challenger->SetString(keys::kHostKey, auth_info.challenger.host());
  challenger->SetInteger(keys::kPortKey, auth_info.challenger.port());
  dict->Set(keys::kChallengerKey, challenger);
  dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers()));
  if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
    dict->Set(keys::kResponseHeadersKey,
              GetResponseHeadersList(request->response_headers()));
  }
  args.Append(dict);

  if (DispatchEvent(profile, request, listeners, args)) {
    blocked_requests_[request->identifier()].event = kOnAuthRequired;
    blocked_requests_[request->identifier()].is_incognito |=
        IsIncognitoProfile(profile);
    blocked_requests_[request->identifier()].request = request;
    blocked_requests_[request->identifier()].auth_callback = callback;
    blocked_requests_[request->identifier()].auth_credentials = credentials;
    blocked_requests_[request->identifier()].net_log = &request->net_log();
    return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_IO_PENDING;
  }
  return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
}

void ExtensionWebRequestEventRouter::OnBeforeRedirect(
    void* profile,
    ExtensionInfoMap* extension_info_map,
    net::URLRequest* request,
    const GURL& new_location) {
  // We hide events from the system context as well as sensitive requests.
  if (!profile ||
      WebRequestPermissions::HideRequest(extension_info_map, request))
    return;

  if (GetAndSetSignaled(request->identifier(), kOnBeforeRedirect))
    return;

  ClearSignaled(request->identifier(), kOnBeforeRequest);
  ClearSignaled(request->identifier(), kOnBeforeSendHeaders);
  ClearSignaled(request->identifier(), kOnSendHeaders);
  ClearSignaled(request->identifier(), kOnHeadersReceived);

  int extra_info_spec = 0;
  std::vector<const EventListener*> listeners =
      GetMatchingListeners(profile, extension_info_map,
                           keys::kOnBeforeRedirectEvent, request,
                           &extra_info_spec);
  if (listeners.empty())
    return;

  int http_status_code = request->GetResponseCode();

  std::string response_ip = request->GetSocketAddress().host();

  ListValue args;
  DictionaryValue* dict = new DictionaryValue();
  ExtractRequestInfo(request, dict);
  dict->SetString(keys::kRedirectUrlKey, new_location.spec());
  dict->SetInteger(keys::kStatusCodeKey, http_status_code);
  if (!response_ip.empty())
    dict->SetString(keys::kIpKey, response_ip);
  dict->SetBoolean(keys::kFromCache, request->was_cached());
  dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers()));
  if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
    dict->Set(keys::kResponseHeadersKey,
              GetResponseHeadersList(request->response_headers()));
  }
  args.Append(dict);

  DispatchEvent(profile, request, listeners, args);
}

void ExtensionWebRequestEventRouter::OnResponseStarted(
    void* profile,
    ExtensionInfoMap* extension_info_map,
    net::URLRequest* request) {
  // We hide events from the system context as well as sensitive requests.
  if (!profile ||
      WebRequestPermissions::HideRequest(extension_info_map, request))
    return;

  // OnResponseStarted is even triggered, when the request was cancelled.
  if (request->status().status() != net::URLRequestStatus::SUCCESS)
    return;

  int extra_info_spec = 0;
  std::vector<const EventListener*> listeners =
      GetMatchingListeners(profile, extension_info_map,
                           keys::kOnResponseStartedEvent, request,
                           &extra_info_spec);
  if (listeners.empty())
    return;

  // UrlRequestFileJobs do not send headers, so we simulate their behavior.
  int response_code = 200;
  if (request->response_headers())
    response_code = request->response_headers()->response_code();

  std::string response_ip = request->GetSocketAddress().host();

  ListValue args;
  DictionaryValue* dict = new DictionaryValue();
  ExtractRequestInfo(request, dict);
  if (!response_ip.empty())
    dict->SetString(keys::kIpKey, response_ip);
  dict->SetBoolean(keys::kFromCache, request->was_cached());
  dict->SetInteger(keys::kStatusCodeKey, response_code);
  dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers()));
  if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
    dict->Set(keys::kResponseHeadersKey,
              GetResponseHeadersList(request->response_headers()));
  }
  args.Append(dict);

  DispatchEvent(profile, request, listeners, args);
}

void ExtensionWebRequestEventRouter::OnCompleted(
    void* profile,
    ExtensionInfoMap* extension_info_map,
    net::URLRequest* request) {
  // We hide events from the system context as well as sensitive requests.
  // However, if the request first became sensitive after redirecting we have
  // already signaled it and thus we have to signal the end of it. This is
  // risk-free because the handler cannot modify the request now.
  if (!profile ||
      (WebRequestPermissions::HideRequest(extension_info_map, request) &&
       !WasSignaled(*request)))
    return;

  request_time_tracker_->LogRequestEndTime(request->identifier(),
                                           base::Time::Now());

  DCHECK(request->status().status() == net::URLRequestStatus::SUCCESS);

  DCHECK(!GetAndSetSignaled(request->identifier(), kOnCompleted));

  ClearPendingCallbacks(request);

  int extra_info_spec = 0;
  std::vector<const EventListener*> listeners =
      GetMatchingListeners(profile, extension_info_map,
                           keys::kOnCompletedEvent, request, &extra_info_spec);
  if (listeners.empty())
    return;

  // UrlRequestFileJobs do not send headers, so we simulate their behavior.
  int response_code = 200;
  if (request->response_headers())
    response_code = request->response_headers()->response_code();

  std::string response_ip = request->GetSocketAddress().host();

  ListValue args;
  DictionaryValue* dict = new DictionaryValue();
  ExtractRequestInfo(request, dict);
  dict->SetInteger(keys::kStatusCodeKey, response_code);
  if (!response_ip.empty())
    dict->SetString(keys::kIpKey, response_ip);
  dict->SetBoolean(keys::kFromCache, request->was_cached());
  dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers()));
  if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
    dict->Set(keys::kResponseHeadersKey,
              GetResponseHeadersList(request->response_headers()));
  }
  args.Append(dict);

  DispatchEvent(profile, request, listeners, args);
}

void ExtensionWebRequestEventRouter::OnErrorOccurred(
    void* profile,
    ExtensionInfoMap* extension_info_map,
    net::URLRequest* request,
    bool started) {
  // We hide events from the system context as well as sensitive requests.
  // However, if the request first became sensitive after redirecting we have
  // already signaled it and thus we have to signal the end of it. This is
  // risk-free because the handler cannot modify the request now.
  if (!profile ||
      (WebRequestPermissions::HideRequest(extension_info_map, request) &&
       !WasSignaled(*request)))
    return;

  request_time_tracker_->LogRequestEndTime(request->identifier(),
                                           base::Time::Now());

  DCHECK(request->status().status() == net::URLRequestStatus::FAILED ||
         request->status().status() == net::URLRequestStatus::CANCELED);

  DCHECK(!GetAndSetSignaled(request->identifier(), kOnErrorOccurred));

  ClearPendingCallbacks(request);

  int extra_info_spec = 0;
  std::vector<const EventListener*> listeners =
      GetMatchingListeners(profile, extension_info_map,
                           web_request::OnErrorOccurred::kEventName, request,
                           &extra_info_spec);
  if (listeners.empty())
    return;

  ListValue args;
  DictionaryValue* dict = new DictionaryValue();
  ExtractRequestInfo(request, dict);
  if (started) {
    std::string response_ip = request->GetSocketAddress().host();
    if (!response_ip.empty())
      dict->SetString(keys::kIpKey, response_ip);
  }
  dict->SetBoolean(keys::kFromCache, request->was_cached());
  dict->SetString(keys::kErrorKey,
                  net::ErrorToString(request->status().error()));
  args.Append(dict);

  DispatchEvent(profile, request, listeners, args);
}

void ExtensionWebRequestEventRouter::OnURLRequestDestroyed(
    void* profile, net::URLRequest* request) {
  ClearPendingCallbacks(request);

  signaled_requests_.erase(request->identifier());

  request_time_tracker_->LogRequestEndTime(request->identifier(),
                                           base::Time::Now());
}

void ExtensionWebRequestEventRouter::ClearPendingCallbacks(
    net::URLRequest* request) {
  blocked_requests_.erase(request->identifier());
}

bool ExtensionWebRequestEventRouter::DispatchEvent(
    void* profile_id,
    net::URLRequest* request,
    const std::vector<const EventListener*>& listeners,
    const ListValue& args) {
  // TODO(mpcomplete): Consider consolidating common (extension_id,json_args)
  // pairs into a single message sent to a list of sub_event_names.
  int num_handlers_blocking = 0;
  for (std::vector<const EventListener*>::const_iterator it = listeners.begin();
       it != listeners.end(); ++it) {
    // Filter out the optional keys that this listener didn't request.
    scoped_ptr<ListValue> args_filtered(args.DeepCopy());
    DictionaryValue* dict = NULL;
    CHECK(args_filtered->GetDictionary(0, &dict) && dict);
    if (!((*it)->extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS))
      dict->Remove(keys::kRequestHeadersKey, NULL);
    if (!((*it)->extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS))
      dict->Remove(keys::kResponseHeadersKey, NULL);

    extensions::EventRouter::DispatchEvent(
        (*it)->ipc_sender.get(), profile_id,
        (*it)->extension_id, (*it)->sub_event_name,
        args_filtered.Pass(),
        extensions::EventRouter::USER_GESTURE_UNKNOWN,
        extensions::EventFilteringInfo());
    if ((*it)->extra_info_spec &
        (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) {
      (*it)->blocked_requests.insert(request->identifier());
      ++num_handlers_blocking;

      request->SetLoadStateParam(
          l10n_util::GetStringFUTF16(IDS_LOAD_STATE_PARAMETER_EXTENSION,
                                     UTF8ToUTF16((*it)->extension_name)));
    }
  }

  if (num_handlers_blocking > 0) {
    blocked_requests_[request->identifier()].request = request;
    blocked_requests_[request->identifier()].is_incognito |=
        IsIncognitoProfile(profile_id);
    blocked_requests_[request->identifier()].num_handlers_blocking +=
        num_handlers_blocking;
    blocked_requests_[request->identifier()].blocking_time = base::Time::Now();

    return true;
  }

  return false;
}

void ExtensionWebRequestEventRouter::OnEventHandled(
    void* profile,
    const std::string& extension_id,
    const std::string& event_name,
    const std::string& sub_event_name,
    uint64 request_id,
    EventResponse* response) {
  EventListener listener;
  listener.extension_id = extension_id;
  listener.sub_event_name = sub_event_name;

  // The listener may have been removed (e.g. due to the process going away)
  // before we got here.
  std::set<EventListener>::iterator found =
      listeners_[profile][event_name].find(listener);
  if (found != listeners_[profile][event_name].end())
    found->blocked_requests.erase(request_id);

  DecrementBlockCount(profile, extension_id, event_name, request_id, response);
}

bool ExtensionWebRequestEventRouter::AddEventListener(
    void* profile,
    const std::string& extension_id,
    const std::string& extension_name,
    const std::string& event_name,
    const std::string& sub_event_name,
    const RequestFilter& filter,
    int extra_info_spec,
    int embedder_process_id,
    int embedder_routing_id,
    int webview_instance_id,
    base::WeakPtr<IPC::Sender> ipc_sender) {

  if (!IsWebRequestEvent(event_name))
    return false;

  EventListener listener;
  listener.extension_id = extension_id;
  listener.extension_name = extension_name;
  listener.sub_event_name = sub_event_name;
  listener.filter = filter;
  listener.extra_info_spec = extra_info_spec;
  listener.ipc_sender = ipc_sender;
  listener.embedder_process_id = embedder_process_id;
  listener.embedder_routing_id = embedder_routing_id;
  listener.webview_instance_id = webview_instance_id;
  if (listener.webview_instance_id)
    RecordAction(content::UserMetricsAction("WebView.WebRequest.AddListener"));

  if (listeners_[profile][event_name].count(listener) != 0u) {
    // This is likely an abuse of the API by a malicious extension.
    return false;
  }
  listeners_[profile][event_name].insert(listener);
  return true;
}

void ExtensionWebRequestEventRouter::RemoveEventListener(
    void* profile,
    const std::string& extension_id,
    const std::string& sub_event_name) {
  size_t slash_sep = sub_event_name.find('/');
  std::string event_name = sub_event_name.substr(0, slash_sep);

  if (!IsWebRequestEvent(event_name))
    return;

  EventListener listener;
  listener.extension_id = extension_id;
  listener.sub_event_name = sub_event_name;

  // It's possible for AddEventListener to fail asynchronously. In that case,
  // the renderer believes the listener exists, while the browser does not.
  // Ignore a RemoveEventListener in that case.
  std::set<EventListener>::iterator found =
      listeners_[profile][event_name].find(listener);
  if (found == listeners_[profile][event_name].end())
    return;

  CHECK_EQ(listeners_[profile][event_name].count(listener), 1u) <<
      "extension=" << extension_id << " event=" << event_name;

  // Unblock any request that this event listener may have been blocking.
  for (std::set<uint64>::iterator it = found->blocked_requests.begin();
       it != found->blocked_requests.end(); ++it) {
    DecrementBlockCount(profile, extension_id, event_name, *it, NULL);
  }

  listeners_[profile][event_name].erase(listener);

  helpers::ClearCacheOnNavigation();
}

void ExtensionWebRequestEventRouter::RemoveWebViewEventListeners(
    void* profile,
    const std::string& extension_id,
    int embedder_process_id,
    int embedder_routing_id,
    int webview_instance_id) {
  // Iterate over all listeners of all WebRequest events to delete
  // any listeners that belong to the provided <webview>.
  ListenerMapForProfile& map_for_profile = listeners_[profile];
  for (ListenerMapForProfile::iterator event_iter = map_for_profile.begin();
       event_iter != map_for_profile.end(); ++event_iter) {
    std::vector<EventListener> listeners_to_delete;
    std::set<EventListener>& listeners = event_iter->second;
    for (std::set<EventListener>::iterator listener_iter = listeners.begin();
         listener_iter != listeners.end(); ++listener_iter) {
      const EventListener& listener = *listener_iter;
      // TODO(fsamuel): Investigate making <webview> instance IDs unique within
      // a process.
      if (listener.embedder_process_id == embedder_process_id &&
          listener.embedder_routing_id == embedder_routing_id &&
          listener.webview_instance_id == webview_instance_id)
        listeners_to_delete.push_back(listener);
    }
    for (size_t i = 0; i < listeners_to_delete.size(); ++i) {
      EventListener& listener = listeners_to_delete[i];
      content::BrowserThread::PostTask(
          content::BrowserThread::UI,
          FROM_HERE,
          base::Bind(&RemoveEventListenerOnUI,
                     profile,
                     listener.sub_event_name,
                     embedder_process_id,
                     extension_id));
    }
  }
}

void ExtensionWebRequestEventRouter::OnOTRProfileCreated(
    void* original_profile, void* otr_profile) {
  cross_profile_map_[original_profile] = std::make_pair(false, otr_profile);
  cross_profile_map_[otr_profile] = std::make_pair(true, original_profile);
}

void ExtensionWebRequestEventRouter::OnOTRProfileDestroyed(
    void* original_profile, void* otr_profile) {
  cross_profile_map_.erase(otr_profile);
  cross_profile_map_.erase(original_profile);
}

void ExtensionWebRequestEventRouter::AddCallbackForPageLoad(
    const base::Closure& callback) {
  callbacks_for_page_load_.push_back(callback);
}

bool ExtensionWebRequestEventRouter::IsPageLoad(
    net::URLRequest* request) const {
  bool is_main_frame = false;
  int64 frame_id = -1;
  bool parent_is_main_frame = false;
  int64 parent_frame_id = -1;
  int tab_id = -1;
  int window_id = -1;
  int render_process_host_id = -1;
  int routing_id = -1;
  ResourceType::Type resource_type = ResourceType::LAST_TYPE;

  ExtractRequestInfoDetails(request, &is_main_frame, &frame_id,
                            &parent_is_main_frame, &parent_frame_id,
                            &tab_id, &window_id, &render_process_host_id,
                            &routing_id, &resource_type);

  return resource_type == ResourceType::MAIN_FRAME;
}

void ExtensionWebRequestEventRouter::NotifyPageLoad() {
  for (CallbacksForPageLoad::const_iterator i =
           callbacks_for_page_load_.begin();
       i != callbacks_for_page_load_.end(); ++i) {
    i->Run();
  }
  callbacks_for_page_load_.clear();
}

void* ExtensionWebRequestEventRouter::GetCrossProfile(void* profile) const {
  CrossProfileMap::const_iterator cross_profile =
      cross_profile_map_.find(profile);
  if (cross_profile == cross_profile_map_.end())
    return NULL;
  return cross_profile->second.second;
}

bool ExtensionWebRequestEventRouter::IsIncognitoProfile(void* profile) const {
  CrossProfileMap::const_iterator cross_profile =
      cross_profile_map_.find(profile);
  if (cross_profile == cross_profile_map_.end())
    return false;
  return cross_profile->second.first;
}

bool ExtensionWebRequestEventRouter::WasSignaled(
    const net::URLRequest& request) const {
  SignaledRequestMap::const_iterator flag =
      signaled_requests_.find(request.identifier());
  return (flag != signaled_requests_.end()) && (flag->second != 0);
}

void ExtensionWebRequestEventRouter::GetMatchingListenersImpl(
    void* profile,
    ExtensionInfoMap* extension_info_map,
    bool crosses_incognito,
    const std::string& event_name,
    const GURL& url,
    int tab_id,
    int window_id,
    int render_process_host_id,
    int routing_id,
    ResourceType::Type resource_type,
    bool is_async_request,
    bool is_request_from_extension,
    int* extra_info_spec,
    std::vector<const ExtensionWebRequestEventRouter::EventListener*>*
        matching_listeners) {
  std::string web_request_event_name(event_name);
  ExtensionRendererState::WebViewInfo webview_info;
  bool is_guest = ExtensionRendererState::GetInstance()->
      GetWebViewInfo(render_process_host_id, routing_id, &webview_info);
  if (is_guest)
    web_request_event_name.replace(0, sizeof(kWebRequest) - 1, kWebView);

  std::set<EventListener>& listeners =
      listeners_[profile][web_request_event_name];
  for (std::set<EventListener>::iterator it = listeners.begin();
       it != listeners.end(); ++it) {
    if (!it->ipc_sender.get()) {
      // The IPC sender has been deleted. This listener will be removed soon
      // via a call to RemoveEventListener. For now, just skip it.
      continue;
    }

    if (is_guest &&
        (it->embedder_process_id != webview_info.embedder_process_id ||
         it->embedder_routing_id != webview_info.embedder_routing_id ||
         it->webview_instance_id != webview_info.instance_id))
      continue;

    if (!it->filter.urls.is_empty() && !it->filter.urls.MatchesURL(url))
      continue;
    if (it->filter.tab_id != -1 && tab_id != it->filter.tab_id)
      continue;
    if (it->filter.window_id != -1 && window_id != it->filter.window_id)
      continue;
    if (!it->filter.types.empty() &&
        std::find(it->filter.types.begin(), it->filter.types.end(),
                  resource_type) == it->filter.types.end())
      continue;

    if (!is_guest && !WebRequestPermissions::CanExtensionAccessURL(
            extension_info_map, it->extension_id, url, crosses_incognito,
            WebRequestPermissions::REQUIRE_HOST_PERMISSION))
      continue;

    bool blocking_listener =
        (it->extra_info_spec &
            (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) != 0;

    // We do not want to notify extensions about XHR requests that are
    // triggered by themselves. This is a workaround to prevent deadlocks
    // in case of synchronous XHR requests that block the extension renderer
    // and therefore prevent the extension from processing the request
    // handler. This is only a problem for blocking listeners.
    // http://crbug.com/105656
    bool synchronous_xhr_from_extension = !is_async_request &&
        is_request_from_extension && resource_type == ResourceType::XHR;

    // Only send webRequest events for URLs the extension has access to.
    if (blocking_listener && synchronous_xhr_from_extension)
      continue;

    matching_listeners->push_back(&(*it));
    *extra_info_spec |= it->extra_info_spec;
  }
}

std::vector<const ExtensionWebRequestEventRouter::EventListener*>
ExtensionWebRequestEventRouter::GetMatchingListeners(
    void* profile,
    ExtensionInfoMap* extension_info_map,
    const std::string& event_name,
    net::URLRequest* request,
    int* extra_info_spec) {
  // TODO(mpcomplete): handle profile == NULL (should collect all listeners).
  *extra_info_spec = 0;

  bool is_main_frame = false;
  int64 frame_id = -1;
  bool parent_is_main_frame = false;
  int64 parent_frame_id = -1;
  int tab_id = -1;
  int window_id = -1;
  int render_process_host_id = -1;
  int routing_id = -1;
  ResourceType::Type resource_type = ResourceType::LAST_TYPE;
  const GURL& url = request->url();

  ExtractRequestInfoDetails(request, &is_main_frame, &frame_id,
                            &parent_is_main_frame, &parent_frame_id,
                            &tab_id, &window_id, &render_process_host_id,
                            &routing_id, &resource_type);

  std::vector<const ExtensionWebRequestEventRouter::EventListener*>
      matching_listeners;

  bool is_request_from_extension =
      IsRequestFromExtension(request, extension_info_map);

  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
  // We are conservative here and assume requests are asynchronous in case
  // we don't have an info object. We don't want to risk a deadlock.
  bool is_async_request = !info || info->IsAsync();

  GetMatchingListenersImpl(
      profile, extension_info_map, false, event_name, url,
      tab_id, window_id, render_process_host_id, routing_id, resource_type,
      is_async_request, is_request_from_extension, extra_info_spec,
      &matching_listeners);
  void* cross_profile = GetCrossProfile(profile);
  if (cross_profile) {
    GetMatchingListenersImpl(
        cross_profile, extension_info_map, true, event_name, url, tab_id,
        window_id, render_process_host_id, routing_id, resource_type,
        is_async_request, is_request_from_extension, extra_info_spec,
        &matching_listeners);
  }

  return matching_listeners;
}

namespace {

helpers::EventResponseDelta* CalculateDelta(
    ExtensionWebRequestEventRouter::BlockedRequest* blocked_request,
    ExtensionWebRequestEventRouter::EventResponse* response) {
  switch (blocked_request->event) {
    case ExtensionWebRequestEventRouter::kOnBeforeRequest:
      return helpers::CalculateOnBeforeRequestDelta(
          response->extension_id, response->extension_install_time,
          response->cancel, response->new_url);
    case ExtensionWebRequestEventRouter::kOnBeforeSendHeaders: {
      net::HttpRequestHeaders* old_headers = blocked_request->request_headers;
      net::HttpRequestHeaders* new_headers = response->request_headers.get();
      return helpers::CalculateOnBeforeSendHeadersDelta(
          response->extension_id, response->extension_install_time,
          response->cancel, old_headers, new_headers);
    }
    case ExtensionWebRequestEventRouter::kOnHeadersReceived: {
      const net::HttpResponseHeaders* old_headers =
          blocked_request->original_response_headers.get();
      helpers::ResponseHeaders* new_headers =
          response->response_headers.get();
      return helpers::CalculateOnHeadersReceivedDelta(
          response->extension_id, response->extension_install_time,
          response->cancel, old_headers, new_headers);
    }
    case ExtensionWebRequestEventRouter::kOnAuthRequired:
      return helpers::CalculateOnAuthRequiredDelta(
          response->extension_id, response->extension_install_time,
          response->cancel, &response->auth_credentials);
    default:
      NOTREACHED();
      break;
  }
  return NULL;
}

Value* SerializeResponseHeaders(const helpers::ResponseHeaders& headers) {
  scoped_ptr<ListValue> serialized_headers(new ListValue());
  for (helpers::ResponseHeaders::const_iterator i = headers.begin();
       i != headers.end(); ++i) {
    serialized_headers->Append(ToHeaderDictionary(i->first, i->second));
  }
  return serialized_headers.release();
}

// Convert a RequestCookieModifications/ResponseCookieModifications object to a
// ListValue which summarizes the changes made.  This is templated since the
// two types (request/response) are different but contain essentially the same
// fields.
template<typename CookieType>
ListValue* SummarizeCookieModifications(
    const std::vector<linked_ptr<CookieType> >& modifications) {
  scoped_ptr<ListValue> cookie_modifications(new ListValue());
  for (typename std::vector<linked_ptr<CookieType> >::const_iterator i =
           modifications.begin();
       i != modifications.end(); ++i) {
    scoped_ptr<DictionaryValue> summary(new DictionaryValue());
    const CookieType& mod = *i->get();
    switch (mod.type) {
      case helpers::ADD:
        summary->SetString(activitylog::kCookieModificationTypeKey,
                           activitylog::kCookieModificationAdd);
        break;
      case helpers::EDIT:
        summary->SetString(activitylog::kCookieModificationTypeKey,
                           activitylog::kCookieModificationEdit);
        break;
      case helpers::REMOVE:
        summary->SetString(activitylog::kCookieModificationTypeKey,
                           activitylog::kCookieModificationRemove);
        break;
    }
    if (mod.filter) {
      if (mod.filter->name)
        summary->SetString(activitylog::kCookieFilterNameKey,
                           *mod.modification->name);
      if (mod.filter->domain)
        summary->SetString(activitylog::kCookieFilterDomainKey,
                           *mod.modification->name);
    }
    if (mod.modification) {
      if (mod.modification->name)
        summary->SetString(activitylog::kCookieModDomainKey,
                           *mod.modification->name);
      if (mod.modification->domain)
        summary->SetString(activitylog::kCookieModDomainKey,
                           *mod.modification->name);
    }
    cookie_modifications->Append(summary.release());
  }
  return cookie_modifications.release();
}

// Converts an EventResponseDelta object to a dictionary value suitable for the
// activity log.
scoped_ptr<DictionaryValue> SummarizeResponseDelta(
    const std::string& event_name,
    const helpers::EventResponseDelta& delta) {
  scoped_ptr<DictionaryValue> details(new DictionaryValue());
  if (delta.cancel) {
    details->SetBoolean(activitylog::kCancelKey, true);
  }
  if (!delta.new_url.is_empty()) {
      details->SetString(activitylog::kNewUrlKey, delta.new_url.spec());
  }

  scoped_ptr<ListValue> modified_headers(new ListValue());
  net::HttpRequestHeaders::Iterator iter(delta.modified_request_headers);
  while (iter.GetNext()) {
    modified_headers->Append(ToHeaderDictionary(iter.name(), iter.value()));
  }
  if (!modified_headers->empty()) {
    details->Set(activitylog::kModifiedRequestHeadersKey,
                 modified_headers.release());
  }

  scoped_ptr<ListValue> deleted_headers(new ListValue());
  deleted_headers->AppendStrings(delta.deleted_request_headers);
  if (!deleted_headers->empty()) {
    details->Set(activitylog::kDeletedRequestHeadersKey,
                 deleted_headers.release());
  }

  if (!delta.added_response_headers.empty()) {
    details->Set(activitylog::kAddedRequestHeadersKey,
                 SerializeResponseHeaders(delta.added_response_headers));
  }
  if (!delta.deleted_response_headers.empty()) {
    details->Set(activitylog::kDeletedResponseHeadersKey,
                 SerializeResponseHeaders(delta.deleted_response_headers));
  }
  if (delta.auth_credentials) {
    details->SetString(activitylog::kAuthCredentialsKey,
                       UTF16ToUTF8(delta.auth_credentials->username()) + ":*");
  }

  if (!delta.response_cookie_modifications.empty()) {
    details->Set(
        activitylog::kResponseCookieModificationsKey,
        SummarizeCookieModifications(delta.response_cookie_modifications));
  }

  return details.Pass();
}

void LogExtensionActivity(void* profile_id,
                          bool is_incognito,
                          const std::string& extension_id,
                          const GURL& url,
                          const std::string& api_call,
                          scoped_ptr<DictionaryValue> details) {
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    BrowserThread::PostTask(BrowserThread::UI,
                            FROM_HERE,
                            base::Bind(&LogExtensionActivity,
                                       profile_id,
                                       is_incognito,
                                       extension_id,
                                       url,
                                       api_call,
                                       base::Passed(&details)));
  } else {
    Profile* profile = static_cast<Profile*>(profile_id);
    if (!g_browser_process->profile_manager()->IsValidProfile(profile))
      return;
    scoped_refptr<extensions::Action> action =
        new extensions::Action(extension_id,
                               base::Time::Now(),
                               extensions::Action::ACTION_WEB_REQUEST,
                               api_call);
    action->set_page_url(url);
    action->set_page_incognito(is_incognito);
    action->mutable_other()->Set(activity_log_constants::kActionWebRequest,
                                 details.release());
    extensions::ActivityLog::GetInstance(profile)->LogAction(action);
  }
}

}  // namespace

void ExtensionWebRequestEventRouter::DecrementBlockCount(
    void* profile,
    const std::string& extension_id,
    const std::string& event_name,
    uint64 request_id,
    EventResponse* response) {
  scoped_ptr<EventResponse> response_scoped(response);

  // It's possible that this request was deleted, or cancelled by a previous
  // event handler. If so, ignore this response.
  if (blocked_requests_.find(request_id) == blocked_requests_.end())
    return;

  BlockedRequest& blocked_request = blocked_requests_[request_id];
  int num_handlers_blocking = --blocked_request.num_handlers_blocking;
  CHECK_GE(num_handlers_blocking, 0);

  if (response) {
    helpers::EventResponseDelta* delta =
        CalculateDelta(&blocked_request, response);

    LogExtensionActivity(profile,
                         blocked_request.is_incognito,
                         extension_id,
                         blocked_request.request->url(),
                         event_name,
                         SummarizeResponseDelta(event_name, *delta));

    blocked_request.response_deltas.push_back(
        linked_ptr<helpers::EventResponseDelta>(delta));
  }

  base::TimeDelta block_time =
      base::Time::Now() - blocked_request.blocking_time;
  if (!extension_id.empty()) {
    request_time_tracker_->IncrementExtensionBlockTime(
        extension_id, request_id, block_time);
  } else {
    // |extension_id| is empty for requests blocked on startup waiting for the
    // declarative rules to be read from disk.
    UMA_HISTOGRAM_TIMES("Extensions.NetworkDelayStartup", block_time);
  }

  if (num_handlers_blocking == 0) {
    ExecuteDeltas(profile, request_id, true);
  } else {
    // Update the URLRequest to indicate it is now blocked on a different
    // extension.
    std::set<EventListener>& listeners = listeners_[profile][event_name];

    for (std::set<EventListener>::iterator it = listeners.begin();
         it != listeners.end(); ++it) {
      if (it->blocked_requests.count(request_id)) {
        blocked_request.request->SetLoadStateParam(
            l10n_util::GetStringFUTF16(IDS_LOAD_STATE_PARAMETER_EXTENSION,
                                       UTF8ToUTF16(it->extension_name)));
        break;
      }
    }
  }
}

void ExtensionWebRequestEventRouter::SendMessages(
    void* profile,
    const BlockedRequest& blocked_request) {
  const helpers::EventResponseDeltas& deltas = blocked_request.response_deltas;
  for (helpers::EventResponseDeltas::const_iterator delta = deltas.begin();
       delta != deltas.end(); ++delta) {
    const std::set<std::string>& messages = (*delta)->messages_to_extension;
    for (std::set<std::string>::const_iterator message = messages.begin();
         message != messages.end(); ++message) {
      scoped_ptr<base::DictionaryValue> argument(new base::DictionaryValue);
      ExtractRequestInfo(blocked_request.request, argument.get());
      argument->SetString(keys::kMessageKey, *message);
      argument->SetString(keys::kStageKey,
                          GetRequestStageAsString(blocked_request.event));

      BrowserThread::PostTask(
          BrowserThread::UI,
          FROM_HERE,
          base::Bind(&SendOnMessageEventOnUI,
                     profile,
                     (*delta)->extension_id,
                     base::Passed(&argument)));
    }
  }
}

int ExtensionWebRequestEventRouter::ExecuteDeltas(
    void* profile,
    uint64 request_id,
    bool call_callback) {
  BlockedRequest& blocked_request = blocked_requests_[request_id];
  CHECK(blocked_request.num_handlers_blocking == 0);
  helpers::EventResponseDeltas& deltas = blocked_request.response_deltas;
  base::TimeDelta block_time =
      base::Time::Now() - blocked_request.blocking_time;
  request_time_tracker_->IncrementTotalBlockTime(request_id, block_time);

  bool credentials_set = false;

  deltas.sort(&helpers::InDecreasingExtensionInstallationTimeOrder);
  ExtensionWarningSet warnings;

  bool canceled = false;
  helpers::MergeCancelOfResponses(
      blocked_request.response_deltas,
      &canceled,
      blocked_request.net_log);

  if (blocked_request.event == kOnBeforeRequest) {
    CHECK(!blocked_request.callback.is_null());
    helpers::MergeOnBeforeRequestResponses(
        blocked_request.response_deltas,
        blocked_request.new_url,
        &warnings,
        blocked_request.net_log);
  } else if (blocked_request.event == kOnBeforeSendHeaders) {
    CHECK(!blocked_request.callback.is_null());
    helpers::MergeOnBeforeSendHeadersResponses(
        blocked_request.response_deltas,
        blocked_request.request_headers,
        &warnings,
        blocked_request.net_log);
  } else if (blocked_request.event == kOnHeadersReceived) {
    CHECK(!blocked_request.callback.is_null());
    helpers::MergeOnHeadersReceivedResponses(
        blocked_request.response_deltas,
        blocked_request.original_response_headers.get(),
        blocked_request.override_response_headers,
        &warnings,
        blocked_request.net_log);
  } else if (blocked_request.event == kOnAuthRequired) {
    CHECK(blocked_request.callback.is_null());
    CHECK(!blocked_request.auth_callback.is_null());
    credentials_set = helpers::MergeOnAuthRequiredResponses(
       blocked_request.response_deltas,
       blocked_request.auth_credentials,
       &warnings,
       blocked_request.net_log);
  } else {
    NOTREACHED();
  }

  SendMessages(profile, blocked_request);

  if (!warnings.empty()) {
    BrowserThread::PostTask(
        BrowserThread::UI,
        FROM_HERE,
        base::Bind(&ExtensionWarningService::NotifyWarningsOnUI,
                   profile, warnings));
  }

  if (canceled) {
    request_time_tracker_->SetRequestCanceled(request_id);
  } else if (blocked_request.new_url &&
             !blocked_request.new_url->is_empty()) {
    request_time_tracker_->SetRequestRedirected(request_id);
  }

  // This triggers onErrorOccurred if canceled is true.
  int rv = canceled ? net::ERR_BLOCKED_BY_CLIENT : net::OK;

  if (!blocked_request.callback.is_null()) {
    net::CompletionCallback callback = blocked_request.callback;
    // Ensure that request is removed before callback because the callback
    // might trigger the next event.
    blocked_requests_.erase(request_id);
    if (call_callback)
      callback.Run(rv);
  } else if (!blocked_request.auth_callback.is_null()) {
    net::NetworkDelegate::AuthRequiredResponse response =
        net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
    if (canceled) {
      response = net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_CANCEL_AUTH;
    } else if (credentials_set) {
      response = net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_SET_AUTH;
    }
    net::NetworkDelegate::AuthCallback callback = blocked_request.auth_callback;
    blocked_requests_.erase(request_id);
    if (call_callback)
      callback.Run(response);
  } else {
    blocked_requests_.erase(request_id);
  }
  return rv;
}

bool ExtensionWebRequestEventRouter::ProcessDeclarativeRules(
    void* profile,
    ExtensionInfoMap* extension_info_map,
    const std::string& event_name,
    net::URLRequest* request,
    extensions::RequestStage request_stage,
    const net::HttpResponseHeaders* original_response_headers) {
  // If this check fails, check that the active stages are up-to-date in
  // browser/extensions/api/declarative_webrequest/request_stage.h .
  DCHECK(request_stage & extensions::kActiveStages);

  // Rules of the current |profile| may apply but we need to check also whether
  // there are applicable rules from extensions whose background page
  // spans from regular to incognito mode.

  // First parameter identifies the registry, the second indicates whether the
  // registry belongs to the cross profile.
  typedef std::pair<extensions::WebRequestRulesRegistry*, bool>
      RelevantRegistry;
  typedef std::vector<RelevantRegistry> RelevantRegistries;
  RelevantRegistries relevant_registries;

  if (rules_registries_.find(profile) != rules_registries_.end()) {
    relevant_registries.push_back(
        std::make_pair(rules_registries_[profile].get(), false));
  }

  void* cross_profile = GetCrossProfile(profile);
  if (cross_profile &&
      rules_registries_.find(cross_profile) != rules_registries_.end()) {
    relevant_registries.push_back(
        std::make_pair(rules_registries_[cross_profile].get(), true));
  }

  // The following block is experimentally enabled and its impact on load time
  // logged with UMA Extensions.NetworkDelayRegistryLoad. crbug.com/175961
  for (RelevantRegistries::iterator i = relevant_registries.begin();
       i != relevant_registries.end(); ++i) {
    extensions::WebRequestRulesRegistry* rules_registry = i->first;
    if (!rules_registry->ready().is_signaled()) {
      // The rules registry is still loading. Block this request until it
      // finishes.
      rules_registry->ready().Post(
          FROM_HERE,
          base::Bind(&ExtensionWebRequestEventRouter::OnRulesRegistryReady,
                     AsWeakPtr(),
                     profile,
                     event_name,
                     request->identifier(),
                     request_stage));
      blocked_requests_[request->identifier()].num_handlers_blocking++;
      blocked_requests_[request->identifier()].request = request;
      blocked_requests_[request->identifier()].is_incognito |=
          IsIncognitoProfile(profile);
      blocked_requests_[request->identifier()].blocking_time =
          base::Time::Now();
      blocked_requests_[request->identifier()].original_response_headers =
          original_response_headers;
      blocked_requests_[request->identifier()].extension_info_map =
          extension_info_map;
      return true;
    }
  }

  base::Time start = base::Time::Now();

  bool deltas_created = false;
  for (RelevantRegistries::iterator i = relevant_registries.begin();
       i != relevant_registries.end(); ++i) {
    extensions::WebRequestRulesRegistry* rules_registry =
        i->first;
    helpers::EventResponseDeltas result =
        rules_registry->CreateDeltas(
            extension_info_map,
            extensions::WebRequestData(
                request, request_stage, original_response_headers),
            i->second);

    if (!result.empty()) {
      helpers::EventResponseDeltas& deltas =
          blocked_requests_[request->identifier()].response_deltas;
      deltas.insert(deltas.end(), result.begin(), result.end());
      deltas_created = true;
    }
  }

  base::TimeDelta elapsed_time = start - base::Time::Now();
  UMA_HISTOGRAM_TIMES("Extensions.DeclarativeWebRequestNetworkDelay",
                      elapsed_time);

  return deltas_created;
}

void ExtensionWebRequestEventRouter::OnRulesRegistryReady(
    void* profile,
    const std::string& event_name,
    uint64 request_id,
    extensions::RequestStage request_stage) {
  // It's possible that this request was deleted, or cancelled by a previous
  // event handler. If so, ignore this response.
  if (blocked_requests_.find(request_id) == blocked_requests_.end())
    return;

  BlockedRequest& blocked_request = blocked_requests_[request_id];
  base::TimeDelta block_time =
      base::Time::Now() - blocked_request.blocking_time;
  UMA_HISTOGRAM_TIMES("Extensions.NetworkDelayRegistryLoad", block_time);

  ProcessDeclarativeRules(profile,
                          blocked_request.extension_info_map,
                          event_name,
                          blocked_request.request,
                          request_stage,
                          blocked_request.original_response_headers.get());
  // Reset to NULL so that nobody relies on this being set.
  blocked_request.extension_info_map = NULL;
  DecrementBlockCount(profile, std::string(), event_name, request_id, NULL);
}

bool ExtensionWebRequestEventRouter::GetAndSetSignaled(uint64 request_id,
                                                       EventTypes event_type) {
  SignaledRequestMap::iterator iter = signaled_requests_.find(request_id);
  if (iter == signaled_requests_.end()) {
    signaled_requests_[request_id] = event_type;
    return false;
  }
  bool was_signaled_before = (iter->second & event_type) != 0;
  iter->second |= event_type;
  return was_signaled_before;
}

void ExtensionWebRequestEventRouter::ClearSignaled(uint64 request_id,
                                                   EventTypes event_type) {
  SignaledRequestMap::iterator iter = signaled_requests_.find(request_id);
  if (iter == signaled_requests_.end())
    return;
  iter->second &= ~event_type;
}

// Special QuotaLimitHeuristic for WebRequestHandlerBehaviorChangedFunction.
//
// Each call of webRequest.handlerBehaviorChanged() clears the in-memory cache
// of WebKit at the time of the next page load (top level navigation event).
// This quota heuristic is intended to limit the number of times the cache is
// cleared by an extension.
//
// As we want to account for the number of times the cache is really cleared
// (opposed to the number of times webRequest.handlerBehaviorChanged() is
// called), we cannot decide whether a call of
// webRequest.handlerBehaviorChanged() should trigger a quota violation at the
// time it is called. Instead we only decrement the bucket counter at the time
// when the cache is cleared (when page loads happen).
class ClearCacheQuotaHeuristic : public QuotaLimitHeuristic {
 public:
  ClearCacheQuotaHeuristic(const Config& config, BucketMapper* map)
      : QuotaLimitHeuristic(
            config,
            map,
            "MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES"),
        callback_registered_(false),
        weak_ptr_factory_(this) {}
  virtual ~ClearCacheQuotaHeuristic() {}
  virtual bool Apply(Bucket* bucket,
                     const base::TimeTicks& event_time) OVERRIDE;

 private:
  // Callback that is triggered by the ExtensionWebRequestEventRouter on a page
  // load.
  //
  // We don't need to take care of the life time of |bucket|: It is owned by the
  // BucketMapper of our base class in |QuotaLimitHeuristic::bucket_mapper_|. As
  // long as |this| exists, the respective BucketMapper and its bucket will
  // exist as well.
  void OnPageLoad(Bucket* bucket);

  // Flag to prevent that we register more than one call back in-between
  // clearing the cache.
  bool callback_registered_;

  base::WeakPtrFactory<ClearCacheQuotaHeuristic> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(ClearCacheQuotaHeuristic);
};

bool ClearCacheQuotaHeuristic::Apply(Bucket* bucket,
                                     const base::TimeTicks& event_time) {
  if (event_time > bucket->expiration())
    bucket->Reset(config(), event_time);

  // Call bucket->DeductToken() on a new page load, this is when
  // webRequest.handlerBehaviorChanged() clears the cache.
  if (!callback_registered_) {
    ExtensionWebRequestEventRouter::GetInstance()->AddCallbackForPageLoad(
        base::Bind(&ClearCacheQuotaHeuristic::OnPageLoad,
                   weak_ptr_factory_.GetWeakPtr(),
                   bucket));
    callback_registered_ = true;
  }

  // We only check whether tokens are left here. Deducting a token happens in
  // OnPageLoad().
  return bucket->has_tokens();
}

void ClearCacheQuotaHeuristic::OnPageLoad(Bucket* bucket) {
  callback_registered_ = false;
  bucket->DeductToken();
}

bool WebRequestAddEventListener::RunImpl() {
  // Argument 0 is the callback, which we don't use here.
  ExtensionWebRequestEventRouter::RequestFilter filter;
  DictionaryValue* value = NULL;
  error_.clear();
  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &value));
  // Failure + an empty error string means a fatal error.
  EXTENSION_FUNCTION_VALIDATE(filter.InitFromValue(*value, &error_) ||
                              !error_.empty());
  if (!error_.empty())
    return false;

  int extra_info_spec = 0;
  if (HasOptionalArgument(2)) {
    ListValue* value = NULL;
    EXTENSION_FUNCTION_VALIDATE(args_->GetList(2, &value));
    EXTENSION_FUNCTION_VALIDATE(
        ExtensionWebRequestEventRouter::ExtraInfoSpec::InitFromValue(
            *value, &extra_info_spec));
  }

  std::string event_name;
  EXTENSION_FUNCTION_VALIDATE(args_->GetString(3, &event_name));

  std::string sub_event_name;
  EXTENSION_FUNCTION_VALIDATE(args_->GetString(4, &sub_event_name));

  int webview_instance_id = 0;
  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(5, &webview_instance_id));

  base::WeakPtr<ChromeRenderMessageFilter> ipc_sender = ipc_sender_weak();

  int embedder_process_id =
      ipc_sender.get() ? ipc_sender->render_process_id() : -1;
  int embedder_routing_id = routing_id();

  const Extension* extension =
      extension_info_map()->extensions().GetByID(extension_id());
  std::string extension_name = extension ? extension->name() : extension_id();

  bool is_guest = webview_instance_id != 0;
  // We check automatically whether the extension has the 'webRequest'
  // permission. For blocking calls we require the additional permission
  // 'webRequestBlocking'.
  if ((!is_guest && extra_info_spec &
          (ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING |
           ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING)) &&
       !extension->HasAPIPermission(
           extensions::APIPermission::kWebRequestBlocking)) {
    error_ = keys::kBlockingPermissionRequired;
    return false;
  }

  // We allow to subscribe to patterns that are broader than the host
  // permissions. E.g., we could subscribe to http://www.example.com/*
  // while having host permissions for http://www.example.com/foo/* and
  // http://www.example.com/bar/*.
  // For this reason we do only a coarse check here to warn the extension
  // developer if he does something obviously wrong.
  if (!is_guest && extensions::PermissionsData::GetEffectiveHostPermissions(
          extension).is_empty()) {
    error_ = keys::kHostPermissionsRequired;
    return false;
  }

  bool success =
      ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
          profile_id(), extension_id(), extension_name,
          event_name, sub_event_name, filter, extra_info_spec,
          embedder_process_id, embedder_routing_id, webview_instance_id,
          ipc_sender_weak());
  EXTENSION_FUNCTION_VALIDATE(success);

  helpers::ClearCacheOnNavigation();

  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
      &helpers::NotifyWebRequestAPIUsed,
      profile_id(), make_scoped_refptr(GetExtension())));

  return true;
}

bool WebRequestEventHandled::RunImpl() {
  std::string event_name;
  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &event_name));

  std::string sub_event_name;
  EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &sub_event_name));

  std::string request_id_str;
  EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &request_id_str));
  uint64 request_id;
  EXTENSION_FUNCTION_VALIDATE(base::StringToUint64(request_id_str,
                                                   &request_id));

  scoped_ptr<ExtensionWebRequestEventRouter::EventResponse> response;
  if (HasOptionalArgument(3)) {
    DictionaryValue* value = NULL;
    EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(3, &value));

    if (!value->empty()) {
      base::Time install_time =
          extension_info_map()->GetInstallTime(extension_id());
      response.reset(new ExtensionWebRequestEventRouter::EventResponse(
          extension_id(), install_time));
    }

    if (value->HasKey("cancel")) {
      // Don't allow cancel mixed with other keys.
      if (value->HasKey("redirectUrl") || value->HasKey("requestHeaders")) {
        error_ = keys::kInvalidBlockingResponse;
        return false;
      }

      bool cancel = false;
      EXTENSION_FUNCTION_VALIDATE(value->GetBoolean("cancel", &cancel));
      response->cancel = cancel;
    }

    if (value->HasKey("redirectUrl")) {
      std::string new_url_str;
      EXTENSION_FUNCTION_VALIDATE(value->GetString("redirectUrl",
                                                   &new_url_str));
      response->new_url = GURL(new_url_str);
      if (!response->new_url.is_valid()) {
        error_ = ErrorUtils::FormatErrorMessage(
            keys::kInvalidRedirectUrl, new_url_str);
        return false;
      }
    }

    if (value->HasKey("requestHeaders")) {
      ListValue* request_headers_value = NULL;
      response->request_headers.reset(new net::HttpRequestHeaders());
      EXTENSION_FUNCTION_VALIDATE(value->GetList(keys::kRequestHeadersKey,
                                                 &request_headers_value));
      for (size_t i = 0; i < request_headers_value->GetSize(); ++i) {
        DictionaryValue* header_value = NULL;
        std::string name;
        std::string value;
        EXTENSION_FUNCTION_VALIDATE(
            request_headers_value->GetDictionary(i, &header_value));
        EXTENSION_FUNCTION_VALIDATE(
            FromHeaderDictionary(header_value, &name, &value));
        response->request_headers->SetHeader(name, value);
      }
    }

    if (value->HasKey("responseHeaders")) {
      scoped_ptr<helpers::ResponseHeaders> response_headers(
          new helpers::ResponseHeaders());
      ListValue* response_headers_value = NULL;
      EXTENSION_FUNCTION_VALIDATE(value->GetList(keys::kResponseHeadersKey,
                                                 &response_headers_value));
      for (size_t i = 0; i < response_headers_value->GetSize(); ++i) {
        DictionaryValue* header_value = NULL;
        std::string name;
        std::string value;
        EXTENSION_FUNCTION_VALIDATE(
            response_headers_value->GetDictionary(i, &header_value));
        EXTENSION_FUNCTION_VALIDATE(
            FromHeaderDictionary(header_value, &name, &value));
        response_headers->push_back(helpers::ResponseHeader(name, value));
      }
      response->response_headers.reset(response_headers.release());
    }

    if (value->HasKey(keys::kAuthCredentialsKey)) {
      DictionaryValue* credentials_value = NULL;
      EXTENSION_FUNCTION_VALIDATE(value->GetDictionary(
          keys::kAuthCredentialsKey,
          &credentials_value));
      string16 username;
      string16 password;
      EXTENSION_FUNCTION_VALIDATE(
          credentials_value->GetString(keys::kUsernameKey, &username));
      EXTENSION_FUNCTION_VALIDATE(
          credentials_value->GetString(keys::kPasswordKey, &password));
      response->auth_credentials.reset(
          new net::AuthCredentials(username, password));
    }
  }

  ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled(
      profile_id(), extension_id(), event_name, sub_event_name, request_id,
      response.release());

  return true;
}

void WebRequestHandlerBehaviorChangedFunction::GetQuotaLimitHeuristics(
    QuotaLimitHeuristics* heuristics) const {
  QuotaLimitHeuristic::Config config = {
    // See web_request.json for current value.
    web_request::MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES,
    base::TimeDelta::FromMinutes(10)
  };
  QuotaLimitHeuristic::BucketMapper* bucket_mapper =
      new QuotaLimitHeuristic::SingletonBucketMapper();
  ClearCacheQuotaHeuristic* heuristic =
      new ClearCacheQuotaHeuristic(config, bucket_mapper);
  heuristics->push_back(heuristic);
}

void WebRequestHandlerBehaviorChangedFunction::OnQuotaExceeded(
    const std::string& violation_error) {
  // Post warning message.
  ExtensionWarningSet warnings;
  warnings.insert(
      ExtensionWarning::CreateRepeatedCacheFlushesWarning(extension_id()));
  BrowserThread::PostTask(
      BrowserThread::UI,
      FROM_HERE,
      base::Bind(&ExtensionWarningService::NotifyWarningsOnUI,
                 profile_id(), warnings));

  // Continue gracefully.
  Run();
}

bool WebRequestHandlerBehaviorChangedFunction::RunImpl() {
  helpers::ClearCacheOnNavigation();
  return true;
}

void SendExtensionWebRequestStatusToHost(content::RenderProcessHost* host) {
  Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext());
  if (!profile || !profile->GetExtensionService())
    return;

  bool adblock = false;
  bool adblock_plus = false;
  bool other = false;
  const ExtensionSet* extensions =
      profile->GetExtensionService()->extensions();
  for (ExtensionSet::const_iterator it = extensions->begin();
       it != extensions->end(); ++it) {
    if (profile->GetExtensionService()->HasUsedWebRequest(it->get())) {
      if ((*it)->name().find("Adblock Plus") != std::string::npos) {
        adblock_plus = true;
      } else if ((*it)->name().find("AdBlock") != std::string::npos) {
        adblock = true;
      } else {
        other = true;
      }
    }
  }

  host->Send(new ExtensionMsg_UsingWebRequestAPI(adblock, adblock_plus, other));
}
