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