15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/web_request/web_request_api.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind_helpers.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chrome_content_browser_client.h"
20a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/extensions/activity_log/activity_action_constants.h"
21a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/extensions/activity_log/activity_actions.h"
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/extensions/activity_log/activity_log.h"
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/extensions/activity_log/web_request_constants.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/declarative_webrequest/request_stage.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/web_request/upload_data_presenter.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/web_request/web_request_api_constants.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/web_request/web_request_time_tracker.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/event_router.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_info_map.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_prefs.h"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_renderer_state.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_system.h"
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_warning_service.h"
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_warning_set.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/renderer_host/chrome_render_message_filter.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/api/web_request.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_constants.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_messages.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/features/feature.h"
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/common/extensions/permissions/permissions_data.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_message_filter.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/resource_request_info.h"
547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/user_metrics.h"
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/error_utils.h"
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/event_filtering_info.h"
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/url_pattern.h"
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/auth.h"
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/upload_data_stream.h"
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request.h"
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::DictionaryValue;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::ListValue;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::StringValue;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using chrome::VersionInfo;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserMessageFilter;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::ResourceRequestInfo;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using extensions::ErrorUtils;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension;
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using extensions::ExtensionWarning;
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using extensions::ExtensionWarningService;
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using extensions::ExtensionWarningSet;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Feature;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::web_navigation_api_helpers::GetFrameId;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace helpers = extension_web_request_api_helpers;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace keys = extension_web_request_api_constants;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace web_request = extensions::api::web_request;
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace declarative_keys = extensions::declarative_webrequest_constants;
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace activitylog = activity_log_web_request_constants;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kWebRequest[] = "webRequest";
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kWebView[] = "webview";
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// List of all the webRequest events.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kWebRequestEvents[] = {
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  keys::kOnBeforeRedirectEvent,
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  keys::kOnBeforeRequestEvent,
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  keys::kOnBeforeSendHeadersEvent,
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  keys::kOnCompletedEvent,
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  keys::kOnErrorOccurredEvent,
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  keys::kOnSendHeadersEvent,
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  keys::kOnAuthRequiredEvent,
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  keys::kOnResponseStartedEvent,
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  keys::kOnHeadersReceivedEvent,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ARRAYEND(array) (array + arraysize(array))
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char* GetRequestStageAsString(
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ExtensionWebRequestEventRouter::EventTypes type) {
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (type) {
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kInvalidEvent:
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "Invalid";
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnBeforeRequest:
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return keys::kOnBeforeRequest;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnBeforeSendHeaders:
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return keys::kOnBeforeSendHeaders;
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnSendHeaders:
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return keys::kOnSendHeaders;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnHeadersReceived:
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return keys::kOnHeadersReceived;
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnBeforeRedirect:
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return keys::kOnBeforeRedirect;
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnAuthRequired:
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return keys::kOnAuthRequired;
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnResponseStarted:
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return keys::kOnResponseStarted;
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnErrorOccurred:
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return keys::kOnErrorOccurred;
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnCompleted:
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return keys::kOnCompleted;
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTREACHED();
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return "Not reached";
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsWebRequestEvent(const std::string& event_name) {
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string web_request_event_name(event_name);
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (web_request_event_name.find(kWebView) != std::string::npos)
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    web_request_event_name.replace(0, sizeof(kWebView) - 1, kWebRequest);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::find(kWebRequestEvents, ARRAYEND(kWebRequestEvents),
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                   web_request_event_name) != ARRAYEND(kWebRequestEvents);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns whether |request| has been triggered by an extension in
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |extension_info_map|.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsRequestFromExtension(const net::URLRequest* request,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const ExtensionInfoMap* extension_info_map) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |extension_info_map| is NULL for system-level requests.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension_info_map)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If this request was not created by the ResourceDispatcher, |info| is NULL.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All requests from extensions are created by the ResourceDispatcher.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!info)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return extension_info_map->process_map().Contains(info->GetChildID());
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtractRequestInfoDetails(net::URLRequest* request,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               bool* is_main_frame,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               int64* frame_id,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               bool* parent_is_main_frame,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               int64* parent_frame_id,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               int* tab_id,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               int* window_id,
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               int* render_process_host_id,
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               int* routing_id,
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               ResourceType::Type* resource_type) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!request->GetUserData(NULL))
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExtensionRendererState::GetInstance()->GetTabAndWindowId(
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info->GetChildID(), info->GetRouteID(), tab_id, window_id);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *frame_id = info->GetFrameID();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *is_main_frame = info->IsMainFrame();
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *parent_frame_id = info->GetParentFrameID();
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *parent_is_main_frame = info->ParentIsMainFrame();
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *render_process_host_id = info->GetChildID();
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *routing_id = info->GetRouteID();
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Restrict the resource type to the values we care about.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (helpers::IsRelevantResourceType(info->GetResourceType()))
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *resource_type = info->GetResourceType();
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *resource_type = ResourceType::LAST_TYPE;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Extracts from |request| information for the keys requestId, url, method,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// frameId, tabId, type, and timeStamp and writes these into |out| to be passed
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on to extensions.
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtractRequestInfo(net::URLRequest* request, DictionaryValue* out) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_main_frame = false;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 frame_id = -1;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool parent_is_main_frame = false;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 parent_frame_id = -1;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int frame_id_for_extension = -1;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int parent_frame_id_for_extension = -1;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int tab_id = -1;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int window_id = -1;
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int render_process_host_id = -1;
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int routing_id = -1;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceType::Type resource_type = ResourceType::LAST_TYPE;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtractRequestInfoDetails(request, &is_main_frame, &frame_id,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &parent_is_main_frame, &parent_frame_id, &tab_id,
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            &window_id, &render_process_host_id, &routing_id,
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            &resource_type);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_id_for_extension = GetFrameId(is_main_frame, frame_id);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parent_frame_id_for_extension = GetFrameId(parent_is_main_frame,
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             parent_frame_id);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->SetString(keys::kRequestIdKey,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Uint64ToString(request->identifier()));
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->SetString(keys::kUrlKey, request->url().spec());
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->SetString(keys::kMethodKey, request->method());
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->SetInteger(keys::kFrameIdKey, frame_id_for_extension);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->SetInteger(keys::kParentFrameIdKey, parent_frame_id_for_extension);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->SetInteger(keys::kTabIdKey, tab_id);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->SetString(keys::kTypeKey, helpers::ResourceTypeToString(resource_type));
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->SetDouble(keys::kTimeStampKey, base::Time::Now().ToDoubleT() * 1000);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Extracts the body from |request| and writes the data into |out|.
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtractRequestInfoBody(const net::URLRequest* request,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            DictionaryValue* out) {
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const net::UploadDataStream* upload_data = request->get_upload();
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!upload_data ||
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (request->method() != "POST" && request->method() != "PUT"))
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Need to exit without "out->Set(keys::kRequestBodyKey, ...);" .
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* requestBody = new DictionaryValue();
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->Set(keys::kRequestBodyKey, requestBody);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the data presenters, ordered by how specific they are.
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extensions::ParsedDataPresenter parsed_data_presenter(*request);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extensions::RawDataPresenter raw_data_presenter;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extensions::UploadDataPresenter* const presenters[] = {
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    &parsed_data_presenter,    // 1: any parseable forms? (Specific to forms.)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    &raw_data_presenter        // 2: any data at all? (Non-specific.)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Keys for the results of the corresponding presenters.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* const kKeys[] = {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    keys::kRequestBodyFormDataKey,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    keys::kRequestBodyRawKey
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ScopedVector<net::UploadElementReader>& readers =
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      upload_data->element_readers();
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool some_succeeded = false;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; !some_succeeded && i < arraysize(presenters); ++i) {
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ScopedVector<net::UploadElementReader>::const_iterator reader;
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (reader = readers.begin(); reader != readers.end(); ++reader)
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      presenters[i]->FeedNext(**reader);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (presenters[i]->Succeeded()) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      requestBody->Set(kKeys[i], presenters[i]->Result().release());
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      some_succeeded = true;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!some_succeeded)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    requestBody->SetString(keys::kRequestBodyErrorKey, "Unknown error.");
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts a HttpHeaders dictionary to a |name|, |value| pair. Returns
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// true if successful.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FromHeaderDictionary(const DictionaryValue* header_value,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          std::string* name,
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          std::string* value) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!header_value->GetString(keys::kHeaderNameKey, name))
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We require either a "value" or a "binaryValue" entry.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!(header_value->HasKey(keys::kHeaderValueKey) ^
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        header_value->HasKey(keys::kHeaderBinaryValueKey)))
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (header_value->HasKey(keys::kHeaderValueKey)) {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!header_value->GetString(keys::kHeaderValueKey, value)) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (header_value->HasKey(keys::kHeaderBinaryValueKey)) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ListValue* list = NULL;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!header_value->GetList(keys::kHeaderBinaryValueKey, &list) ||
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !helpers::CharListToString(list, value)) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts the |name|, |value| pair of a http header to a HttpHeaders
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dictionary. Ownership is passed to the caller.
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DictionaryValue* ToHeaderDictionary(const std::string& name,
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const std::string& value) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* header = new DictionaryValue();
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header->SetString(keys::kHeaderNameKey, name);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsStringUTF8(value)) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    header->SetString(keys::kHeaderValueKey, value);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    header->Set(keys::kHeaderBinaryValueKey,
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                helpers::StringToCharList(value));
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return header;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a list of HttpHeaders (see the extension API JSON). If |headers| is
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NULL, the list is empty. Ownership is passed to the caller.
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ListValue* GetResponseHeadersList(const net::HttpResponseHeaders* headers) {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListValue* headers_value = new ListValue();
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (headers) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* iter = NULL;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string value;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (headers->EnumerateHeaderLines(&iter, &name, &value))
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers_value->Append(ToHeaderDictionary(name, value));
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return headers_value;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ListValue* GetRequestHeadersList(const net::HttpRequestHeaders& headers) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListValue* headers_value = new ListValue();
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext(); )
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    headers_value->Append(ToHeaderDictionary(it.name(), it.value()));
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return headers_value;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a StringValue with the status line of |headers|. If |headers| is
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NULL, an empty string is returned.  Ownership is passed to the caller.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StringValue* GetStatusLine(net::HttpResponseHeaders* headers) {
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return new StringValue(headers ? headers->GetStatusLine() : std::string());
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void RemoveEventListenerOnUI(
33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void* profile_id,
33790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const std::string& event_name,
33890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int process_id,
33990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const std::string& extension_id) {
34090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Profile* profile = reinterpret_cast<Profile*>(profile_id);
34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!g_browser_process->profile_manager()->IsValidProfile(profile))
34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
34690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  extensions::EventRouter* event_router =
34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      extensions::ExtensionSystem::Get(profile)->event_router();
34890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!event_router)
34990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
35090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
35190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  content::RenderProcessHost* process =
35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      content::RenderProcessHost::FromID(process_id);
35390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!process)
35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
35690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  event_router->RemoveEventListener(event_name, process, extension_id);
35790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Sends an event to subscribers of chrome.declarativeWebRequest.onMessage.
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |extension_id| identifies the extension that sends and receives the event.
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |event_argument| is passed to the event listener.
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SendOnMessageEventOnUI(
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void* profile_id,
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& extension_id,
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<base::DictionaryValue> event_argument) {
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Profile* profile = reinterpret_cast<Profile*>(profile_id);
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!g_browser_process->profile_manager()->IsValidProfile(profile))
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::ListValue> event_args(new ListValue);
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  event_args->Append(event_argument.release());
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extensions::EventRouter* event_router =
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extensions::ExtensionSystem::Get(profile)->event_router();
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<extensions::Event> event(new extensions::Event(
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      declarative_keys::kOnMessage, event_args.Pass(), profile,
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GURL(), extensions::EventRouter::USER_GESTURE_UNKNOWN,
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extensions::EventFilteringInfo()));
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  event_router->DispatchEventToExtension(extension_id, event.Pass());
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Represents a single unique listener to an event, along with whatever filter
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// parameters and extra_info_spec were specified at the time the listener was
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// added.
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// NOTE(benjhayden) New APIs should not use this sub_event_name trick! It does
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// not play well with event pages. See downloads.onDeterminingFilename and
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ExtensionDownloadsEventRouter for an alternative approach.
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ExtensionWebRequestEventRouter::EventListener {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string extension_id;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string extension_name;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string sub_event_name;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RequestFilter filter;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec;
39990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int embedder_process_id;
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int embedder_routing_id;
401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int webview_instance_id;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtr<IPC::Sender> ipc_sender;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable std::set<uint64> blocked_requests;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Comparator to work with std::set.
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator<(const EventListener& that) const {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extension_id < that.extension_id)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extension_id == that.extension_id &&
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sub_event_name < that.sub_event_name)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventListener() : extra_info_spec(0) {}
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Contains info about requests that are blocked waiting for a response from
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// an extension.
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ExtensionWebRequestEventRouter::BlockedRequest {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The request that is being blocked.
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::URLRequest* request;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Whether the request originates from an incognito tab.
4257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  bool is_incognito;
4267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The event that we're currently blocked on.
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventTypes event;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The number of event handlers that we are awaiting a response from.
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_handlers_blocking;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pointer to NetLog to report significant changes to the request for
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // debugging.
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const net::BoundNetLog* net_log;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The callback to call when we get a response from all event handlers.
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::CompletionCallback callback;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If non-empty, this contains the new URL that the request will redirect to.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only valid for OnBeforeRequest.
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL* new_url;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The request headers that will be issued along with this request. Only valid
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for OnBeforeSendHeaders.
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::HttpRequestHeaders* request_headers;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The response headers that were received from the server. Only valid for
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnHeadersReceived.
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<const net::HttpResponseHeaders> original_response_headers;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Location where to override response headers. Only valid for
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnHeadersReceived.
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<net::HttpResponseHeaders>* override_response_headers;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If non-empty, this contains the auth credentials that may be filled in.
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only valid for OnAuthRequired.
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::AuthCredentials* auth_credentials;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The callback to invoke for auth. If |auth_callback.is_null()| is false,
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |callback| must be NULL.
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only valid for OnAuthRequired.
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::NetworkDelegate::AuthCallback auth_callback;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Time the request was paused. Used for logging purposes.
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time blocking_time;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Changes requested by extensions.
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helpers::EventResponseDeltas response_deltas;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Provider of meta data about extensions, only used and non-NULL for events
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that are delayed until the rules registry is ready.
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionInfoMap* extension_info_map;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlockedRequest()
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : request(NULL),
4777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        is_incognito(false),
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        event(kInvalidEvent),
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_handlers_blocking(0),
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_log(NULL),
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new_url(NULL),
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        request_headers(NULL),
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        override_response_headers(NULL),
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        auth_credentials(NULL),
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extension_info_map(NULL) {}
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionWebRequestEventRouter::RequestFilter::InitFromValue(
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const DictionaryValue& value, std::string* error) {
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!value.HasKey("urls"))
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (DictionaryValue::Iterator it(value); !it.IsAtEnd(); it.Advance()) {
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (it.key() == "urls") {
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const ListValue* urls_value = NULL;
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!it.value().GetAsList(&urls_value))
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < urls_value->GetSize(); ++i) {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string url;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        URLPattern pattern(
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS |
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            URLPattern::SCHEME_FTP | URLPattern::SCHEME_FILE |
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            URLPattern::SCHEME_EXTENSION);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!urls_value->GetString(i, &url) ||
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            pattern.Parse(url) != URLPattern::PARSE_SUCCESS) {
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          *error = ErrorUtils::FormatErrorMessage(
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              keys::kInvalidRequestFilterUrl, url);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        urls.AddPattern(pattern);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (it.key() == "types") {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const ListValue* types_value = NULL;
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!it.value().GetAsList(&types_value))
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < types_value->GetSize(); ++i) {
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string type_str;
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ResourceType::Type type;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!types_value->GetString(i, &type_str) ||
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            !helpers::ParseResourceType(type_str, &type))
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        types.push_back(type);
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (it.key() == "tabId") {
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!it.value().GetAsInteger(&tab_id))
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (it.key() == "windowId") {
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!it.value().GetAsInteger(&window_id))
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionWebRequestEventRouter::ExtraInfoSpec::InitFromValue(
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ListValue& value, int* extra_info_spec) {
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *extra_info_spec = 0;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < value.GetSize(); ++i) {
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string str;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!value.GetString(i, &str))
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (str == "requestHeaders")
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *extra_info_spec |= REQUEST_HEADERS;
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (str == "responseHeaders")
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *extra_info_spec |= RESPONSE_HEADERS;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (str == "blocking")
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *extra_info_spec |= BLOCKING;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (str == "asyncBlocking")
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *extra_info_spec |= ASYNC_BLOCKING;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (str == "requestBody")
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *extra_info_spec |= REQUEST_BODY;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // BLOCKING and ASYNC_BLOCKING are mutually exclusive.
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*extra_info_spec & BLOCKING) && (*extra_info_spec & ASYNC_BLOCKING))
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebRequestEventRouter::EventResponse::EventResponse(
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id, const base::Time& extension_install_time)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : extension_id(extension_id),
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_install_time(extension_install_time),
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cancel(false) {
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebRequestEventRouter::EventResponse::~EventResponse() {
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebRequestEventRouter::RequestFilter::RequestFilter()
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : tab_id(-1), window_id(-1) {
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebRequestEventRouter::RequestFilter::~RequestFilter() {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ExtensionWebRequestEventRouter
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebRequestEventRouter* ExtensionWebRequestEventRouter::GetInstance() {
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Singleton<ExtensionWebRequestEventRouter>::get();
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebRequestEventRouter::ExtensionWebRequestEventRouter()
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : request_time_tracker_(new ExtensionWebRequestTimeTracker) {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebRequestEventRouter::~ExtensionWebRequestEventRouter() {
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::RegisterRulesRegistry(
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<extensions::WebRequestRulesRegistry> rules_registry) {
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rules_registry.get())
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rules_registries_[profile] = rules_registry;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rules_registries_.erase(profile);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionWebRequestEventRouter::OnBeforeRequest(
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionInfoMap* extension_info_map,
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::CompletionCallback& callback,
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL* new_url) {
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We hide events from the system context as well as sensitive requests.
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile ||
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebRequestPermissions::HideRequest(extension_info_map, request))
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsPageLoad(request))
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyPageLoad();
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_time_tracker_->LogRequestStartTime(request->identifier(),
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             base::Time::Now(),
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             request->url(),
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             profile);
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether to initialized blocked_requests_.
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool initialize_blocked_requests = false;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  initialize_blocked_requests |=
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ProcessDeclarativeRules(profile, extension_info_map,
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              keys::kOnBeforeRequestEvent, request,
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              extensions::ON_BEFORE_REQUEST, NULL);
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const EventListener*> listeners =
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetMatchingListeners(profile, extension_info_map,
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           keys::kOnBeforeRequestEvent, request,
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           &extra_info_spec);
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!listeners.empty() &&
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !GetAndSetSignaled(request->identifier(), kOnBeforeRequest)) {
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ListValue args;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* dict = new DictionaryValue();
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtractRequestInfo(request, dict);
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extra_info_spec & ExtraInfoSpec::REQUEST_BODY)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExtractRequestInfoBody(request, dict);
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    args.Append(dict);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    initialize_blocked_requests |=
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DispatchEvent(profile, request, listeners, args);
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!initialize_blocked_requests)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;  // Nobody saw a reason for modifying the request.
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].event = kOnBeforeRequest;
6597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  blocked_requests_[request->identifier()].is_incognito |=
6607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      IsIncognitoProfile(profile);
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  blocked_requests_[request->identifier()].request = request;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].callback = callback;
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].new_url = new_url;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].net_log = &request->net_log();
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (blocked_requests_[request->identifier()].num_handlers_blocking == 0) {
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If there are no blocking handlers, only the declarative rules tried
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to modify the request and we can respond synchronously.
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ExecuteDeltas(profile, request->identifier(),
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         false /* call_callback*/);
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_IO_PENDING;
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionWebRequestEventRouter::OnBeforeSendHeaders(
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionInfoMap* extension_info_map,
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::CompletionCallback& callback,
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::HttpRequestHeaders* headers) {
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We hide events from the system context as well as sensitive requests.
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile ||
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebRequestPermissions::HideRequest(extension_info_map, request))
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool initialize_blocked_requests = false;
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  initialize_blocked_requests |=
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ProcessDeclarativeRules(profile, extension_info_map,
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              keys::kOnBeforeSendHeadersEvent, request,
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              extensions::ON_BEFORE_SEND_HEADERS, NULL);
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const EventListener*> listeners =
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetMatchingListeners(profile, extension_info_map,
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           keys::kOnBeforeSendHeadersEvent, request,
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &extra_info_spec);
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!listeners.empty() &&
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !GetAndSetSignaled(request->identifier(), kOnBeforeSendHeaders)) {
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ListValue args;
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* dict = new DictionaryValue();
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtractRequestInfo(request, dict);
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dict->Set(keys::kRequestHeadersKey, GetRequestHeadersList(*headers));
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    args.Append(dict);
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    initialize_blocked_requests |=
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DispatchEvent(profile, request, listeners, args);
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!initialize_blocked_requests)
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;  // Nobody saw a reason for modifying the request.
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].event = kOnBeforeSendHeaders;
7167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  blocked_requests_[request->identifier()].is_incognito |=
7177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      IsIncognitoProfile(profile);
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  blocked_requests_[request->identifier()].request = request;
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].callback = callback;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].request_headers = headers;
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].net_log = &request->net_log();
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (blocked_requests_[request->identifier()].num_handlers_blocking == 0) {
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If there are no blocking handlers, only the declarative rules tried
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to modify the request and we can respond synchronously.
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ExecuteDeltas(profile, request->identifier(),
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         false /* call_callback*/);
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_IO_PENDING;
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::OnSendHeaders(
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionInfoMap* extension_info_map,
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::HttpRequestHeaders& headers) {
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We hide events from the system context as well as sensitive requests.
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile ||
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebRequestPermissions::HideRequest(extension_info_map, request))
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetAndSetSignaled(request->identifier(), kOnSendHeaders))
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearSignaled(request->identifier(), kOnBeforeRedirect);
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const EventListener*> listeners =
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetMatchingListeners(profile, extension_info_map,
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           keys::kOnSendHeadersEvent, request,
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           &extra_info_spec);
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listeners.empty())
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListValue args;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* dict = new DictionaryValue();
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtractRequestInfo(request, dict);
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->Set(keys::kRequestHeadersKey, GetRequestHeadersList(headers));
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args.Append(dict);
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DispatchEvent(profile, request, listeners, args);
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionWebRequestEventRouter::OnHeadersReceived(
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionInfoMap* extension_info_map,
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::CompletionCallback& callback,
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::HttpResponseHeaders* original_response_headers,
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::HttpResponseHeaders>* override_response_headers) {
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We hide events from the system context as well as sensitive requests.
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile ||
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebRequestPermissions::HideRequest(extension_info_map, request))
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool initialize_blocked_requests = false;
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  initialize_blocked_requests |=
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ProcessDeclarativeRules(profile, extension_info_map,
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              keys::kOnHeadersReceivedEvent, request,
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              extensions::ON_HEADERS_RECEIVED,
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              original_response_headers);
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const EventListener*> listeners =
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetMatchingListeners(profile, extension_info_map,
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           keys::kOnHeadersReceivedEvent, request,
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &extra_info_spec);
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!listeners.empty() &&
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !GetAndSetSignaled(request->identifier(), kOnHeadersReceived)) {
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ListValue args;
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* dict = new DictionaryValue();
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtractRequestInfo(request, dict);
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->SetString(keys::kStatusLineKey,
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        original_response_headers->GetStatusLine());
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dict->Set(keys::kResponseHeadersKey,
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          GetResponseHeadersList(original_response_headers));
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    args.Append(dict);
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    initialize_blocked_requests |=
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DispatchEvent(profile, request, listeners, args);
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!initialize_blocked_requests)
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::OK;  // Nobody saw a reason for modifying the request.
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].event = kOnHeadersReceived;
8137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  blocked_requests_[request->identifier()].is_incognito |=
8147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      IsIncognitoProfile(profile);
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  blocked_requests_[request->identifier()].request = request;
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].callback = callback;
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].net_log = &request->net_log();
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].override_response_headers =
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      override_response_headers;
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_[request->identifier()].original_response_headers =
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      original_response_headers;
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (blocked_requests_[request->identifier()].num_handlers_blocking == 0) {
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If there are no blocking handlers, only the declarative rules tried
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to modify the request and we can respond synchronously.
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ExecuteDeltas(profile, request->identifier(),
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         false /* call_callback*/);
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_IO_PENDING;
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)net::NetworkDelegate::AuthRequiredResponse
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebRequestEventRouter::OnAuthRequired(
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionInfoMap* extension_info_map,
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::AuthChallengeInfo& auth_info,
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::NetworkDelegate::AuthCallback& callback,
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::AuthCredentials* credentials) {
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No profile means that this is for authentication challenges in the
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // system context. Skip in that case. Also skip sensitive requests.
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile ||
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebRequestPermissions::HideRequest(extension_info_map, request))
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const EventListener*> listeners =
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetMatchingListeners(profile, extension_info_map,
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           keys::kOnAuthRequiredEvent, request,
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           &extra_info_spec);
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listeners.empty())
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListValue args;
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* dict = new DictionaryValue();
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtractRequestInfo(request, dict);
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetBoolean(keys::kIsProxyKey, auth_info.is_proxy);
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!auth_info.scheme.empty())
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->SetString(keys::kSchemeKey, auth_info.scheme);
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!auth_info.realm.empty())
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->SetString(keys::kRealmKey, auth_info.realm);
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* challenger = new DictionaryValue();
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  challenger->SetString(keys::kHostKey, auth_info.challenger.host());
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  challenger->SetInteger(keys::kPortKey, auth_info.challenger.port());
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->Set(keys::kChallengerKey, challenger);
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers()));
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->Set(keys::kResponseHeadersKey,
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetResponseHeadersList(request->response_headers()));
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args.Append(dict);
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (DispatchEvent(profile, request, listeners, args)) {
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_[request->identifier()].event = kOnAuthRequired;
8767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    blocked_requests_[request->identifier()].is_incognito |=
8777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        IsIncognitoProfile(profile);
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    blocked_requests_[request->identifier()].request = request;
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_[request->identifier()].auth_callback = callback;
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_[request->identifier()].auth_credentials = credentials;
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_[request->identifier()].net_log = &request->net_log();
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_IO_PENDING;
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::OnBeforeRedirect(
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionInfoMap* extension_info_map,
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& new_location) {
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We hide events from the system context as well as sensitive requests.
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile ||
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebRequestPermissions::HideRequest(extension_info_map, request))
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetAndSetSignaled(request->identifier(), kOnBeforeRedirect))
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearSignaled(request->identifier(), kOnBeforeRequest);
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearSignaled(request->identifier(), kOnBeforeSendHeaders);
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearSignaled(request->identifier(), kOnSendHeaders);
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearSignaled(request->identifier(), kOnHeadersReceived);
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const EventListener*> listeners =
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetMatchingListeners(profile, extension_info_map,
9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           keys::kOnBeforeRedirectEvent, request,
9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           &extra_info_spec);
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listeners.empty())
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int http_status_code = request->GetResponseCode();
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string response_ip = request->GetSocketAddress().host();
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListValue args;
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* dict = new DictionaryValue();
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtractRequestInfo(request, dict);
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetString(keys::kRedirectUrlKey, new_location.spec());
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetInteger(keys::kStatusCodeKey, http_status_code);
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!response_ip.empty())
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->SetString(keys::kIpKey, response_ip);
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetBoolean(keys::kFromCache, request->was_cached());
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers()));
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->Set(keys::kResponseHeadersKey,
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetResponseHeadersList(request->response_headers()));
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args.Append(dict);
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DispatchEvent(profile, request, listeners, args);
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::OnResponseStarted(
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionInfoMap* extension_info_map,
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request) {
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We hide events from the system context as well as sensitive requests.
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile ||
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebRequestPermissions::HideRequest(extension_info_map, request))
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnResponseStarted is even triggered, when the request was cancelled.
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request->status().status() != net::URLRequestStatus::SUCCESS)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const EventListener*> listeners =
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetMatchingListeners(profile, extension_info_map,
9512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           keys::kOnResponseStartedEvent, request,
9522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           &extra_info_spec);
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listeners.empty())
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // UrlRequestFileJobs do not send headers, so we simulate their behavior.
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int response_code = 200;
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request->response_headers())
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_code = request->response_headers()->response_code();
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string response_ip = request->GetSocketAddress().host();
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListValue args;
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* dict = new DictionaryValue();
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtractRequestInfo(request, dict);
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!response_ip.empty())
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->SetString(keys::kIpKey, response_ip);
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetBoolean(keys::kFromCache, request->was_cached());
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetInteger(keys::kStatusCodeKey, response_code);
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers()));
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->Set(keys::kResponseHeadersKey,
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetResponseHeadersList(request->response_headers()));
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args.Append(dict);
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DispatchEvent(profile, request, listeners, args);
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::OnCompleted(
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionInfoMap* extension_info_map,
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request) {
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We hide events from the system context as well as sensitive requests.
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // However, if the request first became sensitive after redirecting we have
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // already signaled it and thus we have to signal the end of it. This is
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // risk-free because the handler cannot modify the request now.
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile ||
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (WebRequestPermissions::HideRequest(extension_info_map, request) &&
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       !WasSignaled(*request)))
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_time_tracker_->LogRequestEndTime(request->identifier(),
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           base::Time::Now());
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request->status().status() == net::URLRequestStatus::SUCCESS);
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!GetAndSetSignaled(request->identifier(), kOnCompleted));
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearPendingCallbacks(request);
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const EventListener*> listeners =
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetMatchingListeners(profile, extension_info_map,
10052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           keys::kOnCompletedEvent, request, &extra_info_spec);
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listeners.empty())
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // UrlRequestFileJobs do not send headers, so we simulate their behavior.
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int response_code = 200;
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request->response_headers())
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_code = request->response_headers()->response_code();
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string response_ip = request->GetSocketAddress().host();
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListValue args;
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* dict = new DictionaryValue();
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtractRequestInfo(request, dict);
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetInteger(keys::kStatusCodeKey, response_code);
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!response_ip.empty())
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->SetString(keys::kIpKey, response_ip);
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetBoolean(keys::kFromCache, request->was_cached());
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->Set(keys::kStatusLineKey, GetStatusLine(request->response_headers()));
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->Set(keys::kResponseHeadersKey,
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              GetResponseHeadersList(request->response_headers()));
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args.Append(dict);
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DispatchEvent(profile, request, listeners, args);
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::OnErrorOccurred(
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionInfoMap* extension_info_map,
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool started) {
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We hide events from the system context as well as sensitive requests.
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // However, if the request first became sensitive after redirecting we have
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // already signaled it and thus we have to signal the end of it. This is
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // risk-free because the handler cannot modify the request now.
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile ||
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (WebRequestPermissions::HideRequest(extension_info_map, request) &&
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       !WasSignaled(*request)))
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_time_tracker_->LogRequestEndTime(request->identifier(),
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           base::Time::Now());
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request->status().status() == net::URLRequestStatus::FAILED ||
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         request->status().status() == net::URLRequestStatus::CANCELED);
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!GetAndSetSignaled(request->identifier(), kOnErrorOccurred));
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearPendingCallbacks(request);
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const EventListener*> listeners =
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetMatchingListeners(profile, extension_info_map,
10602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           keys::kOnErrorOccurredEvent, request,
10612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           &extra_info_spec);
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listeners.empty())
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListValue args;
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* dict = new DictionaryValue();
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtractRequestInfo(request, dict);
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (started) {
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string response_ip = request->GetSocketAddress().host();
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!response_ip.empty())
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dict->SetString(keys::kIpKey, response_ip);
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetBoolean(keys::kFromCache, request->was_cached());
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetString(keys::kErrorKey,
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  net::ErrorToString(request->status().error()));
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args.Append(dict);
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DispatchEvent(profile, request, listeners, args);
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::OnURLRequestDestroyed(
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile, net::URLRequest* request) {
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearPendingCallbacks(request);
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signaled_requests_.erase(request->identifier());
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_time_tracker_->LogRequestEndTime(request->identifier(),
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           base::Time::Now());
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::ClearPendingCallbacks(
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request) {
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_requests_.erase(request->identifier());
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionWebRequestEventRouter::DispatchEvent(
10972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void* profile_id,
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<const EventListener*>& listeners,
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ListValue& args) {
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(mpcomplete): Consider consolidating common (extension_id,json_args)
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pairs into a single message sent to a list of sub_event_names.
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_handlers_blocking = 0;
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<const EventListener*>::const_iterator it = listeners.begin();
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != listeners.end(); ++it) {
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Filter out the optional keys that this listener didn't request.
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ListValue> args_filtered(args.DeepCopy());
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* dict = NULL;
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(args_filtered->GetDictionary(0, &dict) && dict);
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!((*it)->extra_info_spec & ExtraInfoSpec::REQUEST_HEADERS))
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dict->Remove(keys::kRequestHeadersKey, NULL);
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!((*it)->extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS))
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dict->Remove(keys::kResponseHeadersKey, NULL);
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions::EventRouter::DispatchEvent(
11162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (*it)->ipc_sender.get(), profile_id,
11172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (*it)->extension_id, (*it)->sub_event_name,
1118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        args_filtered.Pass(),
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extensions::EventRouter::USER_GESTURE_UNKNOWN,
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extensions::EventFilteringInfo());
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*it)->extra_info_spec &
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) {
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (*it)->blocked_requests.insert(request->identifier());
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++num_handlers_blocking;
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request->SetLoadStateParam(
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          l10n_util::GetStringFUTF16(IDS_LOAD_STATE_PARAMETER_EXTENSION,
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     UTF8ToUTF16((*it)->extension_name)));
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_handlers_blocking > 0) {
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_[request->identifier()].request = request;
11347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    blocked_requests_[request->identifier()].is_incognito |=
11357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        IsIncognitoProfile(profile_id);
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_[request->identifier()].num_handlers_blocking +=
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_handlers_blocking;
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_[request->identifier()].blocking_time = base::Time::Now();
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::OnEventHandled(
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id,
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& event_name,
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& sub_event_name,
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint64 request_id,
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EventResponse* response) {
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventListener listener;
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.extension_id = extension_id;
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.sub_event_name = sub_event_name;
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The listener may have been removed (e.g. due to the process going away)
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // before we got here.
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<EventListener>::iterator found =
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      listeners_[profile][event_name].find(listener);
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found != listeners_[profile][event_name].end())
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    found->blocked_requests.erase(request_id);
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DecrementBlockCount(profile, extension_id, event_name, request_id, response);
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionWebRequestEventRouter::AddEventListener(
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id,
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_name,
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& event_name,
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& sub_event_name,
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const RequestFilter& filter,
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int extra_info_spec,
117590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int embedder_process_id,
1176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int embedder_routing_id,
1177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int webview_instance_id,
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::WeakPtr<IPC::Sender> ipc_sender) {
117990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsWebRequestEvent(event_name))
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventListener listener;
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.extension_id = extension_id;
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.extension_name = extension_name;
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.sub_event_name = sub_event_name;
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.filter = filter;
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.extra_info_spec = extra_info_spec;
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.ipc_sender = ipc_sender;
119090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  listener.embedder_process_id = embedder_process_id;
1191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  listener.embedder_routing_id = embedder_routing_id;
1192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  listener.webview_instance_id = webview_instance_id;
11937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (listener.webview_instance_id)
11947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    RecordAction(content::UserMetricsAction("WebView.WebRequest.AddListener"));
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (listeners_[profile][event_name].count(listener) != 0u) {
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This is likely an abuse of the API by a malicious extension.
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listeners_[profile][event_name].insert(listener);
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::RemoveEventListener(
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id,
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& sub_event_name) {
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t slash_sep = sub_event_name.find('/');
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string event_name = sub_event_name.substr(0, slash_sep);
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsWebRequestEvent(event_name))
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventListener listener;
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.extension_id = extension_id;
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listener.sub_event_name = sub_event_name;
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's possible for AddEventListener to fail asynchronously. In that case,
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the renderer believes the listener exists, while the browser does not.
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ignore a RemoveEventListener in that case.
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<EventListener>::iterator found =
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      listeners_[profile][event_name].find(listener);
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found == listeners_[profile][event_name].end())
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(listeners_[profile][event_name].count(listener), 1u) <<
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "extension=" << extension_id << " event=" << event_name;
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unblock any request that this event listener may have been blocking.
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<uint64>::iterator it = found->blocked_requests.begin();
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != found->blocked_requests.end(); ++it) {
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DecrementBlockCount(profile, extension_id, event_name, *it, NULL);
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listeners_[profile][event_name].erase(listener);
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helpers::ClearCacheOnNavigation();
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
124090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ExtensionWebRequestEventRouter::RemoveWebViewEventListeners(
124190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    void* profile,
124290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& extension_id,
124390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int embedder_process_id,
1244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int webview_instance_id) {
124590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Iterate over all listeners of all WebRequest events to delete
124690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // any listeners that belong to the provided <webview>.
124790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ListenerMapForProfile& map_for_profile = listeners_[profile];
124890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (ListenerMapForProfile::iterator event_iter = map_for_profile.begin();
124990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       event_iter != map_for_profile.end(); ++event_iter) {
125090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    std::vector<EventListener> listeners_to_delete;
125190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    std::set<EventListener>& listeners = event_iter->second;
125290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (std::set<EventListener>::iterator listener_iter = listeners.begin();
125390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         listener_iter != listeners.end(); ++listener_iter) {
125490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const EventListener& listener = *listener_iter;
125590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (listener.embedder_process_id == embedder_process_id &&
1256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          listener.webview_instance_id == webview_instance_id)
125790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        listeners_to_delete.push_back(listener);
125890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
125990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (size_t i = 0; i < listeners_to_delete.size(); ++i) {
126090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      EventListener& listener = listeners_to_delete[i];
126190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      content::BrowserThread::PostTask(
126290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          content::BrowserThread::UI,
126390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          FROM_HERE,
126490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          base::Bind(&RemoveEventListenerOnUI,
126590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     profile,
126690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     listener.sub_event_name,
126790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     embedder_process_id,
126890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     extension_id));
126990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
127090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
127190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
127290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::OnOTRProfileCreated(
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* original_profile, void* otr_profile) {
12757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  cross_profile_map_[original_profile] = std::make_pair(false, otr_profile);
12767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  cross_profile_map_[otr_profile] = std::make_pair(true, original_profile);
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::OnOTRProfileDestroyed(
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* original_profile, void* otr_profile) {
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cross_profile_map_.erase(otr_profile);
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cross_profile_map_.erase(original_profile);
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::AddCallbackForPageLoad(
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& callback) {
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callbacks_for_page_load_.push_back(callback);
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionWebRequestEventRouter::IsPageLoad(
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request) const {
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_main_frame = false;
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 frame_id = -1;
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool parent_is_main_frame = false;
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 parent_frame_id = -1;
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int tab_id = -1;
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int window_id = -1;
12982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int render_process_host_id = -1;
12992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int routing_id = -1;
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceType::Type resource_type = ResourceType::LAST_TYPE;
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtractRequestInfoDetails(request, &is_main_frame, &frame_id,
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &parent_is_main_frame, &parent_frame_id,
13042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            &tab_id, &window_id, &render_process_host_id,
13052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            &routing_id, &resource_type);
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return resource_type == ResourceType::MAIN_FRAME;
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::NotifyPageLoad() {
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (CallbacksForPageLoad::const_iterator i =
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           callbacks_for_page_load_.begin();
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != callbacks_for_page_load_.end(); ++i) {
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i->Run();
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callbacks_for_page_load_.clear();
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* ExtensionWebRequestEventRouter::GetCrossProfile(void* profile) const {
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CrossProfileMap::const_iterator cross_profile =
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cross_profile_map_.find(profile);
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cross_profile == cross_profile_map_.end())
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
13247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return cross_profile->second.second;
13257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
13267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
13277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool ExtensionWebRequestEventRouter::IsIncognitoProfile(void* profile) const {
13287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  CrossProfileMap::const_iterator cross_profile =
13297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      cross_profile_map_.find(profile);
13307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (cross_profile == cross_profile_map_.end())
13317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return false;
13327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return cross_profile->second.first;
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionWebRequestEventRouter::WasSignaled(
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::URLRequest& request) const {
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignaledRequestMap::const_iterator flag =
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      signaled_requests_.find(request.identifier());
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (flag != signaled_requests_.end()) && (flag->second != 0);
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::GetMatchingListenersImpl(
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionInfoMap* extension_info_map,
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool crosses_incognito,
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& event_name,
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int tab_id,
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int window_id,
13502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int render_process_host_id,
13512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int routing_id,
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResourceType::Type resource_type,
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_async_request,
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_request_from_extension,
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int* extra_info_spec,
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<const ExtensionWebRequestEventRouter::EventListener*>*
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        matching_listeners) {
135890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string web_request_event_name(event_name);
1359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ExtensionRendererState::WebViewInfo webview_info;
13602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_guest = ExtensionRendererState::GetInstance()->
1361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      GetWebViewInfo(render_process_host_id, routing_id, &webview_info);
136290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (is_guest)
136390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    web_request_event_name.replace(0, sizeof(kWebRequest) - 1, kWebView);
136490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
136590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::set<EventListener>& listeners =
136690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      listeners_[profile][web_request_event_name];
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<EventListener>::iterator it = listeners.begin();
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != listeners.end(); ++it) {
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!it->ipc_sender.get()) {
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The IPC sender has been deleted. This listener will be removed soon
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // via a call to RemoveEventListener. For now, just skip it.
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
137590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (is_guest &&
1376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        (it->embedder_process_id != webview_info.embedder_process_id ||
1377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         it->embedder_routing_id != webview_info.embedder_routing_id ||
1378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         it->webview_instance_id != webview_info.instance_id))
13792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
13802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!it->filter.urls.is_empty() && !it->filter.urls.MatchesURL(url))
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->filter.tab_id != -1 && tab_id != it->filter.tab_id)
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->filter.window_id != -1 && window_id != it->filter.window_id)
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!it->filter.types.empty() &&
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::find(it->filter.types.begin(), it->filter.types.end(),
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  resource_type) == it->filter.types.end())
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
139290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!is_guest && !WebRequestPermissions::CanExtensionAccessURL(
1393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            extension_info_map, it->extension_id, url, crosses_incognito,
1394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            WebRequestPermissions::REQUIRE_HOST_PERMISSION))
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool blocking_listener =
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (it->extra_info_spec &
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) != 0;
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We do not want to notify extensions about XHR requests that are
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // triggered by themselves. This is a workaround to prevent deadlocks
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // in case of synchronous XHR requests that block the extension renderer
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and therefore prevent the extension from processing the request
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // handler. This is only a problem for blocking listeners.
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // http://crbug.com/105656
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool synchronous_xhr_from_extension = !is_async_request &&
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        is_request_from_extension && resource_type == ResourceType::XHR;
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Only send webRequest events for URLs the extension has access to.
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (blocking_listener && synchronous_xhr_from_extension)
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    matching_listeners->push_back(&(*it));
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *extra_info_spec |= it->extra_info_spec;
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::vector<const ExtensionWebRequestEventRouter::EventListener*>
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionWebRequestEventRouter::GetMatchingListeners(
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionInfoMap* extension_info_map,
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& event_name,
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int* extra_info_spec) {
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(mpcomplete): handle profile == NULL (should collect all listeners).
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *extra_info_spec = 0;
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_main_frame = false;
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 frame_id = -1;
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool parent_is_main_frame = false;
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 parent_frame_id = -1;
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int tab_id = -1;
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int window_id = -1;
14352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int render_process_host_id = -1;
14362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int routing_id = -1;
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceType::Type resource_type = ResourceType::LAST_TYPE;
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GURL& url = request->url();
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtractRequestInfoDetails(request, &is_main_frame, &frame_id,
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &parent_is_main_frame, &parent_frame_id,
14422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            &tab_id, &window_id, &render_process_host_id,
14432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            &routing_id, &resource_type);
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const ExtensionWebRequestEventRouter::EventListener*>
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      matching_listeners;
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_request_from_extension =
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IsRequestFromExtension(request, extension_info_map);
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We are conservative here and assume requests are asynchronous in case
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we don't have an info object. We don't want to risk a deadlock.
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_async_request = !info || info->IsAsync();
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetMatchingListenersImpl(
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile, extension_info_map, false, event_name, url,
14582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tab_id, window_id, render_process_host_id, routing_id, resource_type,
14592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      is_async_request, is_request_from_extension, extra_info_spec,
14602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &matching_listeners);
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* cross_profile = GetCrossProfile(profile);
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cross_profile) {
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetMatchingListenersImpl(
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cross_profile, extension_info_map, true, event_name, url, tab_id,
14652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        window_id, render_process_host_id, routing_id, resource_type,
14662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        is_async_request, is_request_from_extension, extra_info_spec,
14672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &matching_listeners);
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return matching_listeners;
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)helpers::EventResponseDelta* CalculateDelta(
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionWebRequestEventRouter::BlockedRequest* blocked_request,
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionWebRequestEventRouter::EventResponse* response) {
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (blocked_request->event) {
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnBeforeRequest:
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return helpers::CalculateOnBeforeRequestDelta(
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response->extension_id, response->extension_install_time,
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response->cancel, response->new_url);
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnBeforeSendHeaders: {
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::HttpRequestHeaders* old_headers = blocked_request->request_headers;
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::HttpRequestHeaders* new_headers = response->request_headers.get();
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return helpers::CalculateOnBeforeSendHeadersDelta(
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response->extension_id, response->extension_install_time,
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response->cancel, old_headers, new_headers);
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnHeadersReceived: {
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const net::HttpResponseHeaders* old_headers =
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          blocked_request->original_response_headers.get();
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      helpers::ResponseHeaders* new_headers =
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response->response_headers.get();
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return helpers::CalculateOnHeadersReceivedDelta(
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response->extension_id, response->extension_install_time,
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response->cancel, old_headers, new_headers);
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ExtensionWebRequestEventRouter::kOnAuthRequired:
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return helpers::CalculateOnAuthRequiredDelta(
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response->extension_id, response->extension_install_time,
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response->cancel, &response->auth_credentials);
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Value* SerializeResponseHeaders(const helpers::ResponseHeaders& headers) {
1511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ListValue> serialized_headers(new ListValue());
1512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (helpers::ResponseHeaders::const_iterator i = headers.begin();
1513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       i != headers.end(); ++i) {
1514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    serialized_headers->Append(ToHeaderDictionary(i->first, i->second));
1515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return serialized_headers.release();
1517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Convert a RequestCookieModifications/ResponseCookieModifications object to a
1520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// ListValue which summarizes the changes made.  This is templated since the
1521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// two types (request/response) are different but contain essentially the same
1522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// fields.
1523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)template<typename CookieType>
1524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ListValue* SummarizeCookieModifications(
1525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::vector<linked_ptr<CookieType> >& modifications) {
1526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ListValue> cookie_modifications(new ListValue());
1527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (typename std::vector<linked_ptr<CookieType> >::const_iterator i =
1528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           modifications.begin();
1529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       i != modifications.end(); ++i) {
1530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<DictionaryValue> summary(new DictionaryValue());
1531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const CookieType& mod = *i->get();
1532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    switch (mod.type) {
1533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case helpers::ADD:
1534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        summary->SetString(activitylog::kCookieModificationTypeKey,
1535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           activitylog::kCookieModificationAdd);
1536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
1537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case helpers::EDIT:
1538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        summary->SetString(activitylog::kCookieModificationTypeKey,
1539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           activitylog::kCookieModificationEdit);
1540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
1541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case helpers::REMOVE:
1542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        summary->SetString(activitylog::kCookieModificationTypeKey,
1543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           activitylog::kCookieModificationRemove);
1544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
1545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (mod.filter) {
1547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (mod.filter->name)
1548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        summary->SetString(activitylog::kCookieFilterNameKey,
1549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           *mod.modification->name);
1550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (mod.filter->domain)
1551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        summary->SetString(activitylog::kCookieFilterDomainKey,
1552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           *mod.modification->name);
1553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (mod.modification) {
1555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (mod.modification->name)
1556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        summary->SetString(activitylog::kCookieModDomainKey,
1557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           *mod.modification->name);
1558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (mod.modification->domain)
1559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        summary->SetString(activitylog::kCookieModDomainKey,
1560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           *mod.modification->name);
1561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cookie_modifications->Append(summary.release());
1563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return cookie_modifications.release();
1565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Converts an EventResponseDelta object to a dictionary value suitable for the
15687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// activity log.
15697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochscoped_ptr<DictionaryValue> SummarizeResponseDelta(
1570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& event_name,
1571c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const helpers::EventResponseDelta& delta) {
1572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<DictionaryValue> details(new DictionaryValue());
1573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (delta.cancel) {
1574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    details->SetBoolean(activitylog::kCancelKey, true);
1575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!delta.new_url.is_empty()) {
1577c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      details->SetString(activitylog::kNewUrlKey, delta.new_url.spec());
1578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ListValue> modified_headers(new ListValue());
1581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  net::HttpRequestHeaders::Iterator iter(delta.modified_request_headers);
1582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (iter.GetNext()) {
1583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    modified_headers->Append(ToHeaderDictionary(iter.name(), iter.value()));
1584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!modified_headers->empty()) {
1586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    details->Set(activitylog::kModifiedRequestHeadersKey,
1587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 modified_headers.release());
1588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ListValue> deleted_headers(new ListValue());
1591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  deleted_headers->AppendStrings(delta.deleted_request_headers);
1592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!deleted_headers->empty()) {
1593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    details->Set(activitylog::kDeletedRequestHeadersKey,
1594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 deleted_headers.release());
1595c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!delta.added_response_headers.empty()) {
1598c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    details->Set(activitylog::kAddedRequestHeadersKey,
1599c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 SerializeResponseHeaders(delta.added_response_headers));
1600c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!delta.deleted_response_headers.empty()) {
1602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    details->Set(activitylog::kDeletedResponseHeadersKey,
1603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 SerializeResponseHeaders(delta.deleted_response_headers));
1604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (delta.auth_credentials) {
1606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    details->SetString(activitylog::kAuthCredentialsKey,
1607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       UTF16ToUTF8(delta.auth_credentials->username()) + ":*");
1608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!delta.response_cookie_modifications.empty()) {
1611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    details->Set(
1612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        activitylog::kResponseCookieModificationsKey,
1613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        SummarizeCookieModifications(delta.response_cookie_modifications));
1614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return details.Pass();
1617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid LogExtensionActivity(void* profile_id,
16207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                          bool is_incognito,
1621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          const std::string& extension_id,
1622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          const GURL& url,
1623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          const std::string& api_call,
16247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                          scoped_ptr<DictionaryValue> details) {
1625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
1626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BrowserThread::PostTask(BrowserThread::UI,
1627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            FROM_HERE,
1628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            base::Bind(&LogExtensionActivity,
16297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                       profile_id,
16307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                       is_incognito,
1631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       extension_id,
1632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       url,
1633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       api_call,
16347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                       base::Passed(&details)));
1635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
16367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    Profile* profile = static_cast<Profile*>(profile_id);
16377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (!g_browser_process->profile_manager()->IsValidProfile(profile))
16387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return;
1639a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    scoped_refptr<extensions::Action> action =
1640a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        new extensions::Action(extension_id,
1641a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                               base::Time::Now(),
1642a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                               extensions::Action::ACTION_WEB_REQUEST,
1643a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                               api_call);
1644a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    action->set_page_url(url);
1645a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    action->set_page_incognito(is_incognito);
1646a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    action->mutable_other()->Set(activity_log_constants::kActionWebRequest,
1647a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                 details.release());
1648a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    extensions::ActivityLog::GetInstance(profile)->LogAction(action);
1649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::DecrementBlockCount(
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id,
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& event_name,
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint64 request_id,
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EventResponse* response) {
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<EventResponse> response_scoped(response);
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's possible that this request was deleted, or cancelled by a previous
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // event handler. If so, ignore this response.
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (blocked_requests_.find(request_id) == blocked_requests_.end())
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlockedRequest& blocked_request = blocked_requests_[request_id];
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_handlers_blocking = --blocked_request.num_handlers_blocking;
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_GE(num_handlers_blocking, 0);
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response) {
1672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    helpers::EventResponseDelta* delta =
1673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        CalculateDelta(&blocked_request, response);
1674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1675868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (extensions::ActivityLog::IsLogEnabledOnAnyProfile()) {
16767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      LogExtensionActivity(profile,
16777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                           blocked_request.is_incognito,
1678c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           extension_id,
1679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           blocked_request.request->url(),
1680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           event_name,
1681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           SummarizeResponseDelta(event_name, *delta));
1682c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1683c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_request.response_deltas.push_back(
1685c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        linked_ptr<helpers::EventResponseDelta>(delta));
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta block_time =
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::Now() - blocked_request.blocking_time;
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension_id.empty()) {
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_time_tracker_->IncrementExtensionBlockTime(
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extension_id, request_id, block_time);
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |extension_id| is empty for requests blocked on startup waiting for the
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // declarative rules to be read from disk.
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_TIMES("Extensions.NetworkDelayStartup", block_time);
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_handlers_blocking == 0) {
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExecuteDeltas(profile, request_id, true);
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Update the URLRequest to indicate it is now blocked on a different
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // extension.
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::set<EventListener>& listeners = listeners_[profile][event_name];
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::set<EventListener>::iterator it = listeners.begin();
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         it != listeners.end(); ++it) {
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (it->blocked_requests.count(request_id)) {
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.request->SetLoadStateParam(
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            l10n_util::GetStringFUTF16(IDS_LOAD_STATE_PARAMETER_EXTENSION,
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       UTF8ToUTF16(it->extension_name)));
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExtensionWebRequestEventRouter::SendMessages(
17192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void* profile,
17202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const BlockedRequest& blocked_request) {
17212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const helpers::EventResponseDeltas& deltas = blocked_request.response_deltas;
17222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (helpers::EventResponseDeltas::const_iterator delta = deltas.begin();
17232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       delta != deltas.end(); ++delta) {
17242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::set<std::string>& messages = (*delta)->messages_to_extension;
17252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (std::set<std::string>::const_iterator message = messages.begin();
17262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         message != messages.end(); ++message) {
17272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scoped_ptr<base::DictionaryValue> argument(new base::DictionaryValue);
17282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ExtractRequestInfo(blocked_request.request, argument.get());
17292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      argument->SetString(keys::kMessageKey, *message);
17302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      argument->SetString(keys::kStageKey,
17312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          GetRequestStageAsString(blocked_request.event));
17322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      BrowserThread::PostTask(
17342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          BrowserThread::UI,
17352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          FROM_HERE,
17362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::Bind(&SendOnMessageEventOnUI,
17372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     profile,
17382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     (*delta)->extension_id,
17392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     base::Passed(&argument)));
17402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
17412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
17422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
17432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ExtensionWebRequestEventRouter::ExecuteDeltas(
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint64 request_id,
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool call_callback) {
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlockedRequest& blocked_request = blocked_requests_[request_id];
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(blocked_request.num_handlers_blocking == 0);
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helpers::EventResponseDeltas& deltas = blocked_request.response_deltas;
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta block_time =
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::Now() - blocked_request.blocking_time;
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_time_tracker_->IncrementTotalBlockTime(request_id, block_time);
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool credentials_set = false;
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  deltas.sort(&helpers::InDecreasingExtensionInstallationTimeOrder);
17582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExtensionWarningSet warnings;
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool canceled = false;
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helpers::MergeCancelOfResponses(
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocked_request.response_deltas,
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &canceled,
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocked_request.net_log);
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (blocked_request.event == kOnBeforeRequest) {
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(!blocked_request.callback.is_null());
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helpers::MergeOnBeforeRequestResponses(
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.response_deltas,
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.new_url,
17712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &warnings,
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.net_log);
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (blocked_request.event == kOnBeforeSendHeaders) {
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(!blocked_request.callback.is_null());
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helpers::MergeOnBeforeSendHeadersResponses(
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.response_deltas,
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.request_headers,
17782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &warnings,
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.net_log);
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (blocked_request.event == kOnHeadersReceived) {
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(!blocked_request.callback.is_null());
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helpers::MergeOnHeadersReceivedResponses(
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.response_deltas,
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.original_response_headers.get(),
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.override_response_headers,
17862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &warnings,
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocked_request.net_log);
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (blocked_request.event == kOnAuthRequired) {
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(blocked_request.callback.is_null());
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(!blocked_request.auth_callback.is_null());
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    credentials_set = helpers::MergeOnAuthRequiredResponses(
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       blocked_request.response_deltas,
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       blocked_request.auth_credentials,
17942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       &warnings,
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       blocked_request.net_log);
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendMessages(profile, blocked_request);
18012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!warnings.empty()) {
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserThread::UI,
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
18062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&ExtensionWarningService::NotifyWarningsOnUI,
18072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   profile, warnings));
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (canceled) {
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_time_tracker_->SetRequestCanceled(request_id);
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (blocked_request.new_url &&
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             !blocked_request.new_url->is_empty()) {
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_time_tracker_->SetRequestRedirected(request_id);
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This triggers onErrorOccurred if canceled is true.
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = canceled ? net::ERR_BLOCKED_BY_CLIENT : net::OK;
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!blocked_request.callback.is_null()) {
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::CompletionCallback callback = blocked_request.callback;
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ensure that request is removed before callback because the callback
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // might trigger the next event.
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_.erase(request_id);
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (call_callback)
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.Run(rv);
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (!blocked_request.auth_callback.is_null()) {
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::NetworkDelegate::AuthRequiredResponse response =
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (canceled) {
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response = net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_CANCEL_AUTH;
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (credentials_set) {
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response = net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_SET_AUTH;
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::NetworkDelegate::AuthCallback callback = blocked_request.auth_callback;
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_.erase(request_id);
18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (call_callback)
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.Run(response);
18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_requests_.erase(request_id);
18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionWebRequestEventRouter::ProcessDeclarativeRules(
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionInfoMap* extension_info_map,
18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& event_name,
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request,
18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions::RequestStage request_stage,
18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::HttpResponseHeaders* original_response_headers) {
18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If this check fails, check that the active stages are up-to-date in
18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // browser/extensions/api/declarative_webrequest/request_stage.h .
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request_stage & extensions::kActiveStages);
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Rules of the current |profile| may apply but we need to check also whether
18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there are applicable rules from extensions whose background page
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // spans from regular to incognito mode.
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First parameter identifies the registry, the second indicates whether the
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // registry belongs to the cross profile.
18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::pair<extensions::WebRequestRulesRegistry*, bool>
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RelevantRegistry;
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::vector<RelevantRegistry> RelevantRegistries;
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RelevantRegistries relevant_registries;
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rules_registries_.find(profile) != rules_registries_.end()) {
18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    relevant_registries.push_back(
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::make_pair(rules_registries_[profile].get(), false));
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* cross_profile = GetCrossProfile(profile);
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cross_profile &&
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rules_registries_.find(cross_profile) != rules_registries_.end()) {
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    relevant_registries.push_back(
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::make_pair(rules_registries_[cross_profile].get(), true));
18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The following block is experimentally enabled and its impact on load time
18802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // logged with UMA Extensions.NetworkDelayRegistryLoad. crbug.com/175961
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (RelevantRegistries::iterator i = relevant_registries.begin();
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != relevant_registries.end(); ++i) {
18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions::WebRequestRulesRegistry* rules_registry = i->first;
188490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!rules_registry->ready().is_signaled()) {
18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The rules registry is still loading. Block this request until it
18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // finishes.
188790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      rules_registry->ready().Post(
188890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          FROM_HERE,
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&ExtensionWebRequestEventRouter::OnRulesRegistryReady,
189090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     AsWeakPtr(),
189190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     profile,
189290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     event_name,
189390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     request->identifier(),
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     request_stage));
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocked_requests_[request->identifier()].num_handlers_blocking++;
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocked_requests_[request->identifier()].request = request;
18977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      blocked_requests_[request->identifier()].is_incognito |=
18987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          IsIncognitoProfile(profile);
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocked_requests_[request->identifier()].blocking_time =
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Time::Now();
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocked_requests_[request->identifier()].original_response_headers =
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          original_response_headers;
19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocked_requests_[request->identifier()].extension_info_map =
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          extension_info_map;
19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time start = base::Time::Now();
19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool deltas_created = false;
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (RelevantRegistries::iterator i = relevant_registries.begin();
19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != relevant_registries.end(); ++i) {
19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions::WebRequestRulesRegistry* rules_registry =
19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        i->first;
19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helpers::EventResponseDeltas result =
19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rules_registry->CreateDeltas(
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            extension_info_map,
19192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            extensions::WebRequestData(
19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                request, request_stage, original_response_headers),
19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            i->second);
19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!result.empty()) {
19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      helpers::EventResponseDeltas& deltas =
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          blocked_requests_[request->identifier()].response_deltas;
19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      deltas.insert(deltas.end(), result.begin(), result.end());
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      deltas_created = true;
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta elapsed_time = start - base::Time::Now();
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_TIMES("Extensions.DeclarativeWebRequestNetworkDelay",
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      elapsed_time);
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return deltas_created;
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::OnRulesRegistryReady(
19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& event_name,
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint64 request_id,
19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions::RequestStage request_stage) {
19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's possible that this request was deleted, or cancelled by a previous
19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // event handler. If so, ignore this response.
19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (blocked_requests_.find(request_id) == blocked_requests_.end())
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlockedRequest& blocked_request = blocked_requests_[request_id];
19492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta block_time =
19502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Time::Now() - blocked_request.blocking_time;
19512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UMA_HISTOGRAM_TIMES("Extensions.NetworkDelayRegistryLoad", block_time);
19522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1953868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ProcessDeclarativeRules(profile,
1954868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          blocked_request.extension_info_map,
1955868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          event_name,
1956868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          blocked_request.request,
1957868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          request_stage,
1958868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          blocked_request.original_response_headers.get());
19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset to NULL so that nobody relies on this being set.
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_request.extension_info_map = NULL;
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DecrementBlockCount(profile, std::string(), event_name, request_id, NULL);
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionWebRequestEventRouter::GetAndSetSignaled(uint64 request_id,
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       EventTypes event_type) {
19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignaledRequestMap::iterator iter = signaled_requests_.find(request_id);
19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == signaled_requests_.end()) {
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    signaled_requests_[request_id] = event_type;
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool was_signaled_before = (iter->second & event_type) != 0;
19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  iter->second |= event_type;
19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return was_signaled_before;
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionWebRequestEventRouter::ClearSignaled(uint64 request_id,
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   EventTypes event_type) {
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SignaledRequestMap::iterator iter = signaled_requests_.find(request_id);
19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == signaled_requests_.end())
19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  iter->second &= ~event_type;
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Special QuotaLimitHeuristic for WebRequestHandlerBehaviorChangedFunction.
19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Each call of webRequest.handlerBehaviorChanged() clears the in-memory cache
19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of WebKit at the time of the next page load (top level navigation event).
19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This quota heuristic is intended to limit the number of times the cache is
19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cleared by an extension.
19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// As we want to account for the number of times the cache is really cleared
19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (opposed to the number of times webRequest.handlerBehaviorChanged() is
19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// called), we cannot decide whether a call of
19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// webRequest.handlerBehaviorChanged() should trigger a quota violation at the
19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// time it is called. Instead we only decrement the bucket counter at the time
19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// when the cache is cleared (when page loads happen).
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClearCacheQuotaHeuristic : public QuotaLimitHeuristic {
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearCacheQuotaHeuristic(const Config& config, BucketMapper* map)
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : QuotaLimitHeuristic(
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            config,
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            map,
20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES"),
20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        callback_registered_(false),
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        weak_ptr_factory_(this) {}
20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ClearCacheQuotaHeuristic() {}
20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Apply(Bucket* bucket,
20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const base::TimeTicks& event_time) OVERRIDE;
20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callback that is triggered by the ExtensionWebRequestEventRouter on a page
20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // load.
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't need to take care of the life time of |bucket|: It is owned by the
20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // BucketMapper of our base class in |QuotaLimitHeuristic::bucket_mapper_|. As
20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // long as |this| exists, the respective BucketMapper and its bucket will
20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // exist as well.
20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnPageLoad(Bucket* bucket);
20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flag to prevent that we register more than one call back in-between
20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // clearing the cache.
20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool callback_registered_;
20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<ClearCacheQuotaHeuristic> weak_ptr_factory_;
20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ClearCacheQuotaHeuristic);
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ClearCacheQuotaHeuristic::Apply(Bucket* bucket,
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const base::TimeTicks& event_time) {
20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event_time > bucket->expiration())
20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bucket->Reset(config(), event_time);
20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Call bucket->DeductToken() on a new page load, this is when
20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // webRequest.handlerBehaviorChanged() clears the cache.
20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!callback_registered_) {
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionWebRequestEventRouter::GetInstance()->AddCallbackForPageLoad(
20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&ClearCacheQuotaHeuristic::OnPageLoad,
20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(),
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   bucket));
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_registered_ = true;
20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We only check whether tokens are left here. Deducting a token happens in
20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnPageLoad().
20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bucket->has_tokens();
20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClearCacheQuotaHeuristic::OnPageLoad(Bucket* bucket) {
20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_registered_ = false;
20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bucket->DeductToken();
20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRequestAddEventListener::RunImpl() {
20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Argument 0 is the callback, which we don't use here.
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionWebRequestEventRouter::RequestFilter filter;
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* value = NULL;
20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  error_.clear();
20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &value));
20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Failure + an empty error string means a fatal error.
20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(filter.InitFromValue(*value, &error_) ||
20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              !error_.empty());
20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!error_.empty())
20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int extra_info_spec = 0;
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasOptionalArgument(2)) {
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ListValue* value = NULL;
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXTENSION_FUNCTION_VALIDATE(args_->GetList(2, &value));
20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXTENSION_FUNCTION_VALIDATE(
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ExtensionWebRequestEventRouter::ExtraInfoSpec::InitFromValue(
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *value, &extra_info_spec));
20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string event_name;
20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(args_->GetString(3, &event_name));
20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string sub_event_name;
20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(args_->GetString(4, &sub_event_name));
20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2081868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int webview_instance_id = 0;
2082868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(5, &webview_instance_id));
208390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
208490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::WeakPtr<ChromeRenderMessageFilter> ipc_sender = ipc_sender_weak();
208590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
208690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int embedder_process_id =
208790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      ipc_sender.get() ? ipc_sender->render_process_id() : -1;
2088868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int embedder_routing_id = routing_id();
208990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Extension* extension =
20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_info_map()->extensions().GetByID(extension_id());
20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string extension_name = extension ? extension->name() : extension_id();
20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2094868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool is_guest = webview_instance_id != 0;
20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We check automatically whether the extension has the 'webRequest'
20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // permission. For blocking calls we require the additional permission
20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 'webRequestBlocking'.
209890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if ((!is_guest && extra_info_spec &
20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING |
21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           ExtensionWebRequestEventRouter::ExtraInfoSpec::ASYNC_BLOCKING)) &&
21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       !extension->HasAPIPermission(
21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           extensions::APIPermission::kWebRequestBlocking)) {
21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = keys::kBlockingPermissionRequired;
21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We allow to subscribe to patterns that are broader than the host
21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // permissions. E.g., we could subscribe to http://www.example.com/*
21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // while having host permissions for http://www.example.com/foo/* and
21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://www.example.com/bar/*.
21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For this reason we do only a coarse check here to warn the extension
21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // developer if he does something obviously wrong.
211390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!is_guest && extensions::PermissionsData::GetEffectiveHostPermissions(
211490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          extension).is_empty()) {
21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = keys::kHostPermissionsRequired;
21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success =
21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExtensionWebRequestEventRouter::GetInstance()->AddEventListener(
21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          profile_id(), extension_id(), extension_name,
212290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          event_name, sub_event_name, filter, extra_info_spec,
2123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          embedder_process_id, embedder_routing_id, webview_instance_id,
2124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          ipc_sender_weak());
21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(success);
21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helpers::ClearCacheOnNavigation();
21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
2130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &helpers::NotifyWebRequestAPIUsed,
21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_id(), make_scoped_refptr(GetExtension())));
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRequestEventHandled::RunImpl() {
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string event_name;
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &event_name));
21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string sub_event_name;
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &sub_event_name));
21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string request_id_str;
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &request_id_str));
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64 request_id;
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(base::StringToUint64(request_id_str,
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   &request_id));
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ExtensionWebRequestEventRouter::EventResponse> response;
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasOptionalArgument(3)) {
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* value = NULL;
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(3, &value));
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!value->empty()) {
21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time install_time =
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          extension_info_map()->GetInstallTime(extension_id());
21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response.reset(new ExtensionWebRequestEventRouter::EventResponse(
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          extension_id(), install_time));
21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (value->HasKey("cancel")) {
21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Don't allow cancel mixed with other keys.
21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (value->HasKey("redirectUrl") || value->HasKey("requestHeaders")) {
21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        error_ = keys::kInvalidBlockingResponse;
21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool cancel = false;
21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXTENSION_FUNCTION_VALIDATE(value->GetBoolean("cancel", &cancel));
21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response->cancel = cancel;
21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (value->HasKey("redirectUrl")) {
21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string new_url_str;
21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXTENSION_FUNCTION_VALIDATE(value->GetString("redirectUrl",
21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   &new_url_str));
21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response->new_url = GURL(new_url_str);
21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!response->new_url.is_valid()) {
21792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        error_ = ErrorUtils::FormatErrorMessage(
21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            keys::kInvalidRedirectUrl, new_url_str);
21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (value->HasKey("requestHeaders")) {
21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ListValue* request_headers_value = NULL;
21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response->request_headers.reset(new net::HttpRequestHeaders());
21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXTENSION_FUNCTION_VALIDATE(value->GetList(keys::kRequestHeadersKey,
21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 &request_headers_value));
21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < request_headers_value->GetSize(); ++i) {
21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DictionaryValue* header_value = NULL;
21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string name;
21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string value;
21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXTENSION_FUNCTION_VALIDATE(
21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            request_headers_value->GetDictionary(i, &header_value));
21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXTENSION_FUNCTION_VALIDATE(
21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            FromHeaderDictionary(header_value, &name, &value));
21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        response->request_headers->SetHeader(name, value);
21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (value->HasKey("responseHeaders")) {
22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<helpers::ResponseHeaders> response_headers(
22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new helpers::ResponseHeaders());
22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ListValue* response_headers_value = NULL;
22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXTENSION_FUNCTION_VALIDATE(value->GetList(keys::kResponseHeadersKey,
22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 &response_headers_value));
22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < response_headers_value->GetSize(); ++i) {
22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DictionaryValue* header_value = NULL;
22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string name;
22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string value;
22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXTENSION_FUNCTION_VALIDATE(
22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            response_headers_value->GetDictionary(i, &header_value));
22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXTENSION_FUNCTION_VALIDATE(
22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            FromHeaderDictionary(header_value, &name, &value));
22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        response_headers->push_back(helpers::ResponseHeader(name, value));
22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response->response_headers.reset(response_headers.release());
22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (value->HasKey(keys::kAuthCredentialsKey)) {
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DictionaryValue* credentials_value = NULL;
22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXTENSION_FUNCTION_VALIDATE(value->GetDictionary(
22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          keys::kAuthCredentialsKey,
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &credentials_value));
22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string16 username;
22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string16 password;
22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXTENSION_FUNCTION_VALIDATE(
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          credentials_value->GetString(keys::kUsernameKey, &username));
22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXTENSION_FUNCTION_VALIDATE(
22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          credentials_value->GetString(keys::kPasswordKey, &password));
22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response->auth_credentials.reset(
22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new net::AuthCredentials(username, password));
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled(
22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_id(), extension_id(), event_name, sub_event_name, request_id,
22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response.release());
22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRequestHandlerBehaviorChangedFunction::GetQuotaLimitHeuristics(
22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    QuotaLimitHeuristics* heuristics) const {
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuotaLimitHeuristic::Config config = {
22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See web_request.json for current value.
22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    web_request::MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES,
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta::FromMinutes(10)
22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuotaLimitHeuristic::BucketMapper* bucket_mapper =
22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new QuotaLimitHeuristic::SingletonBucketMapper();
22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearCacheQuotaHeuristic* heuristic =
22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ClearCacheQuotaHeuristic(config, bucket_mapper);
22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  heuristics->push_back(heuristic);
22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRequestHandlerBehaviorChangedFunction::OnQuotaExceeded(
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& violation_error) {
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Post warning message.
22612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExtensionWarningSet warnings;
22622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  warnings.insert(
22632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ExtensionWarning::CreateRepeatedCacheFlushesWarning(extension_id()));
22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::UI,
22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
22672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&ExtensionWarningService::NotifyWarningsOnUI,
22682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 profile_id(), warnings));
22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Continue gracefully.
22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Run();
22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool WebRequestHandlerBehaviorChangedFunction::RunImpl() {
22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helpers::ClearCacheOnNavigation();
22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SendExtensionWebRequestStatusToHost(content::RenderProcessHost* host) {
22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext());
22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile || !profile->GetExtensionService())
22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool adblock = false;
22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool adblock_plus = false;
22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool other = false;
22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ExtensionSet* extensions =
22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile->GetExtensionService()->extensions();
22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ExtensionSet::const_iterator it = extensions->begin();
22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != extensions->end(); ++it) {
22917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (profile->GetExtensionService()->HasUsedWebRequest(it->get())) {
22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((*it)->name().find("Adblock Plus") != std::string::npos) {
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        adblock_plus = true;
22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if ((*it)->name().find("AdBlock") != std::string::npos) {
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        adblock = true;
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        other = true;
22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  host->Send(new ExtensionMsg_UsingWebRequestAPI(adblock, adblock_plus, other));
23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2304