1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_action.h"
6
7 #include "base/files/file_path.h"
8 #include "base/json/json_file_value_serializer.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/path_service.h"
13 #include "base/test/values_test_util.h"
14 #include "base/time/time.h"
15 #include "base/values.h"
16 #include "chrome/browser/extensions/api/declarative_webrequest/request_stage.h"
17 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condition.h"
18 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_constants.h"
19 #include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h"
20 #include "chrome/common/chrome_paths.h"
21 #include "chrome/common/extensions/extension_constants.h"
22 #include "chrome/common/extensions/extension_test_util.h"
23 #include "content/public/test/test_browser_thread_bundle.h"
24 #include "extensions/browser/info_map.h"
25 #include "extensions/common/extension.h"
26 #include "net/base/request_priority.h"
27 #include "net/http/http_response_headers.h"
28 #include "net/url_request/url_request_test_util.h"
29 #include "testing/gmock/include/gmock/gmock.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31
32 using base::DictionaryValue;
33 using base::ListValue;
34 using extension_test_util::LoadManifestUnchecked;
35 using testing::HasSubstr;
36
37 namespace extensions {
38
39 namespace {
40
41 const char kUnknownActionType[] = "unknownType";
42
CreateSetOfActions(const char * json)43 scoped_ptr<WebRequestActionSet> CreateSetOfActions(const char* json) {
44 scoped_ptr<Value> parsed_value(base::test::ParseJson(json));
45 const ListValue* parsed_list;
46 CHECK(parsed_value->GetAsList(&parsed_list));
47
48 WebRequestActionSet::AnyVector actions;
49 for (ListValue::const_iterator it = parsed_list->begin();
50 it != parsed_list->end();
51 ++it) {
52 const DictionaryValue* dict;
53 CHECK((*it)->GetAsDictionary(&dict));
54 actions.push_back(linked_ptr<base::Value>(dict->DeepCopy()));
55 }
56
57 std::string error;
58 bool bad_message = false;
59
60 scoped_ptr<WebRequestActionSet> action_set(
61 WebRequestActionSet::Create(NULL, actions, &error, &bad_message));
62 EXPECT_EQ("", error);
63 EXPECT_FALSE(bad_message);
64 CHECK(action_set);
65 return action_set.Pass();
66 }
67
68 } // namespace
69
70 namespace keys = declarative_webrequest_constants;
71
72 class WebRequestActionWithThreadsTest : public testing::Test {
73 public:
WebRequestActionWithThreadsTest()74 WebRequestActionWithThreadsTest()
75 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
76
77 protected:
78 virtual void SetUp() OVERRIDE;
79
80 // Creates a URL request for URL |url_string|, and applies the actions from
81 // |action_set| as if they were triggered by the extension with
82 // |extension_id| during |stage|.
83 bool ActionWorksOnRequest(const char* url_string,
84 const std::string& extension_id,
85 const WebRequestActionSet* action_set,
86 RequestStage stage);
87
88 // Expects a JSON description of an |action| requiring <all_urls> host
89 // permission, and checks that only an extensions with full host permissions
90 // can execute that action at |stage|. Also checks that the action is not
91 // executable for http://clients1.google.com.
92 void CheckActionNeedsAllUrls(const char* action, RequestStage stage);
93
94 net::TestURLRequestContext context_;
95
96 // An extension with *.com host permissions and the DWR permission.
97 scoped_refptr<Extension> extension_;
98 // An extension with host permissions for all URLs and the DWR permission.
99 scoped_refptr<Extension> extension_all_urls_;
100 scoped_refptr<InfoMap> extension_info_map_;
101
102 private:
103 content::TestBrowserThreadBundle thread_bundle_;
104 };
105
SetUp()106 void WebRequestActionWithThreadsTest::SetUp() {
107 testing::Test::SetUp();
108
109 std::string error;
110 extension_ = LoadManifestUnchecked("permissions",
111 "web_request_com_host_permissions.json",
112 Manifest::INVALID_LOCATION,
113 Extension::NO_FLAGS,
114 "ext_id_1",
115 &error);
116 ASSERT_TRUE(extension_.get()) << error;
117 extension_all_urls_ =
118 LoadManifestUnchecked("permissions",
119 "web_request_all_host_permissions.json",
120 Manifest::INVALID_LOCATION,
121 Extension::NO_FLAGS,
122 "ext_id_2",
123 &error);
124 ASSERT_TRUE(extension_all_urls_.get()) << error;
125 extension_info_map_ = new InfoMap;
126 ASSERT_TRUE(extension_info_map_.get());
127 extension_info_map_->AddExtension(
128 extension_.get(),
129 base::Time::Now(),
130 false /*incognito_enabled*/,
131 false /*notifications_disabled*/);
132 extension_info_map_->AddExtension(extension_all_urls_.get(),
133 base::Time::Now(),
134 false /*incognito_enabled*/,
135 false /*notifications_disabled*/);
136 }
137
ActionWorksOnRequest(const char * url_string,const std::string & extension_id,const WebRequestActionSet * action_set,RequestStage stage)138 bool WebRequestActionWithThreadsTest::ActionWorksOnRequest(
139 const char* url_string,
140 const std::string& extension_id,
141 const WebRequestActionSet* action_set,
142 RequestStage stage) {
143 net::TestURLRequest regular_request(
144 GURL(url_string), net::DEFAULT_PRIORITY, NULL, &context_);
145 std::list<LinkedPtrEventResponseDelta> deltas;
146 scoped_refptr<net::HttpResponseHeaders> headers(
147 new net::HttpResponseHeaders(""));
148 WebRequestData request_data(®ular_request, stage, headers.get());
149 std::set<std::string> ignored_tags;
150 WebRequestAction::ApplyInfo apply_info = { extension_info_map_.get(),
151 request_data,
152 false /*crosses_incognito*/,
153 &deltas, &ignored_tags };
154 action_set->Apply(extension_id, base::Time(), &apply_info);
155 return (1u == deltas.size() || 0u < ignored_tags.size());
156 }
157
CheckActionNeedsAllUrls(const char * action,RequestStage stage)158 void WebRequestActionWithThreadsTest::CheckActionNeedsAllUrls(
159 const char* action,
160 RequestStage stage) {
161 scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(action));
162
163 // Although |extension_| has matching *.com host permission, |action|
164 // is intentionally forbidden -- in Declarative WR, host permission
165 // for less than all URLs are ignored (except in SendMessageToExtension).
166 EXPECT_FALSE(ActionWorksOnRequest(
167 "http://test.com", extension_->id(), action_set.get(), stage));
168 // With the "<all_urls>" host permission they are allowed.
169 EXPECT_TRUE(ActionWorksOnRequest(
170 "http://test.com", extension_all_urls_->id(), action_set.get(), stage));
171
172 // The protected URLs should not be touched at all.
173 EXPECT_FALSE(ActionWorksOnRequest(
174 "http://clients1.google.com", extension_->id(), action_set.get(), stage));
175 EXPECT_FALSE(ActionWorksOnRequest("http://clients1.google.com",
176 extension_all_urls_->id(),
177 action_set.get(),
178 stage));
179 }
180
TEST(WebRequestActionTest,CreateAction)181 TEST(WebRequestActionTest, CreateAction) {
182 std::string error;
183 bool bad_message = false;
184 scoped_refptr<const WebRequestAction> result;
185
186 // Test wrong data type passed.
187 error.clear();
188 base::ListValue empty_list;
189 result = WebRequestAction::Create(NULL, empty_list, &error, &bad_message);
190 EXPECT_TRUE(bad_message);
191 EXPECT_FALSE(result.get());
192
193 // Test missing instanceType element.
194 base::DictionaryValue input;
195 error.clear();
196 result = WebRequestAction::Create(NULL, input, &error, &bad_message);
197 EXPECT_TRUE(bad_message);
198 EXPECT_FALSE(result.get());
199
200 // Test wrong instanceType element.
201 input.SetString(keys::kInstanceTypeKey, kUnknownActionType);
202 error.clear();
203 result = WebRequestAction::Create(NULL, input, &error, &bad_message);
204 EXPECT_NE("", error);
205 EXPECT_FALSE(result.get());
206
207 // Test success
208 input.SetString(keys::kInstanceTypeKey, keys::kCancelRequestType);
209 error.clear();
210 result = WebRequestAction::Create(NULL, input, &error, &bad_message);
211 EXPECT_EQ("", error);
212 EXPECT_FALSE(bad_message);
213 ASSERT_TRUE(result.get());
214 EXPECT_EQ(WebRequestAction::ACTION_CANCEL_REQUEST, result->type());
215 }
216
TEST(WebRequestActionTest,CreateActionSet)217 TEST(WebRequestActionTest, CreateActionSet) {
218 std::string error;
219 bool bad_message = false;
220 scoped_ptr<WebRequestActionSet> result;
221
222 WebRequestActionSet::AnyVector input;
223
224 // Test empty input.
225 error.clear();
226 result = WebRequestActionSet::Create(NULL, input, &error, &bad_message);
227 EXPECT_TRUE(error.empty()) << error;
228 EXPECT_FALSE(bad_message);
229 ASSERT_TRUE(result.get());
230 EXPECT_TRUE(result->actions().empty());
231 EXPECT_EQ(std::numeric_limits<int>::min(), result->GetMinimumPriority());
232
233 DictionaryValue correct_action;
234 correct_action.SetString(keys::kInstanceTypeKey, keys::kIgnoreRulesType);
235 correct_action.SetInteger(keys::kLowerPriorityThanKey, 10);
236 DictionaryValue incorrect_action;
237 incorrect_action.SetString(keys::kInstanceTypeKey, kUnknownActionType);
238
239 // Test success.
240 input.push_back(linked_ptr<base::Value>(correct_action.DeepCopy()));
241 error.clear();
242 result = WebRequestActionSet::Create(NULL, input, &error, &bad_message);
243 EXPECT_TRUE(error.empty()) << error;
244 EXPECT_FALSE(bad_message);
245 ASSERT_TRUE(result.get());
246 ASSERT_EQ(1u, result->actions().size());
247 EXPECT_EQ(WebRequestAction::ACTION_IGNORE_RULES,
248 result->actions()[0]->type());
249 EXPECT_EQ(10, result->GetMinimumPriority());
250
251 // Test failure.
252 input.push_back(linked_ptr<base::Value>(incorrect_action.DeepCopy()));
253 error.clear();
254 result = WebRequestActionSet::Create(NULL, input, &error, &bad_message);
255 EXPECT_NE("", error);
256 EXPECT_FALSE(result.get());
257 }
258
259 // Test capture group syntax conversions of WebRequestRedirectByRegExAction
TEST(WebRequestActionTest,PerlToRe2Style)260 TEST(WebRequestActionTest, PerlToRe2Style) {
261 #define CallPerlToRe2Style WebRequestRedirectByRegExAction::PerlToRe2Style
262 // foo$1bar -> foo\1bar
263 EXPECT_EQ("foo\\1bar", CallPerlToRe2Style("foo$1bar"));
264 // foo\$1bar -> foo$1bar
265 EXPECT_EQ("foo$1bar", CallPerlToRe2Style("foo\\$1bar"));
266 // foo\\$1bar -> foo\\\1bar
267 EXPECT_EQ("foo\\\\\\1bar", CallPerlToRe2Style("foo\\\\$1bar"));
268 // foo\bar -> foobar
269 EXPECT_EQ("foobar", CallPerlToRe2Style("foo\\bar"));
270 // foo$bar -> foo$bar
271 EXPECT_EQ("foo$bar", CallPerlToRe2Style("foo$bar"));
272 #undef CallPerlToRe2Style
273 }
274
TEST_F(WebRequestActionWithThreadsTest,PermissionsToRedirect)275 TEST_F(WebRequestActionWithThreadsTest, PermissionsToRedirect) {
276 const char kAction[] =
277 "[{"
278 " \"instanceType\": \"declarativeWebRequest.RedirectRequest\","
279 " \"redirectUrl\": \"http://www.foobar.com\""
280 "}]";
281 CheckActionNeedsAllUrls(kAction, ON_BEFORE_REQUEST);
282 }
283
TEST_F(WebRequestActionWithThreadsTest,PermissionsToRedirectByRegEx)284 TEST_F(WebRequestActionWithThreadsTest, PermissionsToRedirectByRegEx) {
285 const char kAction[] =
286 "[{"
287 " \"instanceType\": \"declarativeWebRequest.RedirectByRegEx\","
288 " \"from\": \".*\","
289 " \"to\": \"http://www.foobar.com\""
290 "}]";
291 CheckActionNeedsAllUrls(kAction, ON_BEFORE_REQUEST);
292 }
293
TEST_F(WebRequestActionWithThreadsTest,PermissionsToSetRequestHeader)294 TEST_F(WebRequestActionWithThreadsTest, PermissionsToSetRequestHeader) {
295 const char kAction[] =
296 "[{"
297 " \"instanceType\": \"declarativeWebRequest.SetRequestHeader\","
298 " \"name\": \"testname\","
299 " \"value\": \"testvalue\""
300 "}]";
301 CheckActionNeedsAllUrls(kAction, ON_BEFORE_SEND_HEADERS);
302 }
303
TEST_F(WebRequestActionWithThreadsTest,PermissionsToRemoveRequestHeader)304 TEST_F(WebRequestActionWithThreadsTest, PermissionsToRemoveRequestHeader) {
305 const char kAction[] =
306 "[{"
307 " \"instanceType\": \"declarativeWebRequest.RemoveRequestHeader\","
308 " \"name\": \"testname\""
309 "}]";
310 CheckActionNeedsAllUrls(kAction, ON_BEFORE_SEND_HEADERS);
311 }
312
TEST_F(WebRequestActionWithThreadsTest,PermissionsToAddResponseHeader)313 TEST_F(WebRequestActionWithThreadsTest, PermissionsToAddResponseHeader) {
314 const char kAction[] =
315 "[{"
316 " \"instanceType\": \"declarativeWebRequest.AddResponseHeader\","
317 " \"name\": \"testname\","
318 " \"value\": \"testvalue\""
319 "}]";
320 CheckActionNeedsAllUrls(kAction, ON_HEADERS_RECEIVED);
321 }
322
TEST_F(WebRequestActionWithThreadsTest,PermissionsToRemoveResponseHeader)323 TEST_F(WebRequestActionWithThreadsTest, PermissionsToRemoveResponseHeader) {
324 const char kAction[] =
325 "[{"
326 " \"instanceType\": \"declarativeWebRequest.RemoveResponseHeader\","
327 " \"name\": \"testname\""
328 "}]";
329 CheckActionNeedsAllUrls(kAction, ON_HEADERS_RECEIVED);
330 }
331
TEST_F(WebRequestActionWithThreadsTest,PermissionsToSendMessageToExtension)332 TEST_F(WebRequestActionWithThreadsTest, PermissionsToSendMessageToExtension) {
333 const char kAction[] =
334 "[{"
335 " \"instanceType\": \"declarativeWebRequest.SendMessageToExtension\","
336 " \"message\": \"testtext\""
337 "}]";
338 scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(kAction));
339
340 // For sending messages, specific host permissions actually matter.
341 EXPECT_TRUE(ActionWorksOnRequest("http://test.com",
342 extension_->id(),
343 action_set.get(),
344 ON_BEFORE_REQUEST));
345 // With the "<all_urls>" host permission they are allowed.
346 EXPECT_TRUE(ActionWorksOnRequest("http://test.com",
347 extension_all_urls_->id(),
348 action_set.get(),
349 ON_BEFORE_REQUEST));
350
351 // The protected URLs should not be touched at all.
352 EXPECT_FALSE(ActionWorksOnRequest("http://clients1.google.com",
353 extension_->id(),
354 action_set.get(),
355 ON_BEFORE_REQUEST));
356 EXPECT_FALSE(ActionWorksOnRequest("http://clients1.google.com",
357 extension_all_urls_->id(),
358 action_set.get(),
359 ON_BEFORE_REQUEST));
360 }
361
TEST_F(WebRequestActionWithThreadsTest,PermissionsToAddRequestCookie)362 TEST_F(WebRequestActionWithThreadsTest, PermissionsToAddRequestCookie) {
363 const char kAction[] =
364 "[{"
365 " \"instanceType\": \"declarativeWebRequest.AddRequestCookie\","
366 " \"cookie\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
367 "}]";
368 CheckActionNeedsAllUrls(kAction, ON_BEFORE_SEND_HEADERS);
369 }
370
TEST_F(WebRequestActionWithThreadsTest,PermissionsToAddResponseCookie)371 TEST_F(WebRequestActionWithThreadsTest, PermissionsToAddResponseCookie) {
372 const char kAction[] =
373 "[{"
374 " \"instanceType\": \"declarativeWebRequest.AddResponseCookie\","
375 " \"cookie\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
376 "}]";
377 CheckActionNeedsAllUrls(kAction, ON_HEADERS_RECEIVED);
378 }
379
TEST_F(WebRequestActionWithThreadsTest,PermissionsToEditRequestCookie)380 TEST_F(WebRequestActionWithThreadsTest, PermissionsToEditRequestCookie) {
381 const char kAction[] =
382 "[{"
383 " \"instanceType\": \"declarativeWebRequest.EditRequestCookie\","
384 " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" },"
385 " \"modification\": { \"name\": \"name2\", \"value\": \"value2\" }"
386 "}]";
387 CheckActionNeedsAllUrls(kAction, ON_BEFORE_SEND_HEADERS);
388 }
389
TEST_F(WebRequestActionWithThreadsTest,PermissionsToEditResponseCookie)390 TEST_F(WebRequestActionWithThreadsTest, PermissionsToEditResponseCookie) {
391 const char kAction[] =
392 "[{"
393 " \"instanceType\": \"declarativeWebRequest.EditResponseCookie\","
394 " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" },"
395 " \"modification\": { \"name\": \"name2\", \"value\": \"value2\" }"
396 "}]";
397 CheckActionNeedsAllUrls(kAction, ON_HEADERS_RECEIVED);
398 }
399
TEST_F(WebRequestActionWithThreadsTest,PermissionsToRemoveRequestCookie)400 TEST_F(WebRequestActionWithThreadsTest, PermissionsToRemoveRequestCookie) {
401 const char kAction[] =
402 "[{"
403 " \"instanceType\": \"declarativeWebRequest.RemoveRequestCookie\","
404 " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
405 "}]";
406 CheckActionNeedsAllUrls(kAction, ON_BEFORE_SEND_HEADERS);
407 }
408
TEST_F(WebRequestActionWithThreadsTest,PermissionsToRemoveResponseCookie)409 TEST_F(WebRequestActionWithThreadsTest, PermissionsToRemoveResponseCookie) {
410 const char kAction[] =
411 "[{"
412 " \"instanceType\": \"declarativeWebRequest.RemoveResponseCookie\","
413 " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
414 "}]";
415 CheckActionNeedsAllUrls(kAction, ON_HEADERS_RECEIVED);
416 }
417
TEST_F(WebRequestActionWithThreadsTest,PermissionsToCancel)418 TEST_F(WebRequestActionWithThreadsTest, PermissionsToCancel) {
419 const char kAction[] =
420 "[{"
421 " \"instanceType\": \"declarativeWebRequest.CancelRequest\""
422 "}]";
423 scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(kAction));
424
425 // Cancelling requests works without full host permissions.
426 EXPECT_TRUE(ActionWorksOnRequest("http://test.org",
427 extension_->id(),
428 action_set.get(),
429 ON_BEFORE_REQUEST));
430 }
431
TEST_F(WebRequestActionWithThreadsTest,PermissionsToRedirectToTransparentImage)432 TEST_F(WebRequestActionWithThreadsTest,
433 PermissionsToRedirectToTransparentImage) {
434 const char kAction[] =
435 "[{"
436 " \"instanceType\": \"declarativeWebRequest.RedirectToTransparentImage\""
437 "}]";
438 scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(kAction));
439
440 // Redirecting to transparent images works without full host permissions.
441 EXPECT_TRUE(ActionWorksOnRequest("http://test.org",
442 extension_->id(),
443 action_set.get(),
444 ON_BEFORE_REQUEST));
445 }
446
TEST_F(WebRequestActionWithThreadsTest,PermissionsToRedirectToEmptyDocument)447 TEST_F(WebRequestActionWithThreadsTest, PermissionsToRedirectToEmptyDocument) {
448 const char kAction[] =
449 "[{"
450 " \"instanceType\": \"declarativeWebRequest.RedirectToEmptyDocument\""
451 "}]";
452 scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(kAction));
453
454 // Redirecting to the empty document works without full host permissions.
455 EXPECT_TRUE(ActionWorksOnRequest("http://test.org",
456 extension_->id(),
457 action_set.get(),
458 ON_BEFORE_REQUEST));
459 }
460
TEST_F(WebRequestActionWithThreadsTest,PermissionsToIgnore)461 TEST_F(WebRequestActionWithThreadsTest, PermissionsToIgnore) {
462 const char kAction[] =
463 "[{"
464 " \"instanceType\": \"declarativeWebRequest.IgnoreRules\","
465 " \"lowerPriorityThan\": 123,"
466 " \"hasTag\": \"some_tag\""
467 "}]";
468 scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(kAction));
469
470 // Ignoring rules works without full host permissions.
471 EXPECT_TRUE(ActionWorksOnRequest("http://test.org",
472 extension_->id(),
473 action_set.get(),
474 ON_BEFORE_REQUEST));
475 }
476
TEST(WebRequestActionTest,GetName)477 TEST(WebRequestActionTest, GetName) {
478 const char kActions[] =
479 "[{"
480 " \"instanceType\": \"declarativeWebRequest.RedirectRequest\","
481 " \"redirectUrl\": \"http://www.foobar.com\""
482 "},"
483 "{"
484 " \"instanceType\": \"declarativeWebRequest.RedirectByRegEx\","
485 " \"from\": \".*\","
486 " \"to\": \"http://www.foobar.com\""
487 "},"
488 "{"
489 " \"instanceType\": \"declarativeWebRequest.SetRequestHeader\","
490 " \"name\": \"testname\","
491 " \"value\": \"testvalue\""
492 "},"
493 "{"
494 " \"instanceType\": \"declarativeWebRequest.RemoveRequestHeader\","
495 " \"name\": \"testname\""
496 "},"
497 "{"
498 " \"instanceType\": \"declarativeWebRequest.AddResponseHeader\","
499 " \"name\": \"testname\","
500 " \"value\": \"testvalue\""
501 "},"
502 "{"
503 " \"instanceType\": \"declarativeWebRequest.RemoveResponseHeader\","
504 " \"name\": \"testname\""
505 "},"
506 "{"
507 " \"instanceType\": \"declarativeWebRequest.SendMessageToExtension\","
508 " \"message\": \"testtext\""
509 "},"
510 "{"
511 " \"instanceType\": \"declarativeWebRequest.AddRequestCookie\","
512 " \"cookie\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
513 "},"
514 "{"
515 " \"instanceType\": \"declarativeWebRequest.AddResponseCookie\","
516 " \"cookie\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
517 "},"
518 "{"
519 " \"instanceType\": \"declarativeWebRequest.EditRequestCookie\","
520 " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" },"
521 " \"modification\": { \"name\": \"name2\", \"value\": \"value2\" }"
522 "},"
523 "{"
524 " \"instanceType\": \"declarativeWebRequest.EditResponseCookie\","
525 " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" },"
526 " \"modification\": { \"name\": \"name2\", \"value\": \"value2\" }"
527 "},"
528 "{"
529 " \"instanceType\": \"declarativeWebRequest.RemoveRequestCookie\","
530 " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
531 "},"
532 "{"
533 " \"instanceType\": \"declarativeWebRequest.RemoveResponseCookie\","
534 " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
535 "},"
536 "{"
537 " \"instanceType\": \"declarativeWebRequest.CancelRequest\""
538 "},"
539 "{"
540 " \"instanceType\": \"declarativeWebRequest.RedirectToTransparentImage\""
541 "},"
542 "{"
543 " \"instanceType\": \"declarativeWebRequest.RedirectToEmptyDocument\""
544 "},"
545 "{"
546 " \"instanceType\": \"declarativeWebRequest.IgnoreRules\","
547 " \"lowerPriorityThan\": 123,"
548 " \"hasTag\": \"some_tag\""
549 "}]";
550 const char* kExpectedNames[] = {
551 "declarativeWebRequest.RedirectRequest",
552 "declarativeWebRequest.RedirectByRegEx",
553 "declarativeWebRequest.SetRequestHeader",
554 "declarativeWebRequest.RemoveRequestHeader",
555 "declarativeWebRequest.AddResponseHeader",
556 "declarativeWebRequest.RemoveResponseHeader",
557 "declarativeWebRequest.SendMessageToExtension",
558 "declarativeWebRequest.AddRequestCookie",
559 "declarativeWebRequest.AddResponseCookie",
560 "declarativeWebRequest.EditRequestCookie",
561 "declarativeWebRequest.EditResponseCookie",
562 "declarativeWebRequest.RemoveRequestCookie",
563 "declarativeWebRequest.RemoveResponseCookie",
564 "declarativeWebRequest.CancelRequest",
565 "declarativeWebRequest.RedirectToTransparentImage",
566 "declarativeWebRequest.RedirectToEmptyDocument",
567 "declarativeWebRequest.IgnoreRules",
568 };
569 scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(kActions));
570 ASSERT_EQ(arraysize(kExpectedNames), action_set->actions().size());
571 size_t index = 0;
572 for (WebRequestActionSet::Actions::const_iterator it =
573 action_set->actions().begin();
574 it != action_set->actions().end();
575 ++it) {
576 EXPECT_EQ(kExpectedNames[index], (*it)->GetName());
577 ++index;
578 }
579 }
580
581 } // namespace extensions
582