summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbattre@chromium.org <battre@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-30 09:11:41 +0000
committerbattre@chromium.org <battre@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-30 09:11:41 +0000
commit8dc590b5e3165d31c730ae2f5cf8a2df0878f699 (patch)
tree75b62dfb7216b6fc28ef650aa9016c71e2b76ce7
parent1f7eba7875a15cc7318f3ce2c039e1ab5f31cd1d (diff)
downloadchromium_src-8dc590b5e3165d31c730ae2f5cf8a2df0878f699.zip
chromium_src-8dc590b5e3165d31c730ae2f5cf8a2df0878f699.tar.gz
chromium_src-8dc590b5e3165d31c730ae2f5cf8a2df0878f699.tar.bz2
Add support for response header manipulation in Declarative WebRequest API
BUG=112155 TEST=no Review URL: https://chromiumcodereview.appspot.com/10451071 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@139509 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc141
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h62
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.cc4
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h2
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.cc7
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.h11
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.cc5
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h5
-rw-r--r--chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc6
-rw-r--r--chrome/browser/extensions/api/web_request/web_request_api.cc75
-rw-r--r--chrome/browser/extensions/api/web_request/web_request_api.h11
-rw-r--r--chrome/common/extensions/api/declarative_web_request.json41
-rw-r--r--chrome/common/extensions/docs/declarativeWebRequest.html177
-rw-r--r--chrome/renderer/resources/extensions/declarative_webrequest_custom_bindings.js6
-rw-r--r--chrome/test/data/extensions/api_test/webrequest/test_declarative.js51
15 files changed, 561 insertions, 43 deletions
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc
index a6b5e0b..271afc1 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc
@@ -9,6 +9,7 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/stringprintf.h"
+#include "base/string_util.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/declarative_webrequest/request_stages.h"
#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h"
@@ -79,6 +80,30 @@ scoped_ptr<WebRequestAction> CreateRemoveRequestHeaderAction(
new WebRequestRemoveRequestHeaderAction(name));
}
+scoped_ptr<WebRequestAction> CreateAddResponseHeaderAction(
+ const base::DictionaryValue* dict,
+ std::string* error,
+ bool* bad_message) {
+ std::string name;
+ std::string value;
+ INPUT_FORMAT_VALIDATE(dict->GetString(keys::kNameKey, &name));
+ INPUT_FORMAT_VALIDATE(dict->GetString(keys::kValueKey, &value));
+ return scoped_ptr<WebRequestAction>(
+ new WebRequestAddResponseHeaderAction(name, value));
+}
+
+scoped_ptr<WebRequestAction> CreateRemoveResponseHeaderAction(
+ const base::DictionaryValue* dict,
+ std::string* error,
+ bool* bad_message) {
+ std::string name;
+ std::string value;
+ INPUT_FORMAT_VALIDATE(dict->GetString(keys::kNameKey, &name));
+ bool has_value = dict->GetString(keys::kValueKey, &value);
+ return scoped_ptr<WebRequestAction>(
+ new WebRequestRemoveResponseHeaderAction(name, value, has_value));
+}
+
scoped_ptr<WebRequestAction> CreateIgnoreRulesAction(
const base::DictionaryValue* dict,
std::string* error,
@@ -103,6 +128,8 @@ struct WebRequestActionFactory {
std::map<std::string, FactoryMethod> factory_methods;
WebRequestActionFactory() {
+ factory_methods[keys::kAddResponseHeaderType] =
+ &CreateAddResponseHeaderAction;
factory_methods[keys::kCancelRequestType] =
&CallConstructorFactoryMethod<WebRequestCancelAction>;
factory_methods[keys::kRedirectRequestType] =
@@ -116,6 +143,8 @@ struct WebRequestActionFactory {
&CreateSetRequestHeaderAction;
factory_methods[keys::kRemoveRequestHeaderType] =
&CreateRemoveRequestHeaderAction;
+ factory_methods[keys::kRemoveResponseHeaderType] =
+ &CreateRemoveResponseHeaderAction;
factory_methods[keys::kIgnoreRulesType] =
&CreateIgnoreRulesAction;
}
@@ -198,13 +227,15 @@ scoped_ptr<WebRequestActionSet> WebRequestActionSet::Create(
std::list<LinkedPtrEventResponseDelta> WebRequestActionSet::CreateDeltas(
net::URLRequest* request,
RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
const std::string& extension_id,
const base::Time& extension_install_time) const {
std::list<LinkedPtrEventResponseDelta> result;
for (Actions::const_iterator i = actions_.begin(); i != actions_.end(); ++i) {
if ((*i)->GetStages() & request_stage) {
LinkedPtrEventResponseDelta delta = (*i)->CreateDelta(request,
- request_stage, extension_id, extension_install_time);
+ request_stage, optional_request_data, extension_id,
+ extension_install_time);
if (delta.get())
result.push_back(delta);
}
@@ -240,6 +271,7 @@ WebRequestAction::Type WebRequestCancelAction::GetType() const {
LinkedPtrEventResponseDelta WebRequestCancelAction::CreateDelta(
net::URLRequest* request,
RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
const std::string& extension_id,
const base::Time& extension_install_time) const {
CHECK(request_stage & GetStages());
@@ -270,6 +302,7 @@ WebRequestAction::Type WebRequestRedirectAction::GetType() const {
LinkedPtrEventResponseDelta WebRequestRedirectAction::CreateDelta(
net::URLRequest* request,
RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
const std::string& extension_id,
const base::Time& extension_install_time) const {
CHECK(request_stage & GetStages());
@@ -305,6 +338,7 @@ LinkedPtrEventResponseDelta
WebRequestRedirectToTransparentImageAction::CreateDelta(
net::URLRequest* request,
RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
const std::string& extension_id,
const base::Time& extension_install_time) const {
CHECK(request_stage & GetStages());
@@ -338,6 +372,7 @@ LinkedPtrEventResponseDelta
WebRequestRedirectToEmptyDocumentAction::CreateDelta(
net::URLRequest* request,
RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
const std::string& extension_id,
const base::Time& extension_install_time) const {
CHECK(request_stage & GetStages());
@@ -374,6 +409,7 @@ LinkedPtrEventResponseDelta
WebRequestSetRequestHeaderAction::CreateDelta(
net::URLRequest* request,
RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
const std::string& extension_id,
const base::Time& extension_install_time) const {
CHECK(request_stage & GetStages());
@@ -408,6 +444,7 @@ LinkedPtrEventResponseDelta
WebRequestRemoveRequestHeaderAction::CreateDelta(
net::URLRequest* request,
RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
const std::string& extension_id,
const base::Time& extension_install_time) const {
CHECK(request_stage & GetStages());
@@ -419,6 +456,107 @@ WebRequestRemoveRequestHeaderAction::CreateDelta(
}
//
+// WebRequestAddResponseHeaderAction
+//
+
+WebRequestAddResponseHeaderAction::WebRequestAddResponseHeaderAction(
+ const std::string& name,
+ const std::string& value)
+ : name_(name),
+ value_(value) {
+}
+
+WebRequestAddResponseHeaderAction::~WebRequestAddResponseHeaderAction() {}
+
+int WebRequestAddResponseHeaderAction::GetStages() const {
+ return ON_HEADERS_RECEIVED;
+}
+
+WebRequestAction::Type
+WebRequestAddResponseHeaderAction::GetType() const {
+ return WebRequestAction::ACTION_ADD_RESPONSE_HEADER;
+}
+
+LinkedPtrEventResponseDelta
+WebRequestAddResponseHeaderAction::CreateDelta(
+ net::URLRequest* request,
+ RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
+ const std::string& extension_id,
+ const base::Time& extension_install_time) const {
+ CHECK(request_stage & GetStages());
+ LinkedPtrEventResponseDelta result(
+ new extension_web_request_api_helpers::EventResponseDelta(
+ extension_id, extension_install_time));
+
+ net::HttpResponseHeaders* headers =
+ optional_request_data.original_response_headers;
+ if (!headers)
+ return result;
+
+ // Don't generate the header if it exists already.
+ if (headers->HasHeaderValue(name_, value_))
+ return result;
+
+ result->added_response_headers.push_back(make_pair(name_, value_));
+ return result;
+}
+
+//
+// WebRequestRemoveResponseHeaderAction
+//
+
+WebRequestRemoveResponseHeaderAction::WebRequestRemoveResponseHeaderAction(
+ const std::string& name,
+ const std::string& value,
+ bool has_value)
+ : name_(name),
+ value_(value),
+ has_value_(has_value) {
+}
+
+WebRequestRemoveResponseHeaderAction::~WebRequestRemoveResponseHeaderAction() {}
+
+int WebRequestRemoveResponseHeaderAction::GetStages() const {
+ return ON_HEADERS_RECEIVED;
+}
+
+WebRequestAction::Type
+WebRequestRemoveResponseHeaderAction::GetType() const {
+ return WebRequestAction::ACTION_REMOVE_RESPONSE_HEADER;
+}
+
+LinkedPtrEventResponseDelta
+WebRequestRemoveResponseHeaderAction::CreateDelta(
+ net::URLRequest* request,
+ RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
+ const std::string& extension_id,
+ const base::Time& extension_install_time) const {
+ CHECK(request_stage & GetStages());
+ LinkedPtrEventResponseDelta result(
+ new extension_web_request_api_helpers::EventResponseDelta(
+ extension_id, extension_install_time));
+ net::HttpResponseHeaders* headers =
+ optional_request_data.original_response_headers;
+ if (!headers)
+ return result;
+ void* iter = NULL;
+ std::string current_value;
+ while (headers->EnumerateHeader(&iter, name_, &current_value)) {
+ if (has_value_ &&
+ (current_value.size() != value_.size() ||
+ !std::equal(current_value.begin(), current_value.end(),
+ value_.begin(),
+ base::CaseInsensitiveCompare<char>()))) {
+ continue;
+ }
+ result->deleted_response_headers.push_back(make_pair(name_, current_value));
+ }
+ return result;
+}
+
+//
// WebRequestIgnoreRulesAction
//
@@ -445,6 +583,7 @@ int WebRequestIgnoreRulesAction::GetMinimumPriority() const {
LinkedPtrEventResponseDelta WebRequestIgnoreRulesAction::CreateDelta(
net::URLRequest* request,
RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
const std::string& extension_id,
const base::Time& extension_install_time) const {
CHECK(request_stage & GetStages());
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h
index 73f37f5..5c8a6cb 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h
@@ -13,6 +13,7 @@
#include "base/compiler_specific.h"
#include "base/memory/linked_ptr.h"
#include "chrome/browser/extensions/api/declarative_webrequest/request_stages.h"
+#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.h"
#include "chrome/common/extensions/api/events.h"
#include "googleurl/src/gurl.h"
@@ -48,6 +49,8 @@ class WebRequestAction {
ACTION_REDIRECT_TO_EMPTY_DOCUMENT,
ACTION_SET_REQUEST_HEADER,
ACTION_REMOVE_REQUEST_HEADER,
+ ACTION_ADD_RESPONSE_HEADER,
+ ACTION_REMOVE_RESPONSE_HEADER,
ACTION_IGNORE_RULES,
};
@@ -80,6 +83,7 @@ class WebRequestAction {
virtual LinkedPtrEventResponseDelta CreateDelta(
net::URLRequest* request,
RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
const std::string& extension_id,
const base::Time& extension_install_time) const = 0;
};
@@ -109,6 +113,7 @@ class WebRequestActionSet {
std::list<LinkedPtrEventResponseDelta> CreateDeltas(
net::URLRequest* request,
RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
const std::string& extension_id,
const base::Time& extension_install_time) const;
@@ -140,6 +145,7 @@ class WebRequestCancelAction : public WebRequestAction {
virtual LinkedPtrEventResponseDelta CreateDelta(
net::URLRequest* request,
RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
const std::string& extension_id,
const base::Time& extension_install_time) const OVERRIDE;
@@ -159,6 +165,7 @@ class WebRequestRedirectAction : public WebRequestAction {
virtual LinkedPtrEventResponseDelta CreateDelta(
net::URLRequest* request,
RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
const std::string& extension_id,
const base::Time& extension_install_time) const OVERRIDE;
@@ -180,6 +187,7 @@ class WebRequestRedirectToTransparentImageAction : public WebRequestAction {
virtual LinkedPtrEventResponseDelta CreateDelta(
net::URLRequest* request,
RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
const std::string& extension_id,
const base::Time& extension_install_time) const OVERRIDE;
@@ -200,6 +208,7 @@ class WebRequestRedirectToEmptyDocumentAction : public WebRequestAction {
virtual LinkedPtrEventResponseDelta CreateDelta(
net::URLRequest* request,
RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
const std::string& extension_id,
const base::Time& extension_install_time) const OVERRIDE;
@@ -220,6 +229,7 @@ class WebRequestSetRequestHeaderAction : public WebRequestAction {
virtual LinkedPtrEventResponseDelta CreateDelta(
net::URLRequest* request,
RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
const std::string& extension_id,
const base::Time& extension_install_time) const OVERRIDE;
@@ -241,6 +251,7 @@ class WebRequestRemoveRequestHeaderAction : public WebRequestAction {
virtual LinkedPtrEventResponseDelta CreateDelta(
net::URLRequest* request,
RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
const std::string& extension_id,
const base::Time& extension_install_time) const OVERRIDE;
@@ -249,6 +260,54 @@ class WebRequestRemoveRequestHeaderAction : public WebRequestAction {
DISALLOW_COPY_AND_ASSIGN(WebRequestRemoveRequestHeaderAction);
};
+// Action that instructs to add a response header.
+class WebRequestAddResponseHeaderAction : public WebRequestAction {
+ public:
+ WebRequestAddResponseHeaderAction(const std::string& name,
+ const std::string& value);
+ virtual ~WebRequestAddResponseHeaderAction();
+
+ // Implementation of WebRequestAction:
+ virtual int GetStages() const OVERRIDE;
+ virtual Type GetType() const OVERRIDE;
+ virtual LinkedPtrEventResponseDelta CreateDelta(
+ net::URLRequest* request,
+ RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
+ const std::string& extension_id,
+ const base::Time& extension_install_time) const OVERRIDE;
+
+ private:
+ std::string name_;
+ std::string value_;
+ DISALLOW_COPY_AND_ASSIGN(WebRequestAddResponseHeaderAction);
+};
+
+// Action that instructs to remove a response header.
+class WebRequestRemoveResponseHeaderAction : public WebRequestAction {
+ public:
+ explicit WebRequestRemoveResponseHeaderAction(const std::string& name,
+ const std::string& value,
+ bool has_value);
+ virtual ~WebRequestRemoveResponseHeaderAction();
+
+ // Implementation of WebRequestAction:
+ virtual int GetStages() const OVERRIDE;
+ virtual Type GetType() const OVERRIDE;
+ virtual LinkedPtrEventResponseDelta CreateDelta(
+ net::URLRequest* request,
+ RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
+ const std::string& extension_id,
+ const base::Time& extension_install_time) const OVERRIDE;
+
+ private:
+ std::string name_;
+ std::string value_;
+ bool has_value_;
+ DISALLOW_COPY_AND_ASSIGN(WebRequestRemoveResponseHeaderAction);
+};
+
// Action that instructs to ignore rules below a certain priority.
class WebRequestIgnoreRulesAction : public WebRequestAction {
public:
@@ -262,6 +321,7 @@ class WebRequestIgnoreRulesAction : public WebRequestAction {
virtual LinkedPtrEventResponseDelta CreateDelta(
net::URLRequest* request,
RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data,
const std::string& extension_id,
const base::Time& extension_install_time) const OVERRIDE;
@@ -271,7 +331,7 @@ class WebRequestIgnoreRulesAction : public WebRequestAction {
};
// TODO(battre) Implement further actions:
-// Redirect to constant url, Redirect by RegEx, Set header, Remove header, ...
+// Redirect by RegEx, Cookie manipulations, ...
} // namespace extensions
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.cc
index ea51728..a6d2a6c 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.cc
@@ -20,6 +20,8 @@ const char kUrlKey[] = "url";
const char kValueKey[] = "value";
// Values of dictionaries, in particular instance types
+const char kAddResponseHeaderType[] =
+ "declarativeWebRequest.AddResponseHeader";
const char kCancelRequestType[] = "declarativeWebRequest.CancelRequest";
const char kIgnoreRulesType[] = "declarativeWebRequest.IgnoreRules";
const char kRedirectRequestType[] = "declarativeWebRequest.RedirectRequest";
@@ -29,6 +31,8 @@ const char kRedirectToTransparentImageType[] =
"declarativeWebRequest.RedirectToTransparentImage";
const char kRemoveRequestHeaderType[] =
"declarativeWebRequest.RemoveRequestHeader";
+const char kRemoveResponseHeaderType[] =
+ "declarativeWebRequest.RemoveResponseHeader";
const char kRequestMatcherType[] = "declarativeWebRequest.RequestMatcher";
const char kSetRequestHeaderType[] = "declarativeWebRequest.SetRequestHeader";
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h b/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h
index 14fb873..86984d0 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h
@@ -24,12 +24,14 @@ extern const char kUrlKey[];
extern const char kValueKey[];
// Values of dictionaries, in particular instance types
+extern const char kAddResponseHeaderType[];
extern const char kCancelRequestType[];
extern const char kIgnoreRulesType[];
extern const char kRedirectRequestType[];
extern const char kRedirectToEmptyDocumentType[];
extern const char kRedirectToTransparentImageType[];
extern const char kRemoveRequestHeaderType[];
+extern const char kRemoveResponseHeaderType[];
extern const char kRequestMatcherType[];
extern const char kSetRequestHeaderType[];
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.cc
index cac8386..1fc8e40 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.cc
@@ -87,9 +87,10 @@ scoped_ptr<WebRequestRule> WebRequestRule::Create(
std::list<LinkedPtrEventResponseDelta> WebRequestRule::CreateDeltas(
net::URLRequest* request,
- RequestStages request_stage) const {
- return actions_->CreateDeltas(request, request_stage, id_.first,
- extension_installation_time_);
+ RequestStages request_stage,
+ const OptionalRequestData& optional_request_data) const {
+ return actions_->CreateDeltas(request, request_stage, optional_request_data,
+ id_.first, extension_installation_time_);
}
int WebRequestRule::GetMinimumPriority() const {
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.h b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.h
index 5187688..d12e2fc 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.h
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.h
@@ -25,6 +25,7 @@ struct EventResponseDelta;
}
namespace net {
+class HttpResponseHeaders;
class URLRequest;
}
@@ -41,6 +42,13 @@ class WebRequestRule {
typedef std::pair<ExtensionId, RuleId> GlobalRuleId;
typedef int Priority;
+ // Container to pass additional information about requests that are not
+ // available in all request stages.
+ struct OptionalRequestData {
+ OptionalRequestData() : original_response_headers(NULL) {}
+ net::HttpResponseHeaders* original_response_headers;
+ };
+
WebRequestRule(const GlobalRuleId& id,
base::Time extension_installation_time,
scoped_ptr<WebRequestConditionSet> conditions,
@@ -64,7 +72,8 @@ class WebRequestRule {
std::list<LinkedPtrEventResponseDelta> CreateDeltas(
net::URLRequest* request,
- RequestStages request_stage) const;
+ RequestStages request_stage,
+ const OptionalRequestData& optional_request_data) const;
// Returns the minimum priority of rules that may be evaluated after
// this rule. Defaults to MAX_INT. Only valid if the conditions of this rule
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 2da96a7..ea2869a 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.cc
@@ -43,7 +43,8 @@ WebRequestRulesRegistry::GetMatches(net::URLRequest* request,
std::list<LinkedPtrEventResponseDelta> WebRequestRulesRegistry::CreateDeltas(
net::URLRequest* request,
- RequestStages request_stage) {
+ RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data) {
std::set<WebRequestRule::GlobalRuleId> matches =
GetMatches(request, request_stage);
@@ -93,7 +94,7 @@ std::list<LinkedPtrEventResponseDelta> WebRequestRulesRegistry::CreateDeltas(
continue;
std::list<LinkedPtrEventResponseDelta> rule_result =
- rule->CreateDeltas(request, request_stage);
+ rule->CreateDeltas(request, request_stage, optional_request_data);
result.splice(result.begin(), rule_result);
min_priorities[extension_id] = std::max(current_min_priority,
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h
index 3beff8f..b71406f 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h
@@ -33,7 +33,6 @@ class URLRequest;
namespace extensions {
class RulesRegistryService;
-class WebRequestRule;
// The WebRequestRulesRegistry is responsible for managing
// the internal representation of rules for the Declarative Web Request API.
@@ -76,7 +75,9 @@ class WebRequestRulesRegistry : public RulesRegistryWithCache {
// Returns which modifications should be executed on the network request
// according to the rules registered in this registry.
std::list<LinkedPtrEventResponseDelta> CreateDeltas(
- net::URLRequest* request, RequestStages request_stage);
+ net::URLRequest* request,
+ RequestStages request_stage,
+ const WebRequestRule::OptionalRequestData& optional_request_data);
// Implementation of RulesRegistryWithCache:
virtual std::string AddRulesImpl(
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 9020ed5..7d322b4 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
@@ -336,7 +336,8 @@ TEST_F(WebRequestRulesRegistryTest, Precedences) {
GURL url("http://www.google.com");
TestURLRequest request(url, NULL);
std::list<LinkedPtrEventResponseDelta> deltas =
- registry->CreateDeltas(&request, ON_BEFORE_REQUEST);
+ registry->CreateDeltas(&request, ON_BEFORE_REQUEST,
+ WebRequestRule::OptionalRequestData());
// The second extension is installed later and will win for this reason
// in conflict resolution.
@@ -382,7 +383,8 @@ TEST_F(WebRequestRulesRegistryTest, Priorities) {
GURL url("http://www.google.com/index.html");
TestURLRequest request(url, NULL);
std::list<LinkedPtrEventResponseDelta> deltas =
- registry->CreateDeltas(&request, ON_BEFORE_REQUEST);
+ registry->CreateDeltas(&request, ON_BEFORE_REQUEST,
+ WebRequestRule::OptionalRequestData());
// The redirect by the first extension is ignored due to the ignore rule.
ASSERT_EQ(1u, deltas.size());
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 e91e8e9..5a73e14 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_api.cc
@@ -16,6 +16,7 @@
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_content_browser_client.h"
+#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_rule.h"
#include "chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry.h"
#include "chrome/browser/extensions/api/web_request/web_request_api_constants.h"
#include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h"
@@ -488,7 +489,7 @@ int ExtensionWebRequestEventRouter::OnBeforeRequest(
bool initialize_blocked_requests = false;
initialize_blocked_requests |=
- ProcessDeclarativeRules(request, extensions::ON_BEFORE_REQUEST);
+ ProcessDeclarativeRules(request, extensions::ON_BEFORE_REQUEST, NULL);
int extra_info_spec = 0;
std::vector<const EventListener*> listeners =
@@ -536,7 +537,8 @@ int ExtensionWebRequestEventRouter::OnBeforeSendHeaders(
bool initialize_blocked_requests = false;
initialize_blocked_requests |=
- ProcessDeclarativeRules(request, extensions::ON_BEFORE_SEND_HEADERS);
+ ProcessDeclarativeRules(request, extensions::ON_BEFORE_SEND_HEADERS,
+ NULL);
int extra_info_spec = 0;
std::vector<const EventListener*> listeners =
@@ -616,40 +618,54 @@ int ExtensionWebRequestEventRouter::OnHeadersReceived(
if (!profile || helpers::HideRequestForURL(request->url()))
return net::OK;
+ bool initialize_blocked_requests = false;
+
+ initialize_blocked_requests |=
+ ProcessDeclarativeRules(request, extensions::ON_HEADERS_RECEIVED,
+ original_response_headers);
+
int extra_info_spec = 0;
std::vector<const EventListener*> listeners =
GetMatchingListeners(profile, extension_info_map,
keys::kOnHeadersReceived, request,
&extra_info_spec);
- if (listeners.empty())
- return net::OK;
-
- if (GetAndSetSignaled(request->identifier(), kOnHeadersReceived))
- return net::OK;
+ if (!listeners.empty() &&
+ !GetAndSetSignaled(request->identifier(), kOnHeadersReceived)) {
+ ListValue args;
+ DictionaryValue* dict = new DictionaryValue();
+ ExtractRequestInfo(request, dict);
+ dict->SetString(keys::kStatusLineKey,
+ original_response_headers->GetStatusLine());
+ if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
+ dict->Set(keys::kResponseHeadersKey,
+ GetResponseHeadersList(original_response_headers));
+ }
+ args.Append(dict);
- ListValue args;
- DictionaryValue* dict = new DictionaryValue();
- ExtractRequestInfo(request, dict);
- dict->SetString(keys::kStatusLineKey,
- original_response_headers->GetStatusLine());
- if (extra_info_spec & ExtraInfoSpec::RESPONSE_HEADERS) {
- dict->Set(keys::kResponseHeadersKey,
- GetResponseHeadersList(original_response_headers));
+ initialize_blocked_requests |=
+ DispatchEvent(profile, request, listeners, args);
}
- args.Append(dict);
- if (DispatchEvent(profile, request, listeners, args)) {
- blocked_requests_[request->identifier()].event = kOnHeadersReceived;
- blocked_requests_[request->identifier()].callback = callback;
- blocked_requests_[request->identifier()].net_log = &request->net_log();
- blocked_requests_[request->identifier()].override_response_headers =
- override_response_headers;
- blocked_requests_[request->identifier()].original_response_headers =
- original_response_headers;
+ if (!initialize_blocked_requests)
+ return net::OK; // Nobody saw a reason for modifying the request.
+
+ blocked_requests_[request->identifier()].event = kOnHeadersReceived;
+ blocked_requests_[request->identifier()].callback = callback;
+ blocked_requests_[request->identifier()].net_log = &request->net_log();
+ blocked_requests_[request->identifier()].override_response_headers =
+ override_response_headers;
+ blocked_requests_[request->identifier()].original_response_headers =
+ original_response_headers;
+
+ if (blocked_requests_[request->identifier()].num_handlers_blocking == 0) {
+ // If there are no blocking handlers, only the declarative rules tried
+ // to modify the request and we can respond synchronously.
+ return ExecuteDeltas(profile, request->identifier(),
+ false /* call_callback*/);
+ } else {
return net::ERR_IO_PENDING;
}
- return net::OK;
}
net::NetworkDelegate::AuthRequiredResponse
@@ -1384,7 +1400,8 @@ int ExtensionWebRequestEventRouter::ExecuteDeltas(
bool ExtensionWebRequestEventRouter::ProcessDeclarativeRules(
net::URLRequest* request,
- extensions::RequestStages request_stage) {
+ extensions::RequestStages request_stage,
+ net::HttpResponseHeaders* original_response_headers) {
if (!rules_registry_.get())
return false;
@@ -1393,8 +1410,12 @@ bool ExtensionWebRequestEventRouter::ProcessDeclarativeRules(
// TODO(battre): Annotate deltas with extension IDs, so that we can
// - Sort deltas by precedence
// - Check whether extensions have host permissions.
+ extensions::WebRequestRule::OptionalRequestData optional_request_data;
+ optional_request_data.original_response_headers =
+ original_response_headers;
std::list<linked_ptr<helpers::EventResponseDelta> > result =
- rules_registry_->CreateDeltas(request, request_stage);
+ rules_registry_->CreateDeltas(request, request_stage,
+ optional_request_data);
base::TimeDelta elapsed_time = start - base::Time::Now();
UMA_HISTOGRAM_TIMES("Extensions.DeclarativeWebRequestNetworkDelay",
diff --git a/chrome/browser/extensions/api/web_request/web_request_api.h b/chrome/browser/extensions/api/web_request/web_request_api.h
index ee7adf3..846381c 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api.h
+++ b/chrome/browser/extensions/api/web_request/web_request_api.h
@@ -330,10 +330,13 @@ class ExtensionWebRequestEventRouter {
// Evaluates the rules of the declarative webrequest API and stores
// modifications to the request that result from WebRequestActions as
- // deltas in |blocked_requests_|. Returns whether any deltas were
- // generated.
- bool ProcessDeclarativeRules(net::URLRequest* request,
- extensions::RequestStages request_stage);
+ // deltas in |blocked_requests_|. |original_response_headers| should only be
+ // set for the OnHeadersReceived stage and NULL otherwise. Returns whether any
+ // deltas were generated.
+ bool ProcessDeclarativeRules(
+ net::URLRequest* request,
+ extensions::RequestStages request_stage,
+ net::HttpResponseHeaders* original_response_headers);
// Sets the flag that |event_type| has been signaled for |request_id|.
// Returns the value of the flag before setting it.
diff --git a/chrome/common/extensions/api/declarative_web_request.json b/chrome/common/extensions/api/declarative_web_request.json
index 3e445d2..0ab3222 100644
--- a/chrome/common/extensions/api/declarative_web_request.json
+++ b/chrome/common/extensions/api/declarative_web_request.json
@@ -100,6 +100,45 @@
}
},
{
+ "id": "declarativeWebRequest.AddResponseHeader",
+ "description": "Adds the response header to the response of this web request. As multiple response headers may share the same name, you need to first remove and then add a new response header in order to replace one.",
+ "type": "object",
+ "properties": {
+ "instanceType": {
+ "type": "string", "enum": ["declarativeWebRequest.AddResponseHeader"],
+ "nodoc": true
+ },
+ "name": {
+ "type": "string",
+ "description": "HTTP response header name."
+ },
+ "value": {
+ "type": "string",
+ "description": "HTTP response header value."
+ }
+ }
+ },
+ {
+ "id": "declarativeWebRequest.RemoveResponseHeader",
+ "description": "Removes all response headers of the specified names and values.",
+ "type": "object",
+ "properties": {
+ "instanceType": {
+ "type": "string", "enum": ["declarativeWebRequest.RemoveResponseHeader"],
+ "nodoc": true
+ },
+ "name": {
+ "type": "string",
+ "description": "HTTP request header name (case-insensitive)."
+ },
+ "value": {
+ "type": "string",
+ "description": "HTTP request header value (case-insensitive).",
+ "optional": true
+ }
+ }
+ },
+ {
"id": "declarativeWebRequest.IgnoreRules",
"description": "Masks all rules that match the specified criteria.",
"type": "object",
@@ -125,12 +164,14 @@
"supportsRules": true,
"conditions": ["declarativeWebRequest.RequestMatcher"],
"actions": [
+ "declarativeWebRequest.AddResponseHeader",
"declarativeWebRequest.CancelRequest",
"declarativeWebRequest.RedirectRequest",
"declarativeWebRequest.RedirectToTransparentImage",
"declarativeWebRequest.RedirectToEmptyDocument",
"declarativeWebRequest.SetRequestHeader",
"declarativeWebRequest.RemoveRequestHeader",
+ "declarativeWebRequest.RemoveResponseHeader",
"declarativeWebRequest.IgnoreRules"
]
}
diff --git a/chrome/common/extensions/docs/declarativeWebRequest.html b/chrome/common/extensions/docs/declarativeWebRequest.html
index 65ee70d..07d2697 100644
--- a/chrome/common/extensions/docs/declarativeWebRequest.html
+++ b/chrome/common/extensions/docs/declarativeWebRequest.html
@@ -251,6 +251,14 @@
<ol>
</ol>
</li><li>
+ <a href="#type-declarativeWebRequest.AddResponseHeader">declarativeWebRequest.AddResponseHeader</a>
+ <ol>
+ </ol>
+ </li><li>
+ <a href="#type-declarativeWebRequest.RemoveResponseHeader">declarativeWebRequest.RemoveResponseHeader</a>
+ <ol>
+ </ol>
+ </li><li>
<a href="#type-declarativeWebRequest.IgnoreRules">declarativeWebRequest.IgnoreRules</a>
<ol>
</ol>
@@ -420,6 +428,15 @@ very fast URL matching algorithm for hundreds of thousands of URLs.
<div>
<div>
<dt>
+ <a href="declarativeWebRequest.html#type-declarativeWebRequest.AddResponseHeader">declarativeWebRequest.AddResponseHeader</a>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ </div>
+ </div><div>
+ <div>
+ <dt>
<a>declarativeWebRequest.CancelRequest</a>
</dt>
</div>
@@ -468,6 +485,15 @@ very fast URL matching algorithm for hundreds of thousands of URLs.
</div><div>
<div>
<dt>
+ <a href="declarativeWebRequest.html#type-declarativeWebRequest.RemoveResponseHeader">declarativeWebRequest.RemoveResponseHeader</a>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ </div>
+ </div><div>
+ <div>
+ <dt>
<a href="declarativeWebRequest.html#type-declarativeWebRequest.IgnoreRules">declarativeWebRequest.IgnoreRules</a>
</dt>
<dd class="todo">
@@ -915,6 +941,157 @@ very fast URL matching algorithm for hundreds of thousands of URLs.
<!-- FUNCTION PARAMETERS -->
</div>
</div><div class="apiItem">
+ <a name="type-declarativeWebRequest.AddResponseHeader"></a>
+ <h4>declarativeWebRequest.AddResponseHeader</h4>
+ <div>
+ <dt>
+ <em>
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span id="typeTemplate">
+ <span>
+ <span>object</span>
+ </span>
+ </span>
+ )
+ </div>
+ </em>
+ </dt>
+ <dd>Adds the response header to the response of this web request. As multiple response headers may share the same name, you need to first remove and then add a new response header in order to replace one.</dd>
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>name</var>
+ <em>
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span id="typeTemplate">
+ <span>
+ <span>string</span>
+ </span>
+ </span>
+ )
+ </div>
+ </em>
+ </dt>
+ <dd>HTTP response header name.</dd>
+ <!-- OBJECT PROPERTIES -->
+ <!-- OBJECT METHODS -->
+ <!-- OBJECT EVENT FIELDS -->
+ <!-- FUNCTION PARAMETERS -->
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>value</var>
+ <em>
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span id="typeTemplate">
+ <span>
+ <span>string</span>
+ </span>
+ </span>
+ )
+ </div>
+ </em>
+ </dt>
+ <dd>HTTP response header value.</dd>
+ <!-- OBJECT PROPERTIES -->
+ <!-- OBJECT METHODS -->
+ <!-- OBJECT EVENT FIELDS -->
+ <!-- FUNCTION PARAMETERS -->
+ </div>
+ </div>
+ </dl>
+ </dd>
+ <!-- OBJECT METHODS -->
+ <!-- OBJECT EVENT FIELDS -->
+ <!-- FUNCTION PARAMETERS -->
+ </div>
+ </div><div class="apiItem">
+ <a name="type-declarativeWebRequest.RemoveResponseHeader"></a>
+ <h4>declarativeWebRequest.RemoveResponseHeader</h4>
+ <div>
+ <dt>
+ <em>
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span id="typeTemplate">
+ <span>
+ <span>object</span>
+ </span>
+ </span>
+ )
+ </div>
+ </em>
+ </dt>
+ <dd>Removes all response headers of the specified names and values.</dd>
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>name</var>
+ <em>
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span id="typeTemplate">
+ <span>
+ <span>string</span>
+ </span>
+ </span>
+ )
+ </div>
+ </em>
+ </dt>
+ <dd>HTTP request header name (case-insensitive).</dd>
+ <!-- OBJECT PROPERTIES -->
+ <!-- OBJECT METHODS -->
+ <!-- OBJECT EVENT FIELDS -->
+ <!-- FUNCTION PARAMETERS -->
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>value</var>
+ <em>
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span id="typeTemplate">
+ <span>
+ <span>string</span>
+ </span>
+ </span>
+ )
+ </div>
+ </em>
+ </dt>
+ <dd>HTTP request header value (case-insensitive).</dd>
+ <!-- OBJECT PROPERTIES -->
+ <!-- OBJECT METHODS -->
+ <!-- OBJECT EVENT FIELDS -->
+ <!-- FUNCTION PARAMETERS -->
+ </div>
+ </div>
+ </dl>
+ </dd>
+ <!-- OBJECT METHODS -->
+ <!-- OBJECT EVENT FIELDS -->
+ <!-- FUNCTION PARAMETERS -->
+ </div>
+ </div><div class="apiItem">
<a name="type-declarativeWebRequest.IgnoreRules"></a>
<h4>declarativeWebRequest.IgnoreRules</h4>
<div>
diff --git a/chrome/renderer/resources/extensions/declarative_webrequest_custom_bindings.js b/chrome/renderer/resources/extensions/declarative_webrequest_custom_bindings.js
index 4d4db1a..5a8d798 100644
--- a/chrome/renderer/resources/extensions/declarative_webrequest_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/declarative_webrequest_custom_bindings.js
@@ -48,6 +48,12 @@ chromeHidden.registerCustomHook('declarativeWebRequest', function(api) {
chrome.declarativeWebRequest.RemoveRequestHeader = function(parameters) {
setupInstance(this, parameters, 'RemoveRequestHeader');
};
+ chrome.declarativeWebRequest.AddResponseHeader = function(parameters) {
+ setupInstance(this, parameters, 'AddResponseHeader');
+ };
+ chrome.declarativeWebRequest.RemoveResponseHeader = function(parameters) {
+ setupInstance(this, parameters, 'RemoveResponseHeader');
+ };
chrome.declarativeWebRequest.RedirectToTransparentImage =
function(parameters) {
setupInstance(this, parameters, 'RedirectToTransparentImage');
diff --git a/chrome/test/data/extensions/api_test/webrequest/test_declarative.js b/chrome/test/data/extensions/api_test/webrequest/test_declarative.js
index be22dd6..e6e621f 100644
--- a/chrome/test/data/extensions/api_test/webrequest/test_declarative.js
+++ b/chrome/test/data/extensions/api_test/webrequest/test_declarative.js
@@ -3,6 +3,8 @@
// found in the LICENSE file.
var onRequest = chrome.declarativeWebRequest.onRequest;
+var AddResponseHeader =
+ chrome.declarativeWebRequest.AddResponseHeader;
var RequestMatcher = chrome.declarativeWebRequest.RequestMatcher;
var CancelRequest = chrome.declarativeWebRequest.CancelRequest;
var RedirectRequest = chrome.declarativeWebRequest.RedirectRequest;
@@ -14,6 +16,8 @@ var SetRequestHeader =
chrome.declarativeWebRequest.SetRequestHeader;
var RemoveRequestHeader =
chrome.declarativeWebRequest.RemoveRequestHeader;
+var RemoveResponseHeader =
+ chrome.declarativeWebRequest.RemoveResponseHeader;
var IgnoreRules =
chrome.declarativeWebRequest.IgnoreRules;
@@ -36,6 +40,10 @@ function getURLHttpRedirectTest() {
"files/extensions/api_test/webrequest/declarative/a.html");
}
+function getURLSetCookie() {
+ return getServerURL('set-cookie?Foo=Bar');
+}
+
runTests([
function testCancelRequest() {
ignoreUnexpected = true;
@@ -222,6 +230,49 @@ runTests([
});
},
+ function testAddResponseHeader() {
+ ignoreUnexpected = true;
+ expect(); // Used for initialization.
+ onRequest.addRules(
+ [{conditions: [new RequestMatcher()],
+ actions: [new AddResponseHeader({name: "Set-Cookie", value: "Bar=baz"})]
+ }],
+ function() {
+ navigateAndWait(getURLEchoUserAgent(), function() {
+ chrome.test.listenOnce(chrome.extension.onRequest, function(request) {
+ chrome.test.assertTrue(request.pass, "Cookie was not added.");
+ });
+ chrome.tabs.executeScript(tabId,
+ {
+ code: "chrome.extension.sendRequest(" +
+ "{pass: document.cookie.indexOf('Bar') != -1});"
+ });
+ });
+ });
+ },
+
+ function testRemoveResponseHeader() {
+ ignoreUnexpected = true;
+ expect(); // Used for initialization.
+ onRequest.addRules(
+ [{conditions: [new RequestMatcher()],
+ actions: [new RemoveResponseHeader({name: "Set-Cookie",
+ value: "FoO=bAR"})]
+ }],
+ function() {
+ navigateAndWait(getURLSetCookie(), function() {
+ chrome.test.listenOnce(chrome.extension.onRequest, function(request) {
+ chrome.test.assertTrue(request.pass, "Cookie was not removed.");
+ });
+ chrome.tabs.executeScript(tabId,
+ {
+ code: "chrome.extension.sendRequest(" +
+ "{pass: document.cookie.indexOf('Foo') == -1});"
+ });
+ });
+ });
+ },
+
function testPriorities() {
ignoreUnexpected = true;
expect(