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#ifndef CHROME_BROWSER_POLICY_URL_BLACKLIST_MANAGER_H_
6#define CHROME_BROWSER_POLICY_URL_BLACKLIST_MANAGER_H_
7
8#include <map>
9#include <string>
10
11#include "base/basictypes.h"
12#include "base/callback_forward.h"
13#include "base/compiler_specific.h"
14#include "base/containers/hash_tables.h"
15#include "base/memory/scoped_ptr.h"
16#include "base/memory/weak_ptr.h"
17#include "base/prefs/pref_change_registrar.h"
18#include "components/url_matcher/url_matcher.h"
19
20class GURL;
21class PrefService;
22
23namespace base {
24class ListValue;
25}
26
27namespace net {
28class URLRequest;
29}
30
31namespace user_prefs {
32class PrefRegistrySyncable;
33}
34
35namespace policy {
36
37// Contains a set of filters to block and allow certain URLs, and matches GURLs
38// against this set. The filters are currently kept in memory.
39class URLBlacklist {
40 public:
41  URLBlacklist();
42  virtual ~URLBlacklist();
43
44  // Allows or blocks URLs matching one of the filters, depending on |allow|.
45  void AddFilters(bool allow, const base::ListValue* filters);
46
47  // URLs matching one of the |filters| will be blocked. The filter format is
48  // documented at
49  // http://www.chromium.org/administrators/url-blacklist-filter-format.
50  void Block(const base::ListValue* filters);
51
52  // URLs matching one of the |filters| will be allowed. If a URL is both
53  // Blocked and Allowed, Allow takes precedence.
54  void Allow(const base::ListValue* filters);
55
56  // Returns true if the URL is blocked.
57  bool IsURLBlocked(const GURL& url) const;
58
59  // Returns the number of items in the list.
60  size_t Size() const;
61
62  // Splits a URL filter into its components. A GURL isn't used because these
63  // can be invalid URLs e.g. "google.com".
64  // Returns false if the URL couldn't be parsed.
65  // The |host| is preprocessed so it can be passed to URLMatcher for the
66  // appropriate condition.
67  // The optional username and password are ignored.
68  // |match_subdomains| specifies whether the filter should include subdomains
69  // of the hostname (if it is one.)
70  // |port| is 0 if none is explicitly defined.
71  // |path| does not include query parameters.
72  static bool FilterToComponents(const std::string& filter,
73                                 std::string* scheme,
74                                 std::string* host,
75                                 bool* match_subdomains,
76                                 uint16* port,
77                                 std::string* path);
78
79  // Creates a condition set that can be used with the |url_matcher|. |id| needs
80  // to be a unique number that will be returned by the |url_matcher| if the URL
81  // matches that condition set.
82  static scoped_refptr<url_matcher::URLMatcherConditionSet> CreateConditionSet(
83      url_matcher::URLMatcher* url_matcher,
84      url_matcher::URLMatcherConditionSet::ID id,
85      const std::string& scheme,
86      const std::string& host,
87      bool match_subdomains,
88      uint16 port,
89      const std::string& path);
90
91 private:
92  struct FilterComponents;
93
94  // Returns true if |lhs| takes precedence over |rhs|.
95  static bool FilterTakesPrecedence(const FilterComponents& lhs,
96                                    const FilterComponents& rhs);
97
98  url_matcher::URLMatcherConditionSet::ID id_;
99  std::map<url_matcher::URLMatcherConditionSet::ID, FilterComponents> filters_;
100  scoped_ptr<url_matcher::URLMatcher> url_matcher_;
101
102  DISALLOW_COPY_AND_ASSIGN(URLBlacklist);
103};
104
105// Tracks the blacklist policies for a given profile, and updates it on changes.
106//
107// This class interacts with both the UI thread, where notifications of pref
108// changes are received from, and the IO thread, which owns it (in the
109// ProfileIOData) and checks for blacklisted URLs (from ChromeNetworkDelegate).
110//
111// It must be constructed on the UI thread, to set up |ui_weak_ptr_factory_| and
112// the prefs listeners.
113//
114// ShutdownOnUIThread must be called from UI before destruction, to release
115// the prefs listeners on the UI thread. This is done from ProfileIOData.
116//
117// Update tasks from the UI thread can post safely to the IO thread, since the
118// destruction order of Profile and ProfileIOData guarantees that if this
119// exists in UI, then a potential destruction on IO will come after any task
120// posted to IO from that method on UI. This is used to go through IO before
121// the actual update starts, and grab a WeakPtr.
122class URLBlacklistManager {
123 public:
124  // Must be constructed on the UI thread.
125  explicit URLBlacklistManager(PrefService* pref_service);
126  virtual ~URLBlacklistManager();
127
128  // Must be called on the UI thread, before destruction.
129  void ShutdownOnUIThread();
130
131  // Returns true if |url| is blocked by the current blacklist. Must be called
132  // from the IO thread.
133  bool IsURLBlocked(const GURL& url) const;
134
135  // Returns true if |request| is blocked by the current blacklist.
136  // Only main frame and sub frame requests may be blocked; other sub resources
137  // or background downloads (e.g. extensions updates, sync, etc) are not
138  // filtered. The sync signin page is also not filtered.
139  // Must be called from the IO thread.
140  bool IsRequestBlocked(const net::URLRequest& request) const;
141
142  // Replaces the current blacklist. Must be called on the IO thread.
143  // Virtual for testing.
144  virtual void SetBlacklist(scoped_ptr<URLBlacklist> blacklist);
145
146  // Registers the preferences related to blacklisting in the given PrefService.
147  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
148
149 protected:
150  // Used to delay updating the blacklist while the preferences are
151  // changing, and execute only one update per simultaneous prefs changes.
152  void ScheduleUpdate();
153
154  // Updates the blacklist using the current preference values.
155  // Virtual for testing.
156  virtual void Update();
157
158  // Starts the blacklist update on the IO thread, using the filters in
159  // |block| and |allow|. Protected for testing.
160  void UpdateOnIO(scoped_ptr<base::ListValue> block,
161                  scoped_ptr<base::ListValue> allow);
162
163 private:
164  // ---------
165  // UI thread
166  // ---------
167
168  // Used to post update tasks to the UI thread.
169  base::WeakPtrFactory<URLBlacklistManager> ui_weak_ptr_factory_;
170
171  // Used to track the policies and update the blacklist on changes.
172  PrefChangeRegistrar pref_change_registrar_;
173  PrefService* pref_service_;  // Weak.
174
175  // ---------
176  // IO thread
177  // ---------
178
179  // Used to get |weak_ptr_| to self on the IO thread.
180  base::WeakPtrFactory<URLBlacklistManager> io_weak_ptr_factory_;
181
182  // The current blacklist.
183  scoped_ptr<URLBlacklist> blacklist_;
184
185  DISALLOW_COPY_AND_ASSIGN(URLBlacklistManager);
186};
187
188}  // namespace policy
189
190#endif  // CHROME_BROWSER_POLICY_URL_BLACKLIST_MANAGER_H_
191