• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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 COMPONENTS_POLICY_CORE_BROWSER_URL_BLACKLIST_MANAGER_H_
6 #define COMPONENTS_POLICY_CORE_BROWSER_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/ref_counted.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/prefs/pref_change_registrar.h"
19 #include "components/policy/policy_export.h"
20 #include "components/url_matcher/url_matcher.h"
21 #include "url/gurl.h"
22 
23 class PrefService;
24 
25 namespace base {
26 class ListValue;
27 class SequencedTaskRunner;
28 }
29 
30 namespace net {
31 class URLRequest;
32 }
33 
34 namespace user_prefs {
35 class PrefRegistrySyncable;
36 }
37 
38 namespace policy {
39 
40 // Contains a set of filters to block and allow certain URLs, and matches GURLs
41 // against this set. The filters are currently kept in memory.
42 class POLICY_EXPORT URLBlacklist {
43  public:
44   // This is meant to be bound to url_fixer::SegmentURL. See that function
45   // for documentation on the parameters and return value.
46   typedef std::string (*SegmentURLCallback)(const std::string&, url::Parsed*);
47 
48   explicit URLBlacklist(SegmentURLCallback segment_url);
49   virtual ~URLBlacklist();
50 
51   // Allows or blocks URLs matching one of the filters, depending on |allow|.
52   void AddFilters(bool allow, const base::ListValue* filters);
53 
54   // URLs matching one of the |filters| will be blocked. The filter format is
55   // documented at
56   // http://www.chromium.org/administrators/url-blacklist-filter-format.
57   void Block(const base::ListValue* filters);
58 
59   // URLs matching one of the |filters| will be allowed. If a URL is both
60   // Blocked and Allowed, Allow takes precedence.
61   void Allow(const base::ListValue* filters);
62 
63   // Returns true if the URL is blocked.
64   bool IsURLBlocked(const GURL& url) const;
65 
66   // Returns the number of items in the list.
67   size_t Size() const;
68 
69   // Splits a URL filter into its components. A GURL isn't used because these
70   // can be invalid URLs e.g. "google.com".
71   // Returns false if the URL couldn't be parsed.
72   // The |host| is preprocessed so it can be passed to URLMatcher for the
73   // appropriate condition.
74   // The optional username and password are ignored.
75   // |match_subdomains| specifies whether the filter should include subdomains
76   // of the hostname (if it is one.)
77   // |port| is 0 if none is explicitly defined.
78   // |path| does not include query parameters.
79   // |query| contains the query parameters ('?' not included).
80   static bool FilterToComponents(SegmentURLCallback segment_url,
81                                  const std::string& filter,
82                                  std::string* scheme,
83                                  std::string* host,
84                                  bool* match_subdomains,
85                                  uint16* port,
86                                  std::string* path,
87                                  std::string* query);
88 
89   // Creates a condition set that can be used with the |url_matcher|. |id| needs
90   // to be a unique number that will be returned by the |url_matcher| if the URL
91   // matches that condition set. |allow| indicates if it is a white-list (true)
92   // or black-list (false) filter.
93   static scoped_refptr<url_matcher::URLMatcherConditionSet> CreateConditionSet(
94       url_matcher::URLMatcher* url_matcher,
95       url_matcher::URLMatcherConditionSet::ID id,
96       const std::string& scheme,
97       const std::string& host,
98       bool match_subdomains,
99       uint16 port,
100       const std::string& path,
101       const std::string& query,
102       bool allow);
103 
104  private:
105   struct FilterComponents;
106 
107   // Returns true if |lhs| takes precedence over |rhs|.
108   static bool FilterTakesPrecedence(const FilterComponents& lhs,
109                                     const FilterComponents& rhs);
110 
111   SegmentURLCallback segment_url_;
112   url_matcher::URLMatcherConditionSet::ID id_;
113   std::map<url_matcher::URLMatcherConditionSet::ID, FilterComponents> filters_;
114   scoped_ptr<url_matcher::URLMatcher> url_matcher_;
115 
116   DISALLOW_COPY_AND_ASSIGN(URLBlacklist);
117 };
118 
119 // Tracks the blacklist policies for a given profile, and updates it on changes.
120 //
121 // This class interacts with both the UI thread, where notifications of pref
122 // changes are received from, and the IO thread, which owns it (in the
123 // ProfileIOData) and checks for blacklisted URLs (from ChromeNetworkDelegate).
124 //
125 // It must be constructed on the UI thread, to set up |ui_weak_ptr_factory_| and
126 // the prefs listeners.
127 //
128 // ShutdownOnUIThread must be called from UI before destruction, to release
129 // the prefs listeners on the UI thread. This is done from ProfileIOData.
130 //
131 // Update tasks from the UI thread can post safely to the IO thread, since the
132 // destruction order of Profile and ProfileIOData guarantees that if this
133 // exists in UI, then a potential destruction on IO will come after any task
134 // posted to IO from that method on UI. This is used to go through IO before
135 // the actual update starts, and grab a WeakPtr.
136 class POLICY_EXPORT URLBlacklistManager {
137  public:
138   // Returns true if the blacklist should be overridden for |url| and sets
139   // |block| to true if it should be blocked and false otherwise.
140   // |reason| is set to the exact reason for blocking |url| iff |block| is true.
141   typedef base::Callback<bool(const GURL& url, bool* block, int* reason)>
142       OverrideBlacklistCallback;
143 
144   // Must be constructed on the UI thread.
145   // |background_task_runner| is used to build the blacklist in a background
146   // thread.
147   // |io_task_runner| must be backed by the IO thread.
148   // |segment_url| is used to break a URL spec into its components.
149   URLBlacklistManager(
150       PrefService* pref_service,
151       const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
152       const scoped_refptr<base::SequencedTaskRunner>& io_task_runner,
153       URLBlacklist::SegmentURLCallback segment_url,
154       OverrideBlacklistCallback override_blacklist);
155   virtual ~URLBlacklistManager();
156 
157   // Must be called on the UI thread, before destruction.
158   void ShutdownOnUIThread();
159 
160   // Returns true if |url| is blocked by the current blacklist. Must be called
161   // from the IO thread.
162   bool IsURLBlocked(const GURL& url) const;
163 
164   // Returns true if |request| is blocked by the current blacklist.
165   // Only main frame and sub frame requests may be blocked; other sub resources
166   // or background downloads (e.g. extensions updates, sync, etc) are not
167   // filtered. The sync signin page is also not filtered.
168   // |reason| is populated with the exact reason for blocking the url if and
169   // only if the return value is true otherwise it is left untouched.
170   // Must be called from the IO thread.
171   bool IsRequestBlocked(const net::URLRequest& request, int* reason) const;
172 
173   // Replaces the current blacklist. Must be called on the IO thread.
174   // Virtual for testing.
175   virtual void SetBlacklist(scoped_ptr<URLBlacklist> blacklist);
176 
177   // Registers the preferences related to blacklisting in the given PrefService.
178   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
179 
180  protected:
181   // Used to delay updating the blacklist while the preferences are
182   // changing, and execute only one update per simultaneous prefs changes.
183   void ScheduleUpdate();
184 
185   // Updates the blacklist using the current preference values.
186   // Virtual for testing.
187   virtual void Update();
188 
189   // Starts the blacklist update on the IO thread, using the filters in
190   // |block| and |allow|. Protected for testing.
191   void UpdateOnIO(scoped_ptr<base::ListValue> block,
192                   scoped_ptr<base::ListValue> allow);
193 
194  private:
195   // ---------
196   // UI thread
197   // ---------
198 
199   // Used to track the policies and update the blacklist on changes.
200   PrefChangeRegistrar pref_change_registrar_;
201   PrefService* pref_service_;  // Weak.
202 
203   // Used to post tasks to a background thread.
204   scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
205 
206   // Used to post tasks to the IO thread.
207   scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
208 
209   // Used to break a URL into its components.
210   URLBlacklist::SegmentURLCallback segment_url_;
211 
212   // Used to optionally skip blacklisting for some URLs.
213   OverrideBlacklistCallback override_blacklist_;
214 
215   // ---------
216   // IO thread
217   // ---------
218 
219   // Used to post tasks to the UI thread.
220   scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
221 
222   // The current blacklist.
223   scoped_ptr<URLBlacklist> blacklist_;
224 
225   // Used to post update tasks to the UI thread.
226   base::WeakPtrFactory<URLBlacklistManager> ui_weak_ptr_factory_;
227 
228   // Used to get |weak_ptr_| to self on the IO thread.
229   base::WeakPtrFactory<URLBlacklistManager> io_weak_ptr_factory_;
230 
231   DISALLOW_COPY_AND_ASSIGN(URLBlacklistManager);
232 };
233 
234 }  // namespace policy
235 
236 #endif  // COMPONENTS_POLICY_CORE_BROWSER_URL_BLACKLIST_MANAGER_H_
237