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