summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbattre@chromium.org <battre@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-30 17:21:41 +0000
committerbattre@chromium.org <battre@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-30 17:21:41 +0000
commit3dfa4c08bd73745edd13e38b9d832eac0dabd925 (patch)
treea7c16fbfdc08f8d7e7d85f8402bc49ca12f8f249
parent9a80715bd54cf030c89a9b0941551fe8bc028df9 (diff)
downloadchromium_src-3dfa4c08bd73745edd13e38b9d832eac0dabd925.zip
chromium_src-3dfa4c08bd73745edd13e38b9d832eac0dabd925.tar.gz
chromium_src-3dfa4c08bd73745edd13e38b9d832eac0dabd925.tar.bz2
Refactor and fix declarative webRequest API permissions
This CL introduces proper host permission checking for the declarative webRequest API. It moves the permission checking code from web_request_api.cc into a separate class that is shared with the declarative WebRequest API. BUG=112155 TEST=no TBR=mirandac@chromium.org,akalin@chromium.org,ben@chromium.org Review URL: https://chromiumcodereview.appspot.com/10831008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148965 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/api/declarative/rules_registry_service.cc20
-rw-r--r--chrome/browser/extensions/api/declarative/rules_registry_storage_delegate.cc43
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc60
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h37
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc10
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.cc10
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.h9
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.cc9
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h2
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc4
-rw-r--r--chrome/browser/extensions/api/web_request/web_request_api.cc185
-rw-r--r--chrome/browser/extensions/api/web_request/web_request_api.h12
-rw-r--r--chrome/browser/extensions/api/web_request/web_request_api_helpers.cc58
-rw-r--r--chrome/browser/extensions/api/web_request/web_request_api_helpers.h3
-rw-r--r--chrome/browser/extensions/api/web_request/web_request_api_unittest.cc45
-rw-r--r--chrome/browser/extensions/api/web_request/web_request_apitest.cc93
-rw-r--r--chrome/browser/extensions/api/web_request/web_request_permissions.cc105
-rw-r--r--chrome/browser/extensions/api/web_request/web_request_permissions.h36
-rw-r--r--chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc59
-rw-r--r--chrome/browser/extensions/extension_info_map.cc2
-rw-r--r--chrome/browser/extensions/extension_info_map.h2
-rw-r--r--chrome/browser/extensions/extension_system.cc31
-rw-r--r--chrome/browser/extensions/extension_system.h10
-rw-r--r--chrome/browser/extensions/test_extension_system.h3
-rw-r--r--chrome/browser/profiles/off_the_record_profile_impl.cc2
-rw-r--r--chrome/browser/profiles/profile_manager.cc3
-rw-r--r--chrome/browser/sync/glue/extension_data_type_controller.cc2
-rw-r--r--chrome/browser/sync/glue/extension_setting_data_type_controller.cc2
-rw-r--r--chrome/browser/sync/glue/theme_data_type_controller.cc2
-rw-r--r--chrome/browser/sync/test/integration/sync_app_helper.cc6
-rw-r--r--chrome/browser/sync/test/integration/sync_extension_helper.cc2
-rw-r--r--chrome/chrome_browser_extensions.gypi3
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/test/data/extensions/api_test/webrequest_permissions/spanning/background.js19
-rw-r--r--chrome/test/data/extensions/api_test/webrequest_permissions/spanning/manifest.json11
-rw-r--r--chrome/test/data/extensions/api_test/webrequest_permissions/split/background.js30
-rw-r--r--chrome/test/data/extensions/api_test/webrequest_permissions/split/manifest.json11
37 files changed, 662 insertions, 280 deletions
diff --git a/chrome/browser/extensions/api/declarative/rules_registry_service.cc b/chrome/browser/extensions/api/declarative/rules_registry_service.cc
index aead2a9..24e7f32 100644
--- a/chrome/browser/extensions/api/declarative/rules_registry_service.cc
+++ b/chrome/browser/extensions/api/declarative/rules_registry_service.cc
@@ -22,15 +22,20 @@ namespace extensions {
namespace {
// Returns the key to use for storing declarative rules in the state store.
-std::string GetDeclarativeRuleStorageKey(const std::string& event_name) {
- return "declarative_rules." + event_name;
+std::string GetDeclarativeRuleStorageKey(const std::string& event_name,
+ bool incognito) {
+ if (incognito)
+ return "declarative_rules.incognito." + event_name;
+ else
+ return "declarative_rules." + event_name;
}
// Registers |web_request_rules_registry| on the IO thread.
void RegisterToExtensionWebRequestEventRouterOnIO(
+ void* profile,
scoped_refptr<WebRequestRulesRegistry> web_request_rules_registry) {
ExtensionWebRequestEventRouter::GetInstance()->RegisterRulesRegistry(
- web_request_rules_registry);
+ profile, web_request_rules_registry);
}
} // namespace
@@ -39,7 +44,7 @@ RulesRegistryService::RulesRegistryService(Profile* profile)
: profile_(profile) {
if (profile) {
registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
- content::Source<Profile>(profile));
+ content::Source<Profile>(profile->GetOriginalProfile()));
}
}
@@ -54,7 +59,8 @@ void RulesRegistryService::RegisterDefaultRulesRegistries() {
new WebRequestRulesRegistry(profile_, delegate));
delegate->InitOnUIThread(profile_, web_request_rules_registry,
GetDeclarativeRuleStorageKey(
- declarative_webrequest_constants::kOnRequest));
+ declarative_webrequest_constants::kOnRequest,
+ profile_->IsOffTheRecord()));
delegates_.push_back(delegate);
RegisterRulesRegistry(declarative_webrequest_constants::kOnRequest,
@@ -62,14 +68,14 @@ void RulesRegistryService::RegisterDefaultRulesRegistries() {
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::Bind(&RegisterToExtensionWebRequestEventRouterOnIO,
- web_request_rules_registry));
+ profile_, web_request_rules_registry));
}
void RulesRegistryService::Shutdown() {
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::Bind(&RegisterToExtensionWebRequestEventRouterOnIO,
- scoped_refptr<WebRequestRulesRegistry>(NULL)));
+ profile_, scoped_refptr<WebRequestRulesRegistry>(NULL)));
}
void RulesRegistryService::RegisterRulesRegistry(
diff --git a/chrome/browser/extensions/api/declarative/rules_registry_storage_delegate.cc b/chrome/browser/extensions/api/declarative/rules_registry_storage_delegate.cc
index 010e140..41e51a1 100644
--- a/chrome/browser/extensions/api/declarative/rules_registry_storage_delegate.cc
+++ b/chrome/browser/extensions/api/declarative/rules_registry_storage_delegate.cc
@@ -5,8 +5,11 @@
#include "chrome/browser/extensions/api/declarative/rules_registry_storage_delegate.h"
#include "base/bind.h"
+#include "chrome/browser/extensions/extension_info_map.h"
+#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/state_store.h"
+#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/extensions/extension.h"
#include "content/public/browser/browser_thread.h"
@@ -64,6 +67,10 @@ class RulesRegistryStorageDelegate::Inner
~Inner();
+ // Initialization of the storage delegate if it is used in the context of
+ // an incognito profile.
+ void InitForOTRProfile();
+
// NotificationObserver
virtual void Observe(
int type,
@@ -164,16 +171,35 @@ RulesRegistryStorageDelegate::Inner::Inner(
rules_registry_thread_(rules_registry->GetOwnerThread()),
rules_registry_(rules_registry),
ready_(false) {
- registrar_->Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
- content::Source<Profile>(profile));
- registrar_->Add(this, chrome::NOTIFICATION_EXTENSIONS_READY,
- content::Source<Profile>(profile));
+ if (!profile_->IsOffTheRecord()) {
+ registrar_->Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
+ content::Source<Profile>(profile));
+ registrar_->Add(this, chrome::NOTIFICATION_EXTENSIONS_READY,
+ content::Source<Profile>(profile));
+ } else {
+ registrar_->Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
+ content::Source<Profile>(profile->GetOriginalProfile()));
+ InitForOTRProfile();
+ }
}
RulesRegistryStorageDelegate::Inner::~Inner() {
DCHECK(!registrar_.get());
}
+void RulesRegistryStorageDelegate::Inner::InitForOTRProfile() {
+ ExtensionService* extension_service =
+ extensions::ExtensionSystem::Get(profile_)->extension_service();
+ const ExtensionSet* extensions = extension_service->extensions();
+ for (ExtensionSet::const_iterator i = extensions->begin();
+ i != extensions->end(); ++i) {
+ if ((*i)->HasAPIPermission(APIPermission::kDeclarativeWebRequest) &&
+ extension_service->IsIncognitoEnabled((*i)->id()))
+ ReadFromStorage((*i)->id());
+ }
+ ready_ = true;
+}
+
void RulesRegistryStorageDelegate::Inner::Observe(
int type,
const content::NotificationSource& source,
@@ -186,7 +212,14 @@ void RulesRegistryStorageDelegate::Inner::Observe(
// declarative rules, not just webRequest.
if (extension->HasAPIPermission(
APIPermission::kDeclarativeWebRequest)) {
- ReadFromStorage(extension->id());
+ ExtensionInfoMap* extension_info_map =
+ ExtensionSystem::Get(profile_)->info_map();
+ if (profile_->IsOffTheRecord() &&
+ !extension_info_map->IsIncognitoEnabled(extension->id())) {
+ // Ignore this extension.
+ } else {
+ ReadFromStorage(extension->id());
+ }
}
} else if (type == chrome::NOTIFICATION_EXTENSIONS_READY) {
CheckIfReady();
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc
index 4a01ff0..9301dc0 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc
@@ -15,6 +15,7 @@
#include "chrome/browser/extensions/api/declarative_webrequest/request_stages.h"
#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h"
#include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h"
+#include "chrome/browser/extensions/api/web_request/web_request_permissions.h"
#include "chrome/browser/extensions/extension_info_map.h"
#include "chrome/common/extensions/extension.h"
#include "net/url_request/url_request.h"
@@ -198,19 +199,24 @@ int WebRequestAction::GetMinimumPriority() const {
return std::numeric_limits<int>::min();
}
-bool WebRequestAction::HasPermission(const extensions::Extension* extension,
- const net::URLRequest* request) const {
- // TODO(battre): Consider the permission to access requests from the incognito
- // profile.
- // TODO(battre): There should be a single place to check permissions for both
- // the WebRequest API and the Declarative WebRequest API.
- if (helpers::HideRequest(request))
+bool WebRequestAction::HasPermission(const ExtensionInfoMap* extension_info_map,
+ const std::string& extension_id,
+ const net::URLRequest* request,
+ bool crosses_incognito) const {
+ if (WebRequestPermissions::HideRequest(request))
return false;
- if (extension && !helpers::CanExtensionAccessURL(extension, request->url()))
- return false;
- // System requests are passed to extensions without host permissions.
- // This is the same behavior as found in
- // ExtensionWebRequestEventRouter::GetMatchingListenersImpl.
+
+ // In unit tests we don't have an extension_info_map object here and skip host
+ // permission checks.
+ if (!extension_info_map)
+ return true;
+
+ return WebRequestPermissions::CanExtensionAccessURL(
+ extension_info_map, extension_id, request->url(), crosses_incognito,
+ ShouldEnforceHostPermissions());
+}
+
+bool WebRequestAction::ShouldEnforceHostPermissions() const {
return true;
}
@@ -272,15 +278,17 @@ scoped_ptr<WebRequestActionSet> WebRequestActionSet::Create(
}
std::list<LinkedPtrEventResponseDelta> WebRequestActionSet::CreateDeltas(
- const extensions::Extension* extension,
+ const ExtensionInfoMap* extension_info_map,
+ const std::string& extension_id,
net::URLRequest* request,
+ bool crosses_incognito,
RequestStages request_stage,
const WebRequestRule::OptionalRequestData& optional_request_data,
- const std::string& extension_id,
const base::Time& extension_install_time) const {
std::list<LinkedPtrEventResponseDelta> result;
for (Actions::const_iterator i = actions_.begin(); i != actions_.end(); ++i) {
- if (!(*i)->HasPermission(extension, request))
+ if (!(*i)->HasPermission(extension_info_map, extension_id, request,
+ crosses_incognito))
continue;
if ((*i)->GetStages() & request_stage) {
LinkedPtrEventResponseDelta delta = (*i)->CreateDelta(request,
@@ -382,12 +390,9 @@ WebRequestRedirectToTransparentImageAction::GetType() const {
return WebRequestAction::ACTION_REDIRECT_TO_TRANSPARENT_IMAGE;
}
-bool WebRequestRedirectToTransparentImageAction::HasPermission(
- const extensions::Extension* extension,
- const net::URLRequest* request) const {
- // TODO(battre): Consider the permission to access requests from the incognito
- // profile.
- return true;
+bool WebRequestRedirectToTransparentImageAction::ShouldEnforceHostPermissions()
+ const {
+ return false;
}
LinkedPtrEventResponseDelta
@@ -423,10 +428,9 @@ WebRequestRedirectToEmptyDocumentAction::GetType() const {
return WebRequestAction::ACTION_REDIRECT_TO_EMPTY_DOCUMENT;
}
-bool WebRequestRedirectToEmptyDocumentAction::HasPermission(
- const extensions::Extension* extension,
- const net::URLRequest* request) const {
- return true;
+bool
+WebRequestRedirectToEmptyDocumentAction::ShouldEnforceHostPermissions() const {
+ return false;
}
LinkedPtrEventResponseDelta
@@ -744,10 +748,8 @@ int WebRequestIgnoreRulesAction::GetMinimumPriority() const {
return minimum_priority_;
}
-bool WebRequestIgnoreRulesAction::HasPermission(
- const extensions::Extension* extension,
- const net::URLRequest* request) const {
- return true;
+bool WebRequestIgnoreRulesAction::ShouldEnforceHostPermissions() const {
+ return false;
}
LinkedPtrEventResponseDelta WebRequestIgnoreRulesAction::CreateDelta(
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h
index 01f7e4a..96d0a3d 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h
@@ -17,6 +17,8 @@
#include "googleurl/src/gurl.h"
#include "unicode/regex.h"
+class WebRequestPermission;
+
namespace base {
class DictionaryValue;
class Time;
@@ -72,12 +74,21 @@ class WebRequestAction {
// this rule. Defaults to MIN_INT.
virtual int GetMinimumPriority() const;
- // Returns whether |extension| has permission to execute this action
- // on |request|. Defaults to checking the host permission.
- // |extension| may only be NULL for during testing, in which case
- // host permissions are ignored.
- virtual bool HasPermission(const extensions::Extension* extension,
- const net::URLRequest* request) const;
+ // Returns whether the specified extension has permission to execute this
+ // action on |request|. Checks the host permission if
+ // ShouldEnforceHostPermissions instructs to do that.
+ // |extension_info_map| may only be NULL for during testing, in which case
+ // host permissions are ignored. |crosses_incognito| specifies
+ // whether the request comes from a different profile than |extension_id|
+ // but was processed because the extension is in spanning mode.
+ virtual bool HasPermission(const ExtensionInfoMap* extension_info_map,
+ const std::string& extension_id,
+ const net::URLRequest* request,
+ bool crosses_incognito) const;
+
+ // Returns whether host permissions shall be enforced by this actions.
+ // Used by the standard implementation of HasPermission. Defaults to true.
+ virtual bool ShouldEnforceHostPermissions() const;
// Factory method that instantiates a concrete WebRequestAction
// implementation according to |json_action|, the representation of the
@@ -123,11 +134,12 @@ class WebRequestActionSet {
// |actions_| that can be executed at |request_stage|. If |extension|
// is not NULL, permissions of extensions are checked.
std::list<LinkedPtrEventResponseDelta> CreateDeltas(
- const extensions::Extension* extension,
+ const ExtensionInfoMap* extension_info_map,
+ const std::string& extension_id,
net::URLRequest* request,
+ bool crosses_incognito,
RequestStages request_stage,
const WebRequestRule::OptionalRequestData& optional_request_data,
- const std::string& extension_id,
const base::Time& extension_install_time) const;
// Returns the minimum priority of rules that may be evaluated after
@@ -197,8 +209,7 @@ class WebRequestRedirectToTransparentImageAction : public WebRequestAction {
// Implementation of WebRequestAction:
virtual int GetStages() const OVERRIDE;
virtual Type GetType() const OVERRIDE;
- virtual bool HasPermission(const extensions::Extension* extension,
- const net::URLRequest* request) const OVERRIDE;
+ virtual bool ShouldEnforceHostPermissions() const OVERRIDE;
virtual LinkedPtrEventResponseDelta CreateDelta(
net::URLRequest* request,
RequestStages request_stage,
@@ -220,8 +231,7 @@ class WebRequestRedirectToEmptyDocumentAction : public WebRequestAction {
// Implementation of WebRequestAction:
virtual int GetStages() const OVERRIDE;
virtual Type GetType() const OVERRIDE;
- virtual bool HasPermission(const extensions::Extension* extension,
- const net::URLRequest* request) const OVERRIDE;
+ virtual bool ShouldEnforceHostPermissions() const OVERRIDE;
virtual LinkedPtrEventResponseDelta CreateDelta(
net::URLRequest* request,
RequestStages request_stage,
@@ -366,8 +376,7 @@ class WebRequestIgnoreRulesAction : public WebRequestAction {
virtual int GetStages() const OVERRIDE;
virtual Type GetType() const OVERRIDE;
virtual int GetMinimumPriority() const OVERRIDE;
- virtual bool HasPermission(const extensions::Extension* extension,
- const net::URLRequest* request) const OVERRIDE;
+ virtual bool ShouldEnforceHostPermissions() const OVERRIDE;
virtual LinkedPtrEventResponseDelta CreateDelta(
net::URLRequest* request,
RequestStages request_stage,
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc
index bb95594..1161258 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc
@@ -148,14 +148,16 @@ TEST(WebRequestActionTest, TestPermissions) {
// Check that redirect works on regular URLs but not on protected URLs.
TestURLRequest regular_request(GURL("http://test.com"), NULL, &context);
std::list<LinkedPtrEventResponseDelta> deltas =
- action_set->CreateDeltas(NULL, &regular_request, ON_BEFORE_REQUEST,
- WebRequestRule::OptionalRequestData(), "ext1", base::Time());
+ action_set->CreateDeltas(NULL, "ext1", &regular_request, false,
+ ON_BEFORE_REQUEST, WebRequestRule::OptionalRequestData(),
+ base::Time());
EXPECT_EQ(1u, deltas.size());
TestURLRequest protected_request(GURL(extension_urls::kGalleryBrowsePrefix),
NULL, &context);
- deltas = action_set->CreateDeltas(NULL, &protected_request, ON_BEFORE_REQUEST,
- WebRequestRule::OptionalRequestData(), "ext1", base::Time());
+ deltas = action_set->CreateDeltas(NULL, "ext1", &protected_request, false,
+ ON_BEFORE_REQUEST, WebRequestRule::OptionalRequestData(),
+ base::Time());
EXPECT_EQ(0u, deltas.size());
}
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.cc
index 1b5ccb747..b7fb22b 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.cc
@@ -8,6 +8,8 @@
#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h"
#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.h"
#include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h"
+#include "chrome/browser/extensions/api/web_request/web_request_permissions.h"
+#include "chrome/browser/extensions/extension_info_map.h"
#include "chrome/common/extensions/extension.h"
namespace {
@@ -87,12 +89,14 @@ scoped_ptr<WebRequestRule> WebRequestRule::Create(
}
std::list<LinkedPtrEventResponseDelta> WebRequestRule::CreateDeltas(
- const extensions::Extension* extension,
+ const ExtensionInfoMap* extension_info_map,
net::URLRequest* request,
+ bool crosses_incognito,
RequestStages request_stage,
const OptionalRequestData& optional_request_data) const {
- return actions_->CreateDeltas(extension, request, request_stage,
- optional_request_data, id_.first, extension_installation_time_);
+ return actions_->CreateDeltas(extension_info_map, extension_id(), request,
+ crosses_incognito, request_stage, optional_request_data,
+ extension_installation_time_);
}
int WebRequestRule::GetMinimumPriority() const {
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.h b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.h
index 40ddae6..d590de7 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.h
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.h
@@ -13,11 +13,14 @@
#include "chrome/browser/extensions/api/declarative/rules_registry.h"
#include "chrome/browser/extensions/api/declarative_webrequest/request_stages.h"
+class ExtensionInfoMap;
+class WebRequestPermissions;
+
namespace extensions {
class Extension;
class URLMatcherConditionFactory;
-class WebRequestConditionSet;
class WebRequestActionSet;
+class WebRequestConditionSet;
}
namespace extension_web_request_api_helpers {
@@ -66,6 +69,7 @@ class WebRequestRule {
std::string* error);
const GlobalRuleId& id() const { return id_; }
+ const std::string& extension_id() const { return id_.first; }
const WebRequestConditionSet& conditions() const { return *conditions_; }
const WebRequestActionSet& actions() const { return *actions_; }
Priority priority() const { return priority_; }
@@ -78,8 +82,9 @@ class WebRequestRule {
// have have sufficient permissions to modify the |request|. The returned list
// may be empty in this case.
std::list<LinkedPtrEventResponseDelta> CreateDeltas(
- const extensions::Extension* extension,
+ const ExtensionInfoMap* extension_info_map,
net::URLRequest* request,
+ bool crosses_incognito,
RequestStages request_stage,
const OptionalRequestData& optional_request_data) const;
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.cc
index ce978b2..ad0348b 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.cc
@@ -8,6 +8,7 @@
#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.h"
#include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h"
+#include "chrome/browser/extensions/api/web_request/web_request_permissions.h"
#include "chrome/browser/extensions/extension_system.h"
#include "net/url_request/url_request.h"
@@ -46,6 +47,7 @@ WebRequestRulesRegistry::GetMatches(net::URLRequest* request,
std::list<LinkedPtrEventResponseDelta> WebRequestRulesRegistry::CreateDeltas(
const ExtensionInfoMap* extension_info_map,
net::URLRequest* request,
+ bool crosses_incognito,
RequestStages request_stage,
const WebRequestRule::OptionalRequestData& optional_request_data) {
if (webrequest_rules_.empty())
@@ -92,9 +94,6 @@ std::list<LinkedPtrEventResponseDelta> WebRequestRulesRegistry::CreateDeltas(
const ExtensionId& extension_id = rule_id.first;
const WebRequestRule* rule = webrequest_rules_[rule_id].get();
CHECK(rule);
- const extensions::Extension* extension = NULL;
- if (extension_info_map)
- extension = extension_info_map->extensions().GetByID(extension_id);
// Skip rule if a previous rule of this extension instructed to ignore
// all rules with a lower priority than min_priorities[extension_id].
@@ -103,8 +102,8 @@ std::list<LinkedPtrEventResponseDelta> WebRequestRulesRegistry::CreateDeltas(
continue;
std::list<LinkedPtrEventResponseDelta> rule_result =
- rule->CreateDeltas(extension, request, request_stage,
- optional_request_data);
+ rule->CreateDeltas(extension_info_map, request, crosses_incognito,
+ request_stage, optional_request_data);
result.splice(result.begin(), rule_result);
min_priorities[extension_id] = std::max(current_min_priority,
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h
index 55f0083..cb01240 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h
@@ -20,6 +20,7 @@
#include "chrome/common/extensions/matcher/url_matcher.h"
class Profile;
+class WebRequestPermissions;
namespace extension_web_request_api_helpers {
struct EventResponseDelta;
@@ -76,6 +77,7 @@ class WebRequestRulesRegistry : public RulesRegistryWithCache {
std::list<LinkedPtrEventResponseDelta> CreateDeltas(
const ExtensionInfoMap* extension_info_map,
net::URLRequest* request,
+ bool crosses_incognito,
RequestStages request_stage,
const WebRequestRule::OptionalRequestData& optional_request_data);
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
index 9253137..9a8f4a1 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
@@ -338,7 +338,7 @@ TEST_F(WebRequestRulesRegistryTest, Precedences) {
TestURLRequestContext context;
TestURLRequest request(url, NULL, &context);
std::list<LinkedPtrEventResponseDelta> deltas =
- registry->CreateDeltas(NULL, &request, ON_BEFORE_REQUEST,
+ registry->CreateDeltas(NULL, &request, false, ON_BEFORE_REQUEST,
WebRequestRule::OptionalRequestData());
// The second extension is installed later and will win for this reason
@@ -386,7 +386,7 @@ TEST_F(WebRequestRulesRegistryTest, Priorities) {
TestURLRequestContext context;
TestURLRequest request(url, NULL, &context);
std::list<LinkedPtrEventResponseDelta> deltas =
- registry->CreateDeltas(NULL, &request, ON_BEFORE_REQUEST,
+ registry->CreateDeltas(NULL, &request, false, ON_BEFORE_REQUEST,
WebRequestRule::OptionalRequestData());
// The redirect by the first extension is ignored due to the ignore rule.
diff --git a/chrome/browser/extensions/api/web_request/web_request_api.cc b/chrome/browser/extensions/api/web_request/web_request_api.cc
index 10f1d58..7c2f278 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_api.cc
@@ -455,8 +455,12 @@ ExtensionWebRequestEventRouter::~ExtensionWebRequestEventRouter() {
}
void ExtensionWebRequestEventRouter::RegisterRulesRegistry(
+ void* profile,
scoped_refptr<extensions::WebRequestRulesRegistry> rules_registry) {
- rules_registry_ = rules_registry;
+ if (rules_registry.get())
+ rules_registries_[profile] = rules_registry;
+ else
+ rules_registries_.erase(profile);
}
int ExtensionWebRequestEventRouter::OnBeforeRequest(
@@ -466,7 +470,7 @@ int ExtensionWebRequestEventRouter::OnBeforeRequest(
const net::CompletionCallback& callback,
GURL* new_url) {
// We hide events from the system context as well as sensitive requests.
- if (!profile || helpers::HideRequest(request))
+ if (!profile || WebRequestPermissions::HideRequest(request))
return net::OK;
if (IsPageLoad(request))
@@ -525,7 +529,7 @@ int ExtensionWebRequestEventRouter::OnBeforeSendHeaders(
const net::CompletionCallback& callback,
net::HttpRequestHeaders* headers) {
// We hide events from the system context as well as sensitive requests.
- if (!profile || helpers::HideRequest(request))
+ if (!profile || WebRequestPermissions::HideRequest(request))
return net::OK;
bool initialize_blocked_requests = false;
@@ -577,7 +581,7 @@ void ExtensionWebRequestEventRouter::OnSendHeaders(
net::URLRequest* request,
const net::HttpRequestHeaders& headers) {
// We hide events from the system context as well as sensitive requests.
- if (!profile || helpers::HideRequest(request))
+ if (!profile || WebRequestPermissions::HideRequest(request))
return;
if (GetAndSetSignaled(request->identifier(), kOnSendHeaders))
@@ -610,7 +614,7 @@ int ExtensionWebRequestEventRouter::OnHeadersReceived(
net::HttpResponseHeaders* original_response_headers,
scoped_refptr<net::HttpResponseHeaders>* override_response_headers) {
// We hide events from the system context as well as sensitive requests.
- if (!profile || helpers::HideRequest(request))
+ if (!profile || WebRequestPermissions::HideRequest(request))
return net::OK;
bool initialize_blocked_requests = false;
@@ -675,7 +679,7 @@ ExtensionWebRequestEventRouter::OnAuthRequired(
net::AuthCredentials* credentials) {
// No profile means that this is for authentication challenges in the
// system context. Skip in that case. Also skip sensitive requests.
- if (!profile || helpers::HideRequest(request))
+ if (!profile || WebRequestPermissions::HideRequest(request))
return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
int extra_info_spec = 0;
@@ -720,7 +724,7 @@ void ExtensionWebRequestEventRouter::OnBeforeRedirect(
net::URLRequest* request,
const GURL& new_location) {
// We hide events from the system context as well as sensitive requests.
- if (!profile || helpers::HideRequest(request))
+ if (!profile || WebRequestPermissions::HideRequest(request))
return;
if (GetAndSetSignaled(request->identifier(), kOnBeforeRedirect))
@@ -765,7 +769,7 @@ void ExtensionWebRequestEventRouter::OnResponseStarted(
ExtensionInfoMap* extension_info_map,
net::URLRequest* request) {
// We hide events from the system context as well as sensitive requests.
- if (!profile || helpers::HideRequest(request))
+ if (!profile || WebRequestPermissions::HideRequest(request))
return;
// OnResponseStarted is even triggered, when the request was cancelled.
@@ -808,7 +812,7 @@ void ExtensionWebRequestEventRouter::OnCompleted(
ExtensionInfoMap* extension_info_map,
net::URLRequest* request) {
// We hide events from the system context as well as sensitive requests.
- if (!profile || helpers::HideRequest(request))
+ if (!profile || WebRequestPermissions::HideRequest(request))
return;
request_time_tracker_->LogRequestEndTime(request->identifier(),
@@ -857,7 +861,7 @@ void ExtensionWebRequestEventRouter::OnErrorOccurred(
net::URLRequest* request,
bool started) {
// We hide events from the system context as well as sensitive requests.
- if (!profile || helpers::HideRequest(request))
+ if (!profile || WebRequestPermissions::HideRequest(request))
return;
request_time_tracker_->LogRequestEndTime(request->identifier(),
@@ -1087,6 +1091,14 @@ void ExtensionWebRequestEventRouter::NotifyPageLoad() {
callbacks_for_page_load_.clear();
}
+void* ExtensionWebRequestEventRouter::GetCrossProfile(void* profile) const {
+ CrossProfileMap::const_iterator cross_profile =
+ cross_profile_map_.find(profile);
+ if (cross_profile == cross_profile_map_.end())
+ return NULL;
+ return cross_profile->second;
+}
+
void ExtensionWebRequestEventRouter::GetMatchingListenersImpl(
void* profile,
ExtensionInfoMap* extension_info_map,
@@ -1120,36 +1132,26 @@ void ExtensionWebRequestEventRouter::GetMatchingListenersImpl(
resource_type) == it->filter.types.end())
continue;
- // extension_info_map can be NULL if this is a system-level request.
- if (extension_info_map) {
- const Extension* extension =
- extension_info_map->extensions().GetByID(it->extension_id);
-
- // Check if this event crosses incognito boundaries when it shouldn't.
- if (!extension ||
- (crosses_incognito &&
- !extension_info_map->CanCrossIncognito(extension)))
- continue;
-
- bool blocking_listener =
- (it->extra_info_spec &
- (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) != 0;
-
- // We do not want to notify extensions about XHR requests that are
- // triggered by themselves. This is a workaround to prevent deadlocks
- // in case of synchronous XHR requests that block the extension renderer
- // and therefore prevent the extension from processing the request
- // handler. This is only a problem for blocking listeners.
- // http://crbug.com/105656
- bool possibly_synchronous_xhr_from_extension =
- is_request_from_extension && resource_type == ResourceType::XHR;
-
- // Only send webRequest events for URLs the extension has access to.
- if (!helpers::CanExtensionAccessURL(extension, url) ||
- (blocking_listener && possibly_synchronous_xhr_from_extension)) {
- continue;
- }
- }
+ if (!WebRequestPermissions::CanExtensionAccessURL(
+ extension_info_map, it->extension_id, url, crosses_incognito, true))
+ continue;
+
+ bool blocking_listener =
+ (it->extra_info_spec &
+ (ExtraInfoSpec::BLOCKING | ExtraInfoSpec::ASYNC_BLOCKING)) != 0;
+
+ // We do not want to notify extensions about XHR requests that are
+ // triggered by themselves. This is a workaround to prevent deadlocks
+ // in case of synchronous XHR requests that block the extension renderer
+ // and therefore prevent the extension from processing the request
+ // handler. This is only a problem for blocking listeners.
+ // http://crbug.com/105656
+ bool possibly_synchronous_xhr_from_extension =
+ is_request_from_extension && resource_type == ResourceType::XHR;
+
+ // Only send webRequest events for URLs the extension has access to.
+ if (blocking_listener && possibly_synchronous_xhr_from_extension)
+ continue;
matching_listeners->push_back(&(*it));
*extra_info_spec |= it->extra_info_spec;
@@ -1189,13 +1191,12 @@ ExtensionWebRequestEventRouter::GetMatchingListeners(
profile, extension_info_map, false, event_name, url,
tab_id, window_id, resource_type, is_request_from_extension,
extra_info_spec, &matching_listeners);
- CrossProfileMap::const_iterator cross_profile =
- cross_profile_map_.find(profile);
- if (cross_profile != cross_profile_map_.end()) {
+ void* cross_profile = GetCrossProfile(profile);
+ if (cross_profile) {
GetMatchingListenersImpl(
- cross_profile->second, extension_info_map, true, event_name, url,
- tab_id, window_id, resource_type, is_request_from_extension,
- extra_info_spec, &matching_listeners);
+ cross_profile, extension_info_map, true, event_name, url, tab_id,
+ window_id, resource_type, is_request_from_extension, extra_info_spec,
+ &matching_listeners);
}
return matching_listeners;
@@ -1401,51 +1402,83 @@ bool ExtensionWebRequestEventRouter::ProcessDeclarativeRules(
net::URLRequest* request,
extensions::RequestStages request_stage,
net::HttpResponseHeaders* original_response_headers) {
- if (!rules_registry_.get())
- return false;
+ // Rules of the current |profile| may apply but we need to check also whether
+ // there are applicable rules from extensions whose background page
+ // spans from regular to incognito mode.
+
+ // First parameter identifies the registry, the second indicates whether the
+ // registry belongs to the cross profile.
+ typedef std::pair<extensions::WebRequestRulesRegistry*, bool>
+ RelevantRegistry;
+ typedef std::vector<RelevantRegistry> RelevantRegistries;
+ RelevantRegistries relevant_registries;
+
+ if (rules_registries_.find(profile) != rules_registries_.end()) {
+ relevant_registries.push_back(
+ std::make_pair(rules_registries_[profile].get(), false));
+ }
+
+ void* cross_profile = GetCrossProfile(profile);
+ if (cross_profile &&
+ rules_registries_.find(cross_profile) != rules_registries_.end()) {
+ relevant_registries.push_back(
+ std::make_pair(rules_registries_[cross_profile].get(), true));
+ }
// TODO(mpcomplete): Eventually we'll want to turn this on, but for now,
// we won't block startup for declarative webrequest. I want to measure
// its effect first.
#if defined(BLOCK_STARTUP_ON_DECLARATIVE_RULES)
- if (!rules_registry_->IsReady()) {
- // The rules registry is still loading. Block this request until it
- // finishes.
- rules_registry_->AddReadyCallback(
- base::Bind(&ExtensionWebRequestEventRouter::OnRulesRegistryReady,
- AsWeakPtr(), profile, event_name, request->identifier(),
- request_stage));
- blocked_requests_[request->identifier()].num_handlers_blocking++;
- blocked_requests_[request->identifier()].request = request;
- blocked_requests_[request->identifier()].blocking_time = base::Time::Now();
- blocked_requests_[request->identifier()].original_response_headers =
- original_response_headers;
- blocked_requests_[request->identifier()].extension_info_map =
- extension_info_map;
- return true;
+ for (RelevantRegistries::iterator i = relevant_registries.begin();
+ i != relevant_registries.end(); ++i) {
+ extensions::WebRequestRulesRegistry* rules_registry = i->first;
+ if (!rules_registry->IsReady()) {
+ // The rules registry is still loading. Block this request until it
+ // finishes.
+ rules_registry->AddReadyCallback(
+ base::Bind(&ExtensionWebRequestEventRouter::OnRulesRegistryReady,
+ AsWeakPtr(), profile, event_name, request->identifier(),
+ request_stage));
+ blocked_requests_[request->identifier()].num_handlers_blocking++;
+ blocked_requests_[request->identifier()].request = request;
+ blocked_requests_[request->identifier()].blocking_time =
+ base::Time::Now();
+ blocked_requests_[request->identifier()].original_response_headers =
+ original_response_headers;
+ blocked_requests_[request->identifier()].extension_info_map =
+ extension_info_map;
+ return true;
+ }
}
#endif
base::Time start = base::Time::Now();
- extensions::WebRequestRule::OptionalRequestData optional_request_data;
- optional_request_data.original_response_headers =
- original_response_headers;
- helpers::EventResponseDeltas result =
- rules_registry_->CreateDeltas(extension_info_map, request,
- request_stage, optional_request_data);
+ bool deltas_created = false;
+ for (RelevantRegistries::iterator i = relevant_registries.begin();
+ i != relevant_registries.end(); ++i) {
+ extensions::WebRequestRulesRegistry* rules_registry =
+ i->first;
+ extensions::WebRequestRule::OptionalRequestData optional_request_data;
+ optional_request_data.original_response_headers =
+ original_response_headers;
+ helpers::EventResponseDeltas result =
+ rules_registry->CreateDeltas(extension_info_map, request,
+ i->second, request_stage, optional_request_data);
+
+ if (!result.empty()) {
+ helpers::EventResponseDeltas& deltas =
+ blocked_requests_[request->identifier()].response_deltas;
+ deltas.insert(deltas.end(), result.begin(), result.end());
+ deltas_created = true;
+ }
+ }
base::TimeDelta elapsed_time = start - base::Time::Now();
UMA_HISTOGRAM_TIMES("Extensions.DeclarativeWebRequestNetworkDelay",
elapsed_time);
- if (result.empty())
- return false;
-
- helpers::EventResponseDeltas& deltas =
- blocked_requests_[request->identifier()].response_deltas;
- deltas.insert(deltas.end(), result.begin(), result.end());
- return true;
+ return deltas_created;
}
void ExtensionWebRequestEventRouter::OnRulesRegistryReady(
diff --git a/chrome/browser/extensions/api/web_request/web_request_api.h b/chrome/browser/extensions/api/web_request/web_request_api.h
index 4142a38..e392599 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api.h
+++ b/chrome/browser/extensions/api/web_request/web_request_api.h
@@ -16,6 +16,7 @@
#include "base/time.h"
#include "chrome/browser/extensions/api/declarative_webrequest/request_stages.h"
#include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h"
+#include "chrome/browser/extensions/api/web_request/web_request_permissions.h"
#include "chrome/browser/extensions/extension_function.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/url_pattern_set.h"
@@ -132,7 +133,10 @@ class ExtensionWebRequestEventRouter
static ExtensionWebRequestEventRouter* GetInstance();
+ // Registers a rule registry. Pass null for |rules_registry| to unregister
+ // the rule registry for |profile|.
void RegisterRulesRegistry(
+ void* profile,
scoped_refptr<extensions::WebRequestRulesRegistry> rules_registry);
// Dispatches the OnBeforeRequest event to any extensions whose filters match
@@ -363,6 +367,10 @@ class ExtensionWebRequestEventRouter
// Called on a page load to process all registered callbacks.
void NotifyPageLoad();
+ // Returns the matching cross profile (the regular profile if |profile| is
+ // OTR and vice versa).
+ void* GetCrossProfile(void* profile) const;
+
// A map for each profile that maps an event name to a set of extensions that
// are listening to that event.
ListenerMap listeners_;
@@ -385,7 +393,9 @@ class ExtensionWebRequestEventRouter
CallbacksForPageLoad callbacks_for_page_load_;
- scoped_refptr<extensions::WebRequestRulesRegistry> rules_registry_;
+ // Maps each profile (and OTRProfile) to its respective rules registry.
+ std::map<void*, scoped_refptr<extensions::WebRequestRulesRegistry> >
+ rules_registries_;
DISALLOW_COPY_AND_ASSIGN(ExtensionWebRequestEventRouter);
};
diff --git a/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc b/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc
index da74647..b7c8831 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc
@@ -537,64 +537,6 @@ bool MergeOnAuthRequiredResponses(
return credentials_set;
}
-namespace {
-
-// Returns true if the URL is sensitive and requests to this URL must not be
-// modified/canceled by extensions, e.g. because it is targeted to the webstore
-// to check for updates, extension blacklisting, etc.
-bool IsSensitiveURL(const GURL& url) {
- // TODO(battre) Merge this, CanExtensionAccessURL of web_request_api.cc and
- // Extension::CanExecuteScriptOnPage into one function.
- bool is_webstore_gallery_url =
- StartsWithASCII(url.spec(), extension_urls::kGalleryBrowsePrefix, true);
- bool sensitive_chrome_url = false;
- if (EndsWith(url.host(), "google.com", true)) {
- sensitive_chrome_url |= (url.host() == "www.google.com") &&
- StartsWithASCII(url.path(), "/chrome", true);
- sensitive_chrome_url |= (url.host() == "chrome.google.com");
- if (StartsWithASCII(url.host(), "client", true)) {
- for (int i = 0; i < 10; ++i) {
- sensitive_chrome_url |=
- (StringPrintf("client%d.google.com", i) == url.host());
- }
- }
- }
- GURL::Replacements replacements;
- replacements.ClearQuery();
- replacements.ClearRef();
- GURL url_without_query = url.ReplaceComponents(replacements);
- return is_webstore_gallery_url || sensitive_chrome_url ||
- extension_urls::IsWebstoreUpdateUrl(url_without_query) ||
- extension_urls::IsBlacklistUpdateUrl(url);
-}
-
-// Returns true if the scheme is one we want to allow extensions to have access
-// to. Extensions still need specific permissions for a given URL, which is
-// covered by CanExtensionAccessURL.
-bool HasWebRequestScheme(const GURL& url) {
- return (url.SchemeIs(chrome::kAboutScheme) ||
- url.SchemeIs(chrome::kFileScheme) ||
- url.SchemeIs(chrome::kFileSystemScheme) ||
- url.SchemeIs(chrome::kFtpScheme) ||
- url.SchemeIs(chrome::kHttpScheme) ||
- url.SchemeIs(chrome::kHttpsScheme) ||
- url.SchemeIs(chrome::kExtensionScheme));
-}
-
-} // namespace
-
-bool HideRequest(const net::URLRequest* request) {
- const GURL& url = request->url();
- const GURL& first_party_url = request->first_party_for_cookies();
- bool hide = false;
- if (first_party_url.is_valid()) {
- hide = IsSensitiveURL(first_party_url) ||
- !HasWebRequestScheme(first_party_url);
- }
- if (!hide)
- hide = IsSensitiveURL(url) || !HasWebRequestScheme(url);
- return hide;
-}
#define ARRAYEND(array) (array + arraysize(array))
diff --git a/chrome/browser/extensions/api/web_request/web_request_api_helpers.h b/chrome/browser/extensions/api/web_request/web_request_api_helpers.h
index ea748e4..7487ca7 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api_helpers.h
+++ b/chrome/browser/extensions/api/web_request/web_request_api_helpers.h
@@ -172,9 +172,6 @@ bool MergeOnAuthRequiredResponses(
std::set<std::string>* conflicting_extensions,
const net::BoundNetLog* net_log);
-// Returns true if the request shall not be reported to extensions.
-bool HideRequest(const net::URLRequest* request);
-
// Returns whether |type| is a ResourceType that is handled by the web request
// API.
bool IsRelevantResourceType(ResourceType::Type type);
diff --git a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
index 7797be5..756566a 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
@@ -1487,48 +1487,3 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnAuthRequiredResponses) {
EXPECT_EQ(3u, capturing_net_log.GetSize());
}
-TEST(ExtensionWebRequestHelpersTest, TestHideRequestForURL) {
- MessageLoopForIO message_loop;
- TestURLRequestContext context;
- const char* sensitive_urls[] = {
- "http://www.google.com/chrome",
- "https://www.google.com/chrome",
- "http://www.google.com/chrome/foobar",
- "https://www.google.com/chrome/foobar",
- "http://chrome.google.com",
- "https://chrome.google.com",
- "http://client2.google.com",
- "https://client2.google.com",
- // No http version of webstore.
- "https://chrome.google.com/webstore",
- "http://clients2.google.com/service/update2/crx",
- "https://clients2.google.com/service/update2/crx",
- "http://www.gstatic.com/chrome/extensions/blacklist",
- "https://www.gstatic.com/chrome/extensions/blacklist",
- "notregisteredscheme://www.foobar.com"
- };
- const char* non_sensitive_urls[] = {
- "http://www.google.com/"
- };
- // Check that requests are rejected based on the destination
- for (size_t i = 0; i < arraysize(sensitive_urls); ++i) {
- GURL sensitive_url(sensitive_urls[i]);
- TestURLRequest request(sensitive_url, NULL, &context);
- EXPECT_TRUE(helpers::HideRequest(&request)) << sensitive_urls[i];
- }
- // Check that requests are accepted if they don't touch sensitive urls.
- for (size_t i = 0; i < arraysize(non_sensitive_urls); ++i) {
- GURL non_sensitive_url(non_sensitive_urls[i]);
- TestURLRequest request(non_sensitive_url, NULL, &context);
- EXPECT_FALSE(helpers::HideRequest(&request)) << non_sensitive_urls[i];
- }
- // Check that requests are rejected if their first party url is sensitive.
- ASSERT_GE(arraysize(non_sensitive_urls), 1u);
- GURL non_sensitive_url(non_sensitive_urls[0]);
- for (size_t i = 0; i < arraysize(sensitive_urls); ++i) {
- TestURLRequest request(non_sensitive_url, NULL, &context);
- GURL sensitive_url(sensitive_urls[i]);
- request.set_first_party_for_cookies(sensitive_url);
- EXPECT_TRUE(helpers::HideRequest(&request)) << sensitive_urls[i];
- }
-}
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
index 0ad09f0..55220b9 100644
--- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -6,6 +6,7 @@
#include "chrome/browser/extensions/api/web_request/web_request_api.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
@@ -62,6 +63,13 @@ class ExtensionWebRequestApiTest : public ExtensionApiTest {
host_resolver()->AddRule("*", "127.0.0.1");
ASSERT_TRUE(StartTestServer());
}
+
+ void RunPermissionTest(
+ const char* extension_directory,
+ bool load_extension_with_incognito_permission,
+ bool wait_for_extension_loaded_in_incognito,
+ const char* expected_content_regular_window,
+ const char* exptected_content_incognito_window);
};
IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, WebRequestApi) {
@@ -132,3 +140,88 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, WebRequestDeclarative) {
ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_declarative.html")) <<
message_;
}
+
+void ExtensionWebRequestApiTest::RunPermissionTest(
+ const char* extension_directory,
+ bool load_extension_with_incognito_permission,
+ bool wait_for_extension_loaded_in_incognito,
+ const char* expected_content_regular_window,
+ const char* exptected_content_incognito_window) {
+ ResultCatcher catcher;
+ catcher.RestrictToProfile(browser()->profile());
+ ResultCatcher catcher_incognito;
+ catcher_incognito.RestrictToProfile(
+ browser()->profile()->GetOffTheRecordProfile());
+
+ ExtensionTestMessageListener listener("done", true);
+ ExtensionTestMessageListener listener_incognito("done_incognito", true);
+
+ ASSERT_TRUE(LoadExtensionWithOptions(
+ test_data_dir_.AppendASCII("webrequest_permissions")
+ .AppendASCII(extension_directory),
+ load_extension_with_incognito_permission,
+ false));
+
+ // Test that navigation in regular window is properly redirected.
+ EXPECT_TRUE(listener.WaitUntilSatisfied());
+
+ // This navigation should be redirected.
+ ui_test_utils::NavigateToURL(
+ browser(),
+ test_server()->GetURL("files/extensions/test_file.html"));
+
+ std::string body;
+ WebContents* tab = chrome::GetActiveWebContents(browser());
+ ASSERT_TRUE(content::ExecuteJavaScriptAndExtractString(
+ tab->GetRenderViewHost(), L"",
+ L"window.domAutomationController.send(document.body.textContent)",
+ &body));
+ EXPECT_EQ(expected_content_regular_window, body);
+
+ // Test that navigation in OTR window is properly redirected.
+ Browser* otr_browser = ui_test_utils::OpenURLOffTheRecord(
+ browser()->profile(), GURL("about:blank"));
+
+ if (wait_for_extension_loaded_in_incognito)
+ EXPECT_TRUE(listener_incognito.WaitUntilSatisfied());
+
+ // This navigation should be redirected if
+ // load_extension_with_incognito_permission is true.
+ ui_test_utils::NavigateToURL(
+ otr_browser,
+ test_server()->GetURL("files/extensions/test_file.html"));
+
+ body.clear();
+ WebContents* otr_tab = chrome::GetActiveWebContents(otr_browser);
+ ASSERT_TRUE(content::ExecuteJavaScriptAndExtractString(
+ otr_tab->GetRenderViewHost(), L"",
+ L"window.domAutomationController.send(document.body.textContent)",
+ &body));
+ EXPECT_EQ(exptected_content_incognito_window, body);
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
+ WebRequestDeclarativePermissionSpanning1) {
+ // Test spanning with incognito permission.
+ RunPermissionTest("spanning", true, false, "redirected1", "redirected1");
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
+ WebRequestDeclarativePermissionSpanning2) {
+ // Test spanning without incognito permission.
+ RunPermissionTest("spanning", false, false, "redirected1", "");
+}
+
+
+IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
+ WebRequestDeclarativePermissionSplit1) {
+ // Test split with incognito permission.
+ RunPermissionTest("split", true, true, "redirected1", "redirected2");
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
+ WebRequestDeclarativePermissionSplit2) {
+ // Test split without incognito permission.
+ RunPermissionTest("split", false, false, "redirected1", "");
+}
+
diff --git a/chrome/browser/extensions/api/web_request/web_request_permissions.cc b/chrome/browser/extensions/api/web_request/web_request_permissions.cc
new file mode 100644
index 0000000..ca84616
--- /dev/null
+++ b/chrome/browser/extensions/api/web_request/web_request_permissions.cc
@@ -0,0 +1,105 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/web_request/web_request_permissions.h"
+
+#include "base/string_util.h"
+#include "base/stringprintf.h"
+#include "chrome/browser/extensions/extension_info_map.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/url_constants.h"
+#include "googleurl/src/gurl.h"
+#include "net/url_request/url_request.h"
+
+namespace {
+
+// Returns true if the URL is sensitive and requests to this URL must not be
+// modified/canceled by extensions, e.g. because it is targeted to the webstore
+// to check for updates, extension blacklisting, etc.
+bool IsSensitiveURL(const GURL& url) {
+ // TODO(battre) Merge this, CanExtensionAccessURL of web_request_api.cc and
+ // Extension::CanExecuteScriptOnPage into one function.
+ bool is_webstore_gallery_url =
+ StartsWithASCII(url.spec(), extension_urls::kGalleryBrowsePrefix, true);
+ bool sensitive_chrome_url = false;
+ if (EndsWith(url.host(), "google.com", true)) {
+ sensitive_chrome_url |= (url.host() == "www.google.com") &&
+ StartsWithASCII(url.path(), "/chrome", true);
+ sensitive_chrome_url |= (url.host() == "chrome.google.com");
+ if (StartsWithASCII(url.host(), "client", true)) {
+ for (int i = 0; i < 10; ++i) {
+ sensitive_chrome_url |=
+ (StringPrintf("client%d.google.com", i) == url.host());
+ }
+ }
+ }
+ GURL::Replacements replacements;
+ replacements.ClearQuery();
+ replacements.ClearRef();
+ GURL url_without_query = url.ReplaceComponents(replacements);
+ return is_webstore_gallery_url || sensitive_chrome_url ||
+ extension_urls::IsWebstoreUpdateUrl(url_without_query) ||
+ extension_urls::IsBlacklistUpdateUrl(url);
+}
+
+// Returns true if the scheme is one we want to allow extensions to have access
+// to. Extensions still need specific permissions for a given URL, which is
+// covered by CanExtensionAccessURL.
+bool HasWebRequestScheme(const GURL& url) {
+ return (url.SchemeIs(chrome::kAboutScheme) ||
+ url.SchemeIs(chrome::kFileScheme) ||
+ url.SchemeIs(chrome::kFileSystemScheme) ||
+ url.SchemeIs(chrome::kFtpScheme) ||
+ url.SchemeIs(chrome::kHttpScheme) ||
+ url.SchemeIs(chrome::kHttpsScheme) ||
+ url.SchemeIs(chrome::kExtensionScheme));
+}
+
+} // namespace
+
+// static
+bool WebRequestPermissions::HideRequest(const net::URLRequest* request) {
+ const GURL& url = request->url();
+ const GURL& first_party_url = request->first_party_for_cookies();
+ bool hide = false;
+ if (first_party_url.is_valid()) {
+ hide = IsSensitiveURL(first_party_url) ||
+ !HasWebRequestScheme(first_party_url);
+ }
+ if (!hide)
+ hide = IsSensitiveURL(url) || !HasWebRequestScheme(url);
+ return hide;
+}
+
+// static
+bool WebRequestPermissions::CanExtensionAccessURL(
+ const ExtensionInfoMap* extension_info_map,
+ const std::string& extension_id,
+ const GURL& url,
+ bool crosses_incognito,
+ bool enforce_host_permissions) {
+ // extension_info_map can be NULL in testing.
+ if (!extension_info_map)
+ return true;
+
+ const extensions::Extension* extension =
+ extension_info_map->extensions().GetByID(extension_id);
+ if (!extension)
+ return false;
+
+ // Check if this event crosses incognito boundaries when it shouldn't.
+ if (crosses_incognito && !extension_info_map->CanCrossIncognito(extension))
+ return false;
+
+ if (enforce_host_permissions) {
+ // about: URLs are not covered in host permissions, but are allowed anyway.
+ bool host_permissions_ok = (url.SchemeIs(chrome::kAboutScheme) ||
+ extension->HasHostPermission(url) ||
+ url.GetOrigin() == extension->url());
+ if (!host_permissions_ok)
+ return false;
+ }
+
+ return true;
+}
diff --git a/chrome/browser/extensions/api/web_request/web_request_permissions.h b/chrome/browser/extensions/api/web_request/web_request_permissions.h
new file mode 100644
index 0000000..d7923b9
--- /dev/null
+++ b/chrome/browser/extensions/api/web_request/web_request_permissions.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_WEB_REQUEST_WEB_REQUEST_PERMISSIONS_H_
+#define CHROME_BROWSER_EXTENSIONS_API_WEB_REQUEST_WEB_REQUEST_PERMISSIONS_H_
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+
+class ExtensionInfoMap;
+class GURL;
+
+namespace net {
+class URLRequest;
+}
+
+// This class is used to test whether extensions may modify web requests.
+class WebRequestPermissions {
+ public:
+ // Returns true if the request shall not be reported to extensions.
+ static bool HideRequest(const net::URLRequest* request);
+
+ static bool CanExtensionAccessURL(const ExtensionInfoMap* extension_info_map,
+ const std::string& extension_id,
+ const GURL& url,
+ bool crosses_incognito,
+ bool enforce_host_permissions);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(WebRequestPermissions);
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_WEB_REQUEST_WEB_REQUEST_PERMISSIONS_H_
diff --git a/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc b/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc
new file mode 100644
index 0000000..7a83e58
--- /dev/null
+++ b/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc
@@ -0,0 +1,59 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/web_request/web_request_permissions.h"
+
+#include "base/message_loop.h"
+#include "chrome/test/base/testing_profile.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(ExtensionWebRequestHelpersTest, TestHideRequestForURL) {
+ MessageLoopForIO message_loop;
+ TestURLRequestContext context;
+ const char* sensitive_urls[] = {
+ "http://www.google.com/chrome",
+ "https://www.google.com/chrome",
+ "http://www.google.com/chrome/foobar",
+ "https://www.google.com/chrome/foobar",
+ "http://chrome.google.com",
+ "https://chrome.google.com",
+ "http://client2.google.com",
+ "https://client2.google.com",
+ // No http version of webstore.
+ "https://chrome.google.com/webstore",
+ "http://clients2.google.com/service/update2/crx",
+ "https://clients2.google.com/service/update2/crx",
+ "http://www.gstatic.com/chrome/extensions/blacklist",
+ "https://www.gstatic.com/chrome/extensions/blacklist",
+ "notregisteredscheme://www.foobar.com"
+ };
+ const char* non_sensitive_urls[] = {
+ "http://www.google.com/"
+ };
+ // Check that requests are rejected based on the destination
+ for (size_t i = 0; i < arraysize(sensitive_urls); ++i) {
+ GURL sensitive_url(sensitive_urls[i]);
+ TestURLRequest request(sensitive_url, NULL, &context);
+ EXPECT_TRUE(WebRequestPermissions::HideRequest(&request))
+ << sensitive_urls[i];
+ }
+ // Check that requests are accepted if they don't touch sensitive urls.
+ for (size_t i = 0; i < arraysize(non_sensitive_urls); ++i) {
+ GURL non_sensitive_url(non_sensitive_urls[i]);
+ TestURLRequest request(non_sensitive_url, NULL, &context);
+ EXPECT_FALSE(WebRequestPermissions::HideRequest(&request))
+ << non_sensitive_urls[i];
+ }
+ // Check that requests are rejected if their first party url is sensitive.
+ ASSERT_GE(arraysize(non_sensitive_urls), 1u);
+ GURL non_sensitive_url(non_sensitive_urls[0]);
+ for (size_t i = 0; i < arraysize(sensitive_urls); ++i) {
+ TestURLRequest request(non_sensitive_url, NULL, &context);
+ GURL sensitive_url(sensitive_urls[i]);
+ request.set_first_party_for_cookies(sensitive_url);
+ EXPECT_TRUE(WebRequestPermissions::HideRequest(&request))
+ << sensitive_urls[i];
+ }
+}
diff --git a/chrome/browser/extensions/extension_info_map.cc b/chrome/browser/extensions/extension_info_map.cc
index 3f9bb73..c9b072d 100644
--- a/chrome/browser/extensions/extension_info_map.cc
+++ b/chrome/browser/extensions/extension_info_map.cc
@@ -93,7 +93,7 @@ bool ExtensionInfoMap::IsIncognitoEnabled(
return false;
}
-bool ExtensionInfoMap::CanCrossIncognito(const Extension* extension) {
+bool ExtensionInfoMap::CanCrossIncognito(const Extension* extension) const {
// This is duplicated from ExtensionService :(.
return IsIncognitoEnabled(extension->id()) &&
!extension->incognito_split_mode();
diff --git a/chrome/browser/extensions/extension_info_map.h b/chrome/browser/extensions/extension_info_map.h
index 42798bf3..5fdb154 100644
--- a/chrome/browser/extensions/extension_info_map.h
+++ b/chrome/browser/extensions/extension_info_map.h
@@ -52,7 +52,7 @@ class ExtensionInfoMap : public base::RefCountedThreadSafe<ExtensionInfoMap> {
// Returns true if the given extension can see events and data from another
// sub-profile (incognito to original profile, or vice versa).
- bool CanCrossIncognito(const extensions::Extension* extension);
+ bool CanCrossIncognito(const extensions::Extension* extension) const;
// Adds an entry to process_map_.
void RegisterExtensionProcess(const std::string& extension_id,
diff --git a/chrome/browser/extensions/extension_system.cc b/chrome/browser/extensions/extension_system.cc
index e5ca663..b451ab0 100644
--- a/chrome/browser/extensions/extension_system.cc
+++ b/chrome/browser/extensions/extension_system.cc
@@ -73,8 +73,6 @@ ExtensionSystemImpl::Shared::Shared(Profile* profile)
}
ExtensionSystemImpl::Shared::~Shared() {
- if (rules_registry_service_.get())
- rules_registry_service_->Shutdown();
}
void ExtensionSystemImpl::Shared::InitPrefs() {
@@ -134,9 +132,6 @@ void ExtensionSystemImpl::Shared::Init(bool extensions_enabled) {
// These services must be registered before the ExtensionService tries to
// load any extensions.
{
- rules_registry_service_.reset(new RulesRegistryService(profile_));
- rules_registry_service_->RegisterDefaultRulesRegistries();
-
management_policy_.reset(new ManagementPolicy);
RegisterManagementPolicyProviders();
}
@@ -236,10 +231,6 @@ EventRouter* ExtensionSystemImpl::Shared::event_router() {
return extension_event_router_.get();
}
-RulesRegistryService* ExtensionSystemImpl::Shared::rules_registry_service() {
- return rules_registry_service_.get();
-}
-
//
// ExtensionSystemImpl
//
@@ -257,13 +248,15 @@ ExtensionSystemImpl::ExtensionSystemImpl(Profile* profile)
}
ExtensionSystemImpl::~ExtensionSystemImpl() {
+ if (rules_registry_service_.get())
+ rules_registry_service_->Shutdown();
}
void ExtensionSystemImpl::Shutdown() {
extension_process_manager_.reset();
}
-void ExtensionSystemImpl::Init(bool extensions_enabled) {
+void ExtensionSystemImpl::InitForRegularProfile(bool extensions_enabled) {
DCHECK(!profile_->IsOffTheRecord());
if (user_script_master() || extension_service())
return; // Already initialized.
@@ -285,9 +278,23 @@ void ExtensionSystemImpl::Init(bool extensions_enabled) {
usb_device_resource_manager_.reset(
new ApiResourceManager<UsbDeviceResource>(BrowserThread::IO));
+ rules_registry_service_.reset(new RulesRegistryService(profile_));
+ rules_registry_service_->RegisterDefaultRulesRegistries();
+
shared_->Init(extensions_enabled);
}
+void ExtensionSystemImpl::InitForOTRProfile() {
+ // Only initialize the RulesRegistryService of the OTR ExtensionSystem if the
+ // regular ExtensionSystem has been initialized properly, as we depend on it.
+ // Some ChromeOS browser tests don't initialize the regular ExtensionSystem
+ // in login-tests.
+ if (extension_service()) {
+ rules_registry_service_.reset(new RulesRegistryService(profile_));
+ rules_registry_service_->RegisterDefaultRulesRegistries();
+ }
+}
+
ExtensionService* ExtensionSystemImpl::extension_service() {
return shared_->extension_service();
}
@@ -335,7 +342,7 @@ EventRouter* ExtensionSystemImpl::event_router() {
}
RulesRegistryService* ExtensionSystemImpl::rules_registry_service() {
- return shared_->rules_registry_service();
+ return rules_registry_service_.get();
}
ApiResourceManager<SerialConnection>*
@@ -343,7 +350,7 @@ ExtensionSystemImpl::serial_connection_manager() {
return serial_connection_manager_.get();
}
-ApiResourceManager<Socket>*ExtensionSystemImpl::socket_manager() {
+ApiResourceManager<Socket>* ExtensionSystemImpl::socket_manager() {
return socket_manager_.get();
}
diff --git a/chrome/browser/extensions/extension_system.h b/chrome/browser/extensions/extension_system.h
index bf225c0..9cf70bd 100644
--- a/chrome/browser/extensions/extension_system.h
+++ b/chrome/browser/extensions/extension_system.h
@@ -58,7 +58,9 @@ class ExtensionSystem : public ProfileKeyedService {
// Initializes extensions machinery.
// Component extensions are always enabled, external and user extensions
// are controlled by |extensions_enabled|.
- virtual void Init(bool extensions_enabled) = 0;
+ virtual void InitForRegularProfile(bool extensions_enabled) = 0;
+
+ virtual void InitForOTRProfile() = 0;
// The ExtensionService is created at startup.
virtual ExtensionService* extension_service() = 0;
@@ -139,7 +141,8 @@ class ExtensionSystemImpl : public ExtensionSystem {
// ProfileKeyedService implementation.
virtual void Shutdown() OVERRIDE;
- virtual void Init(bool extensions_enabled) OVERRIDE;
+ virtual void InitForRegularProfile(bool extensions_enabled) OVERRIDE;
+ virtual void InitForOTRProfile() OVERRIDE;
virtual ExtensionService* extension_service() OVERRIDE; // shared
virtual ManagementPolicy* management_policy() OVERRIDE; // shared
@@ -193,7 +196,6 @@ class ExtensionSystemImpl : public ExtensionSystem {
LazyBackgroundTaskQueue* lazy_background_task_queue();
MessageService* message_service();
EventRouter* event_router();
- RulesRegistryService* rules_registry_service();
private:
Profile* profile_;
@@ -213,7 +215,6 @@ class ExtensionSystemImpl : public ExtensionSystem {
scoped_ptr<MessageService> message_service_;
scoped_ptr<EventRouter> extension_event_router_;
scoped_ptr<ExtensionNavigationObserver> extension_navigation_observer_;
- scoped_ptr<RulesRegistryService> rules_registry_service_;
};
Profile* profile_;
@@ -232,6 +233,7 @@ class ExtensionSystemImpl : public ExtensionSystem {
scoped_ptr<ApiResourceManager<Socket> > socket_manager_;
scoped_ptr<ApiResourceManager<
UsbDeviceResource> > usb_device_resource_manager_;
+ scoped_ptr<RulesRegistryService> rules_registry_service_;
DISALLOW_COPY_AND_ASSIGN(ExtensionSystemImpl);
};
diff --git a/chrome/browser/extensions/test_extension_system.h b/chrome/browser/extensions/test_extension_system.h
index d27f3b0..0f0daf5 100644
--- a/chrome/browser/extensions/test_extension_system.h
+++ b/chrome/browser/extensions/test_extension_system.h
@@ -41,7 +41,8 @@ class TestExtensionSystem : public ExtensionSystem {
// Creates an AlarmManager. Will be NULL otherwise.
void CreateAlarmManager(base::Time (*now)());
- virtual void Init(bool extensions_enabled) OVERRIDE {}
+ virtual void InitForRegularProfile(bool extensions_enabled) OVERRIDE {}
+ virtual void InitForOTRProfile() OVERRIDE {}
void SetExtensionService(ExtensionService* service);
virtual ExtensionService* extension_service() OVERRIDE;
virtual ManagementPolicy* management_policy() OVERRIDE;
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc
index ddf21ed..94f3bab 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl.cc
+++ b/chrome/browser/profiles/off_the_record_profile_impl.cc
@@ -89,6 +89,8 @@ OffTheRecordProfileImpl::OffTheRecordProfileImpl(Profile* real_profile)
void OffTheRecordProfileImpl::Init() {
ProfileDependencyManager::GetInstance()->CreateProfileServices(this, false);
+ extensions::ExtensionSystem::Get(this)->InitForOTRProfile();
+
DCHECK_NE(IncognitoModePrefs::DISABLED,
IncognitoModePrefs::GetAvailability(profile_->GetPrefs()));
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index f8a375b..57c5c0a 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -688,7 +688,8 @@ void ProfileManager::DoFinalInit(Profile* profile, bool go_off_the_record) {
void ProfileManager::DoFinalInitForServices(Profile* profile,
bool go_off_the_record) {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- extensions::ExtensionSystem::Get(profile)->Init(!go_off_the_record);
+ extensions::ExtensionSystem::Get(profile)->InitForRegularProfile(
+ !go_off_the_record);
// During tests, when |profile| is an instance of TestingProfile,
// ExtensionSystem might not create an ExtensionService.
if (extensions::ExtensionSystem::Get(profile)->extension_service()) {
diff --git a/chrome/browser/sync/glue/extension_data_type_controller.cc b/chrome/browser/sync/glue/extension_data_type_controller.cc
index 599e741..e6c8674 100644
--- a/chrome/browser/sync/glue/extension_data_type_controller.cc
+++ b/chrome/browser/sync/glue/extension_data_type_controller.cc
@@ -26,7 +26,7 @@ ExtensionDataTypeController::ExtensionDataTypeController(
ExtensionDataTypeController::~ExtensionDataTypeController() {}
bool ExtensionDataTypeController::StartModels() {
- extensions::ExtensionSystem::Get(profile_)->Init(true);
+ extensions::ExtensionSystem::Get(profile_)->InitForRegularProfile(true);
return true;
}
diff --git a/chrome/browser/sync/glue/extension_setting_data_type_controller.cc b/chrome/browser/sync/glue/extension_setting_data_type_controller.cc
index 2df76b9..b02afcf 100644
--- a/chrome/browser/sync/glue/extension_setting_data_type_controller.cc
+++ b/chrome/browser/sync/glue/extension_setting_data_type_controller.cc
@@ -53,7 +53,7 @@ bool ExtensionSettingDataTypeController::PostTaskOnBackendThread(
bool ExtensionSettingDataTypeController::StartModels() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- extensions::ExtensionSystem::Get(profile_)->Init(true);
+ extensions::ExtensionSystem::Get(profile_)->InitForRegularProfile(true);
return true;
}
diff --git a/chrome/browser/sync/glue/theme_data_type_controller.cc b/chrome/browser/sync/glue/theme_data_type_controller.cc
index 7133805..244f9d0 100644
--- a/chrome/browser/sync/glue/theme_data_type_controller.cc
+++ b/chrome/browser/sync/glue/theme_data_type_controller.cc
@@ -27,7 +27,7 @@ syncer::ModelType ThemeDataTypeController::type() const {
ThemeDataTypeController::~ThemeDataTypeController() {}
bool ThemeDataTypeController::StartModels() {
- extensions::ExtensionSystem::Get(profile_)->Init(true);
+ extensions::ExtensionSystem::Get(profile_)->InitForRegularProfile(true);
return true;
}
diff --git a/chrome/browser/sync/test/integration/sync_app_helper.cc b/chrome/browser/sync/test/integration/sync_app_helper.cc
index 51a2083..256c1ac 100644
--- a/chrome/browser/sync/test/integration/sync_app_helper.cc
+++ b/chrome/browser/sync/test/integration/sync_app_helper.cc
@@ -93,9 +93,11 @@ void SyncAppHelper::SetupIfNecessary(SyncTest* test) {
return;
for (int i = 0; i < test->num_clients(); ++i) {
- extensions::ExtensionSystem::Get(test->GetProfile(i))->Init(true);
+ extensions::ExtensionSystem::Get(
+ test->GetProfile(i))->InitForRegularProfile(true);
}
- extensions::ExtensionSystem::Get(test->verifier())->Init(true);
+ extensions::ExtensionSystem::Get(
+ test->verifier())->InitForRegularProfile(true);
setup_completed_ = true;
}
diff --git a/chrome/browser/sync/test/integration/sync_extension_helper.cc b/chrome/browser/sync/test/integration/sync_extension_helper.cc
index 0621664..b4c0f1d 100644
--- a/chrome/browser/sync/test/integration/sync_extension_helper.cc
+++ b/chrome/browser/sync/test/integration/sync_extension_helper.cc
@@ -243,7 +243,7 @@ bool SyncExtensionHelper::ExtensionStatesMatch(
}
void SyncExtensionHelper::SetupProfile(Profile* profile) {
- extensions::ExtensionSystem::Get(profile)->Init(true);
+ extensions::ExtensionSystem::Get(profile)->InitForRegularProfile(true);
profile_extensions_.insert(make_pair(profile, ExtensionNameMap()));
}
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi
index dbabd94..3e83db9 100644
--- a/chrome/chrome_browser_extensions.gypi
+++ b/chrome/chrome_browser_extensions.gypi
@@ -226,6 +226,8 @@
'browser/extensions/api/web_request/web_request_api_constants.h',
'browser/extensions/api/web_request/web_request_api_helpers.cc',
'browser/extensions/api/web_request/web_request_api_helpers.h',
+ 'browser/extensions/api/web_request/web_request_permissions.cc',
+ 'browser/extensions/api/web_request/web_request_permissions.h',
'browser/extensions/api/web_request/web_request_time_tracker.cc',
'browser/extensions/api/web_request/web_request_time_tracker.h',
'browser/extensions/app_notification.cc',
@@ -625,6 +627,7 @@
['include', '^browser/extensions/api/web_request/web_request_api.cc'],
['include', '^browser/extensions/api/web_request/web_request_api_constants.cc'],
['include', '^browser/extensions/api/web_request/web_request_api_helpers.cc'],
+ ['include', '^browser/extensions/api/web_request/web_request_permissions.cc'],
['include', '^browser/extensions/api/web_request/web_request_time_tracker.cc'],
],
}],
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 144632c..bae35e2 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1221,6 +1221,7 @@
'browser/extensions/api/socket/tcp_socket_unittest.cc',
'browser/extensions/api/web_navigation/frame_navigation_state_unittest.cc',
'browser/extensions/api/web_request/web_request_api_unittest.cc',
+ 'browser/extensions/api/web_request/web_request_permissions_unittest.cc',
'browser/extensions/api/web_request/web_request_time_tracker_unittest.cc',
'browser/extensions/app_notification_manager_sync_unittest.cc',
'browser/extensions/app_notification_manager_unittest.cc',
diff --git a/chrome/test/data/extensions/api_test/webrequest_permissions/spanning/background.js b/chrome/test/data/extensions/api_test/webrequest_permissions/spanning/background.js
new file mode 100644
index 0000000..66a1f8e
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/webrequest_permissions/spanning/background.js
@@ -0,0 +1,19 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+chrome.declarativeWebRequest.onRequest.removeRules();
+var rule = {
+ conditions: [
+ new chrome.declarativeWebRequest.RequestMatcher(
+ {url: {pathContains: '.html'}}),
+ ],
+ actions: [
+ new chrome.declarativeWebRequest.RedirectRequest(
+ {'redirectUrl': 'data:text/plain,redirected1'})
+ ],
+}
+function notifyDone() {
+ chrome.test.sendMessage("done");
+}
+chrome.declarativeWebRequest.onRequest.addRules([rule], notifyDone);
diff --git a/chrome/test/data/extensions/api_test/webrequest_permissions/spanning/manifest.json b/chrome/test/data/extensions/api_test/webrequest_permissions/spanning/manifest.json
new file mode 100644
index 0000000..f638a48
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/webrequest_permissions/spanning/manifest.json
@@ -0,0 +1,11 @@
+{
+ "name": "webRequest",
+ "version": "1.0",
+ "manifest_version": 2,
+ "description": "Tests the permissions of declarative webRequest API.",
+ "permissions": ["declarativeWebRequest", "<all_urls>"],
+ "incognito": "spanning",
+ "background": {
+ "scripts": ["background.js"]
+ }
+}
diff --git a/chrome/test/data/extensions/api_test/webrequest_permissions/split/background.js b/chrome/test/data/extensions/api_test/webrequest_permissions/split/background.js
new file mode 100644
index 0000000..b1df796
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/webrequest_permissions/split/background.js
@@ -0,0 +1,30 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+chrome.declarativeWebRequest.onRequest.removeRules();
+var rule = {
+ conditions: [
+ new chrome.declarativeWebRequest.RequestMatcher(
+ {url: {pathContains: '.html'}}),
+ ],
+ actions: [],
+}
+if (chrome.extension.inIncognitoContext) {
+ rule.actions = [
+ new chrome.declarativeWebRequest.RedirectRequest(
+ {'redirectUrl': 'data:text/plain,redirected2'})
+ ];
+} else {
+ rule.actions = [
+ new chrome.declarativeWebRequest.RedirectRequest(
+ {'redirectUrl': 'data:text/plain,redirected1'})
+ ];
+}
+function notifyDone() {
+ if (chrome.extension.inIncognitoContext)
+ chrome.test.sendMessage("done_incognito");
+ else
+ chrome.test.sendMessage("done");
+}
+chrome.declarativeWebRequest.onRequest.addRules([rule], notifyDone);
diff --git a/chrome/test/data/extensions/api_test/webrequest_permissions/split/manifest.json b/chrome/test/data/extensions/api_test/webrequest_permissions/split/manifest.json
new file mode 100644
index 0000000..f1d3f9e
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/webrequest_permissions/split/manifest.json
@@ -0,0 +1,11 @@
+{
+ "name": "webRequest",
+ "version": "1.0",
+ "manifest_version": 2,
+ "description": "Tests the permissions of declarative webRequest API.",
+ "permissions": ["declarativeWebRequest", "<all_urls>"],
+ "incognito": "split",
+ "background": {
+ "scripts": ["background.js"]
+ }
+}