summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorvabr@chromium.org <vabr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-27 07:44:24 +0000
committervabr@chromium.org <vabr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-27 07:44:24 +0000
commit04e4bbeda497feac5f7fdebabbb13c885294e253 (patch)
tree5ea6ffccfd04698a77b1b8f340c8892085c07620 /chrome
parent54e7e7430fe8ded2a77fead9cc436b5d568d540e (diff)
downloadchromium_src-04e4bbeda497feac5f7fdebabbb13c885294e253.zip
chromium_src-04e4bbeda497feac5f7fdebabbb13c885294e253.tar.gz
chromium_src-04e4bbeda497feac5f7fdebabbb13c885294e253.tar.bz2
Almost all actions in Declarative Web Request require all_urls host permissions
The whitelisted actions are: * ignoring a rule * cancelling a request * redirecting to a blank image or an empty document + SendMessageToExtension only checks the request's URL against the host permissions (does not require full permissions). BUG=145456 Review URL: https://chromiumcodereview.appspot.com/14358004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@196959 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/extensions/api/declarative/declarative_rule.h11
-rw-r--r--chrome/browser/extensions/api/declarative/declarative_rule_unittest.cc13
-rw-r--r--chrome/browser/extensions/api/declarative_content/content_rules_registry.cc8
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc185
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h54
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc467
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.cc97
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h35
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc152
-rw-r--r--chrome/browser/extensions/api/web_request/web_request_api.cc3
-rw-r--r--chrome/browser/extensions/api/web_request/web_request_apitest.cc11
-rw-r--r--chrome/browser/extensions/api/web_request/web_request_permissions.cc24
-rw-r--r--chrome/browser/extensions/api/web_request/web_request_permissions.h20
-rw-r--r--chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc86
-rw-r--r--chrome/browser/extensions/permissions_updater_unittest.cc31
-rw-r--r--chrome/common/extensions/docs/templates/intros/declarativeWebRequest.html28
-rw-r--r--chrome/common/extensions/extension_test_util.cc69
-rw-r--r--chrome/common/extensions/extension_test_util.h35
-rw-r--r--chrome/common/extensions/extension_unittest.cc61
-rw-r--r--chrome/common/extensions/permissions/permission_set_unittest.cc32
-rw-r--r--chrome/test/data/extensions/api_test/declarative/api/manifest.json2
-rw-r--r--chrome/test/data/extensions/api_test/webrequest/manifest.json3
-rw-r--r--chrome/test/data/extensions/api_test/webrequest/permissionless/manifest.json10
-rw-r--r--chrome/test/data/extensions/api_test/webrequest/permissionless/rules.js50
-rw-r--r--chrome/test/data/extensions/api_test/webrequest/test_declarative2.js36
-rw-r--r--chrome/test/data/extensions/api_test/webrequest/test_declarative_permissions.html2
-rw-r--r--chrome/test/data/extensions/api_test/webrequest/test_declarative_permissions.js126
-rw-r--r--chrome/test/data/extensions/api_test/webrequest/test_simple.js46
-rw-r--r--chrome/test/data/extensions/permissions/web_request_all_host_permissions.json5
-rw-r--r--chrome/test/data/extensions/permissions/web_request_com_host_permissions.json5
-rw-r--r--chrome/test/data/extensions/permissions/web_request_no_host.json5
31 files changed, 1064 insertions, 648 deletions
diff --git a/chrome/browser/extensions/api/declarative/declarative_rule.h b/chrome/browser/extensions/api/declarative/declarative_rule.h
index e941155..a2dd1f5 100644
--- a/chrome/browser/extensions/api/declarative/declarative_rule.h
+++ b/chrome/browser/extensions/api/declarative/declarative_rule.h
@@ -15,6 +15,7 @@
#include <string>
#include <vector>
+#include "base/callback.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/stl_util.h"
@@ -190,9 +191,9 @@ class DeclarativeRule {
// Checks whether the set of |conditions| and |actions| are consistent.
// Returns true in case of consistency and MUST set |error| otherwise.
- typedef bool (*ConsistencyChecker)(const ConditionSet* conditions,
- const ActionSet* actions,
- std::string* error);
+ typedef base::Callback<bool(const ConditionSet* conditions,
+ const ActionSet* actions,
+ std::string* error)> ConsistencyChecker;
DeclarativeRule(const GlobalRuleId& id,
const Tags& tags,
@@ -448,8 +449,8 @@ DeclarativeRule<ConditionT, ActionT>::Create(
return error_result.Pass();
CHECK(actions.get());
- if (check_consistency &&
- !check_consistency(conditions.get(), actions.get(), error)) {
+ if (!check_consistency.is_null() &&
+ !check_consistency.Run(conditions.get(), actions.get(), error)) {
DCHECK(!error->empty());
return error_result.Pass();
}
diff --git a/chrome/browser/extensions/api/declarative/declarative_rule_unittest.cc b/chrome/browser/extensions/api/declarative/declarative_rule_unittest.cc
index 5bf39d0..13dc9d8 100644
--- a/chrome/browser/extensions/api/declarative/declarative_rule_unittest.cc
+++ b/chrome/browser/extensions/api/declarative/declarative_rule_unittest.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/extensions/api/declarative/declarative_rule.h"
+#include "base/bind.h"
#include "base/message_loop.h"
#include "base/test/values_test_util.h"
#include "base/values.h"
@@ -305,8 +306,12 @@ TEST(DeclarativeRuleTest, Create) {
URLMatcher matcher;
std::string error;
- scoped_ptr<Rule> rule(Rule::Create(matcher.condition_factory(), kExtensionId,
- install_time, json_rule, NULL, &error));
+ scoped_ptr<Rule> rule(Rule::Create(matcher.condition_factory(),
+ kExtensionId,
+ install_time,
+ json_rule,
+ Rule::ConsistencyChecker(),
+ &error));
EXPECT_EQ("", error);
ASSERT_TRUE(rule.get());
@@ -367,7 +372,7 @@ TEST(DeclarativeRuleTest, CheckConsistency) {
json_rule.get()));
scoped_ptr<Rule> rule(
Rule::Create(matcher.condition_factory(), kExtensionId, base::Time(),
- json_rule, &AtLeastOneCondition, &error));
+ json_rule, base::Bind(AtLeastOneCondition), &error));
EXPECT_TRUE(rule);
EXPECT_EQ("", error);
@@ -385,7 +390,7 @@ TEST(DeclarativeRuleTest, CheckConsistency) {
"}"),
json_rule.get()));
rule = Rule::Create(matcher.condition_factory(), kExtensionId, base::Time(),
- json_rule, &AtLeastOneCondition, &error);
+ json_rule, base::Bind(AtLeastOneCondition), &error);
EXPECT_FALSE(rule);
EXPECT_EQ("No conditions", error);
}
diff --git a/chrome/browser/extensions/api/declarative_content/content_rules_registry.cc b/chrome/browser/extensions/api/declarative_content/content_rules_registry.cc
index eb95b47..9589633 100644
--- a/chrome/browser/extensions/api/declarative_content/content_rules_registry.cc
+++ b/chrome/browser/extensions/api/declarative_content/content_rules_registry.cc
@@ -139,8 +139,12 @@ std::string ContentRulesRegistry::AddRulesImpl(
DCHECK(content_rules_.find(rule_id) == content_rules_.end());
scoped_ptr<ContentRule> content_rule(
- ContentRule::Create(url_matcher_.condition_factory(), extension_id,
- extension_installation_time, *rule, NULL, &error));
+ ContentRule::Create(url_matcher_.condition_factory(),
+ extension_id,
+ extension_installation_time,
+ *rule,
+ ContentRule::ConsistencyChecker(),
+ &error));
if (!error.empty()) {
// Clean up temporary condition sets created during rule creation.
url_matcher_.ClearUnusedConditionSets();
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc
index 2459ee9..5394689 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc
@@ -329,10 +329,16 @@ struct WebRequestActionFactory {
(* FactoryMethod)(const base::DictionaryValue* /* dict */ ,
std::string* /* error */,
bool* /* bad_message */);
+
+ typedef std::map<WebRequestAction::Type, const std::string> ActionNames;
+
// Maps the name of a declarativeWebRequest action type to the factory
// function creating it.
std::map<std::string, FactoryMethod> factory_methods;
+ // Translates action types into the corresponding JavaScript names.
+ ActionNames action_names;
+
WebRequestActionFactory() {
factory_methods[keys::kAddRequestCookieType] =
&CreateRequestCookieAction;
@@ -369,6 +375,44 @@ struct WebRequestActionFactory {
&CreateIgnoreRulesAction;
factory_methods[keys::kSendMessageToExtensionType] =
&CreateSendMessageToExtensionAction;
+
+#define INSERT_ACTION_NAME(type, name) \
+ action_names.insert(ActionNames::value_type(type, name));
+ std::vector<std::string> names_buffer;
+ names_buffer.push_back(keys::kAddRequestCookieType);
+ names_buffer.push_back(keys::kEditRequestCookieType);
+ names_buffer.push_back(keys::kRemoveRequestCookieType);
+ INSERT_ACTION_NAME(WebRequestAction::ACTION_MODIFY_REQUEST_COOKIE,
+ JoinString(names_buffer, ", "));
+ names_buffer.clear();
+ names_buffer.push_back(keys::kAddResponseCookieType);
+ names_buffer.push_back(keys::kEditResponseCookieType);
+ names_buffer.push_back(keys::kRemoveResponseCookieType);
+ INSERT_ACTION_NAME(WebRequestAction::ACTION_MODIFY_RESPONSE_COOKIE,
+ JoinString(names_buffer, ", "));
+ INSERT_ACTION_NAME(WebRequestAction::ACTION_ADD_RESPONSE_HEADER,
+ keys::kAddResponseHeaderType);
+ INSERT_ACTION_NAME(WebRequestAction::ACTION_CANCEL_REQUEST,
+ keys::kCancelRequestType);
+ INSERT_ACTION_NAME(WebRequestAction::ACTION_REDIRECT_BY_REGEX_DOCUMENT,
+ keys::kRedirectByRegExType);
+ INSERT_ACTION_NAME(WebRequestAction::ACTION_REDIRECT_REQUEST,
+ keys::kRedirectRequestType);
+ INSERT_ACTION_NAME(WebRequestAction::ACTION_REDIRECT_TO_TRANSPARENT_IMAGE,
+ keys::kRedirectToTransparentImageType);
+ INSERT_ACTION_NAME(WebRequestAction::ACTION_REDIRECT_TO_EMPTY_DOCUMENT,
+ keys::kRedirectToEmptyDocumentType);
+ INSERT_ACTION_NAME(WebRequestAction::ACTION_SET_REQUEST_HEADER,
+ keys::kSetRequestHeaderType);
+ INSERT_ACTION_NAME(WebRequestAction::ACTION_REMOVE_REQUEST_HEADER,
+ keys::kRemoveRequestHeaderType);
+ INSERT_ACTION_NAME(WebRequestAction::ACTION_REMOVE_RESPONSE_HEADER,
+ keys::kRemoveResponseHeaderType);
+ INSERT_ACTION_NAME(WebRequestAction::ACTION_IGNORE_RULES,
+ keys::kIgnoreRulesType);
+ INSERT_ACTION_NAME(WebRequestAction::ACTION_SEND_MESSAGE_TO_EXTENSION,
+ keys::kSendMessageToExtensionType);
+#undef INSERT_ACTION_NAME
}
};
@@ -381,17 +425,19 @@ base::LazyInstance<WebRequestActionFactory>::Leaky
// WebRequestAction
//
-WebRequestAction::WebRequestAction() {}
-
WebRequestAction::~WebRequestAction() {}
-int WebRequestAction::GetMinimumPriority() const {
- return std::numeric_limits<int>::min();
+const std::string& WebRequestAction::GetName() const {
+ const WebRequestActionFactory::ActionNames& names =
+ g_web_request_action_factory.Get().action_names;
+ std::map<WebRequestAction::Type, const std::string>::const_iterator it =
+ names.find(GetType());
+ CHECK(it != names.end());
+ return it->second;
}
-WebRequestAction::HostPermissionsStrategy
-WebRequestAction::GetHostPermissionsStrategy() const {
- return STRATEGY_DEFAULT;
+int WebRequestAction::GetMinimumPriority() const {
+ return std::numeric_limits<int>::min();
}
bool WebRequestAction::HasPermission(const ExtensionInfoMap* extension_info_map,
@@ -406,31 +452,21 @@ bool WebRequestAction::HasPermission(const ExtensionInfoMap* extension_info_map,
if (!extension_info_map)
return true;
- HostPermissionsStrategy strategy = GetHostPermissionsStrategy();
- if (strategy == STRATEGY_NONE || strategy == STRATEGY_DEFAULT) {
- bool check_host_permissions = strategy != STRATEGY_NONE;
- return WebRequestPermissions::CanExtensionAccessURL(
- extension_info_map, extension_id, request->url(), crosses_incognito,
- check_host_permissions);
- }
- return true;
-}
-
-bool WebRequestAction::DeltaHasPermission(
- const ExtensionInfoMap* extension_info_map,
- const std::string& extension_id,
- const net::URLRequest* request,
- bool crosses_incognito,
- const LinkedPtrEventResponseDelta& delta) const {
- if (GetHostPermissionsStrategy() == STRATEGY_ALLOW_SAME_DOMAIN) {
- return
- net::RegistryControlledDomainService::SameDomainOrHost(
- request->url(), delta->new_url) ||
- WebRequestPermissions::CanExtensionAccessURL(
- extension_info_map, extension_id, request->url(), crosses_incognito,
- true);
+ WebRequestPermissions::HostPermissionsCheck permission_check =
+ WebRequestPermissions::REQUIRE_ALL_URLS;
+ switch (host_permissions_strategy()) {
+ case STRATEGY_DEFAULT: // Default value is already set.
+ break;
+ case STRATEGY_NONE:
+ permission_check = WebRequestPermissions::DO_NOT_CHECK_HOST;
+ break;
+ case STRATEGY_HOST:
+ permission_check = WebRequestPermissions::REQUIRE_HOST_PERMISSION;
+ break;
}
- return true;
+ return WebRequestPermissions::CanExtensionAccessURL(
+ extension_info_map, extension_id, request->url(), crosses_incognito,
+ permission_check);
}
// static
@@ -468,13 +504,8 @@ void WebRequestAction::Apply(const std::string& extension_id,
if (GetStages() & apply_info->request_data.stage) {
LinkedPtrEventResponseDelta delta = CreateDelta(
apply_info->request_data, extension_id, extension_install_time);
- if (delta.get()) {
- if (DeltaHasPermission(apply_info->extension_info_map, extension_id,
- apply_info->request_data.request,
- apply_info->crosses_incognito,
- delta))
- apply_info->deltas->push_back(delta);
- }
+ if (delta.get())
+ apply_info->deltas->push_back(delta);
if (GetType() == WebRequestAction::ACTION_IGNORE_RULES) {
const WebRequestIgnoreRulesAction* ignore_action =
static_cast<const WebRequestIgnoreRulesAction*>(this);
@@ -484,12 +515,15 @@ void WebRequestAction::Apply(const std::string& extension_id,
}
}
+WebRequestAction::WebRequestAction(HostPermissionsStrategy strategy)
+ : host_permissions_strategy_(strategy) {}
//
// WebRequestCancelAction
//
-WebRequestCancelAction::WebRequestCancelAction() {}
+WebRequestCancelAction::WebRequestCancelAction()
+ : WebRequestAction(STRATEGY_NONE) {}
WebRequestCancelAction::~WebRequestCancelAction() {}
@@ -502,11 +536,6 @@ WebRequestAction::Type WebRequestCancelAction::GetType() const {
return WebRequestAction::ACTION_CANCEL_REQUEST;
}
-WebRequestAction::HostPermissionsStrategy
-WebRequestCancelAction::GetHostPermissionsStrategy() const {
- return WebRequestAction::STRATEGY_NONE;
-}
-
LinkedPtrEventResponseDelta WebRequestCancelAction::CreateDelta(
const WebRequestData& request_data,
const std::string& extension_id,
@@ -523,7 +552,7 @@ LinkedPtrEventResponseDelta WebRequestCancelAction::CreateDelta(
//
WebRequestRedirectAction::WebRequestRedirectAction(const GURL& redirect_url)
- : redirect_url_(redirect_url) {}
+ : WebRequestAction(STRATEGY_DEFAULT), redirect_url_(redirect_url) {}
WebRequestRedirectAction::~WebRequestRedirectAction() {}
@@ -535,11 +564,6 @@ WebRequestAction::Type WebRequestRedirectAction::GetType() const {
return WebRequestAction::ACTION_REDIRECT_REQUEST;
}
-WebRequestAction::HostPermissionsStrategy
-WebRequestRedirectAction::GetHostPermissionsStrategy() const {
- return WebRequestAction::STRATEGY_ALLOW_SAME_DOMAIN;
-}
-
LinkedPtrEventResponseDelta WebRequestRedirectAction::CreateDelta(
const WebRequestData& request_data,
const std::string& extension_id,
@@ -558,7 +582,8 @@ LinkedPtrEventResponseDelta WebRequestRedirectAction::CreateDelta(
//
WebRequestRedirectToTransparentImageAction::
-WebRequestRedirectToTransparentImageAction() {}
+ WebRequestRedirectToTransparentImageAction()
+ : WebRequestAction(STRATEGY_NONE) {}
WebRequestRedirectToTransparentImageAction::
~WebRequestRedirectToTransparentImageAction() {}
@@ -572,11 +597,6 @@ WebRequestRedirectToTransparentImageAction::GetType() const {
return WebRequestAction::ACTION_REDIRECT_TO_TRANSPARENT_IMAGE;
}
-WebRequestAction::HostPermissionsStrategy
-WebRequestRedirectToTransparentImageAction::GetHostPermissionsStrategy() const {
- return WebRequestAction::STRATEGY_NONE;
-}
-
LinkedPtrEventResponseDelta
WebRequestRedirectToTransparentImageAction::CreateDelta(
const WebRequestData& request_data,
@@ -594,7 +614,8 @@ WebRequestRedirectToTransparentImageAction::CreateDelta(
//
WebRequestRedirectToEmptyDocumentAction::
-WebRequestRedirectToEmptyDocumentAction() {}
+ WebRequestRedirectToEmptyDocumentAction()
+ : WebRequestAction(STRATEGY_NONE) {}
WebRequestRedirectToEmptyDocumentAction::
~WebRequestRedirectToEmptyDocumentAction() {}
@@ -608,11 +629,6 @@ WebRequestRedirectToEmptyDocumentAction::GetType() const {
return WebRequestAction::ACTION_REDIRECT_TO_EMPTY_DOCUMENT;
}
-WebRequestAction::HostPermissionsStrategy
-WebRequestRedirectToEmptyDocumentAction::GetHostPermissionsStrategy() const {
- return WebRequestAction::STRATEGY_NONE;
-}
-
LinkedPtrEventResponseDelta
WebRequestRedirectToEmptyDocumentAction::CreateDelta(
const WebRequestData& request_data,
@@ -632,7 +648,8 @@ WebRequestRedirectToEmptyDocumentAction::CreateDelta(
WebRequestRedirectByRegExAction::WebRequestRedirectByRegExAction(
scoped_ptr<RE2> from_pattern,
const std::string& to_pattern)
- : from_pattern_(from_pattern.Pass()),
+ : WebRequestAction(STRATEGY_DEFAULT),
+ from_pattern_(from_pattern.Pass()),
to_pattern_(to_pattern.data(), to_pattern.size()) {}
WebRequestRedirectByRegExAction::~WebRequestRedirectByRegExAction() {}
@@ -698,11 +715,6 @@ WebRequestAction::Type WebRequestRedirectByRegExAction::GetType() const {
return WebRequestAction::ACTION_REDIRECT_BY_REGEX_DOCUMENT;
}
-WebRequestAction::HostPermissionsStrategy
-WebRequestRedirectByRegExAction::GetHostPermissionsStrategy() const {
- return WebRequestAction::STRATEGY_ALLOW_SAME_DOMAIN;
-}
-
LinkedPtrEventResponseDelta WebRequestRedirectByRegExAction::CreateDelta(
const WebRequestData& request_data,
const std::string& extension_id,
@@ -731,9 +743,7 @@ LinkedPtrEventResponseDelta WebRequestRedirectByRegExAction::CreateDelta(
WebRequestSetRequestHeaderAction::WebRequestSetRequestHeaderAction(
const std::string& name,
const std::string& value)
- : name_(name),
- value_(value) {
-}
+ : WebRequestAction(STRATEGY_DEFAULT), name_(name), value_(value) {}
WebRequestSetRequestHeaderAction::~WebRequestSetRequestHeaderAction() {}
@@ -764,8 +774,7 @@ WebRequestSetRequestHeaderAction::CreateDelta(
WebRequestRemoveRequestHeaderAction::WebRequestRemoveRequestHeaderAction(
const std::string& name)
- : name_(name) {
-}
+ : WebRequestAction(STRATEGY_DEFAULT), name_(name) {}
WebRequestRemoveRequestHeaderAction::~WebRequestRemoveRequestHeaderAction() {}
@@ -797,9 +806,7 @@ WebRequestRemoveRequestHeaderAction::CreateDelta(
WebRequestAddResponseHeaderAction::WebRequestAddResponseHeaderAction(
const std::string& name,
const std::string& value)
- : name_(name),
- value_(value) {
-}
+ : WebRequestAction(STRATEGY_DEFAULT), name_(name), value_(value) {}
WebRequestAddResponseHeaderAction::~WebRequestAddResponseHeaderAction() {}
@@ -841,10 +848,10 @@ WebRequestRemoveResponseHeaderAction::WebRequestRemoveResponseHeaderAction(
const std::string& name,
const std::string& value,
bool has_value)
- : name_(name),
+ : WebRequestAction(STRATEGY_DEFAULT),
+ name_(name),
value_(value),
- has_value_(has_value) {
-}
+ has_value_(has_value) {}
WebRequestRemoveResponseHeaderAction::~WebRequestRemoveResponseHeaderAction() {}
@@ -892,9 +899,9 @@ WebRequestRemoveResponseHeaderAction::CreateDelta(
WebRequestIgnoreRulesAction::WebRequestIgnoreRulesAction(
int minimum_priority,
const std::string& ignore_tag)
- : minimum_priority_(minimum_priority),
- ignore_tag_(ignore_tag) {
-}
+ : WebRequestAction(STRATEGY_NONE),
+ minimum_priority_(minimum_priority),
+ ignore_tag_(ignore_tag) {}
WebRequestIgnoreRulesAction::~WebRequestIgnoreRulesAction() {}
@@ -911,11 +918,6 @@ int WebRequestIgnoreRulesAction::GetMinimumPriority() const {
return minimum_priority_;
}
-WebRequestAction::HostPermissionsStrategy
-WebRequestIgnoreRulesAction::GetHostPermissionsStrategy() const {
- return WebRequestAction::STRATEGY_NONE;
-}
-
LinkedPtrEventResponseDelta WebRequestIgnoreRulesAction::CreateDelta(
const WebRequestData& request_data,
const std::string& extension_id,
@@ -930,7 +932,8 @@ LinkedPtrEventResponseDelta WebRequestIgnoreRulesAction::CreateDelta(
WebRequestRequestCookieAction::WebRequestRequestCookieAction(
linked_ptr<RequestCookieModification> request_cookie_modification)
- : request_cookie_modification_(request_cookie_modification) {
+ : WebRequestAction(STRATEGY_DEFAULT),
+ request_cookie_modification_(request_cookie_modification) {
CHECK(request_cookie_modification_.get());
}
@@ -963,7 +966,8 @@ LinkedPtrEventResponseDelta WebRequestRequestCookieAction::CreateDelta(
WebRequestResponseCookieAction::WebRequestResponseCookieAction(
linked_ptr<ResponseCookieModification> response_cookie_modification)
- : response_cookie_modification_(response_cookie_modification) {
+ : WebRequestAction(STRATEGY_DEFAULT),
+ response_cookie_modification_(response_cookie_modification) {
CHECK(response_cookie_modification_.get());
}
@@ -996,8 +1000,7 @@ LinkedPtrEventResponseDelta WebRequestResponseCookieAction::CreateDelta(
WebRequestSendMessageToExtensionAction::WebRequestSendMessageToExtensionAction(
const std::string& message)
- : message_(message) {
-}
+ : WebRequestAction(STRATEGY_HOST), message_(message) {}
WebRequestSendMessageToExtensionAction::
~WebRequestSendMessageToExtensionAction() {}
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h
index 2785cfc..41c3639 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h
@@ -51,7 +51,10 @@ typedef linked_ptr<extension_web_request_api_helpers::EventResponseDelta>
// Base class for all WebRequestActions of the declarative Web Request API.
class WebRequestAction {
public:
- // Type identifiers for concrete WebRequestActions.
+ // Type identifiers for concrete WebRequestActions. If you add a new type,
+ // also update |action_names| in WebRequestActionFactory, update the
+ // unittest WebRequestActionTest.GetName, and add a
+ // WebRequestActionWithThreadsTest.Permission* unittest.
enum Type {
ACTION_CANCEL_REQUEST,
ACTION_REDIRECT_REQUEST,
@@ -70,13 +73,11 @@ class WebRequestAction {
// Strategies for checking host permissions.
enum HostPermissionsStrategy {
- STRATEGY_NONE, // Do not check host permissions.
- STRATEGY_DEFAULT, // Check host permissions in HasPermission,
+ STRATEGY_NONE, // Do not check host permissions.
+ STRATEGY_DEFAULT, // Check for host permissions for all URLs
// before creating the delta.
- STRATEGY_ALLOW_SAME_DOMAIN, // Skip host permission checks if the request
- // URL and new URL have the same domain.
- // Do these checks in DeltaHasPermission,
- // after creating the delta.
+ STRATEGY_HOST, // Check that host permissions match the URL
+ // of the request.
};
// Information necessary to decide how to apply a WebRequestAction
@@ -90,7 +91,6 @@ class WebRequestAction {
std::set<std::string>* ignored_tags;
};
- WebRequestAction();
virtual ~WebRequestAction();
// Returns a bit vector representing extensions::RequestStage. The bit vector
@@ -100,15 +100,17 @@ class WebRequestAction {
virtual Type GetType() const = 0;
+ // Return the JavaScript type name corresponding to GetType(). If there are
+ // more names, they are returned separated by a colon.
+ const std::string& GetName() const;
+
// Returns the minimum priority of rules that may be evaluated after
// this rule. Defaults to MIN_INT.
virtual int GetMinimumPriority() const;
- // Returns whether host permissions checks depend on the resulting delta
- // and therefore must be checked in DeltaHasPermission, after the delta
- // is created, rather than in HasPermission, before it is created.
- // Defaults to STRATEGY_DEFAULT.
- virtual HostPermissionsStrategy GetHostPermissionsStrategy() const;
+ HostPermissionsStrategy host_permissions_strategy() const {
+ return host_permissions_strategy_;
+ }
// Returns whether the specified extension has permission to execute this
// action on |request|. Checks the host permission if the host permissions
@@ -122,19 +124,6 @@ class WebRequestAction {
const net::URLRequest* request,
bool crosses_incognito) const;
- // Returns whether the specified extension has permission to modify the
- // |request| with this |delta|. This check is in addition to HasPermission;
- // if either fails, the request will not be modified. Unlike HasPermission,
- // it runs after the change is created, so it can use the full information
- // about what the change would be. Checks the host permission if the strategy
- // is STRATEGY_ALLOW_SAME_DOMAIN.
- virtual bool DeltaHasPermission(
- const ExtensionInfoMap* extension_info_map,
- const std::string& extension_id,
- const net::URLRequest* request,
- bool crosses_incognito,
- const LinkedPtrEventResponseDelta& delta) const;
-
// Factory method that instantiates a concrete WebRequestAction
// implementation according to |json_action|, the representation of the
// WebRequestAction as received from the extension API.
@@ -157,6 +146,13 @@ class WebRequestAction {
void Apply(const std::string& extension_id,
base::Time extension_install_time,
ApplyInfo* apply_info) const;
+
+ protected:
+ explicit WebRequestAction(HostPermissionsStrategy strategy);
+
+ private:
+ // Defaults to STRATEGY_DEFAULT.
+ const HostPermissionsStrategy host_permissions_strategy_;
};
typedef DeclarativeActionSet<WebRequestAction> WebRequestActionSet;
@@ -174,7 +170,6 @@ class WebRequestCancelAction : public WebRequestAction {
// Implementation of WebRequestAction:
virtual int GetStages() const OVERRIDE;
virtual Type GetType() const OVERRIDE;
- virtual HostPermissionsStrategy GetHostPermissionsStrategy() const OVERRIDE;
virtual LinkedPtrEventResponseDelta CreateDelta(
const WebRequestData& request_data,
const std::string& extension_id,
@@ -193,7 +188,6 @@ class WebRequestRedirectAction : public WebRequestAction {
// Implementation of WebRequestAction:
virtual int GetStages() const OVERRIDE;
virtual Type GetType() const OVERRIDE;
- virtual HostPermissionsStrategy GetHostPermissionsStrategy() const OVERRIDE;
virtual LinkedPtrEventResponseDelta CreateDelta(
const WebRequestData& request_data,
const std::string& extension_id,
@@ -214,7 +208,6 @@ class WebRequestRedirectToTransparentImageAction : public WebRequestAction {
// Implementation of WebRequestAction:
virtual int GetStages() const OVERRIDE;
virtual Type GetType() const OVERRIDE;
- virtual HostPermissionsStrategy GetHostPermissionsStrategy() const OVERRIDE;
virtual LinkedPtrEventResponseDelta CreateDelta(
const WebRequestData& request_data,
const std::string& extension_id,
@@ -234,7 +227,6 @@ class WebRequestRedirectToEmptyDocumentAction : public WebRequestAction {
// Implementation of WebRequestAction:
virtual int GetStages() const OVERRIDE;
virtual Type GetType() const OVERRIDE;
- virtual HostPermissionsStrategy GetHostPermissionsStrategy() const OVERRIDE;
virtual LinkedPtrEventResponseDelta CreateDelta(
const WebRequestData& request_data,
const std::string& extension_id,
@@ -260,7 +252,6 @@ class WebRequestRedirectByRegExAction : public WebRequestAction {
// Implementation of WebRequestAction:
virtual int GetStages() const OVERRIDE;
virtual Type GetType() const OVERRIDE;
- virtual HostPermissionsStrategy GetHostPermissionsStrategy() const OVERRIDE;
virtual LinkedPtrEventResponseDelta CreateDelta(
const WebRequestData& request_data,
const std::string& extension_id,
@@ -368,7 +359,6 @@ class WebRequestIgnoreRulesAction : public WebRequestAction {
virtual int GetStages() const OVERRIDE;
virtual Type GetType() const OVERRIDE;
virtual int GetMinimumPriority() const OVERRIDE;
- virtual HostPermissionsStrategy GetHostPermissionsStrategy() const OVERRIDE;
virtual LinkedPtrEventResponseDelta CreateDelta(
const WebRequestData& request_data,
const std::string& extension_id,
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 77a0a46..6abc921 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc
@@ -4,23 +4,175 @@
#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h"
+#include "base/files/file_path.h"
+#include "base/json/json_file_value_serializer.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
+#include "base/path_service.h"
+#include "base/test/values_test_util.h"
+#include "base/time.h"
#include "base/values.h"
+#include "chrome/browser/extensions/api/declarative_webrequest/request_stage.h"
#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.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/extension_info_map.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/extensions/extension_test_util.h"
+#include "content/public/test/test_browser_thread.h"
+#include "net/http/http_response_headers.h"
#include "net/url_request/url_request_test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using base::DictionaryValue;
+using base::ListValue;
+using extension_test_util::LoadManifestUnchecked;
+using testing::HasSubstr;
+
+namespace extensions {
+
namespace {
+
const char kUnknownActionType[] = "unknownType";
-} // namespace
-namespace extensions {
+scoped_ptr<WebRequestActionSet> CreateSetOfActions(const char* json) {
+ scoped_ptr<Value> parsed_value(base::test::ParseJson(json));
+ const ListValue* parsed_list;
+ CHECK(parsed_value->GetAsList(&parsed_list));
+
+ WebRequestActionSet::AnyVector actions;
+ for (ListValue::const_iterator it = parsed_list->begin();
+ it != parsed_list->end();
+ ++it) {
+ const DictionaryValue* dict;
+ CHECK((*it)->GetAsDictionary(&dict));
+ actions.push_back(linked_ptr<base::Value>(dict->DeepCopy()));
+ }
+
+ std::string error;
+ bool bad_message = false;
+
+ scoped_ptr<WebRequestActionSet> action_set(
+ WebRequestActionSet::Create(actions, &error, &bad_message));
+ EXPECT_EQ("", error);
+ EXPECT_FALSE(bad_message);
+ CHECK(action_set);
+ return action_set.Pass();
+}
+
+} // namespace
namespace keys = declarative_webrequest_constants;
+class WebRequestActionWithThreadsTest : public testing::Test {
+ public:
+ WebRequestActionWithThreadsTest()
+ : io_thread_(content::BrowserThread::IO, &message_loop_) {}
+
+ protected:
+ virtual void SetUp() OVERRIDE;
+
+ // Creates a URL request for URL |url_string|, and applies the actions from
+ // |action_set| as if they were triggered by the extension with
+ // |extension_id| during |stage|.
+ bool ActionWorksOnRequest(const char* url_string,
+ const std::string& extension_id,
+ const WebRequestActionSet* action_set,
+ RequestStage stage);
+
+ // Expects a JSON description of an |action| requiring <all_urls> host
+ // permission, and checks that only an extensions with full host permissions
+ // can execute that action at |stage|. Also checks that the action is not
+ // executable for http://clients1.google.com.
+ void CheckActionNeedsAllUrls(const char* action, RequestStage stage);
+
+ net::TestURLRequestContext context_;
+
+ // An extension with *.com host permissions and the DWR permission.
+ scoped_refptr<Extension> extension_;
+ // An extension with host permissions for all URLs and the DWR permission.
+ scoped_refptr<Extension> extension_all_urls_;
+ scoped_refptr<ExtensionInfoMap> extension_info_map_;
+
+ private:
+ MessageLoopForIO message_loop_;
+ content::TestBrowserThread io_thread_;
+};
+
+void WebRequestActionWithThreadsTest::SetUp() {
+ testing::Test::SetUp();
+
+ std::string error;
+ extension_ = LoadManifestUnchecked("permissions",
+ "web_request_com_host_permissions.json",
+ Manifest::INVALID_LOCATION,
+ Extension::NO_FLAGS,
+ "ext_id_1",
+ &error);
+ ASSERT_TRUE(extension_) << error;
+ extension_all_urls_ =
+ LoadManifestUnchecked("permissions",
+ "web_request_all_host_permissions.json",
+ Manifest::INVALID_LOCATION,
+ Extension::NO_FLAGS,
+ "ext_id_2",
+ &error);
+ ASSERT_TRUE(extension_all_urls_) << error;
+ extension_info_map_ = new ExtensionInfoMap;
+ ASSERT_TRUE(extension_info_map_);
+ extension_info_map_->AddExtension(
+ extension_.get(), base::Time::Now(), false /*incognito_enabled*/);
+ extension_info_map_->AddExtension(extension_all_urls_.get(),
+ base::Time::Now(),
+ false /*incognito_enabled*/);
+}
+
+bool WebRequestActionWithThreadsTest::ActionWorksOnRequest(
+ const char* url_string,
+ const std::string& extension_id,
+ const WebRequestActionSet* action_set,
+ RequestStage stage) {
+ net::TestURLRequest regular_request(GURL(url_string), NULL, &context_, NULL);
+ std::list<LinkedPtrEventResponseDelta> deltas;
+ scoped_refptr<net::HttpResponseHeaders> headers(
+ new net::HttpResponseHeaders(""));
+ WebRequestData request_data(&regular_request, stage, headers);
+ std::set<std::string> ignored_tags;
+ WebRequestAction::ApplyInfo apply_info = {
+ extension_info_map_, request_data, false /*crosses_incognito*/, &deltas,
+ &ignored_tags
+ };
+ action_set->Apply(extension_id, base::Time(), &apply_info);
+ return (1u == deltas.size() || 0u < ignored_tags.size());
+}
+
+void WebRequestActionWithThreadsTest::CheckActionNeedsAllUrls(
+ const char* action,
+ RequestStage stage) {
+ scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(action));
+
+ // Although |extension_| has matching *.com host permission, |action|
+ // is intentionally forbidden -- in Declarative WR, host permission
+ // for less than all URLs are ignored (except in SendMessageToExtension).
+ EXPECT_FALSE(ActionWorksOnRequest(
+ "http://test.com", extension_->id(), action_set.get(), stage));
+ // With the "<all_urls>" host permission they are allowed.
+ EXPECT_TRUE(ActionWorksOnRequest(
+ "http://test.com", extension_all_urls_->id(), action_set.get(), stage));
+
+ // The protected URLs should not be touched at all.
+ EXPECT_FALSE(ActionWorksOnRequest(
+ "http://clients1.google.com", extension_->id(), action_set.get(), stage));
+ EXPECT_FALSE(ActionWorksOnRequest("http://clients1.google.com",
+ extension_all_urls_->id(),
+ action_set.get(),
+ stage));
+}
+
TEST(WebRequestActionTest, CreateAction) {
std::string error;
bool bad_message = false;
@@ -115,45 +267,288 @@ TEST(WebRequestActionTest, PerlToRe2Style) {
#undef CallPerlToRe2Style
}
-TEST(WebRequestActionTest, TestPermissions) {
- // Necessary for TestURLRequest.
- MessageLoop message_loop(MessageLoop::TYPE_IO);
- net::TestURLRequestContext context;
+TEST_F(WebRequestActionWithThreadsTest, PermissionsToRedirect) {
+ const char kAction[] =
+ "[{"
+ " \"instanceType\": \"declarativeWebRequest.RedirectRequest\","
+ " \"redirectUrl\": \"http://www.foobar.com\""
+ "}]";
+ CheckActionNeedsAllUrls(kAction, ON_BEFORE_REQUEST);
+}
- std::string error;
- bool bad_message = false;
- scoped_ptr<WebRequestActionSet> action_set;
+TEST_F(WebRequestActionWithThreadsTest, PermissionsToRedirectByRegEx) {
+ const char kAction[] =
+ "[{"
+ " \"instanceType\": \"declarativeWebRequest.RedirectByRegEx\","
+ " \"from\": \".*\","
+ " \"to\": \"http://www.foobar.com\""
+ "}]";
+ CheckActionNeedsAllUrls(kAction, ON_BEFORE_REQUEST);
+}
- // Setup redirect to http://www.foobar.com.
- base::DictionaryValue redirect;
- redirect.SetString(keys::kInstanceTypeKey, keys::kRedirectRequestType);
- redirect.SetString(keys::kRedirectUrlKey, "http://www.foobar.com");
+TEST_F(WebRequestActionWithThreadsTest, PermissionsToSetRequestHeader) {
+ const char kAction[] =
+ "[{"
+ " \"instanceType\": \"declarativeWebRequest.SetRequestHeader\","
+ " \"name\": \"testname\","
+ " \"value\": \"testvalue\""
+ "}]";
+ CheckActionNeedsAllUrls(kAction, ON_BEFORE_SEND_HEADERS);
+}
- WebRequestActionSet::AnyVector actions;
- actions.push_back(linked_ptr<base::Value>(redirect.DeepCopy()));
+TEST_F(WebRequestActionWithThreadsTest, PermissionsToRemoveRequestHeader) {
+ const char kAction[] =
+ "[{"
+ " \"instanceType\": \"declarativeWebRequest.RemoveRequestHeader\","
+ " \"name\": \"testname\""
+ "}]";
+ CheckActionNeedsAllUrls(kAction, ON_BEFORE_SEND_HEADERS);
+}
- action_set = WebRequestActionSet::Create(actions, &error, &bad_message);
- EXPECT_EQ("", error);
- EXPECT_FALSE(bad_message);
+TEST_F(WebRequestActionWithThreadsTest, PermissionsToAddResponseHeader) {
+ const char kAction[] =
+ "[{"
+ " \"instanceType\": \"declarativeWebRequest.AddResponseHeader\","
+ " \"name\": \"testname\","
+ " \"value\": \"testvalue\""
+ "}]";
+ CheckActionNeedsAllUrls(kAction, ON_HEADERS_RECEIVED);
+}
- // Check that redirect works on regular URLs but not on protected URLs.
- net::TestURLRequest regular_request(
- GURL("http://test.com"), NULL, &context, NULL);
- std::list<LinkedPtrEventResponseDelta> deltas;
- WebRequestData request_data(&regular_request, ON_BEFORE_REQUEST);
- WebRequestAction::ApplyInfo apply_info = {
- NULL, request_data, false, &deltas
- };
- action_set->Apply("ext1", base::Time(), &apply_info);
- EXPECT_EQ(1u, deltas.size());
-
- net::TestURLRequest protected_request(GURL("http://clients1.google.com"),
- NULL, &context, NULL);
- deltas.clear();
- request_data = WebRequestData(&protected_request, ON_BEFORE_REQUEST);
- // Note that we just updated the request_data reference in apply_info.
- action_set->Apply("ext1", base::Time(), &apply_info);
- EXPECT_EQ(0u, deltas.size());
+TEST_F(WebRequestActionWithThreadsTest, PermissionsToRemoveResponseHeader) {
+ const char kAction[] =
+ "[{"
+ " \"instanceType\": \"declarativeWebRequest.RemoveResponseHeader\","
+ " \"name\": \"testname\""
+ "}]";
+ CheckActionNeedsAllUrls(kAction, ON_HEADERS_RECEIVED);
+}
+
+TEST_F(WebRequestActionWithThreadsTest, PermissionsToSendMessageToExtension) {
+ const char kAction[] =
+ "[{"
+ " \"instanceType\": \"declarativeWebRequest.SendMessageToExtension\","
+ " \"message\": \"testtext\""
+ "}]";
+ scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(kAction));
+
+ // For sending messages, specific host permissions actually matter.
+ EXPECT_TRUE(ActionWorksOnRequest("http://test.com",
+ extension_->id(),
+ action_set.get(),
+ ON_BEFORE_REQUEST));
+ // With the "<all_urls>" host permission they are allowed.
+ EXPECT_TRUE(ActionWorksOnRequest("http://test.com",
+ extension_all_urls_->id(),
+ action_set.get(),
+ ON_BEFORE_REQUEST));
+
+ // The protected URLs should not be touched at all.
+ EXPECT_FALSE(ActionWorksOnRequest("http://clients1.google.com",
+ extension_->id(),
+ action_set.get(),
+ ON_BEFORE_REQUEST));
+ EXPECT_FALSE(ActionWorksOnRequest("http://clients1.google.com",
+ extension_all_urls_->id(),
+ action_set.get(),
+ ON_BEFORE_REQUEST));
+}
+
+TEST_F(WebRequestActionWithThreadsTest, PermissionsToAddRequestCookie) {
+ const char kAction[] =
+ "[{"
+ " \"instanceType\": \"declarativeWebRequest.AddRequestCookie\","
+ " \"cookie\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
+ "}]";
+ CheckActionNeedsAllUrls(kAction, ON_BEFORE_SEND_HEADERS);
+}
+
+TEST_F(WebRequestActionWithThreadsTest, PermissionsToAddResponseCookie) {
+ const char kAction[] =
+ "[{"
+ " \"instanceType\": \"declarativeWebRequest.AddResponseCookie\","
+ " \"cookie\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
+ "}]";
+ CheckActionNeedsAllUrls(kAction, ON_HEADERS_RECEIVED);
+}
+
+TEST_F(WebRequestActionWithThreadsTest, PermissionsToEditRequestCookie) {
+ const char kAction[] =
+ "[{"
+ " \"instanceType\": \"declarativeWebRequest.EditRequestCookie\","
+ " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" },"
+ " \"modification\": { \"name\": \"name2\", \"value\": \"value2\" }"
+ "}]";
+ CheckActionNeedsAllUrls(kAction, ON_BEFORE_SEND_HEADERS);
+}
+
+TEST_F(WebRequestActionWithThreadsTest, PermissionsToEditResponseCookie) {
+ const char kAction[] =
+ "[{"
+ " \"instanceType\": \"declarativeWebRequest.EditResponseCookie\","
+ " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" },"
+ " \"modification\": { \"name\": \"name2\", \"value\": \"value2\" }"
+ "}]";
+ CheckActionNeedsAllUrls(kAction, ON_HEADERS_RECEIVED);
+}
+
+TEST_F(WebRequestActionWithThreadsTest, PermissionsToRemoveRequestCookie) {
+ const char kAction[] =
+ "[{"
+ " \"instanceType\": \"declarativeWebRequest.RemoveRequestCookie\","
+ " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
+ "}]";
+ CheckActionNeedsAllUrls(kAction, ON_BEFORE_SEND_HEADERS);
+}
+
+TEST_F(WebRequestActionWithThreadsTest, PermissionsToRemoveResponseCookie) {
+ const char kAction[] =
+ "[{"
+ " \"instanceType\": \"declarativeWebRequest.RemoveResponseCookie\","
+ " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
+ "}]";
+ CheckActionNeedsAllUrls(kAction, ON_HEADERS_RECEIVED);
+}
+
+TEST_F(WebRequestActionWithThreadsTest, PermissionsToCancel) {
+ const char kAction[] =
+ "[{"
+ " \"instanceType\": \"declarativeWebRequest.CancelRequest\""
+ "}]";
+ scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(kAction));
+
+ // Cancelling requests works without full host permissions.
+ EXPECT_TRUE(ActionWorksOnRequest("http://test.org",
+ extension_->id(),
+ action_set.get(),
+ ON_BEFORE_REQUEST));
+}
+
+TEST_F(WebRequestActionWithThreadsTest,
+ PermissionsToRedirectToTransparentImage) {
+ const char kAction[] =
+ "[{"
+ " \"instanceType\": \"declarativeWebRequest.RedirectToTransparentImage\""
+ "}]";
+ scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(kAction));
+
+ // Redirecting to transparent images works without full host permissions.
+ EXPECT_TRUE(ActionWorksOnRequest("http://test.org",
+ extension_->id(),
+ action_set.get(),
+ ON_BEFORE_REQUEST));
+}
+
+TEST_F(WebRequestActionWithThreadsTest, PermissionsToRedirectToEmptyDocument) {
+ const char kAction[] =
+ "[{"
+ " \"instanceType\": \"declarativeWebRequest.RedirectToEmptyDocument\""
+ "}]";
+ scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(kAction));
+
+ // Redirecting to the empty document works without full host permissions.
+ EXPECT_TRUE(ActionWorksOnRequest("http://test.org",
+ extension_->id(),
+ action_set.get(),
+ ON_BEFORE_REQUEST));
+}
+
+TEST_F(WebRequestActionWithThreadsTest, PermissionsToIgnore) {
+ const char kAction[] =
+ "[{"
+ " \"instanceType\": \"declarativeWebRequest.IgnoreRules\","
+ " \"lowerPriorityThan\": 123,"
+ " \"hasTag\": \"some_tag\""
+ "}]";
+ scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(kAction));
+
+ // Ignoring rules works without full host permissions.
+ EXPECT_TRUE(ActionWorksOnRequest("http://test.org",
+ extension_->id(),
+ action_set.get(),
+ ON_BEFORE_REQUEST));
+}
+
+TEST(WebRequestActionTest, GetName) {
+ const char kActions[] =
+ "[{"
+ " \"instanceType\": \"declarativeWebRequest.RedirectRequest\","
+ " \"redirectUrl\": \"http://www.foobar.com\""
+ "},"
+ "{"
+ " \"instanceType\": \"declarativeWebRequest.RedirectByRegEx\","
+ " \"from\": \".*\","
+ " \"to\": \"http://www.foobar.com\""
+ "},"
+ "{"
+ " \"instanceType\": \"declarativeWebRequest.SetRequestHeader\","
+ " \"name\": \"testname\","
+ " \"value\": \"testvalue\""
+ "},"
+ "{"
+ " \"instanceType\": \"declarativeWebRequest.RemoveRequestHeader\","
+ " \"name\": \"testname\""
+ "},"
+ "{"
+ " \"instanceType\": \"declarativeWebRequest.AddResponseHeader\","
+ " \"name\": \"testname\","
+ " \"value\": \"testvalue\""
+ "},"
+ "{"
+ " \"instanceType\": \"declarativeWebRequest.RemoveResponseHeader\","
+ " \"name\": \"testname\""
+ "},"
+ "{"
+ " \"instanceType\": \"declarativeWebRequest.SendMessageToExtension\","
+ " \"message\": \"testtext\""
+ "},"
+ "{"
+ " \"instanceType\": \"declarativeWebRequest.AddRequestCookie\","
+ " \"cookie\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
+ "},"
+ "{"
+ " \"instanceType\": \"declarativeWebRequest.AddResponseCookie\","
+ " \"cookie\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
+ "},"
+ "{"
+ " \"instanceType\": \"declarativeWebRequest.EditRequestCookie\","
+ " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" },"
+ " \"modification\": { \"name\": \"name2\", \"value\": \"value2\" }"
+ "},"
+ "{"
+ " \"instanceType\": \"declarativeWebRequest.EditResponseCookie\","
+ " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" },"
+ " \"modification\": { \"name\": \"name2\", \"value\": \"value2\" }"
+ "},"
+ "{"
+ " \"instanceType\": \"declarativeWebRequest.RemoveRequestCookie\","
+ " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
+ "},"
+ "{"
+ " \"instanceType\": \"declarativeWebRequest.RemoveResponseCookie\","
+ " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
+ "},"
+ "{"
+ " \"instanceType\": \"declarativeWebRequest.CancelRequest\""
+ "},"
+ "{"
+ " \"instanceType\": \"declarativeWebRequest.RedirectToTransparentImage\""
+ "},"
+ "{"
+ " \"instanceType\": \"declarativeWebRequest.RedirectToEmptyDocument\""
+ "},"
+ "{"
+ " \"instanceType\": \"declarativeWebRequest.IgnoreRules\","
+ " \"lowerPriorityThan\": 123,"
+ " \"hasTag\": \"some_tag\""
+ "}]";
+ scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(kActions));
+ for (WebRequestActionSet::Actions::const_iterator it =
+ action_set->actions().begin();
+ it != action_set->actions().end();
+ ++it) {
+ EXPECT_THAT((*it)->GetName(), HasSubstr("declarativeWebRequest."));
+ }
}
} // namespace extensions
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 0a0cc71..2fdee62 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.cc
@@ -8,17 +8,26 @@
#include <limits>
#include <utility>
+#include "base/bind.h"
#include "base/stl_util.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_system.h"
+#include "chrome/common/extensions/extension.h"
+#include "extensions/common/error_utils.h"
#include "net/url_request/url_request.h"
namespace {
-const char kActionCannotBeExecuted[] = "An action can never be executed "
+
+const char kActionCannotBeExecuted[] = "The action '*' can never be executed "
"because there are is no time in the request life-cycle during which the "
"conditions can be checked and the action can possibly be executed.";
+
+const char kAllURLsPermissionNeeded[] =
+ "To execute the action '*', you need to request host permission for all "
+ "hosts.";
+
} // namespace
namespace extensions {
@@ -145,16 +154,19 @@ std::string WebRequestRulesRegistry::AddRulesImpl(
std::string error;
RulesMap new_webrequest_rules;
+ const Extension* extension =
+ extension_info_map_->extensions().GetByID(extension_id);
for (std::vector<linked_ptr<RulesRegistry::Rule> >::const_iterator rule =
rules.begin(); rule != rules.end(); ++rule) {
WebRequestRule::GlobalRuleId rule_id(extension_id, *(*rule)->id);
DCHECK(webrequest_rules_.find(rule_id) == webrequest_rules_.end());
- scoped_ptr<WebRequestRule> webrequest_rule(
- WebRequestRule::Create(url_matcher_.condition_factory(), extension_id,
- extension_installation_time, *rule,
- &CheckConsistency, &error));
+ scoped_ptr<WebRequestRule> webrequest_rule(WebRequestRule::Create(
+ url_matcher_.condition_factory(),
+ extension_id, extension_installation_time, *rule,
+ base::Bind(&Checker, base::Unretained(extension)),
+ &error));
if (!error.empty()) {
// We don't return here, because we want to clear temporary
// condition sets in the url_matcher_.
@@ -200,9 +212,6 @@ std::string WebRequestRulesRegistry::AddRulesImpl(
ClearCacheOnNavigation();
if (profile_id_ && !webrequest_rules_.empty()) {
- const Extension* extension =
- extension_info_map_->extensions().GetByID(extension_id);
-
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&extension_web_request_api_helpers::NotifyWebRequestAPIUsed,
@@ -280,9 +289,6 @@ WebRequestRulesRegistry::~WebRequestRulesRegistry() {}
base::Time WebRequestRulesRegistry::GetExtensionInstallationTime(
const std::string& extension_id) const {
- if (!extension_info_map_.get()) // May be NULL during testing.
- return base::Time();
-
return extension_info_map_->GetInstallTime(extension_id);
}
@@ -291,35 +297,70 @@ void WebRequestRulesRegistry::ClearCacheOnNavigation() {
}
// static
-bool WebRequestRulesRegistry::CheckConsistency(
- const WebRequestConditionSet* conditions,
+bool WebRequestRulesRegistry::Checker(const Extension* extension,
+ const WebRequestConditionSet* conditions,
+ const WebRequestActionSet* actions,
+ std::string* error) {
+ return (StageChecker(conditions, actions, error) &&
+ HostPermissionsChecker(extension, actions, error));
+}
+
+// static
+bool WebRequestRulesRegistry::HostPermissionsChecker(
+ const Extension* extension,
const WebRequestActionSet* actions,
std::string* error) {
- // Actions and conditions can be checked and executed in specific phases
- // of each web request. We consider a rule inconsistent if there is an action
- // that cannot be triggered by any condition.
+ if (extension->HasEffectiveAccessToAllHosts())
+ return true;
+
+ // Without the permission for all URLs, actions with the STRATEGY_DEFAULT
+ // should not be registered, they would never be able to execute.
for (WebRequestActionSet::Actions::const_iterator action_iter =
actions->actions().begin();
action_iter != actions->actions().end();
++action_iter) {
- bool found_matching_condition = false;
- for (WebRequestConditionSet::Conditions::const_iterator condition_iter =
- conditions->conditions().begin();
- condition_iter != conditions->conditions().end() &&
- !found_matching_condition;
- ++condition_iter) {
- // Test the intersection of bit masks, this is intentionally & and not &&.
- if ((*action_iter)->GetStages() & (*condition_iter)->stages())
- found_matching_condition = true;
- }
- if (!found_matching_condition) {
- *error = kActionCannotBeExecuted;
+ if ((*action_iter)->host_permissions_strategy() ==
+ WebRequestAction::STRATEGY_DEFAULT) {
+ *error = ErrorUtils::FormatErrorMessage(kAllURLsPermissionNeeded,
+ (*action_iter)->GetName());
return false;
}
}
return true;
}
+// static
+bool WebRequestRulesRegistry::StageChecker(
+ const WebRequestConditionSet* conditions,
+ const WebRequestActionSet* actions,
+ std::string* error) {
+ // Actions and conditions can be checked and executed in specific stages
+ // of each web request. A rule is inconsistent if there is an action that
+ // can only be triggered in stages in which no condition can be evaluated.
+
+ // In which stages there are conditions to evaluate.
+ int condition_stages = 0;
+ for (WebRequestConditionSet::Conditions::const_iterator condition_iter =
+ conditions->conditions().begin();
+ condition_iter != conditions->conditions().end();
+ ++condition_iter) {
+ condition_stages |= (*condition_iter)->stages();
+ }
+
+ for (WebRequestActionSet::Actions::const_iterator action_iter =
+ actions->actions().begin();
+ action_iter != actions->actions().end();
+ ++action_iter) {
+ // Test the intersection of bit masks, this is intentionally & and not &&.
+ if ((*action_iter)->GetStages() & condition_stages)
+ continue;
+ // We only get here if no matching condition was found.
+ *error = ErrorUtils::FormatErrorMessage(kActionCannotBeExecuted,
+ (*action_iter)->GetName());
+ return false;
+ }
+ return true;
+}
void WebRequestRulesRegistry::AddTriggeredRules(
const URLMatches& url_matches,
const WebRequestCondition::MatchData& request_data,
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 91d0cdf..99dbd3d 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h
@@ -11,6 +11,7 @@
#include <string>
#include <vector>
+#include "base/gtest_prod_util.h"
#include "base/time.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
@@ -107,19 +108,20 @@ class WebRequestRulesRegistry : public RulesRegistryWithCache {
const std::string& extension_id) const;
virtual void ClearCacheOnNavigation();
+ void SetExtensionInfoMapForTesting(
+ scoped_refptr<ExtensionInfoMap> extension_info_map) {
+ extension_info_map_ = extension_info_map;
+ }
+
const std::set<const WebRequestRule*>&
rules_with_untriggered_conditions_for_test() const {
return rules_with_untriggered_conditions_;
}
private:
- // Checks whether the set of |conditions| and |actions| are consistent,
- // meaning for example that we do not allow combining an |action| that needs
- // to be executed before the |condition| can be fulfilled.
- // Returns true in case of consistency and MUST set |error| otherwise.
- static bool CheckConsistency(const WebRequestConditionSet* conditions,
- const WebRequestActionSet* actions,
- std::string* error);
+ FRIEND_TEST_ALL_PREFIXES(WebRequestRulesRegistrySimpleTest, StageChecker);
+ FRIEND_TEST_ALL_PREFIXES(WebRequestRulesRegistrySimpleTest,
+ HostPermissionsChecker);
typedef std::map<URLMatcherConditionSet::ID, WebRequestRule*> RuleTriggers;
typedef std::map<WebRequestRule::GlobalRuleId, linked_ptr<WebRequestRule> >
@@ -127,6 +129,25 @@ class WebRequestRulesRegistry : public RulesRegistryWithCache {
typedef std::set<URLMatcherConditionSet::ID> URLMatches;
typedef std::set<const WebRequestRule*> RuleSet;
+ // This bundles all consistency checkers. Returns true in case of consistency
+ // and MUST set |error| otherwise.
+ static bool Checker(const Extension* extension,
+ const WebRequestConditionSet* conditions,
+ const WebRequestActionSet* actions,
+ std::string* error);
+
+ // Check that the |extension| has host permissions for all URLs if actions
+ // requiring them are present.
+ static bool HostPermissionsChecker(const Extension* extension,
+ const WebRequestActionSet* actions,
+ std::string* error);
+
+ // Check that every action is applicable in the same request stage as at
+ // least one condition.
+ static bool StageChecker(const WebRequestConditionSet* conditions,
+ const WebRequestActionSet* actions,
+ std::string* error);
+
// This is a helper function to GetMatches. Rules triggered by |url_matches|
// get added to |result| if one of their conditions is fulfilled.
// |request_data| gets passed to IsFulfilled of the rules' condition sets.
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 250d2c8..22a34c9 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
@@ -16,6 +16,7 @@
#include "base/values.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/common/extensions/extension_test_util.h"
#include "content/public/test/test_browser_thread.h"
#include "extensions/common/matcher/url_matcher_constants.h"
#include "net/url_request/url_request_test_util.h"
@@ -34,6 +35,9 @@ const char kRuleId4[] = "rule4";
namespace extensions {
+using base::Value;
+using extension_test_util::LoadManifest;
+using extension_test_util::LoadManifestUnchecked;
using testing::HasSubstr;
namespace helpers = extension_web_request_api_helpers;
@@ -42,9 +46,11 @@ namespace keys2 = url_matcher_constants;
class TestWebRequestRulesRegistry : public WebRequestRulesRegistry {
public:
- TestWebRequestRulesRegistry()
- : WebRequestRulesRegistry(NULL, NULL),
- num_clear_cache_calls_(0) {}
+ explicit TestWebRequestRulesRegistry(
+ scoped_refptr<ExtensionInfoMap> extension_info_map)
+ : WebRequestRulesRegistry(NULL, NULL), num_clear_cache_calls_(0) {
+ SetExtensionInfoMapForTesting(extension_info_map);
+ }
// Returns how often the in-memory caches of the renderers were instructed
// to be cleared.
@@ -59,16 +65,6 @@ class TestWebRequestRulesRegistry : public WebRequestRulesRegistry {
protected:
virtual ~TestWebRequestRulesRegistry() {}
- virtual base::Time GetExtensionInstallationTime(
- const std::string& extension_id) const OVERRIDE {
- if (extension_id == kExtensionId)
- return base::Time() + base::TimeDelta::FromDays(1);
- else if (extension_id == kExtensionId2)
- return base::Time() + base::TimeDelta::FromDays(2);
- else
- return base::Time();
- }
-
virtual void ClearCacheOnNavigation() OVERRIDE {
++num_clear_cache_calls_;
}
@@ -86,6 +82,8 @@ class WebRequestRulesRegistryTest : public testing::Test {
virtual ~WebRequestRulesRegistryTest() {}
+ virtual void SetUp() OVERRIDE;
+
virtual void TearDown() OVERRIDE {
// Make sure that deletion traits of all registries are executed.
message_loop.RunUntilIdle();
@@ -223,11 +221,47 @@ class WebRequestRulesRegistryTest : public testing::Test {
MessageLoop message_loop;
content::TestBrowserThread ui;
content::TestBrowserThread io;
+ // Two extensions with host permissions for all URLs and the DWR permission.
+ // Installation times will be so that |extension_| is older than
+ // |extension2_|.
+ scoped_refptr<Extension> extension_;
+ scoped_refptr<Extension> extension2_;
+ scoped_refptr<ExtensionInfoMap> extension_info_map_;
};
+void WebRequestRulesRegistryTest::SetUp() {
+ testing::Test::SetUp();
+
+ std::string error;
+ extension_ = LoadManifestUnchecked("permissions",
+ "web_request_all_host_permissions.json",
+ Manifest::INVALID_LOCATION,
+ Extension::NO_FLAGS,
+ kExtensionId,
+ &error);
+ ASSERT_TRUE(extension_) << error;
+ extension2_ =
+ LoadManifestUnchecked("permissions",
+ "web_request_all_host_permissions.json",
+ Manifest::INVALID_LOCATION,
+ Extension::NO_FLAGS,
+ kExtensionId2,
+ &error);
+ ASSERT_TRUE(extension2_) << error;
+ extension_info_map_ = new ExtensionInfoMap;
+ ASSERT_TRUE(extension_info_map_);
+ extension_info_map_->AddExtension(extension_.get(),
+ base::Time() + base::TimeDelta::FromDays(1),
+ false /*incognito_enabled*/);
+ extension_info_map_->AddExtension(extension2_.get(),
+ base::Time() + base::TimeDelta::FromDays(2),
+ false /*incognito_enabled*/);
+}
+
+
TEST_F(WebRequestRulesRegistryTest, AddRulesImpl) {
scoped_refptr<TestWebRequestRulesRegistry> registry(
- new TestWebRequestRulesRegistry());
+ new TestWebRequestRulesRegistry(extension_info_map_));
std::string error;
std::vector<linked_ptr<RulesRegistry::Rule> > rules;
@@ -266,7 +300,7 @@ TEST_F(WebRequestRulesRegistryTest, AddRulesImpl) {
TEST_F(WebRequestRulesRegistryTest, RemoveRulesImpl) {
scoped_refptr<TestWebRequestRulesRegistry> registry(
- new TestWebRequestRulesRegistry());
+ new TestWebRequestRulesRegistry(extension_info_map_));
std::string error;
// Setup RulesRegistry to contain two rules.
@@ -314,7 +348,7 @@ TEST_F(WebRequestRulesRegistryTest, RemoveRulesImpl) {
TEST_F(WebRequestRulesRegistryTest, RemoveAllRulesImpl) {
scoped_refptr<TestWebRequestRulesRegistry> registry(
- new TestWebRequestRulesRegistry());
+ new TestWebRequestRulesRegistry(extension_info_map_));
std::string error;
// Setup RulesRegistry to contain two rules, one for each extension.
@@ -366,7 +400,7 @@ TEST_F(WebRequestRulesRegistryTest, RemoveAllRulesImpl) {
// Test precedences between extensions.
TEST_F(WebRequestRulesRegistryTest, Precedences) {
scoped_refptr<WebRequestRulesRegistry> registry(
- new TestWebRequestRulesRegistry());
+ new TestWebRequestRulesRegistry(extension_info_map_));
std::string error;
std::vector<linked_ptr<RulesRegistry::Rule> > rules_to_add_1(1);
@@ -409,7 +443,7 @@ TEST_F(WebRequestRulesRegistryTest, Precedences) {
// Test priorities of rules within one extension.
TEST_F(WebRequestRulesRegistryTest, Priorities) {
scoped_refptr<WebRequestRulesRegistry> registry(
- new TestWebRequestRulesRegistry());
+ new TestWebRequestRulesRegistry(extension_info_map_));
std::string error;
std::vector<linked_ptr<RulesRegistry::Rule> > rules_to_add_1(1);
@@ -495,7 +529,7 @@ TEST_F(WebRequestRulesRegistryTest, IgnoreRulesByTag) {
ASSERT_TRUE(RulesRegistry::Rule::Populate(*value2, rules[1].get()));
scoped_refptr<WebRequestRulesRegistry> registry(
- new TestWebRequestRulesRegistry());
+ new TestWebRequestRulesRegistry(extension_info_map_));
std::string error = registry->AddRulesImpl(kExtensionId, rules);
EXPECT_EQ("", error);
EXPECT_FALSE(registry->IsEmpty());
@@ -517,7 +551,7 @@ TEST_F(WebRequestRulesRegistryTest, IgnoreRulesByTag) {
// GetMatches.
TEST_F(WebRequestRulesRegistryTest, GetMatchesCheckFulfilled) {
scoped_refptr<TestWebRequestRulesRegistry> registry(
- new TestWebRequestRulesRegistry());
+ new TestWebRequestRulesRegistry(extension_info_map_));
const std::string kMatchingUrlAttribute(
"\"url\": { \"pathContains\": \"\" }, \n");
const std::string kNonMatchingNonUrlAttribute(
@@ -565,7 +599,7 @@ TEST_F(WebRequestRulesRegistryTest, GetMatchesCheckFulfilled) {
// differ.
TEST_F(WebRequestRulesRegistryTest, GetMatchesDifferentUrls) {
scoped_refptr<TestWebRequestRulesRegistry> registry(
- new TestWebRequestRulesRegistry());
+ new TestWebRequestRulesRegistry(extension_info_map_));
const std::string kUrlAttribute(
"\"url\": { \"hostContains\": \"url\" }, \n");
const std::string kFirstPartyUrlAttribute(
@@ -622,7 +656,7 @@ TEST_F(WebRequestRulesRegistryTest, GetMatchesDifferentUrls) {
}
}
-TEST_F(WebRequestRulesRegistryTest, CheckConsistency) {
+TEST(WebRequestRulesRegistrySimpleTest, StageChecker) {
// The contentType condition can only be evaluated during ON_HEADERS_RECEIVED
// but the redirect action can only be executed during ON_BEFORE_REQUEST.
// Therefore, this is an inconsistent rule that needs to be flagged.
@@ -646,19 +680,73 @@ TEST_F(WebRequestRulesRegistryTest, CheckConsistency) {
"} ";
scoped_ptr<Value> value(base::JSONReader::Read(kRule));
- ASSERT_TRUE(value.get());
+ ASSERT_TRUE(value);
- std::vector<linked_ptr<RulesRegistry::Rule> > rules;
- rules.push_back(make_linked_ptr(new RulesRegistry::Rule));
- ASSERT_TRUE(RulesRegistry::Rule::Populate(*value, rules.back().get()));
-
- scoped_refptr<WebRequestRulesRegistry> registry(
- new TestWebRequestRulesRegistry());
+ RulesRegistry::Rule rule;
+ ASSERT_TRUE(RulesRegistry::Rule::Populate(*value, &rule));
+ std::string error;
URLMatcher matcher;
- std::string error = registry->AddRulesImpl(kExtensionId, rules);
+ scoped_ptr<WebRequestConditionSet> conditions =
+ WebRequestConditionSet::Create(
+ matcher.condition_factory(), rule.conditions, &error);
+ ASSERT_TRUE(error.empty()) << error;
+ ASSERT_TRUE(conditions);
+
+ bool bad_message = false;
+ scoped_ptr<WebRequestActionSet> actions =
+ WebRequestActionSet::Create(rule.actions, &error, &bad_message);
+ ASSERT_TRUE(error.empty()) << error;
+ ASSERT_FALSE(bad_message);
+ ASSERT_TRUE(actions);
+
+ EXPECT_FALSE(WebRequestRulesRegistry::StageChecker(
+ conditions.get(), actions.get(), &error));
EXPECT_THAT(error, HasSubstr("no time in the request life-cycle"));
- EXPECT_TRUE(registry->IsEmpty());
+ EXPECT_THAT(error, HasSubstr(actions->actions().back()->GetName()));
+}
+
+TEST(WebRequestRulesRegistrySimpleTest, HostPermissionsChecker) {
+ const char kAction[] = // This action requires all URLs host permission.
+ "{ \n"
+ " \"instanceType\": \"declarativeWebRequest.RedirectRequest\",\n"
+ " \"redirectUrl\": \"http://bar.com\" \n"
+ "} ";
+ scoped_ptr<Value> action_value(base::JSONReader::Read(kAction));
+ ASSERT_TRUE(action_value);
+
+ WebRequestActionSet::AnyVector actions;
+ actions.push_back(linked_ptr<base::Value>(action_value.release()));
+ ASSERT_TRUE(actions.back().get());
+
+ std::string error;
+ bool bad_message = false;
+ scoped_ptr<WebRequestActionSet> action_set(
+ WebRequestActionSet::Create(actions, &error, &bad_message));
+ ASSERT_TRUE(error.empty()) << error;
+ ASSERT_FALSE(bad_message);
+ ASSERT_TRUE(action_set);
+
+ scoped_refptr<Extension> extension_no_url(
+ LoadManifest("permissions", "web_request_no_host.json"));
+ scoped_refptr<Extension> extension_some_urls(
+ LoadManifest("permissions", "web_request_com_host_permissions.json"));
+ scoped_refptr<Extension> extension_all_urls(
+ LoadManifest("permissions", "web_request_all_host_permissions.json"));
+
+ EXPECT_TRUE(WebRequestRulesRegistry::HostPermissionsChecker(
+ extension_all_urls.get(), action_set.get(), &error));
+ EXPECT_TRUE(error.empty()) << error;
+
+ EXPECT_FALSE(WebRequestRulesRegistry::HostPermissionsChecker(
+ extension_some_urls.get(), action_set.get(), &error));
+ EXPECT_THAT(error, HasSubstr("permission for all"));
+ EXPECT_THAT(error, HasSubstr(action_set->actions().back()->GetName()));
+
+ EXPECT_FALSE(WebRequestRulesRegistry::HostPermissionsChecker(
+ extension_no_url.get(), action_set.get(), &error));
+ EXPECT_THAT(error, HasSubstr("permission for all"));
+ EXPECT_THAT(error, HasSubstr(action_set->actions().back()->GetName()));
}
TEST_F(WebRequestRulesRegistryTest, CheckOriginAndPathRegEx) {
@@ -688,7 +776,7 @@ TEST_F(WebRequestRulesRegistryTest, CheckOriginAndPathRegEx) {
ASSERT_TRUE(RulesRegistry::Rule::Populate(*value, rules.back().get()));
scoped_refptr<WebRequestRulesRegistry> registry(
- new TestWebRequestRulesRegistry());
+ new TestWebRequestRulesRegistry(extension_info_map_));
URLMatcher matcher;
std::string error = registry->AddRulesImpl(kExtensionId, rules);
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 27ef5a3..260bff4 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_api.cc
@@ -1288,7 +1288,8 @@ void ExtensionWebRequestEventRouter::GetMatchingListenersImpl(
continue;
if (!WebRequestPermissions::CanExtensionAccessURL(
- extension_info_map, it->extension_id, url, crosses_incognito, true))
+ extension_info_map, it->extension_id, url, crosses_incognito,
+ WebRequestPermissions::REQUIRE_HOST_PERMISSION))
continue;
bool blocking_listener =
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 2f53bb5..200e12d 100644
--- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -159,17 +159,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
<< message_;
}
-IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
- WebRequestDeclarativePermissions) {
- ExtensionTestMessageListener listener("rules all registered", false);
- ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
- "webrequest/permissionless")));
- EXPECT_TRUE(listener.WaitUntilSatisfied());
- ASSERT_TRUE(RunExtensionSubtest(
- "webrequest", "test_declarative_permissions.html")) <<
- message_;
-}
-
void ExtensionWebRequestApiTest::RunPermissionTest(
const char* extension_directory,
bool load_extension_with_incognito_permission,
diff --git a/chrome/browser/extensions/api/web_request/web_request_permissions.cc b/chrome/browser/extensions/api/web_request/web_request_permissions.cc
index 9baaef4..cf981c9 100644
--- a/chrome/browser/extensions/api/web_request/web_request_permissions.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_permissions.cc
@@ -97,7 +97,7 @@ bool WebRequestPermissions::CanExtensionAccessURL(
const std::string& extension_id,
const GURL& url,
bool crosses_incognito,
- bool enforce_host_permissions) {
+ HostPermissionsCheck host_permissions_check) {
// extension_info_map can be NULL in testing.
if (!extension_info_map)
return true;
@@ -111,13 +111,21 @@ bool WebRequestPermissions::CanExtensionAccessURL(
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;
+ switch (host_permissions_check) {
+ case DO_NOT_CHECK_HOST:
+ break;
+ case REQUIRE_HOST_PERMISSION:
+ // about: URLs are not covered in host permissions, but are allowed
+ // anyway.
+ if (!((url.SchemeIs(chrome::kAboutScheme) ||
+ extension->HasHostPermission(url) ||
+ url.GetOrigin() == extension->url())))
+ return false;
+ break;
+ case REQUIRE_ALL_URLS:
+ if (!extension->HasEffectiveAccessToAllHosts())
+ return false;
+ break;
}
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
index 1d1297c..6ff0f43 100644
--- a/chrome/browser/extensions/api/web_request/web_request_permissions.h
+++ b/chrome/browser/extensions/api/web_request/web_request_permissions.h
@@ -20,15 +20,25 @@ class URLRequest;
// This class is used to test whether extensions may modify web requests.
class WebRequestPermissions {
public:
+ // Different host permission checking modes for CanExtensionAccessURL.
+ enum HostPermissionsCheck {
+ DO_NOT_CHECK_HOST = 0, // No check.
+ REQUIRE_HOST_PERMISSION, // Permission needed for given URL.
+ REQUIRE_ALL_URLS // Permission needed for <all_urls>.
+ };
+
// Returns true if the request shall not be reported to extensions.
static bool HideRequest(const ExtensionInfoMap* extension_info_map,
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);
+ // |host_permission_check| controls how permissions are checked with regard to
+ // |url|.
+ static bool CanExtensionAccessURL(
+ const ExtensionInfoMap* extension_info_map,
+ const std::string& extension_id,
+ const GURL& url,
+ bool crosses_incognito,
+ HostPermissionsCheck host_permissions_check);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(WebRequestPermissions);
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
index 0a59184..357c0d5 100644
--- a/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc
@@ -7,12 +7,67 @@
#include "base/message_loop.h"
#include "chrome/browser/extensions/extension_info_map.h"
#include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/extensions/extension_manifest_constants.h"
+#include "chrome/common/extensions/extension_test_util.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/resource_request_info.h"
+#include "content/public/test/test_browser_thread.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
using content::ResourceRequestInfo;
+using extensions::Extension;
+using extensions::Manifest;
+using extension_test_util::LoadManifestUnchecked;
+
+class ExtensionWebRequestHelpersTestWithThreadsTest : public testing::Test {
+ public:
+ ExtensionWebRequestHelpersTestWithThreadsTest()
+ : io_thread_(content::BrowserThread::IO, &message_loop_) {}
+
+ protected:
+ virtual void SetUp() OVERRIDE;
+
+ protected:
+ net::TestURLRequestContext context;
+
+ // This extension has Web Request permissions, but no host permission.
+ scoped_refptr<Extension> permissionless_extension_;
+ // This extension has Web Request permissions, and *.com a host permission.
+ scoped_refptr<Extension> com_extension_;
+ scoped_refptr<ExtensionInfoMap> extension_info_map_;
+
+ private:
+ MessageLoopForIO message_loop_;
+ content::TestBrowserThread io_thread_;
+};
+
+void ExtensionWebRequestHelpersTestWithThreadsTest::SetUp() {
+ testing::Test::SetUp();
+
+ std::string error;
+ permissionless_extension_ = LoadManifestUnchecked("permissions",
+ "web_request_no_host.json",
+ Manifest::INVALID_LOCATION,
+ Extension::NO_FLAGS,
+ "ext_id_1",
+ &error);
+ ASSERT_TRUE(permissionless_extension_) << error;
+ com_extension_ =
+ LoadManifestUnchecked("permissions",
+ "web_request_com_host_permissions.json",
+ Manifest::INVALID_LOCATION,
+ Extension::NO_FLAGS,
+ "ext_id_2",
+ &error);
+ ASSERT_TRUE(com_extension_) << error;
+ extension_info_map_ = new ExtensionInfoMap;
+ extension_info_map_->AddExtension(permissionless_extension_.get(),
+ base::Time::Now(),
+ false /*incognito_enabled*/);
+ extension_info_map_->AddExtension(
+ com_extension_.get(), base::Time::Now(), false /*incognito_enabled*/);
+}
TEST(ExtensionWebRequestHelpersTest, TestHideRequestForURL) {
MessageLoopForIO message_loop;
@@ -71,3 +126,34 @@ TEST(ExtensionWebRequestHelpersTest, TestHideRequestForURL) {
EXPECT_TRUE(WebRequestPermissions::HideRequest(extension_info_map.get(),
&sensitive_request));
}
+
+TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest,
+ TestCanExtensionAccessURL_HostPermissions) {
+ net::TestURLRequest request(
+ GURL("http://example.com"), NULL, &context, NULL);
+
+ EXPECT_TRUE(WebRequestPermissions::CanExtensionAccessURL(
+ extension_info_map_,
+ permissionless_extension_->id(),
+ request.url(),
+ false /*crosses_incognito*/,
+ WebRequestPermissions::DO_NOT_CHECK_HOST));
+ EXPECT_FALSE(WebRequestPermissions::CanExtensionAccessURL(
+ extension_info_map_,
+ permissionless_extension_->id(),
+ request.url(),
+ false /*crosses_incognito*/,
+ WebRequestPermissions::REQUIRE_HOST_PERMISSION));
+ EXPECT_TRUE(WebRequestPermissions::CanExtensionAccessURL(
+ extension_info_map_,
+ com_extension_->id(),
+ request.url(),
+ false /*crosses_incognito*/,
+ WebRequestPermissions::REQUIRE_HOST_PERMISSION));
+ EXPECT_FALSE(WebRequestPermissions::CanExtensionAccessURL(
+ extension_info_map_,
+ com_extension_->id(),
+ request.url(),
+ false /*crosses_incognito*/,
+ WebRequestPermissions::REQUIRE_ALL_URLS));
+}
diff --git a/chrome/browser/extensions/permissions_updater_unittest.cc b/chrome/browser/extensions/permissions_updater_unittest.cc
index ea5c48f..8552b61 100644
--- a/chrome/browser/extensions/permissions_updater_unittest.cc
+++ b/chrome/browser/extensions/permissions_updater_unittest.cc
@@ -14,6 +14,7 @@
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_test_util.h"
#include "chrome/common/extensions/permissions/permission_set.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/notification_observer.h"
@@ -21,6 +22,8 @@
#include "content/public/browser/notification_service.h"
#include "testing/gtest/include/gtest/gtest.h"
+using extension_test_util::LoadManifest;
+
namespace extensions {
namespace {
@@ -87,24 +90,15 @@ class PermissionsUpdaterListener : public content::NotificationObserver {
class PermissionsUpdaterTest : public ExtensionServiceTestBase {
};
-scoped_refptr<Extension> LoadManifest(std::string* error) {
+scoped_refptr<Extension> LoadOurManifest() {
base::FilePath path;
- PathService::Get(chrome::DIR_TEST_DATA, &path);
- path = path.AppendASCII("extensions")
- .AppendASCII("api_test")
+ path = path.AppendASCII("api_test")
.AppendASCII("permissions")
- .AppendASCII("optional")
- .AppendASCII("manifest.json");
-
- JSONFileValueSerializer serializer(path);
- scoped_ptr<Value> result(serializer.Deserialize(NULL, error));
- if (!result)
- return NULL;
-
- scoped_refptr<Extension> extension = Extension::Create(
- path.DirName(), Manifest::INTERNAL,
- *static_cast<DictionaryValue*>(result.get()), Extension::NO_FLAGS, error);
- return extension;
+ .AppendASCII("optional");
+ return LoadManifest(path.AsUTF8Unsafe(),
+ "manifest.json",
+ Manifest::INTERNAL,
+ Extension::NO_FLAGS);
}
void AddPattern(URLPatternSet* extent, const std::string& pattern) {
@@ -122,9 +116,8 @@ TEST_F(PermissionsUpdaterTest, AddAndRemovePermissions) {
InitializeEmptyExtensionService();
// Load the test extension.
- std::string error;
- scoped_refptr<Extension> extension = LoadManifest(&error);
- ASSERT_TRUE(error.empty()) << error;
+ scoped_refptr<Extension> extension = LoadOurManifest();
+ ASSERT_TRUE(extension.get());
APIPermissionSet default_apis;
default_apis.insert(APIPermission::kManagement);
diff --git a/chrome/common/extensions/docs/templates/intros/declarativeWebRequest.html b/chrome/common/extensions/docs/templates/intros/declarativeWebRequest.html
index c9a295f..154699d 100644
--- a/chrome/common/extensions/docs/templates/intros/declarativeWebRequest.html
+++ b/chrome/common/extensions/docs/templates/intros/declarativeWebRequest.html
@@ -14,8 +14,7 @@ efficiency.
<p>
You must declare the "declarativeWebRequest" permission in the
<a href="manifest.html">extension manifest</a> to use this API,
-along with <a href="declare_permissions.html">host permissions</a> for any
-hosts whose network requests you want to access.
+along with <a href="declare_permissions.html">host permissions</a>.
</p>
<pre>{
@@ -29,18 +28,33 @@ hosts whose network requests you want to access.
}</pre>
<p>
-Note that certain types of non-sensitive requests do not require host
+Note that certain types of non-sensitive actions do not require host
permissions:
<ul>
<li><code>CancelRequest</code>
<li><code>IgnoreRules</code>
<li><code>RedirectToEmptyDocument</code>
<li><code>RedirectToTransparentImage</code>
- <li><code>RedirectByRegEx</code> when the redirect destination has
- the same domain as the original request
- <li><code>RedirectRequest</code> when the redirect destination has
- the same domain as the original request
</ul>
+</p>
+<p>
+The <code>SendMessageToExtension</code> action requires host permissions
+for any hosts whose network requests you want to trigger a message.
+</p>
+<p>
+All other actions require host permissions to all URLs.
+</p>
+<p>
+As an example, if <code>"*://*.google.com"</code> is the only host permission an
+extension has, than such an extension may set up a rule to
+<ul>
+ <li> cancel a request to "http://www.google.com" or "http://anything.else.com"
+ <li> send a message when navigating to "http://www.google.com" but not to
+"http://something.else.com"
+</ul>
+The extension cannot set up a rule to redirect "http://www.google.com" to
+"http://mail.google.com".
+</p>
<h2 id="rules">Rules</h2>
diff --git a/chrome/common/extensions/extension_test_util.cc b/chrome/common/extensions/extension_test_util.cc
index 621db1e..b9b0425 100644
--- a/chrome/common/extensions/extension_test_util.cc
+++ b/chrome/common/extensions/extension_test_util.cc
@@ -2,13 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "chrome/common/extensions/extension_test_util.h"
+
+#include "base/files/file_path.h"
+#include "base/json/json_file_value_serializer.h"
+#include "base/path_service.h"
#include "base/values.h"
+#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_manifest_constants.h"
-#include "chrome/common/extensions/extension_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
using extensions::Extension;
+using extensions::Manifest;
namespace extension_test_util {
@@ -21,4 +27,65 @@ scoped_refptr<Extension> CreateExtensionWithID(std::string id) {
values, Extension::NO_FLAGS, id, &error);
}
+scoped_refptr<Extension> LoadManifestUnchecked(const std::string& dir,
+ const std::string& test_file,
+ Manifest::Location location,
+ int extra_flags,
+ const std::string& id,
+ std::string* error) {
+ base::FilePath path;
+ PathService::Get(chrome::DIR_TEST_DATA, &path);
+ path = path.AppendASCII("extensions")
+ .AppendASCII(dir)
+ .AppendASCII(test_file);
+
+ JSONFileValueSerializer serializer(path);
+ scoped_ptr<Value> result(serializer.Deserialize(NULL, error));
+ if (!result)
+ return NULL;
+ const DictionaryValue* dict;
+ CHECK(result->GetAsDictionary(&dict));
+
+ scoped_refptr<Extension> extension = Extension::Create(
+ path.DirName(), location, *dict, extra_flags, id, error);
+ return extension;
+}
+
+scoped_refptr<Extension> LoadManifestUnchecked(const std::string& dir,
+ const std::string& test_file,
+ Manifest::Location location,
+ int extra_flags,
+ std::string* error) {
+ return LoadManifestUnchecked(
+ dir, test_file, location, extra_flags, std::string(), error);
+}
+
+scoped_refptr<Extension> LoadManifest(const std::string& dir,
+ const std::string& test_file,
+ Manifest::Location location,
+ int extra_flags) {
+ std::string error;
+ scoped_refptr<Extension> extension =
+ LoadManifestUnchecked(dir, test_file, location, extra_flags, &error);
+
+ EXPECT_TRUE(extension) << test_file << ":" << error;
+ return extension;
+}
+
+scoped_refptr<Extension> LoadManifest(const std::string& dir,
+ const std::string& test_file,
+ int extra_flags) {
+ return LoadManifest(dir, test_file, Manifest::INVALID_LOCATION, extra_flags);
+}
+
+scoped_refptr<Extension> LoadManifestStrict(const std::string& dir,
+ const std::string& test_file) {
+ return LoadManifest(dir, test_file, Extension::NO_FLAGS);
+}
+
+scoped_refptr<Extension> LoadManifest(const std::string& dir,
+ const std::string& test_file) {
+ return LoadManifest(dir, test_file, Extension::NO_FLAGS);
+}
+
} // namespace extension_test_util
diff --git a/chrome/common/extensions/extension_test_util.h b/chrome/common/extensions/extension_test_util.h
index a549d98..278f514 100644
--- a/chrome/common/extensions/extension_test_util.h
+++ b/chrome/common/extensions/extension_test_util.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/memory/ref_counted.h"
+#include "chrome/common/extensions/manifest.h"
namespace extensions {
class Extension;
@@ -21,6 +22,40 @@ std::string MakeId(std::string seed);
// Return a very simple extension with id |id|.
scoped_refptr<extensions::Extension> CreateExtensionWithID(std::string id);
+// Helpers for loading manifests, |dir| is relative to chrome::DIR_TEST_DATA
+// followed by "extensions".
+scoped_refptr<extensions::Extension> LoadManifestUnchecked(
+ const std::string& dir,
+ const std::string& test_file,
+ extensions::Manifest::Location location,
+ int extra_flags,
+ const std::string& id,
+ std::string* error);
+
+scoped_refptr<extensions::Extension> LoadManifestUnchecked(
+ const std::string& dir,
+ const std::string& test_file,
+ extensions::Manifest::Location location,
+ int extra_flags,
+ std::string* error);
+
+scoped_refptr<extensions::Extension> LoadManifest(
+ const std::string& dir,
+ const std::string& test_file,
+ extensions::Manifest::Location location,
+ int extra_flags);
+
+scoped_refptr<extensions::Extension> LoadManifest(const std::string& dir,
+ const std::string& test_file,
+ int extra_flags);
+
+scoped_refptr<extensions::Extension> LoadManifestStrict(
+ const std::string& dir,
+ const std::string& test_file);
+
+scoped_refptr<extensions::Extension> LoadManifest(const std::string& dir,
+ const std::string& test_file);
+
} // namespace extension_test_util
#endif // CHROME_COMMON_EXTENSIONS_EXTENSION_TEST_UTIL_H_
diff --git a/chrome/common/extensions/extension_unittest.cc b/chrome/common/extensions/extension_unittest.cc
index c426c2a..62ef7eb 100644
--- a/chrome/common/extensions/extension_unittest.cc
+++ b/chrome/common/extensions/extension_unittest.cc
@@ -6,9 +6,7 @@
#include "base/command_line.h"
#include "base/file_util.h"
-#include "base/files/file_path.h"
#include "base/format_macros.h"
-#include "base/json/json_file_value_serializer.h"
#include "base/path_service.h"
#include "base/stringprintf.h"
#include "base/strings/string_number_conversions.h"
@@ -21,6 +19,7 @@
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_file_util.h"
#include "chrome/common/extensions/extension_manifest_constants.h"
+#include "chrome/common/extensions/extension_test_util.h"
#include "chrome/common/extensions/features/feature.h"
#include "chrome/common/extensions/incognito_handler.h"
#include "chrome/common/extensions/manifest.h"
@@ -45,67 +44,15 @@
#include "ui/gfx/codec/png_codec.h"
using content::SocketPermissionRequest;
+using extension_test_util::LoadManifest;
+using extension_test_util::LoadManifestUnchecked;
+using extension_test_util::LoadManifestStrict;
namespace keys = extension_manifest_keys;
namespace values = extension_manifest_values;
namespace errors = extension_manifest_errors;
namespace extensions {
-namespace {
-
-scoped_refptr<Extension> LoadManifestUnchecked(
- const std::string& dir,
- const std::string& test_file,
- Manifest::Location location,
- int extra_flags,
- std::string* error) {
- base::FilePath path;
- PathService::Get(chrome::DIR_TEST_DATA, &path);
- path = path.AppendASCII("extensions")
- .AppendASCII(dir)
- .AppendASCII(test_file);
-
- JSONFileValueSerializer serializer(path);
- scoped_ptr<Value> result(serializer.Deserialize(NULL, error));
- if (!result.get())
- return NULL;
-
- scoped_refptr<Extension> extension = Extension::Create(
- path.DirName(), location, *static_cast<DictionaryValue*>(result.get()),
- extra_flags, error);
- return extension;
-}
-
-static scoped_refptr<Extension> LoadManifest(const std::string& dir,
- const std::string& test_file,
- Manifest::Location location,
- int extra_flags) {
- std::string error;
- scoped_refptr<Extension> extension = LoadManifestUnchecked(dir, test_file,
- location, extra_flags, &error);
-
- EXPECT_TRUE(extension) << test_file << ":" << error;
- return extension;
-}
-
-static scoped_refptr<Extension> LoadManifest(const std::string& dir,
- const std::string& test_file,
- int extra_flags) {
- return LoadManifest(dir, test_file, Manifest::INVALID_LOCATION, extra_flags);
-}
-
-static scoped_refptr<Extension> LoadManifest(const std::string& dir,
- const std::string& test_file) {
- return LoadManifest(dir, test_file, Extension::NO_FLAGS);
-}
-
-static scoped_refptr<Extension> LoadManifestStrict(
- const std::string& dir,
- const std::string& test_file) {
- return LoadManifest(dir, test_file, Extension::NO_FLAGS);
-}
-
-} // namespace
ExtensionTest::ExtensionTest() : permissions_info_(ChromeAPIPermissions()) {}
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc
index 73cef12..2b99187 100644
--- a/chrome/common/extensions/permissions/permission_set_unittest.cc
+++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -11,6 +11,7 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/api/plugins/plugins_handler.h"
#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_test_util.h"
#include "chrome/common/extensions/extension_unittest.h"
#include "chrome/common/extensions/features/feature.h"
#include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h"
@@ -20,39 +21,12 @@
#include "extensions/common/error_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
+using extension_test_util::LoadManifest;
+
namespace extensions {
namespace {
-scoped_refptr<Extension> LoadManifest(const std::string& dir,
- const std::string& test_file,
- int extra_flags) {
- base::FilePath path;
- PathService::Get(chrome::DIR_TEST_DATA, &path);
- path = path.AppendASCII("extensions")
- .AppendASCII(dir)
- .AppendASCII(test_file);
-
- JSONFileValueSerializer serializer(path);
- std::string error;
- scoped_ptr<Value> result(serializer.Deserialize(NULL, &error));
- if (!result.get()) {
- EXPECT_EQ("", error);
- return NULL;
- }
-
- scoped_refptr<Extension> extension = Extension::Create(
- path.DirName(), Manifest::INVALID_LOCATION,
- *static_cast<DictionaryValue*>(result.get()), extra_flags, &error);
- EXPECT_TRUE(extension) << error;
- return extension;
-}
-
-scoped_refptr<Extension> LoadManifest(const std::string& dir,
- const std::string& test_file) {
- return LoadManifest(dir, test_file, Extension::NO_FLAGS);
-}
-
static void AddPattern(URLPatternSet* extent, const std::string& pattern) {
int schemes = URLPattern::SCHEME_ALL;
extent->AddPattern(URLPattern(schemes, pattern));
diff --git a/chrome/test/data/extensions/api_test/declarative/api/manifest.json b/chrome/test/data/extensions/api_test/declarative/api/manifest.json
index 3e0f3fd..8c1bbd9 100644
--- a/chrome/test/data/extensions/api_test/declarative/api/manifest.json
+++ b/chrome/test/data/extensions/api_test/declarative/api/manifest.json
@@ -7,6 +7,6 @@
"scripts": ["background.js"]
},
"permissions": [
- "declarativeWebRequest"
+ "declarativeWebRequest", "<all_urls>"
]
}
diff --git a/chrome/test/data/extensions/api_test/webrequest/manifest.json b/chrome/test/data/extensions/api_test/webrequest/manifest.json
index 6cf7d40..3ecf7a3 100644
--- a/chrome/test/data/extensions/api_test/webrequest/manifest.json
+++ b/chrome/test/data/extensions/api_test/webrequest/manifest.json
@@ -4,8 +4,7 @@
"manifest_version": 2,
"description": "Tests the webRequest API.",
"permissions": ["webRequest", "webRequestBlocking", "tabs",
- "declarativeWebRequest", "http://*.a.com/*", "https://*.a.com/*",
- "http://non_existing_third_party.com/image.png"],
+ "declarativeWebRequest", "<all_urls>"],
"web_accessible_resources": [
"simpleLoad/a.html",
"complexLoad/a.html",
diff --git a/chrome/test/data/extensions/api_test/webrequest/permissionless/manifest.json b/chrome/test/data/extensions/api_test/webrequest/permissionless/manifest.json
deleted file mode 100644
index c0f2c25..0000000
--- a/chrome/test/data/extensions/api_test/webrequest/permissionless/manifest.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "name": "declarativeWebRequest rules without host permissions",
- "description": "Helper test extension for declarative webRequest; declare rules affecting hosts without having permissions on them.",
- "version": "1",
- "manifest_version": 2,
- "permissions": ["declarativeWebRequest", "http://*.c.com/*"],
- "background": {
- "scripts": ["rules.js"]
- }
-}
diff --git a/chrome/test/data/extensions/api_test/webrequest/permissionless/rules.js b/chrome/test/data/extensions/api_test/webrequest/permissionless/rules.js
deleted file mode 100644
index 32b0ff8..0000000
--- a/chrome/test/data/extensions/api_test/webrequest/permissionless/rules.js
+++ /dev/null
@@ -1,50 +0,0 @@
-// 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.
-
-// See ../test_declarative_permissions.js for the tests that use these rules.
-
-var onRequest = chrome.declarativeWebRequest.onRequest;
-var RequestMatcher = chrome.declarativeWebRequest.RequestMatcher;
-
-chrome.test.getConfig(function(config) {
- addRules(config.testServer.port);
-});
-
-function addRules(testServerPort) {
- onRequest.addRules(
- [{conditions: [new RequestMatcher({
- url: {hostSuffix: '.a.com',
- schemes: ['https']}})],
- actions: [new chrome.declarativeWebRequest.RedirectRequest({
- redirectUrl: 'http://www.a.com:' + testServerPort +
- '/files/nonexistent/redirected' })]
- },
- {conditions: [new RequestMatcher({
- url: {hostSuffix: '.a.com',
- pathSuffix: '/b.html'}})],
- actions: [new chrome.declarativeWebRequest.RedirectRequest({
- redirectUrl: 'http://www.c.com:' + testServerPort +
- '/files/nonexistent/redirected' })]
- },
- {conditions: [new RequestMatcher({
- url: {hostSuffix: '.a.com',
- pathSuffix: '/fake.html'}})],
- actions: [new chrome.declarativeWebRequest.RedirectByRegEx({
- from: '(.*)fake(.*)', to: '$1b$2'
- })]
- },
-
- {conditions: [new RequestMatcher({url: {pathContains: 'blank'}})],
- actions: [new chrome.declarativeWebRequest.RedirectToEmptyDocument()]
- },
- {conditions: [new RequestMatcher({url: {pathContains: 'cancel'}})],
- actions: [new chrome.declarativeWebRequest.CancelRequest()]
- }],
- function(rules) {
- if (chrome.runtime.lastError)
- chrome.test.fail(chrome.runtime.lastError);
- chrome.test.sendMessage("rules all registered");
- }
- );
-}
diff --git a/chrome/test/data/extensions/api_test/webrequest/test_declarative2.js b/chrome/test/data/extensions/api_test/webrequest/test_declarative2.js
index be4b114..b2c9609 100644
--- a/chrome/test/data/extensions/api_test/webrequest/test_declarative2.js
+++ b/chrome/test/data/extensions/api_test/webrequest/test_declarative2.js
@@ -254,42 +254,6 @@ runTests([
);
},
- function testPermission() {
- // Test that a redirect is ignored if the extension has no permission.
- // we load a.html from a.com and issue an XHR to b.com, which is not
- // contained in the extension's host permissions. Therefore, we cannot
- // redirect the XHR from b.com to a.com, and the request returns the
- // original file from b.com.
- ignoreUnexpected = true;
- expect();
- onRequest.addRules(
- [ {'conditions': [new RequestMatcher({'url': {'pathContains': ".json"}})],
- 'actions': [
- new RedirectRequest({'redirectUrl': getURLHttpSimple()})]}
- ],
- function() {
- var callback = chrome.test.callbackAdded();
- navigateAndWait(getURL("simpleLoad/a.html"), function() {
- var asynchronous = false;
- var req = new XMLHttpRequest();
- req.onreadystatechange = function() {
- if (this.readyState != this.DONE)
- return;
- // "{}" is the contents of the file at getURLHttpXHRData().
- if (this.status == 200 && this.responseText == "{}\n") {
- callback();
- } else {
- chrome.test.fail("Redirect was not prevented. Status: " +
- this.status + ", responseText: " + this.responseText);
- }
- };
- req.open("GET", getURLHttpXHRData(), asynchronous);
- req.send();
- });
- }
- );
- },
-
function testRequestHeaders() {
ignoreUnexpected = true;
expect(
diff --git a/chrome/test/data/extensions/api_test/webrequest/test_declarative_permissions.html b/chrome/test/data/extensions/api_test/webrequest/test_declarative_permissions.html
deleted file mode 100644
index 9300144..0000000
--- a/chrome/test/data/extensions/api_test/webrequest/test_declarative_permissions.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<script src="framework.js"></script>
-<script src="test_declarative_permissions.js"></script>
diff --git a/chrome/test/data/extensions/api_test/webrequest/test_declarative_permissions.js b/chrome/test/data/extensions/api_test/webrequest/test_declarative_permissions.js
deleted file mode 100644
index 9609a34..0000000
--- a/chrome/test/data/extensions/api_test/webrequest/test_declarative_permissions.js
+++ /dev/null
@@ -1,126 +0,0 @@
-// 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.
-
-// See permissionless/rules.js for the rules that this test uses.
-
-runTests([
- // Test that it's possible to redirect within the same domain and port
- // (ignoring the scheme) without host permissions.
- function testRedirectSameDomain() {
- ignoreUnexpected = true;
- var testURL = getServerURL(
- 'files/extensions/api_test/webrequest/simpleLoad/a.html',
- 'www.a.com', 'https');
- expect(
- [
- { label: 'onBeforeRedirect',
- event: 'onBeforeRedirect',
- details: {
- url: testURL,
- redirectUrl: getServerURL('files/nonexistent/redirected'),
- statusCode: -1,
- statusLine: '',
- fromCache: false,
- }
- },
- ],
- [ ['onBeforeRedirect'] ]
- );
- navigateAndWait(testURL);
- },
-
- // Test that it's not possible to redirect to a different domain
- // without host permissions on the original domain. We should still
- // load the original URL.
- function testCannotRedirectDifferentDomains() {
- ignoreUnexpected = true;
- var testURL = getServerURL(
- 'files/extensions/api_test/webrequest/simpleLoad/b.html');
- expect(
- [
- { label: 'onCompleted',
- event: 'onCompleted',
- details: {
- url: testURL,
- fromCache: false,
- ip: '127.0.0.1',
- statusCode: 200,
- statusLine: 'HTTP/1.0 200 OK',
- }
- },
- ],
- [ ['onCompleted'] ]
- );
- navigateAndWait(testURL);
- },
-
- // Test that it's possible to redirect by regex within the same
- // domain and port (ignoring the scheme) without host permissions.
- function testRedirectByRegexSameDomain() {
- ignoreUnexpected = true;
- var testURL = getServerURL(
- 'files/extensions/api_test/webrequest/simpleLoad/fake.html');
- expect(
- [
- { label: 'onBeforeRedirect',
- event: 'onBeforeRedirect',
- details: {
- url: testURL,
- redirectUrl: getServerURL(
- 'files/extensions/api_test/webrequest/simpleLoad/b.html'),
- statusCode: -1,
- statusLine: '',
- fromCache: false,
- }
- },
- ],
- [ ['onBeforeRedirect'] ]
- );
- navigateAndWait(testURL);
- },
-
- // Test that it's possible to redirect to a blank page/image
- // without host permissions.
- function testRedirectToEmpty() {
- var testURL = getServerURL('files/nonexistent/blank.html');
- ignoreUnexpected = true;
- expect(
- [
- { label: 'onBeforeRedirect',
- event: 'onBeforeRedirect',
- details: {
- url: testURL,
- redirectUrl: 'data:text/html,',
- statusCode: -1,
- statusLine: '',
- fromCache: false,
- }
- },
- ],
- [ ['onBeforeRedirect'] ]
- );
- navigateAndWait(testURL);
- },
-
- // Test that it's possible to cancel a request without host permissions.
- function testCancelRequest() {
- ignoreUnexpected = true;
- var testURL = getServerURL('files/nonexistent/cancel.html');
- expect(
- [
- { label: 'onErrorOccurred',
- event: 'onErrorOccurred',
- details: {
- url: testURL,
- fromCache: false,
- error: 'net::ERR_BLOCKED_BY_CLIENT'
- }
- },
- ],
- [ ['onErrorOccurred'] ]
- );
- navigateAndWait(testURL);
- },
-
-]);
diff --git a/chrome/test/data/extensions/api_test/webrequest/test_simple.js b/chrome/test/data/extensions/api_test/webrequest/test_simple.js
index b3a1a08..0db4373 100644
--- a/chrome/test/data/extensions/api_test/webrequest/test_simple.js
+++ b/chrome/test/data/extensions/api_test/webrequest/test_simple.js
@@ -11,12 +11,6 @@ function getURLHttpSimpleLoadRedirect() {
return getServerURL('server-redirect?'+getURLHttpSimpleLoad());
}
-// A URL from b.com, which we don't have permission to access.
-function getURLNotVisible() {
- return getServerURL('files/extensions/api_test/webrequest/simpleLoad/b.html',
- 'b.com');
-}
-
runTests([
// Navigates to a blank page.
function simpleLoad() {
@@ -188,44 +182,4 @@ runTests([
["onBeforeRequest", "onErrorOccurred"] ]);
navigateAndWait(getURL("does_not_exist.html"));
},
-
- // Navigates to a page that we don't have access to, then a blank page.
- // We should not see the first navigation.
- function simpleLoadNonVisible() {
- expect(
- [ // events
- { label: "a-onBeforeRequest",
- event: "onBeforeRequest",
- details: {
- url: getURL("simpleLoad/a.html"),
- frameUrl: getURL("simpleLoad/a.html")
- }
- },
- { label: "a-onResponseStarted",
- event: "onResponseStarted",
- details: {
- url: getURL("simpleLoad/a.html"),
- statusCode: 200,
- fromCache: false,
- statusLine: "HTTP/1.1 200 OK",
- // Request to chrome-extension:// url has no IP.
- }
- },
- { label: "a-onCompleted",
- event: "onCompleted",
- details: {
- url: getURL("simpleLoad/a.html"),
- statusCode: 200,
- fromCache: false,
- statusLine: "HTTP/1.1 200 OK",
- // Request to chrome-extension:// url has no IP.
- }
- },
- ],
- [ // event order
- ["a-onBeforeRequest", "a-onResponseStarted", "a-onCompleted"] ]);
- navigateAndWait(getURLNotVisible(), function() {
- navigateAndWait(getURL("simpleLoad/a.html"));
- });
- },
]);
diff --git a/chrome/test/data/extensions/permissions/web_request_all_host_permissions.json b/chrome/test/data/extensions/permissions/web_request_all_host_permissions.json
new file mode 100644
index 0000000..bdd0eae
--- /dev/null
+++ b/chrome/test/data/extensions/permissions/web_request_all_host_permissions.json
@@ -0,0 +1,5 @@
+{
+ "name": "Extension without full host permissions",
+ "version": "1.0",
+ "permissions": ["declarativeWebRequest", "webRequest", "webRequestBlocking", "*://*/*" ]
+}
diff --git a/chrome/test/data/extensions/permissions/web_request_com_host_permissions.json b/chrome/test/data/extensions/permissions/web_request_com_host_permissions.json
new file mode 100644
index 0000000..c035c4c
--- /dev/null
+++ b/chrome/test/data/extensions/permissions/web_request_com_host_permissions.json
@@ -0,0 +1,5 @@
+{
+ "name": "Extension without full host permissions",
+ "version": "1.0",
+ "permissions": ["declarativeWebRequest", "webRequest", "webRequestBlocking", "*://*.com/*" ]
+}
diff --git a/chrome/test/data/extensions/permissions/web_request_no_host.json b/chrome/test/data/extensions/permissions/web_request_no_host.json
new file mode 100644
index 0000000..9564dc1
--- /dev/null
+++ b/chrome/test/data/extensions/permissions/web_request_no_host.json
@@ -0,0 +1,5 @@
+{
+ "name": "Extension without host permissions but with full (D)WR permissions.",
+ "version": "1.0",
+ "permissions": ["declarativeWebRequest", "webRequest", "webRequestBlocking" ]
+}