Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(200)

Side by Side Diff: chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc

Issue 14358004: Almost all actions in Declarative Web Request require all_urls host permissions (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Without error messages yet Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_action .h" 5 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_action .h"
6 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"
7 #include "base/message_loop.h" 11 #include "base/message_loop.h"
12 #include "base/path_service.h"
13 #include "base/test/values_test_util.h"
14 #include "base/time.h"
8 #include "base/values.h" 15 #include "base/values.h"
16 #include "chrome/browser/extensions/api/declarative_webrequest/request_stage.h"
9 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condit ion.h" 17 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_condit ion.h"
10 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_consta nts.h" 18 #include "chrome/browser/extensions/api/declarative_webrequest/webrequest_consta nts.h"
11 #include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h" 19 #include "chrome/browser/extensions/api/web_request/web_request_api_helpers.h"
20 #include "chrome/browser/extensions/extension_info_map.h"
21 #include "chrome/common/chrome_paths.h"
22 #include "chrome/common/extensions/extension.h"
12 #include "chrome/common/extensions/extension_constants.h" 23 #include "chrome/common/extensions/extension_constants.h"
24 #include "chrome/common/extensions/extension_test_util.h"
25 #include "content/public/test/test_browser_thread.h"
26 #include "net/http/http_response_headers.h"
13 #include "net/url_request/url_request_test_util.h" 27 #include "net/url_request/url_request_test_util.h"
14 #include "testing/gtest/include/gtest/gtest.h" 28 #include "testing/gtest/include/gtest/gtest.h"
15 29
16 namespace { 30 using base::DictionaryValue;
17 const char kUnknownActionType[] = "unknownType"; 31 using base::ListValue;
18 } // namespace 32 using extension_test_util::LoadManifestUnchecked;
19 33
20 namespace extensions { 34 namespace extensions {
21 35
36 namespace {
37
38 const char kUnknownActionType[] = "unknownType";
39
40 scoped_ptr<WebRequestActionSet> CreateSetOfActions(const char* json) {
41 scoped_ptr<Value> parsed_value(base::test::ParseJson(json));
42 const ListValue* parsed_list;
43 CHECK(parsed_value->GetAsList(&parsed_list));
44
45 WebRequestActionSet::AnyVector actions;
46 for (ListValue::const_iterator it = parsed_list->begin();
47 it != parsed_list->end();
48 ++it) {
49 const DictionaryValue* dict;
50 CHECK((*it)->GetAsDictionary(&dict));
51 actions.push_back(linked_ptr<base::Value>(dict->DeepCopy()));
52 }
53
54 std::string error;
55 bool bad_message = false;
56
57 scoped_ptr<WebRequestActionSet> action_set(
58 WebRequestActionSet::Create(actions, &error, &bad_message));
59 EXPECT_EQ("", error);
60 EXPECT_FALSE(bad_message);
61 CHECK(action_set);
62 return action_set.Pass();
63 }
64
65 } // namespace
66
22 namespace keys = declarative_webrequest_constants; 67 namespace keys = declarative_webrequest_constants;
23 68
69 class WebRequestActionWithThreadsTest : public testing::Test {
70 public:
71 WebRequestActionWithThreadsTest()
72 : io_thread_(content::BrowserThread::IO, &message_loop_) {}
73
74 protected:
75 virtual void SetUp() OVERRIDE;
76
77 // Creates a URL request for URL |url_string|, and applies the actions from
78 // |action_set| as if they were triggered by the extension with
79 // |extension_id| during |stage|.
80 bool ActionWorksOnRequest(const char* url_string,
81 const std::string& extension_id,
82 const WebRequestActionSet* action_set,
83 RequestStage stage);
84
85 // Expects a JSON description of an |action| requiring <all_urls> host
86 // permission, and checks that only an extensions with full host permissions
87 // can execute that action at |stage|. Also checks that the action is not
88 // executable for http://clients1.google.com.
89 void CheckActionNeedsAllUrls(const char* action, RequestStage stage);
90
91 net::TestURLRequestContext context_;
92
93 // An extension with *.com host permissions and the DWR permission.
94 scoped_refptr<Extension> extension_;
95 // An extension with host permissions for all URLs and the DWR permission.
96 scoped_refptr<Extension> extension_all_urls_;
97 scoped_refptr<ExtensionInfoMap> extension_info_map_;
98
99 private:
100 MessageLoopForIO message_loop_;
101 content::TestBrowserThread io_thread_;
102 };
103
104 void WebRequestActionWithThreadsTest::SetUp() {
105 testing::Test::SetUp();
106
107 std::string error;
108 extension_ = LoadManifestUnchecked("permissions",
109 "web_request_com_host_permissions.json",
110 Manifest::INVALID_LOCATION,
111 Extension::NO_FLAGS,
112 "ext_id_1",
113 &error);
114 ASSERT_TRUE(extension_) << error;
115 extension_all_urls_ =
116 LoadManifestUnchecked("permissions",
117 "web_request_all_host_permissions.json",
118 Manifest::INVALID_LOCATION,
119 Extension::NO_FLAGS,
120 "ext_id_2",
121 &error);
122 ASSERT_TRUE(extension_all_urls_) << error;
123 extension_info_map_ = new ExtensionInfoMap;
124 ASSERT_TRUE(extension_info_map_);
125 extension_info_map_->AddExtension(
126 extension_.get(), base::Time::Now(), false /*incognito_enabled*/);
127 extension_info_map_->AddExtension(extension_all_urls_.get(),
128 base::Time::Now(),
129 false /*incognito_enabled*/);
130 }
131
132 bool WebRequestActionWithThreadsTest::ActionWorksOnRequest(
133 const char* url_string,
134 const std::string& extension_id,
135 const WebRequestActionSet* action_set,
136 RequestStage stage) {
137 net::TestURLRequest regular_request(GURL(url_string), NULL, &context_, NULL);
138 std::list<LinkedPtrEventResponseDelta> deltas;
139 scoped_refptr<net::HttpResponseHeaders> headers(
140 new net::HttpResponseHeaders(""));
141 WebRequestData request_data(&regular_request, stage, headers);
142 std::set<std::string> ignored_tags;
143 WebRequestAction::ApplyInfo apply_info = {
144 extension_info_map_, request_data, false /*crosses_incognito*/, &deltas,
145 &ignored_tags
146 };
147 action_set->Apply(extension_id, base::Time(), &apply_info);
148 return (1u == deltas.size() || 0u < ignored_tags.size());
149 }
150
151 void WebRequestActionWithThreadsTest::CheckActionNeedsAllUrls(
152 const char* action,
153 RequestStage stage) {
154 scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(action));
155
156 // Although |extension_| has matching *.com host permission, |action|
157 // is intentionally forbidden -- in Declarative WR, host permission
158 // for less than all URLs are ignored (except in SendMessageToExtension).
159 EXPECT_FALSE(ActionWorksOnRequest(
160 "http://test.com", extension_->id(), action_set.get(), stage));
161 // With the "<all_urls>" host permission they are allowed.
162 EXPECT_TRUE(ActionWorksOnRequest(
163 "http://test.com", extension_all_urls_->id(), action_set.get(), stage));
164
165 // The protected URLs should not be touched at all.
166 EXPECT_FALSE(ActionWorksOnRequest(
167 "http://clients1.google.com", extension_->id(), action_set.get(), stage));
168 EXPECT_FALSE(ActionWorksOnRequest("http://clients1.google.com",
169 extension_all_urls_->id(),
170 action_set.get(),
171 stage));
172 }
173
24 TEST(WebRequestActionTest, CreateAction) { 174 TEST(WebRequestActionTest, CreateAction) {
25 std::string error; 175 std::string error;
26 bool bad_message = false; 176 bool bad_message = false;
27 scoped_ptr<WebRequestAction> result; 177 scoped_ptr<WebRequestAction> result;
28 178
29 // Test wrong data type passed. 179 // Test wrong data type passed.
30 error.clear(); 180 error.clear();
31 base::ListValue empty_list; 181 base::ListValue empty_list;
32 result = WebRequestAction::Create(empty_list, &error, &bad_message); 182 result = WebRequestAction::Create(empty_list, &error, &bad_message);
33 EXPECT_TRUE(bad_message); 183 EXPECT_TRUE(bad_message);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 EXPECT_EQ("foo$1bar", CallPerlToRe2Style("foo\\$1bar")); 258 EXPECT_EQ("foo$1bar", CallPerlToRe2Style("foo\\$1bar"));
109 // foo\\$1bar -> foo\\\1bar 259 // foo\\$1bar -> foo\\\1bar
110 EXPECT_EQ("foo\\\\\\1bar", CallPerlToRe2Style("foo\\\\$1bar")); 260 EXPECT_EQ("foo\\\\\\1bar", CallPerlToRe2Style("foo\\\\$1bar"));
111 // foo\bar -> foobar 261 // foo\bar -> foobar
112 EXPECT_EQ("foobar", CallPerlToRe2Style("foo\\bar")); 262 EXPECT_EQ("foobar", CallPerlToRe2Style("foo\\bar"));
113 // foo$bar -> foo$bar 263 // foo$bar -> foo$bar
114 EXPECT_EQ("foo$bar", CallPerlToRe2Style("foo$bar")); 264 EXPECT_EQ("foo$bar", CallPerlToRe2Style("foo$bar"));
115 #undef CallPerlToRe2Style 265 #undef CallPerlToRe2Style
116 } 266 }
117 267
118 TEST(WebRequestActionTest, TestPermissions) { 268 TEST_F(WebRequestActionWithThreadsTest, PermissionsToRedirect) {
119 // Necessary for TestURLRequest. 269 const char* action =
120 MessageLoop message_loop(MessageLoop::TYPE_IO); 270 "[{"
121 net::TestURLRequestContext context; 271 " \"instanceType\": \"declarativeWebRequest.RedirectRequest\","
122 272 " \"redirectUrl\": \"http://www.foobar.com\""
123 std::string error; 273 "}]";
124 bool bad_message = false; 274 CheckActionNeedsAllUrls(action, ON_BEFORE_REQUEST);
125 scoped_ptr<WebRequestActionSet> action_set; 275 }
126 276
127 // Setup redirect to http://www.foobar.com. 277 TEST_F(WebRequestActionWithThreadsTest, PermissionsToRedirectByRegEx) {
128 base::DictionaryValue redirect; 278 const char* action =
129 redirect.SetString(keys::kInstanceTypeKey, keys::kRedirectRequestType); 279 "[{"
130 redirect.SetString(keys::kRedirectUrlKey, "http://www.foobar.com"); 280 " \"instanceType\": \"declarativeWebRequest.RedirectByRegEx\","
131 281 " \"from\": \".*\","
132 WebRequestActionSet::AnyVector actions; 282 " \"to\": \"http://www.foobar.com\""
133 actions.push_back(linked_ptr<base::Value>(redirect.DeepCopy())); 283 "}]";
134 284 CheckActionNeedsAllUrls(action, ON_BEFORE_REQUEST);
135 action_set = WebRequestActionSet::Create(actions, &error, &bad_message); 285 }
136 EXPECT_EQ("", error); 286
137 EXPECT_FALSE(bad_message); 287 TEST_F(WebRequestActionWithThreadsTest, PermissionsToSetRequestHeader) {
138 288 const char* action =
139 // Check that redirect works on regular URLs but not on protected URLs. 289 "[{"
140 net::TestURLRequest regular_request( 290 " \"instanceType\": \"declarativeWebRequest.SetRequestHeader\","
141 GURL("http://test.com"), NULL, &context, NULL); 291 " \"name\": \"testname\","
142 std::list<LinkedPtrEventResponseDelta> deltas; 292 " \"value\": \"testvalue\""
143 WebRequestData request_data(&regular_request, ON_BEFORE_REQUEST); 293 "}]";
144 WebRequestAction::ApplyInfo apply_info = { 294 CheckActionNeedsAllUrls(action, ON_BEFORE_SEND_HEADERS);
145 NULL, request_data, false, &deltas 295 }
146 }; 296
147 action_set->Apply("ext1", base::Time(), &apply_info); 297 TEST_F(WebRequestActionWithThreadsTest, PermissionsToRemoveRequestHeader) {
148 EXPECT_EQ(1u, deltas.size()); 298 const char* action =
149 299 "[{"
150 net::TestURLRequest protected_request(GURL("http://clients1.google.com"), 300 " \"instanceType\": \"declarativeWebRequest.RemoveRequestHeader\","
151 NULL, &context, NULL); 301 " \"name\": \"testname\""
152 deltas.clear(); 302 "}]";
153 request_data = WebRequestData(&protected_request, ON_BEFORE_REQUEST); 303 CheckActionNeedsAllUrls(action, ON_BEFORE_SEND_HEADERS);
154 // Note that we just updated the request_data reference in apply_info. 304 }
155 action_set->Apply("ext1", base::Time(), &apply_info); 305
156 EXPECT_EQ(0u, deltas.size()); 306 TEST_F(WebRequestActionWithThreadsTest, PermissionsToAddResponseHeader) {
307 const char* action =
308 "[{"
309 " \"instanceType\": \"declarativeWebRequest.AddResponseHeader\","
310 " \"name\": \"testname\","
311 " \"value\": \"testvalue\""
312 "}]";
313 CheckActionNeedsAllUrls(action, ON_HEADERS_RECEIVED);
314 }
315
316 TEST_F(WebRequestActionWithThreadsTest, PermissionsToRemoveResponseHeader) {
317 const char* action =
318 "[{"
319 " \"instanceType\": \"declarativeWebRequest.RemoveResponseHeader\","
320 " \"name\": \"testname\""
321 "}]";
322 CheckActionNeedsAllUrls(action, ON_HEADERS_RECEIVED);
323 }
324
325 TEST_F(WebRequestActionWithThreadsTest, PermissionsToSendMessageToExtension) {
326 const char* action =
327 "[{"
328 " \"instanceType\": \"declarativeWebRequest.SendMessageToExtension\","
329 " \"message\": \"testtext\""
330 "}]";
331 scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(action));
332
333 // For sending messages, specific host permissions actually matter.
334 EXPECT_TRUE(ActionWorksOnRequest("http://test.com",
335 extension_->id(),
336 action_set.get(),
337 ON_BEFORE_REQUEST));
338 // With the "<all_urls>" host permission they are allowed.
339 EXPECT_TRUE(ActionWorksOnRequest("http://test.com",
340 extension_all_urls_->id(),
341 action_set.get(),
342 ON_BEFORE_REQUEST));
343
344 // The protected URLs should not be touched at all.
345 EXPECT_FALSE(ActionWorksOnRequest("http://clients1.google.com",
346 extension_->id(),
347 action_set.get(),
348 ON_BEFORE_REQUEST));
349 EXPECT_FALSE(ActionWorksOnRequest("http://clients1.google.com",
350 extension_all_urls_->id(),
351 action_set.get(),
352 ON_BEFORE_REQUEST));
353 }
354
355 TEST_F(WebRequestActionWithThreadsTest, PermissionsToAddRequestCookie) {
356 const char* action =
357 "[{"
358 " \"instanceType\": \"declarativeWebRequest.AddRequestCookie\","
359 " \"cookie\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
360 "}]";
361 CheckActionNeedsAllUrls(action, ON_BEFORE_SEND_HEADERS);
362 }
363
364 TEST_F(WebRequestActionWithThreadsTest, PermissionsToAddResponseCookie) {
365 const char* action =
366 "[{"
367 " \"instanceType\": \"declarativeWebRequest.AddResponseCookie\","
368 " \"cookie\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
369 "}]";
370 CheckActionNeedsAllUrls(action, ON_HEADERS_RECEIVED);
371 }
372
373 TEST_F(WebRequestActionWithThreadsTest, PermissionsToEditRequestCookie) {
374 const char* action =
375 "[{"
376 " \"instanceType\": \"declarativeWebRequest.EditRequestCookie\","
377 " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" },"
378 " \"modification\": { \"name\": \"name2\", \"value\": \"value2\" }"
379 "}]";
380 CheckActionNeedsAllUrls(action, ON_BEFORE_SEND_HEADERS);
381 }
382
383 TEST_F(WebRequestActionWithThreadsTest, PermissionsToEditResponseCookie) {
384 const char* action =
385 "[{"
386 " \"instanceType\": \"declarativeWebRequest.EditResponseCookie\","
387 " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" },"
388 " \"modification\": { \"name\": \"name2\", \"value\": \"value2\" }"
389 "}]";
390 CheckActionNeedsAllUrls(action, ON_HEADERS_RECEIVED);
391 }
392
393 TEST_F(WebRequestActionWithThreadsTest, PermissionsToRemoveRequestCookie) {
394 const char* action =
395 "[{"
396 " \"instanceType\": \"declarativeWebRequest.RemoveRequestCookie\","
397 " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
398 "}]";
399 CheckActionNeedsAllUrls(action, ON_BEFORE_SEND_HEADERS);
400 }
401
402 TEST_F(WebRequestActionWithThreadsTest, PermissionsToRemoveResponseCookie) {
403 const char* action =
404 "[{"
405 " \"instanceType\": \"declarativeWebRequest.RemoveResponseCookie\","
406 " \"filter\": { \"name\": \"cookiename\", \"value\": \"cookievalue\" }"
407 "}]";
408 CheckActionNeedsAllUrls(action, ON_HEADERS_RECEIVED);
409 }
410
411 TEST_F(WebRequestActionWithThreadsTest, PermissionsToCancel) {
412 const char* action =
413 "[{"
414 " \"instanceType\": \"declarativeWebRequest.CancelRequest\""
415 "}]";
416 scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(action));
417
418 // Cancelling requests works without full host permissions.
419 EXPECT_TRUE(ActionWorksOnRequest("http://test.org",
420 extension_->id(),
421 action_set.get(),
422 ON_BEFORE_REQUEST));
423 }
424
425 TEST_F(WebRequestActionWithThreadsTest,
426 PermissionsToRedirectToTransparentImage) {
427 const char* action =
428 "[{"
429 " \"instanceType\": \"declarativeWebRequest.RedirectToTransparentImage\""
430 "}]";
431 scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(action));
432
433 // Redirecting to transparent images works without full host permissions.
434 EXPECT_TRUE(ActionWorksOnRequest("http://test.org",
435 extension_->id(),
436 action_set.get(),
437 ON_BEFORE_REQUEST));
438 }
439
440 TEST_F(WebRequestActionWithThreadsTest, PermissionsToRedirectToEmptyDocument) {
441 const char* action =
442 "[{"
443 " \"instanceType\": \"declarativeWebRequest.RedirectToEmptyDocument\""
444 "}]";
445 scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(action));
446
447 // Redirecting to the empty document works without full host permissions.
448 EXPECT_TRUE(ActionWorksOnRequest("http://test.org",
449 extension_->id(),
450 action_set.get(),
451 ON_BEFORE_REQUEST));
452 }
453
454 TEST_F(WebRequestActionWithThreadsTest, PermissionsToIgnore) {
455 const char* action =
456 "[{"
457 " \"instanceType\": \"declarativeWebRequest.IgnoreRules\","
458 " \"lowerPriorityThan\": 123,"
459 " \"hasTag\": \"some_tag\""
460 "}]";
461 scoped_ptr<WebRequestActionSet> action_set(CreateSetOfActions(action));
462
463 // Ignoring rules works without full host permissions.
464 EXPECT_TRUE(ActionWorksOnRequest("http://test.org",
465 extension_->id(),
466 action_set.get(),
467 ON_BEFORE_REQUEST));
157 } 468 }
158 469
159 } // namespace extensions 470 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698