| OLD | NEW |
| (Empty) |
| 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_condit
ion.h" | |
| 6 | |
| 7 #include <set> | |
| 8 | |
| 9 #include "base/memory/scoped_ptr.h" | |
| 10 #include "base/message_loop/message_loop.h" | |
| 11 #include "base/test/values_test_util.h" | |
| 12 #include "base/values.h" | |
| 13 #include "components/url_matcher/url_matcher_constants.h" | |
| 14 #include "content/public/browser/resource_request_info.h" | |
| 15 #include "extensions/browser/api/declarative_webrequest/webrequest_constants.h" | |
| 16 #include "net/base/request_priority.h" | |
| 17 #include "net/url_request/url_request.h" | |
| 18 #include "net/url_request/url_request_test_util.h" | |
| 19 #include "testing/gtest/include/gtest/gtest.h" | |
| 20 | |
| 21 using content::ResourceType; | |
| 22 using url_matcher::URLMatcher; | |
| 23 using url_matcher::URLMatcherConditionSet; | |
| 24 | |
| 25 namespace extensions { | |
| 26 | |
| 27 TEST(WebRequestConditionTest, CreateCondition) { | |
| 28 // Necessary for TestURLRequest. | |
| 29 base::MessageLoopForIO message_loop; | |
| 30 URLMatcher matcher; | |
| 31 | |
| 32 std::string error; | |
| 33 scoped_ptr<WebRequestCondition> result; | |
| 34 | |
| 35 // Test wrong condition name passed. | |
| 36 error.clear(); | |
| 37 result = WebRequestCondition::Create( | |
| 38 NULL, | |
| 39 matcher.condition_factory(), | |
| 40 *base::test::ParseJson( | |
| 41 "{ \"invalid\": \"foobar\", \n" | |
| 42 " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" | |
| 43 "}"), | |
| 44 &error); | |
| 45 EXPECT_FALSE(error.empty()); | |
| 46 EXPECT_FALSE(result.get()); | |
| 47 | |
| 48 // Test wrong datatype in host_suffix. | |
| 49 error.clear(); | |
| 50 result = WebRequestCondition::Create( | |
| 51 NULL, | |
| 52 matcher.condition_factory(), | |
| 53 *base::test::ParseJson( | |
| 54 "{ \n" | |
| 55 " \"url\": [], \n" | |
| 56 " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" | |
| 57 "}"), | |
| 58 &error); | |
| 59 EXPECT_FALSE(error.empty()); | |
| 60 EXPECT_FALSE(result.get()); | |
| 61 | |
| 62 // Test success (can we support multiple criteria?) | |
| 63 error.clear(); | |
| 64 result = WebRequestCondition::Create( | |
| 65 NULL, | |
| 66 matcher.condition_factory(), | |
| 67 *base::test::ParseJson( | |
| 68 "{ \n" | |
| 69 " \"resourceType\": [\"main_frame\"], \n" | |
| 70 " \"url\": { \"hostSuffix\": \"example.com\" }, \n" | |
| 71 " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" | |
| 72 "}"), | |
| 73 &error); | |
| 74 EXPECT_EQ("", error); | |
| 75 ASSERT_TRUE(result.get()); | |
| 76 | |
| 77 URLMatcherConditionSet::Vector url_matcher_condition_set; | |
| 78 result->GetURLMatcherConditionSets(&url_matcher_condition_set); | |
| 79 matcher.AddConditionSets(url_matcher_condition_set); | |
| 80 | |
| 81 net::TestURLRequestContext context; | |
| 82 const GURL http_url("http://www.example.com"); | |
| 83 scoped_ptr<net::URLRequest> match_request(context.CreateRequest( | |
| 84 http_url, net::DEFAULT_PRIORITY, NULL, NULL)); | |
| 85 WebRequestData data(match_request.get(), ON_BEFORE_REQUEST); | |
| 86 WebRequestDataWithMatchIds request_data(&data); | |
| 87 request_data.url_match_ids = matcher.MatchURL(http_url); | |
| 88 EXPECT_EQ(1u, request_data.url_match_ids.size()); | |
| 89 content::ResourceRequestInfo::AllocateForTesting( | |
| 90 match_request.get(), | |
| 91 content::RESOURCE_TYPE_MAIN_FRAME, | |
| 92 NULL, | |
| 93 -1, | |
| 94 -1, | |
| 95 -1, | |
| 96 false); | |
| 97 EXPECT_TRUE(result->IsFulfilled(request_data)); | |
| 98 | |
| 99 const GURL https_url("https://www.example.com"); | |
| 100 scoped_ptr<net::URLRequest> wrong_resource_type(context.CreateRequest( | |
| 101 https_url, net::DEFAULT_PRIORITY, NULL, NULL)); | |
| 102 data.request = wrong_resource_type.get(); | |
| 103 request_data.url_match_ids = matcher.MatchURL(http_url); | |
| 104 // Make sure IsFulfilled does not fail because of URL matching. | |
| 105 EXPECT_EQ(1u, request_data.url_match_ids.size()); | |
| 106 content::ResourceRequestInfo::AllocateForTesting( | |
| 107 wrong_resource_type.get(), | |
| 108 content::RESOURCE_TYPE_SUB_FRAME, | |
| 109 NULL, | |
| 110 -1, | |
| 111 -1, | |
| 112 -1, | |
| 113 false); | |
| 114 EXPECT_FALSE(result->IsFulfilled(request_data)); | |
| 115 } | |
| 116 | |
| 117 TEST(WebRequestConditionTest, CreateConditionFirstPartyForCookies) { | |
| 118 // Necessary for TestURLRequest. | |
| 119 base::MessageLoopForIO message_loop; | |
| 120 URLMatcher matcher; | |
| 121 | |
| 122 std::string error; | |
| 123 scoped_ptr<WebRequestCondition> result; | |
| 124 | |
| 125 result = WebRequestCondition::Create( | |
| 126 NULL, | |
| 127 matcher.condition_factory(), | |
| 128 *base::test::ParseJson( | |
| 129 "{ \n" | |
| 130 " \"firstPartyForCookiesUrl\": { \"hostPrefix\": \"fpfc\"}, \n" | |
| 131 " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" | |
| 132 "}"), | |
| 133 &error); | |
| 134 EXPECT_EQ("", error); | |
| 135 ASSERT_TRUE(result.get()); | |
| 136 | |
| 137 URLMatcherConditionSet::Vector url_matcher_condition_set; | |
| 138 result->GetURLMatcherConditionSets(&url_matcher_condition_set); | |
| 139 matcher.AddConditionSets(url_matcher_condition_set); | |
| 140 | |
| 141 net::TestURLRequestContext context; | |
| 142 const GURL http_url("http://www.example.com"); | |
| 143 const GURL first_party_url("http://fpfc.example.com"); | |
| 144 scoped_ptr<net::URLRequest> match_request(context.CreateRequest( | |
| 145 http_url, net::DEFAULT_PRIORITY, NULL, NULL)); | |
| 146 WebRequestData data(match_request.get(), ON_BEFORE_REQUEST); | |
| 147 WebRequestDataWithMatchIds request_data(&data); | |
| 148 request_data.url_match_ids = matcher.MatchURL(http_url); | |
| 149 EXPECT_EQ(0u, request_data.url_match_ids.size()); | |
| 150 request_data.first_party_url_match_ids = matcher.MatchURL(first_party_url); | |
| 151 EXPECT_EQ(1u, request_data.first_party_url_match_ids.size()); | |
| 152 content::ResourceRequestInfo::AllocateForTesting( | |
| 153 match_request.get(), | |
| 154 content::RESOURCE_TYPE_MAIN_FRAME, | |
| 155 NULL, | |
| 156 -1, | |
| 157 -1, | |
| 158 -1, | |
| 159 false); | |
| 160 EXPECT_TRUE(result->IsFulfilled(request_data)); | |
| 161 } | |
| 162 | |
| 163 // Conditions without UrlFilter attributes need to be independent of URL | |
| 164 // matching results. We test here that: | |
| 165 // 1. A non-empty condition without UrlFilter attributes is fulfilled iff its | |
| 166 // attributes are fulfilled. | |
| 167 // 2. An empty condition (in particular, without UrlFilter attributes) is | |
| 168 // always fulfilled. | |
| 169 TEST(WebRequestConditionTest, NoUrlAttributes) { | |
| 170 // Necessary for TestURLRequest. | |
| 171 base::MessageLoopForIO message_loop; | |
| 172 URLMatcher matcher; | |
| 173 std::string error; | |
| 174 | |
| 175 // The empty condition. | |
| 176 error.clear(); | |
| 177 scoped_ptr<WebRequestCondition> condition_empty = WebRequestCondition::Create( | |
| 178 NULL, | |
| 179 matcher.condition_factory(), | |
| 180 *base::test::ParseJson( | |
| 181 "{ \n" | |
| 182 " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" | |
| 183 "}"), | |
| 184 &error); | |
| 185 EXPECT_EQ("", error); | |
| 186 ASSERT_TRUE(condition_empty.get()); | |
| 187 | |
| 188 // A condition without a UrlFilter attribute, which is always true. | |
| 189 error.clear(); | |
| 190 scoped_ptr<WebRequestCondition> condition_no_url_true = | |
| 191 WebRequestCondition::Create( | |
| 192 NULL, | |
| 193 matcher.condition_factory(), | |
| 194 *base::test::ParseJson( | |
| 195 "{ \n" | |
| 196 " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", " | |
| 197 "\n" | |
| 198 // There is no "1st party for cookies" URL in the requests below, | |
| 199 // therefore all requests are considered first party for cookies. | |
| 200 " \"thirdPartyForCookies\": false, \n" | |
| 201 "}"), | |
| 202 &error); | |
| 203 EXPECT_EQ("", error); | |
| 204 ASSERT_TRUE(condition_no_url_true.get()); | |
| 205 | |
| 206 // A condition without a UrlFilter attribute, which is always false. | |
| 207 error.clear(); | |
| 208 scoped_ptr<WebRequestCondition> condition_no_url_false = | |
| 209 WebRequestCondition::Create( | |
| 210 NULL, | |
| 211 matcher.condition_factory(), | |
| 212 *base::test::ParseJson( | |
| 213 "{ \n" | |
| 214 " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", " | |
| 215 "\n" | |
| 216 " \"thirdPartyForCookies\": true, \n" | |
| 217 "}"), | |
| 218 &error); | |
| 219 EXPECT_EQ("", error); | |
| 220 ASSERT_TRUE(condition_no_url_false.get()); | |
| 221 | |
| 222 net::TestURLRequestContext context; | |
| 223 scoped_ptr<net::URLRequest> https_request(context.CreateRequest( | |
| 224 GURL("https://www.example.com"), net::DEFAULT_PRIORITY, NULL, NULL)); | |
| 225 | |
| 226 // 1. A non-empty condition without UrlFilter attributes is fulfilled iff its | |
| 227 // attributes are fulfilled. | |
| 228 WebRequestData data(https_request.get(), ON_BEFORE_REQUEST); | |
| 229 EXPECT_FALSE( | |
| 230 condition_no_url_false->IsFulfilled(WebRequestDataWithMatchIds(&data))); | |
| 231 | |
| 232 data = WebRequestData(https_request.get(), ON_BEFORE_REQUEST); | |
| 233 EXPECT_TRUE( | |
| 234 condition_no_url_true->IsFulfilled(WebRequestDataWithMatchIds(&data))); | |
| 235 | |
| 236 // 2. An empty condition (in particular, without UrlFilter attributes) is | |
| 237 // always fulfilled. | |
| 238 data = WebRequestData(https_request.get(), ON_BEFORE_REQUEST); | |
| 239 EXPECT_TRUE(condition_empty->IsFulfilled(WebRequestDataWithMatchIds(&data))); | |
| 240 } | |
| 241 | |
| 242 TEST(WebRequestConditionTest, CreateConditionSet) { | |
| 243 // Necessary for TestURLRequest. | |
| 244 base::MessageLoopForIO message_loop; | |
| 245 URLMatcher matcher; | |
| 246 | |
| 247 WebRequestConditionSet::AnyVector conditions; | |
| 248 conditions.push_back(linked_ptr<base::Value>(base::test::ParseJson( | |
| 249 "{ \n" | |
| 250 " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" | |
| 251 " \"url\": { \n" | |
| 252 " \"hostSuffix\": \"example.com\", \n" | |
| 253 " \"schemes\": [\"http\"], \n" | |
| 254 " }, \n" | |
| 255 "}").release())); | |
| 256 conditions.push_back(linked_ptr<base::Value>(base::test::ParseJson( | |
| 257 "{ \n" | |
| 258 " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" | |
| 259 " \"url\": { \n" | |
| 260 " \"hostSuffix\": \"example.com\", \n" | |
| 261 " \"hostPrefix\": \"www\", \n" | |
| 262 " \"schemes\": [\"https\"], \n" | |
| 263 " }, \n" | |
| 264 "}").release())); | |
| 265 | |
| 266 // Test insertion | |
| 267 std::string error; | |
| 268 scoped_ptr<WebRequestConditionSet> result = WebRequestConditionSet::Create( | |
| 269 NULL, matcher.condition_factory(), conditions, &error); | |
| 270 EXPECT_EQ("", error); | |
| 271 ASSERT_TRUE(result.get()); | |
| 272 EXPECT_EQ(2u, result->conditions().size()); | |
| 273 | |
| 274 // Tell the URLMatcher about our shiny new patterns. | |
| 275 URLMatcherConditionSet::Vector url_matcher_condition_set; | |
| 276 result->GetURLMatcherConditionSets(&url_matcher_condition_set); | |
| 277 matcher.AddConditionSets(url_matcher_condition_set); | |
| 278 | |
| 279 // Test that the result is correct and matches http://www.example.com and | |
| 280 // https://www.example.com | |
| 281 GURL http_url("http://www.example.com"); | |
| 282 net::TestURLRequestContext context; | |
| 283 scoped_ptr<net::URLRequest> http_request(context.CreateRequest( | |
| 284 http_url, net::DEFAULT_PRIORITY, NULL, NULL)); | |
| 285 WebRequestData data(http_request.get(), ON_BEFORE_REQUEST); | |
| 286 WebRequestDataWithMatchIds request_data(&data); | |
| 287 request_data.url_match_ids = matcher.MatchURL(http_url); | |
| 288 EXPECT_EQ(1u, request_data.url_match_ids.size()); | |
| 289 EXPECT_TRUE(result->IsFulfilled(*(request_data.url_match_ids.begin()), | |
| 290 request_data)); | |
| 291 | |
| 292 GURL https_url("https://www.example.com"); | |
| 293 request_data.url_match_ids = matcher.MatchURL(https_url); | |
| 294 EXPECT_EQ(1u, request_data.url_match_ids.size()); | |
| 295 scoped_ptr<net::URLRequest> https_request(context.CreateRequest( | |
| 296 https_url, net::DEFAULT_PRIORITY, NULL, NULL)); | |
| 297 data.request = https_request.get(); | |
| 298 EXPECT_TRUE(result->IsFulfilled(*(request_data.url_match_ids.begin()), | |
| 299 request_data)); | |
| 300 | |
| 301 // Check that both, hostPrefix and hostSuffix are evaluated. | |
| 302 GURL https_foo_url("https://foo.example.com"); | |
| 303 request_data.url_match_ids = matcher.MatchURL(https_foo_url); | |
| 304 EXPECT_EQ(0u, request_data.url_match_ids.size()); | |
| 305 scoped_ptr<net::URLRequest> https_foo_request(context.CreateRequest( | |
| 306 https_foo_url, net::DEFAULT_PRIORITY, NULL, NULL)); | |
| 307 data.request = https_foo_request.get(); | |
| 308 EXPECT_FALSE(result->IsFulfilled(-1, request_data)); | |
| 309 } | |
| 310 | |
| 311 TEST(WebRequestConditionTest, TestPortFilter) { | |
| 312 // Necessary for TestURLRequest. | |
| 313 base::MessageLoopForIO message_loop; | |
| 314 URLMatcher matcher; | |
| 315 | |
| 316 WebRequestConditionSet::AnyVector conditions; | |
| 317 conditions.push_back(linked_ptr<base::Value>(base::test::ParseJson( | |
| 318 "{ \n" | |
| 319 " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" | |
| 320 " \"url\": { \n" | |
| 321 " \"ports\": [80, [1000, 1010]], \n" // Allow 80;1000-1010. | |
| 322 " \"hostSuffix\": \"example.com\", \n" | |
| 323 " }, \n" | |
| 324 "}").release())); | |
| 325 | |
| 326 // Test insertion | |
| 327 std::string error; | |
| 328 scoped_ptr<WebRequestConditionSet> result = WebRequestConditionSet::Create( | |
| 329 NULL, matcher.condition_factory(), conditions, &error); | |
| 330 EXPECT_EQ("", error); | |
| 331 ASSERT_TRUE(result.get()); | |
| 332 EXPECT_EQ(1u, result->conditions().size()); | |
| 333 | |
| 334 // Tell the URLMatcher about our shiny new patterns. | |
| 335 URLMatcherConditionSet::Vector url_matcher_condition_set; | |
| 336 result->GetURLMatcherConditionSets(&url_matcher_condition_set); | |
| 337 matcher.AddConditionSets(url_matcher_condition_set); | |
| 338 | |
| 339 std::set<URLMatcherConditionSet::ID> url_match_ids; | |
| 340 | |
| 341 // Test various URLs. | |
| 342 GURL http_url("http://www.example.com"); | |
| 343 net::TestURLRequestContext context; | |
| 344 scoped_ptr<net::URLRequest> http_request(context.CreateRequest( | |
| 345 http_url, net::DEFAULT_PRIORITY, NULL, NULL)); | |
| 346 url_match_ids = matcher.MatchURL(http_url); | |
| 347 ASSERT_EQ(1u, url_match_ids.size()); | |
| 348 | |
| 349 GURL http_url_80("http://www.example.com:80"); | |
| 350 scoped_ptr<net::URLRequest> http_request_80(context.CreateRequest( | |
| 351 http_url_80, net::DEFAULT_PRIORITY, NULL, NULL)); | |
| 352 url_match_ids = matcher.MatchURL(http_url_80); | |
| 353 ASSERT_EQ(1u, url_match_ids.size()); | |
| 354 | |
| 355 GURL http_url_1000("http://www.example.com:1000"); | |
| 356 scoped_ptr<net::URLRequest> http_request_1000(context.CreateRequest( | |
| 357 http_url_1000, net::DEFAULT_PRIORITY, NULL, NULL)); | |
| 358 url_match_ids = matcher.MatchURL(http_url_1000); | |
| 359 ASSERT_EQ(1u, url_match_ids.size()); | |
| 360 | |
| 361 GURL http_url_2000("http://www.example.com:2000"); | |
| 362 scoped_ptr<net::URLRequest> http_request_2000(context.CreateRequest( | |
| 363 http_url_2000, net::DEFAULT_PRIORITY, NULL, NULL)); | |
| 364 url_match_ids = matcher.MatchURL(http_url_2000); | |
| 365 ASSERT_EQ(0u, url_match_ids.size()); | |
| 366 } | |
| 367 | |
| 368 // Create a condition with two attributes: one on the request header and one on | |
| 369 // the response header. The Create() method should fail and complain that it is | |
| 370 // impossible that both conditions are fulfilled at the same time. | |
| 371 TEST(WebRequestConditionTest, ConditionsWithConflictingStages) { | |
| 372 // Necessary for TestURLRequest. | |
| 373 base::MessageLoopForIO message_loop; | |
| 374 URLMatcher matcher; | |
| 375 | |
| 376 std::string error; | |
| 377 scoped_ptr<WebRequestCondition> result; | |
| 378 | |
| 379 // Test error on incompatible application stages for involved attributes. | |
| 380 error.clear(); | |
| 381 result = WebRequestCondition::Create( | |
| 382 NULL, | |
| 383 matcher.condition_factory(), | |
| 384 *base::test::ParseJson( | |
| 385 "{ \n" | |
| 386 " \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n" | |
| 387 // Pass a JS array with one empty object to each of the header | |
| 388 // filters. | |
| 389 " \"requestHeaders\": [{}], \n" | |
| 390 " \"responseHeaders\": [{}], \n" | |
| 391 "}"), | |
| 392 &error); | |
| 393 EXPECT_FALSE(error.empty()); | |
| 394 EXPECT_FALSE(result.get()); | |
| 395 } | |
| 396 | |
| 397 } // namespace extensions | |
| OLD | NEW |