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