Home | History | Annotate | Download | only in policy
      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 "components/policy/core/browser/url_blacklist_manager.h"
      6 
      7 #include <ostream>
      8 
      9 #include "base/basictypes.h"
     10 #include "base/callback.h"
     11 #include "base/message_loop/message_loop.h"
     12 #include "base/message_loop/message_loop_proxy.h"
     13 #include "base/prefs/pref_registry_simple.h"
     14 #include "base/prefs/testing_pref_service.h"
     15 #include "chrome/browser/policy/policy_helpers.h"
     16 #include "components/policy/core/common/policy_pref_names.h"
     17 #include "components/url_fixer/url_fixer.h"
     18 #include "google_apis/gaia/gaia_urls.h"
     19 #include "net/base/load_flags.h"
     20 #include "net/base/net_errors.h"
     21 #include "net/base/request_priority.h"
     22 #include "net/url_request/url_request.h"
     23 #include "net/url_request/url_request_test_util.h"
     24 #include "testing/gtest/include/gtest/gtest.h"
     25 #include "url/gurl.h"
     26 
     27 // TODO(joaodasilva): this file should be moved next to
     28 // components/policy/core/browser/url_blacklist_manager.(cc|h).
     29 // However, url_fixer_upper.h can't be included from the component. Rather
     30 // than having it mocked out, the actual url_fixer::SegmentURL call is used
     31 // to make sure that the parsing of URL filters is correct.
     32 
     33 namespace policy {
     34 
     35 namespace {
     36 
     37 // Helper to get the disambiguated SegmentURL() function.
     38 URLBlacklist::SegmentURLCallback GetSegmentURLCallback() {
     39   return url_fixer::SegmentURL;
     40 }
     41 
     42 class TestingURLBlacklistManager : public URLBlacklistManager {
     43  public:
     44   explicit TestingURLBlacklistManager(PrefService* pref_service)
     45       : URLBlacklistManager(pref_service,
     46                             base::MessageLoopProxy::current(),
     47                             base::MessageLoopProxy::current(),
     48                             GetSegmentURLCallback(),
     49                             base::Bind(OverrideBlacklistForURL)),
     50         update_called_(0),
     51         set_blacklist_called_(false) {}
     52 
     53   virtual ~TestingURLBlacklistManager() {
     54   }
     55 
     56   // Make this method public for testing.
     57   using URLBlacklistManager::ScheduleUpdate;
     58 
     59   // Makes a direct call to UpdateOnIO during tests.
     60   void UpdateOnIOForTesting() {
     61     scoped_ptr<base::ListValue> block(new base::ListValue);
     62     block->Append(new base::StringValue("example.com"));
     63     scoped_ptr<base::ListValue> allow(new base::ListValue);
     64     URLBlacklistManager::UpdateOnIO(block.Pass(), allow.Pass());
     65   }
     66 
     67   // URLBlacklistManager overrides:
     68   virtual void SetBlacklist(scoped_ptr<URLBlacklist> blacklist) OVERRIDE {
     69     set_blacklist_called_ = true;
     70     URLBlacklistManager::SetBlacklist(blacklist.Pass());
     71   }
     72 
     73   virtual void Update() OVERRIDE {
     74     update_called_++;
     75     URLBlacklistManager::Update();
     76   }
     77 
     78   int update_called() const { return update_called_; }
     79   bool set_blacklist_called() const { return set_blacklist_called_; }
     80 
     81  private:
     82   int update_called_;
     83   bool set_blacklist_called_;
     84 
     85   DISALLOW_COPY_AND_ASSIGN(TestingURLBlacklistManager);
     86 };
     87 
     88 class URLBlacklistManagerTest : public testing::Test {
     89  protected:
     90   URLBlacklistManagerTest() {}
     91 
     92   virtual void SetUp() OVERRIDE {
     93     pref_service_.registry()->RegisterListPref(policy_prefs::kUrlBlacklist);
     94     pref_service_.registry()->RegisterListPref(policy_prefs::kUrlWhitelist);
     95     blacklist_manager_.reset(new TestingURLBlacklistManager(&pref_service_));
     96     loop_.RunUntilIdle();
     97   }
     98 
     99   virtual void TearDown() OVERRIDE {
    100     if (blacklist_manager_.get())
    101       blacklist_manager_->ShutdownOnUIThread();
    102     loop_.RunUntilIdle();
    103     // Delete |blacklist_manager_| while |io_thread_| is mapping IO to
    104     // |loop_|.
    105     blacklist_manager_.reset();
    106   }
    107 
    108   base::MessageLoopForIO loop_;
    109   TestingPrefServiceSimple pref_service_;
    110   scoped_ptr<TestingURLBlacklistManager> blacklist_manager_;
    111 };
    112 
    113 // Parameters for the FilterToComponents test.
    114 struct FilterTestParams {
    115  public:
    116   FilterTestParams(const std::string& filter, const std::string& scheme,
    117                    const std::string& host, bool match_subdomains, uint16 port,
    118                    const std::string& path)
    119       : filter_(filter), scheme_(scheme), host_(host),
    120         match_subdomains_(match_subdomains), port_(port), path_(path) {}
    121 
    122   FilterTestParams(const FilterTestParams& params)
    123       : filter_(params.filter_), scheme_(params.scheme_), host_(params.host_),
    124         match_subdomains_(params.match_subdomains_), port_(params.port_),
    125         path_(params.path_) {}
    126 
    127   const FilterTestParams& operator=(const FilterTestParams& params) {
    128     filter_ = params.filter_;
    129     scheme_ = params.scheme_;
    130     host_ = params.host_;
    131     match_subdomains_ = params.match_subdomains_;
    132     port_ = params.port_;
    133     path_ = params.path_;
    134     return *this;
    135   }
    136 
    137   const std::string& filter() const { return filter_; }
    138   const std::string& scheme() const { return scheme_; }
    139   const std::string& host() const { return host_; }
    140   bool match_subdomains() const { return match_subdomains_; }
    141   uint16 port() const { return port_; }
    142   const std::string& path() const { return path_; }
    143 
    144  private:
    145   std::string filter_;
    146   std::string scheme_;
    147   std::string host_;
    148   bool match_subdomains_;
    149   uint16 port_;
    150   std::string path_;
    151 };
    152 
    153 // Make Valgrind happy. Without this function, a generic one will print the
    154 // raw bytes in FilterTestParams, which due to some likely padding will access
    155 // uninitialized memory.
    156 void PrintTo(const FilterTestParams& params, std::ostream* os) {
    157   *os << params.filter();
    158 }
    159 
    160 class URLBlacklistFilterToComponentsTest
    161     : public testing::TestWithParam<FilterTestParams> {
    162  public:
    163   URLBlacklistFilterToComponentsTest() {}
    164 
    165  private:
    166   DISALLOW_COPY_AND_ASSIGN(URLBlacklistFilterToComponentsTest);
    167 };
    168 
    169 }  // namespace
    170 
    171 TEST_P(URLBlacklistFilterToComponentsTest, FilterToComponents) {
    172   std::string scheme;
    173   std::string host;
    174   bool match_subdomains = true;
    175   uint16 port = 42;
    176   std::string path;
    177 
    178   URLBlacklist::FilterToComponents(GetSegmentURLCallback(),
    179                                    GetParam().filter(),
    180                                    &scheme,
    181                                    &host,
    182                                    &match_subdomains,
    183                                    &port,
    184                                    &path,
    185                                    NULL);
    186   EXPECT_EQ(GetParam().scheme(), scheme);
    187   EXPECT_EQ(GetParam().host(), host);
    188   EXPECT_EQ(GetParam().match_subdomains(), match_subdomains);
    189   EXPECT_EQ(GetParam().port(), port);
    190   EXPECT_EQ(GetParam().path(), path);
    191 }
    192 
    193 TEST_F(URLBlacklistManagerTest, SingleUpdateForTwoPrefChanges) {
    194   base::ListValue* blacklist = new base::ListValue;
    195   blacklist->Append(new base::StringValue("*.google.com"));
    196   base::ListValue* whitelist = new base::ListValue;
    197   whitelist->Append(new base::StringValue("mail.google.com"));
    198   pref_service_.SetManagedPref(policy_prefs::kUrlBlacklist, blacklist);
    199   pref_service_.SetManagedPref(policy_prefs::kUrlBlacklist, whitelist);
    200   loop_.RunUntilIdle();
    201 
    202   EXPECT_EQ(1, blacklist_manager_->update_called());
    203 }
    204 
    205 TEST_F(URLBlacklistManagerTest, ShutdownWithPendingTask0) {
    206   // Post an update task to the UI thread.
    207   blacklist_manager_->ScheduleUpdate();
    208   // Shutdown comes before the task is executed.
    209   blacklist_manager_->ShutdownOnUIThread();
    210   blacklist_manager_.reset();
    211   // Run the task after shutdown and deletion.
    212   loop_.RunUntilIdle();
    213 }
    214 
    215 TEST_F(URLBlacklistManagerTest, ShutdownWithPendingTask1) {
    216   // Post an update task.
    217   blacklist_manager_->ScheduleUpdate();
    218   // Shutdown comes before the task is executed.
    219   blacklist_manager_->ShutdownOnUIThread();
    220   // Run the task after shutdown, but before deletion.
    221   loop_.RunUntilIdle();
    222 
    223   EXPECT_EQ(0, blacklist_manager_->update_called());
    224   blacklist_manager_.reset();
    225   loop_.RunUntilIdle();
    226 }
    227 
    228 TEST_F(URLBlacklistManagerTest, ShutdownWithPendingTask2) {
    229   // This posts a task to the FILE thread.
    230   blacklist_manager_->UpdateOnIOForTesting();
    231   // But shutdown happens before it is done.
    232   blacklist_manager_->ShutdownOnUIThread();
    233 
    234   EXPECT_FALSE(blacklist_manager_->set_blacklist_called());
    235   blacklist_manager_.reset();
    236   loop_.RunUntilIdle();
    237 }
    238 
    239 INSTANTIATE_TEST_CASE_P(
    240     URLBlacklistFilterToComponentsTestInstance,
    241     URLBlacklistFilterToComponentsTest,
    242     testing::Values(
    243         FilterTestParams("google.com",
    244                          std::string(),
    245                          ".google.com",
    246                          true,
    247                          0u,
    248                          std::string()),
    249         FilterTestParams(".google.com",
    250                          std::string(),
    251                          "google.com",
    252                          false,
    253                          0u,
    254                          std::string()),
    255         FilterTestParams("http://google.com",
    256                          "http",
    257                          ".google.com",
    258                          true,
    259                          0u,
    260                          std::string()),
    261         FilterTestParams("google.com/",
    262                          std::string(),
    263                          ".google.com",
    264                          true,
    265                          0u,
    266                          "/"),
    267         FilterTestParams("http://google.com:8080/whatever",
    268                          "http",
    269                          ".google.com",
    270                          true,
    271                          8080u,
    272                          "/whatever"),
    273         FilterTestParams("http://user:pass@google.com:8080/whatever",
    274                          "http",
    275                          ".google.com",
    276                          true,
    277                          8080u,
    278                          "/whatever"),
    279         FilterTestParams("123.123.123.123",
    280                          std::string(),
    281                          "123.123.123.123",
    282                          false,
    283                          0u,
    284                          std::string()),
    285         FilterTestParams("https://123.123.123.123",
    286                          "https",
    287                          "123.123.123.123",
    288                          false,
    289                          0u,
    290                          std::string()),
    291         FilterTestParams("123.123.123.123/",
    292                          std::string(),
    293                          "123.123.123.123",
    294                          false,
    295                          0u,
    296                          "/"),
    297         FilterTestParams("http://123.123.123.123:123/whatever",
    298                          "http",
    299                          "123.123.123.123",
    300                          false,
    301                          123u,
    302                          "/whatever"),
    303         FilterTestParams("*",
    304                          std::string(),
    305                          std::string(),
    306                          true,
    307                          0u,
    308                          std::string()),
    309         FilterTestParams("ftp://*",
    310                          "ftp",
    311                          std::string(),
    312                          true,
    313                          0u,
    314                          std::string()),
    315         FilterTestParams("http://*/whatever",
    316                          "http",
    317                          std::string(),
    318                          true,
    319                          0u,
    320                          "/whatever")));
    321 
    322 TEST_F(URLBlacklistManagerTest, Filtering) {
    323   URLBlacklist blacklist(GetSegmentURLCallback());
    324 
    325   // Block domain and all subdomains, for any filtered scheme.
    326   scoped_ptr<base::ListValue> blocked(new base::ListValue);
    327   blocked->Append(new base::StringValue("google.com"));
    328   blacklist.Block(blocked.get());
    329   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://google.com")));
    330   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://google.com/")));
    331   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://google.com/whatever")));
    332   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("https://google.com/")));
    333   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("bogus://google.com/")));
    334   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://notgoogle.com/")));
    335   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://mail.google.com")));
    336   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://x.mail.google.com")));
    337   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("https://x.mail.google.com/")));
    338   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://x.y.google.com/a/b")));
    339   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://youtube.com/")));
    340 
    341   // Filter only http, ftp and ws schemes.
    342   blocked.reset(new base::ListValue);
    343   blocked->Append(new base::StringValue("http://secure.com"));
    344   blocked->Append(new base::StringValue("ftp://secure.com"));
    345   blocked->Append(new base::StringValue("ws://secure.com"));
    346   blacklist.Block(blocked.get());
    347   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://secure.com")));
    348   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://secure.com/whatever")));
    349   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("ftp://secure.com/")));
    350   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("ws://secure.com")));
    351   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("https://secure.com/")));
    352   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("wss://secure.com")));
    353   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://www.secure.com")));
    354   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("https://www.secure.com")));
    355   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("wss://www.secure.com")));
    356 
    357   // Filter only a certain path prefix.
    358   blocked.reset(new base::ListValue);
    359   blocked->Append(new base::StringValue("path.to/ruin"));
    360   blacklist.Block(blocked.get());
    361   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://path.to/ruin")));
    362   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("https://path.to/ruin")));
    363   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://path.to/ruins")));
    364   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://path.to/ruin/signup")));
    365   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://www.path.to/ruin")));
    366   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://path.to/fortune")));
    367 
    368   // Filter only a certain path prefix and scheme.
    369   blocked.reset(new base::ListValue);
    370   blocked->Append(new base::StringValue("https://s.aaa.com/path"));
    371   blacklist.Block(blocked.get());
    372   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("https://s.aaa.com/path")));
    373   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("https://s.aaa.com/path/bbb")));
    374   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://s.aaa.com/path")));
    375   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("https://aaa.com/path")));
    376   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("https://x.aaa.com/path")));
    377   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("https://s.aaa.com/bbb")));
    378   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("https://s.aaa.com/")));
    379 
    380   // Filter only ws and wss schemes.
    381   blocked.reset(new base::ListValue);
    382   blocked->Append(new base::StringValue("ws://ws.aaa.com"));
    383   blocked->Append(new base::StringValue("wss://ws.aaa.com"));
    384   blacklist.Block(blocked.get());
    385   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("ws://ws.aaa.com")));
    386   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("wss://ws.aaa.com")));
    387   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://ws.aaa.com")));
    388   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("https://ws.aaa.com")));
    389   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("ftp://ws.aaa.com")));
    390 
    391   // Test exceptions to path prefixes, and most specific matches.
    392   blocked.reset(new base::ListValue);
    393   scoped_ptr<base::ListValue> allowed(new base::ListValue);
    394   blocked->Append(new base::StringValue("s.xxx.com/a"));
    395   allowed->Append(new base::StringValue("s.xxx.com/a/b"));
    396   blocked->Append(new base::StringValue("https://s.xxx.com/a/b/c"));
    397   allowed->Append(new base::StringValue("https://s.xxx.com/a/b/c/d"));
    398   blacklist.Block(blocked.get());
    399   blacklist.Allow(allowed.get());
    400   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://s.xxx.com/a")));
    401   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://s.xxx.com/a/x")));
    402   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("https://s.xxx.com/a/x")));
    403   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://s.xxx.com/a/b")));
    404   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("https://s.xxx.com/a/b")));
    405   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://s.xxx.com/a/b/x")));
    406   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://s.xxx.com/a/b/c")));
    407   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("https://s.xxx.com/a/b/c")));
    408   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("https://s.xxx.com/a/b/c/x")));
    409   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("https://s.xxx.com/a/b/c/d")));
    410   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://s.xxx.com/a/b/c/d")));
    411   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("https://s.xxx.com/a/b/c/d/x")));
    412   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://s.xxx.com/a/b/c/d/x")));
    413   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://xxx.com/a")));
    414   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://xxx.com/a/b")));
    415 
    416   // Block an ip address.
    417   blocked.reset(new base::ListValue);
    418   blocked->Append(new base::StringValue("123.123.123.123"));
    419   blacklist.Block(blocked.get());
    420   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://123.123.123.123/")));
    421   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://123.123.123.124/")));
    422 
    423   // Open an exception.
    424   allowed.reset(new base::ListValue);
    425   allowed->Append(new base::StringValue("plus.google.com"));
    426   blacklist.Allow(allowed.get());
    427   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://google.com/")));
    428   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://www.google.com/")));
    429   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://plus.google.com/")));
    430 
    431   // Open an exception only when using https for mail.
    432   allowed.reset(new base::ListValue);
    433   allowed->Append(new base::StringValue("https://mail.google.com"));
    434   blacklist.Allow(allowed.get());
    435   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://google.com/")));
    436   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://mail.google.com/")));
    437   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://www.google.com/")));
    438   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("https://www.google.com/")));
    439   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("https://mail.google.com/")));
    440 
    441   // Match exactly "google.com", only for http. Subdomains without exceptions
    442   // are still blocked.
    443   allowed.reset(new base::ListValue);
    444   allowed->Append(new base::StringValue("http://.google.com"));
    445   blacklist.Allow(allowed.get());
    446   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://google.com/")));
    447   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("https://google.com/")));
    448   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://www.google.com/")));
    449 
    450   // A smaller path match in an exact host overrides a longer path for hosts
    451   // that also match subdomains.
    452   blocked.reset(new base::ListValue);
    453   blocked->Append(new base::StringValue("yyy.com/aaa"));
    454   blacklist.Block(blocked.get());
    455   allowed.reset(new base::ListValue);
    456   allowed->Append(new base::StringValue(".yyy.com/a"));
    457   blacklist.Allow(allowed.get());
    458   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://yyy.com")));
    459   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://yyy.com/aaa")));
    460   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://yyy.com/aaa2")));
    461   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://www.yyy.com")));
    462   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://www.yyy.com/aaa")));
    463   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://www.yyy.com/aaa2")));
    464 
    465   // If the exact entry is both allowed and blocked, allowing takes precedence.
    466   blocked.reset(new base::ListValue);
    467   blocked->Append(new base::StringValue("example.com"));
    468   blacklist.Block(blocked.get());
    469   allowed.reset(new base::ListValue);
    470   allowed->Append(new base::StringValue("example.com"));
    471   blacklist.Allow(allowed.get());
    472   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://example.com")));
    473 }
    474 
    475 TEST_F(URLBlacklistManagerTest, QueryParameters) {
    476   URLBlacklist blacklist(GetSegmentURLCallback());
    477   scoped_ptr<base::ListValue> blocked(new base::ListValue);
    478   scoped_ptr<base::ListValue> allowed(new base::ListValue);
    479 
    480   // Block domain and all subdomains, for any filtered scheme.
    481   blocked->AppendString("youtube.com");
    482   allowed->AppendString("youtube.com/watch?v=XYZ");
    483   blacklist.Block(blocked.get());
    484   blacklist.Allow(allowed.get());
    485 
    486   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://youtube.com")));
    487   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://youtube.com/watch?v=123")));
    488   EXPECT_TRUE(
    489       blacklist.IsURLBlocked(GURL("http://youtube.com/watch?v=123&v=XYZ")));
    490   EXPECT_TRUE(
    491       blacklist.IsURLBlocked(GURL("http://youtube.com/watch?v=XYZ&v=123")));
    492   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://youtube.com/watch?v=XYZ")));
    493   EXPECT_FALSE(
    494       blacklist.IsURLBlocked(GURL("http://youtube.com/watch?v=XYZ&foo=bar")));
    495   EXPECT_FALSE(
    496       blacklist.IsURLBlocked(GURL("http://youtube.com/watch?foo=bar&v=XYZ")));
    497 
    498   allowed.reset(new base::ListValue);
    499   allowed->AppendString("youtube.com/watch?av=XYZ&ag=123");
    500   blacklist.Allow(allowed.get());
    501   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://youtube.com")));
    502   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://youtube.com/watch?av=123")));
    503   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://youtube.com/watch?av=XYZ")));
    504   EXPECT_TRUE(
    505       blacklist.IsURLBlocked(GURL("http://youtube.com/watch?av=123&ag=XYZ")));
    506   EXPECT_TRUE(
    507       blacklist.IsURLBlocked(GURL("http://youtube.com/watch?ag=XYZ&av=123")));
    508   EXPECT_FALSE(
    509       blacklist.IsURLBlocked(GURL("http://youtube.com/watch?av=XYZ&ag=123")));
    510   EXPECT_FALSE(
    511       blacklist.IsURLBlocked(GURL("http://youtube.com/watch?ag=123&av=XYZ")));
    512   EXPECT_TRUE(blacklist.IsURLBlocked(
    513       GURL("http://youtube.com/watch?av=XYZ&ag=123&av=123")));
    514   EXPECT_TRUE(blacklist.IsURLBlocked(
    515       GURL("http://youtube.com/watch?av=XYZ&ag=123&ag=1234")));
    516 
    517   allowed.reset(new base::ListValue);
    518   allowed->AppendString("youtube.com/watch?foo=bar*&vid=2*");
    519   blacklist.Allow(allowed.get());
    520   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://youtube.com")));
    521   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://youtube.com/watch?vid=2")));
    522   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://youtube.com/watch?foo=bar")));
    523   EXPECT_FALSE(
    524       blacklist.IsURLBlocked(GURL("http://youtube.com/watch?vid=2&foo=bar")));
    525   EXPECT_FALSE(
    526       blacklist.IsURLBlocked(GURL("http://youtube.com/watch?vid=2&foo=bar1")));
    527   EXPECT_FALSE(
    528       blacklist.IsURLBlocked(GURL("http://youtube.com/watch?vid=234&foo=bar")));
    529   EXPECT_FALSE(blacklist.IsURLBlocked(
    530       GURL("http://youtube.com/watch?vid=234&foo=bar23")));
    531 
    532   blocked.reset(new base::ListValue);
    533   blocked->AppendString("youtube1.com/disallow?v=44678");
    534   blacklist.Block(blocked.get());
    535   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://youtube1.com")));
    536   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://youtube1.com?v=123")));
    537   // Path does not match
    538   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://youtube1.com?v=44678")));
    539   EXPECT_TRUE(
    540       blacklist.IsURLBlocked(GURL("http://youtube1.com/disallow?v=44678")));
    541   EXPECT_FALSE(
    542       blacklist.IsURLBlocked(GURL("http://youtube1.com/disallow?v=4467")));
    543   EXPECT_FALSE(blacklist.IsURLBlocked(
    544       GURL("http://youtube1.com/disallow?v=4467&v=123")));
    545   EXPECT_TRUE(blacklist.IsURLBlocked(
    546       GURL("http://youtube1.com/disallow?v=4467&v=123&v=44678")));
    547 
    548   blocked.reset(new base::ListValue);
    549   blocked->AppendString("youtube1.com/disallow?g=*");
    550   blacklist.Block(blocked.get());
    551   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://youtube1.com")));
    552   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://youtube1.com?ag=123")));
    553   EXPECT_TRUE(
    554       blacklist.IsURLBlocked(GURL("http://youtube1.com/disallow?g=123")));
    555   EXPECT_TRUE(
    556       blacklist.IsURLBlocked(GURL("http://youtube1.com/disallow?ag=13&g=123")));
    557 
    558   blocked.reset(new base::ListValue);
    559   blocked->AppendString("youtube2.com/disallow?a*");
    560   blacklist.Block(blocked.get());
    561   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://youtube2.com")));
    562   EXPECT_TRUE(blacklist.IsURLBlocked(
    563       GURL("http://youtube2.com/disallow?b=123&a21=467")));
    564   EXPECT_TRUE(
    565       blacklist.IsURLBlocked(GURL("http://youtube2.com/disallow?abba=true")));
    566   EXPECT_FALSE(
    567       blacklist.IsURLBlocked(GURL("http://youtube2.com/disallow?baba=true")));
    568 
    569   allowed.reset(new base::ListValue);
    570   blocked.reset(new base::ListValue);
    571   blocked->AppendString("youtube3.com");
    572   allowed->AppendString("youtube3.com/watch?fo*");
    573   blacklist.Block(blocked.get());
    574   blacklist.Allow(allowed.get());
    575   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://youtube3.com")));
    576   EXPECT_TRUE(
    577       blacklist.IsURLBlocked(GURL("http://youtube3.com/watch?b=123&a21=467")));
    578   EXPECT_FALSE(blacklist.IsURLBlocked(
    579       GURL("http://youtube3.com/watch?b=123&a21=467&foo1")));
    580   EXPECT_FALSE(blacklist.IsURLBlocked(
    581       GURL("http://youtube3.com/watch?b=123&a21=467&foo=bar")));
    582   EXPECT_FALSE(blacklist.IsURLBlocked(
    583       GURL("http://youtube3.com/watch?b=123&a21=467&fo=ba")));
    584   EXPECT_FALSE(
    585       blacklist.IsURLBlocked(GURL("http://youtube3.com/watch?foriegn=true")));
    586   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://youtube3.com/watch?fold")));
    587 
    588   allowed.reset(new base::ListValue);
    589   blocked.reset(new base::ListValue);
    590   blocked->AppendString("youtube4.com");
    591   allowed->AppendString("youtube4.com?*");
    592   blacklist.Block(blocked.get());
    593   blacklist.Allow(allowed.get());
    594   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://youtube4.com")));
    595   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://youtube4.com/?hello")));
    596   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://youtube4.com/?foo")));
    597 
    598   allowed.reset(new base::ListValue);
    599   blocked.reset(new base::ListValue);
    600   blocked->AppendString("youtube5.com?foo=bar");
    601   allowed->AppendString("youtube5.com?foo1=bar1&foo2=bar2&");
    602   blacklist.Block(blocked.get());
    603   blacklist.Allow(allowed.get());
    604   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://youtube5.com")));
    605   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://youtube5.com/?foo=bar&a=b")));
    606   // More specific filter is given precedence.
    607   EXPECT_FALSE(blacklist.IsURLBlocked(
    608       GURL("http://youtube5.com/?a=b&foo=bar&foo1=bar1&foo2=bar2")));
    609 }
    610 
    611 TEST_F(URLBlacklistManagerTest, BlockAllWithExceptions) {
    612   URLBlacklist blacklist(GetSegmentURLCallback());
    613 
    614   scoped_ptr<base::ListValue> blocked(new base::ListValue);
    615   scoped_ptr<base::ListValue> allowed(new base::ListValue);
    616   blocked->Append(new base::StringValue("*"));
    617   allowed->Append(new base::StringValue(".www.google.com"));
    618   allowed->Append(new base::StringValue("plus.google.com"));
    619   allowed->Append(new base::StringValue("https://mail.google.com"));
    620   allowed->Append(new base::StringValue("https://very.safe/path"));
    621   blacklist.Block(blocked.get());
    622   blacklist.Allow(allowed.get());
    623   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://random.com")));
    624   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://google.com")));
    625   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://s.www.google.com")));
    626   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://www.google.com")));
    627   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://plus.google.com")));
    628   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("http://s.plus.google.com")));
    629   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://mail.google.com")));
    630   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("https://mail.google.com")));
    631   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("https://s.mail.google.com")));
    632   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("https://very.safe/")));
    633   EXPECT_TRUE(blacklist.IsURLBlocked(GURL("http://very.safe/path")));
    634   EXPECT_FALSE(blacklist.IsURLBlocked(GURL("https://very.safe/path")));
    635 }
    636 
    637 TEST_F(URLBlacklistManagerTest, DontBlockResources) {
    638   scoped_ptr<URLBlacklist> blacklist(new URLBlacklist(GetSegmentURLCallback()));
    639   scoped_ptr<base::ListValue> blocked(new base::ListValue);
    640   blocked->Append(new base::StringValue("google.com"));
    641   blacklist->Block(blocked.get());
    642   blacklist_manager_->SetBlacklist(blacklist.Pass());
    643   EXPECT_TRUE(blacklist_manager_->IsURLBlocked(GURL("http://google.com")));
    644 
    645   net::TestURLRequestContext context;
    646   net::URLRequest request(
    647       GURL("http://google.com"), net::DEFAULT_PRIORITY, NULL, &context);
    648 
    649   int reason = net::ERR_UNEXPECTED;
    650   // Background requests aren't filtered.
    651   EXPECT_FALSE(blacklist_manager_->IsRequestBlocked(request, &reason));
    652 
    653   // Main frames are filtered.
    654   request.SetLoadFlags(net::LOAD_MAIN_FRAME);
    655   EXPECT_TRUE(blacklist_manager_->IsRequestBlocked(request, &reason));
    656   EXPECT_EQ(net::ERR_BLOCKED_BY_ADMINISTRATOR, reason);
    657 
    658   // On most platforms, sync gets a free pass due to signin flows.
    659   bool block_signin_urls = false;
    660 #if defined(OS_CHROMEOS)
    661   // There are no sync specific signin flows on Chrome OS, so no special
    662   // treatment.
    663   block_signin_urls = true;
    664 #endif
    665 
    666   GURL sync_url(GaiaUrls::GetInstance()->service_login_url().Resolve(
    667       "?service=chromiumsync"));
    668   net::URLRequest sync_request(sync_url, net::DEFAULT_PRIORITY, NULL, &context);
    669   sync_request.SetLoadFlags(net::LOAD_MAIN_FRAME);
    670   EXPECT_EQ(block_signin_urls,
    671             blacklist_manager_->IsRequestBlocked(sync_request, &reason));
    672 }
    673 
    674 }  // namespace policy
    675