15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/policy/core/browser/url_blacklist_manager.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_path.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/location.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/sequenced_task_runner.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/task_runner_util.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/policy/core/common/policy_pref_names.h"
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h"
19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "net/base/filename_util.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/load_flags.h"
21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "net/base/net_errors.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_request.h"
2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "url/url_constants.h"
24a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "url/url_parse.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using url_matcher::URLMatcher;
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using url_matcher::URLMatcherCondition;
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using url_matcher::URLMatcherConditionFactory;
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using url_matcher::URLMatcherConditionSet;
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using url_matcher::URLMatcherPortFilter;
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using url_matcher::URLMatcherSchemeFilter;
32a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochusing url_matcher::URLQueryElementMatcherCondition;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace policy {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// List of schemes of URLs that should not be blocked by the "*" wildcard in
3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// the blacklist. Note that URLs with these schemes can still be blocked with
4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// a more specific filter e.g. "chrome-extension://*".
4103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// The schemes are hardcoded here to avoid dependencies on //extensions and
4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// //chrome.
4303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const char* kBypassBlacklistWildcardForSchemes[] = {
4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // For internal extension URLs e.g. the Bookmark Manager and the File
4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Manager on Chrome OS.
4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  "chrome-extension",
4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // NTP on Android.
4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  "chrome-native",
5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
5103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // NTP on other platforms.
5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  "chrome-search",
5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)};
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum filters per policy. Filters over this index are ignored.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMaxFiltersPerPolicy = 1000;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A task that builds the blacklist on a background thread.
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<URLBlacklist> BuildBlacklist(
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::ListValue> block,
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::ListValue> allow,
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    URLBlacklist::SegmentURLCallback segment_url) {
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<URLBlacklist> blacklist(new URLBlacklist(segment_url));
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blacklist->Block(block.get());
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blacklist->Allow(allow.get());
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return blacklist.Pass();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
69a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Tokenise the parameter |query| and add appropriate query element matcher
70a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// conditions to the |query_conditions|.
71a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid ProcessQueryToConditions(
72a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    url_matcher::URLMatcherConditionFactory* condition_factory,
73a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const std::string& query,
74a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    bool allow,
75a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    std::set<URLQueryElementMatcherCondition>* query_conditions) {
76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  url::Component query_left = url::MakeRange(0, query.length());
77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  url::Component key;
78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  url::Component value;
79a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Depending on the filter type being black-list or white-list, the matcher
80a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // choose any or every match. The idea is a URL should be black-listed if
81a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // there is any occurrence of the key value pair. It should be white-listed
82a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // only if every occurrence of the key is followed by the value. This avoids
83a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // situations such as a user appending a white-listed video parameter in the
84a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // end of the query and watching a video of his choice (the last parameter is
85a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // ignored by some web servers like youtube's).
86a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  URLQueryElementMatcherCondition::Type match_type =
87a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      allow ? URLQueryElementMatcherCondition::MATCH_ALL
88a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            : URLQueryElementMatcherCondition::MATCH_ANY;
89a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
90a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  while (ExtractQueryKeyValue(query.data(), &query_left, &key, &value)) {
91a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    URLQueryElementMatcherCondition::QueryElementType query_element_type =
92a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        value.len ? URLQueryElementMatcherCondition::ELEMENT_TYPE_KEY_VALUE
93a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                  : URLQueryElementMatcherCondition::ELEMENT_TYPE_KEY;
94a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    URLQueryElementMatcherCondition::QueryValueMatchType query_value_match_type;
95a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (!value.len && key.len && query[key.end() - 1] == '*') {
96a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      --key.len;
97a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      query_value_match_type =
98a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          URLQueryElementMatcherCondition::QUERY_VALUE_MATCH_PREFIX;
99a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    } else if (value.len && query[value.end() - 1] == '*') {
100a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      --value.len;
101a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      query_value_match_type =
102a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          URLQueryElementMatcherCondition::QUERY_VALUE_MATCH_PREFIX;
103a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    } else {
104a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      query_value_match_type =
105a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          URLQueryElementMatcherCondition::QUERY_VALUE_MATCH_EXACT;
106a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
107a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    query_conditions->insert(
108a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        URLQueryElementMatcherCondition(query.substr(key.begin, key.len),
109a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                        query.substr(value.begin, value.len),
110a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                        query_value_match_type,
111a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                        query_element_type,
112a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                        match_type,
113a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                        condition_factory));
114a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
115a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
116a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
11703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool BypassBlacklistWildcardForURL(const GURL& url) {
11803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const std::string& scheme = url.scheme();
11903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kBypassBlacklistWildcardForSchemes); ++i) {
12003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (scheme == kBypassBlacklistWildcardForSchemes[i])
12103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return true;
12203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
12303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return false;
12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
12503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct URLBlacklist::FilterComponents {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FilterComponents() : port(0), match_subdomains(true), allow(true) {}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~FilterComponents() {}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Returns true if |this| represents the "*" filter in the blacklist.
13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  bool IsBlacklistWildcard() const {
13403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return !allow && host.empty() && scheme.empty() && path.empty() &&
13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)           query.empty() && port == 0 && number_of_key_value_pairs == 0 &&
13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)           match_subdomains;
13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string scheme;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string host;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint16 port;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string path;
143a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  std::string query;
144a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  int number_of_key_value_pairs;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool match_subdomains;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool allow;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)URLBlacklist::URLBlacklist(SegmentURLCallback segment_url)
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : segment_url_(segment_url), id_(0), url_matcher_(new URLMatcher) {}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)URLBlacklist::~URLBlacklist() {}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklist::AddFilters(bool allow,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const base::ListValue* list) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  URLMatcherConditionSet::Vector all_conditions;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t size = std::min(kMaxFiltersPerPolicy, list->GetSize());
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < size; ++i) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string pattern;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success = list->GetString(i, &pattern);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(success);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FilterComponents components;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    components.allow = allow;
164a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (!FilterToComponents(segment_url_,
165a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            pattern,
166a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            &components.scheme,
167a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            &components.host,
168a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            &components.match_subdomains,
169a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            &components.port,
170a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            &components.path,
171a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            &components.query)) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Invalid pattern " << pattern;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
176a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    scoped_refptr<URLMatcherConditionSet> condition_set =
177a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        CreateConditionSet(url_matcher_.get(),
178a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           ++id_,
179a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           components.scheme,
180a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           components.host,
181a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           components.match_subdomains,
182a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           components.port,
183a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           components.path,
184a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           components.query,
185a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           allow);
186a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    components.number_of_key_value_pairs =
187a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        condition_set->query_conditions().size();
188a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    all_conditions.push_back(condition_set);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    filters_[id_] = components;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_matcher_->AddConditionSets(all_conditions);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklist::Block(const base::ListValue* filters) {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddFilters(false, filters);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklist::Allow(const base::ListValue* filters) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddFilters(true, filters);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLBlacklist::IsURLBlocked(const GURL& url) const {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<URLMatcherConditionSet::ID> matching_ids =
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url_matcher_->MatchURL(url);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FilterComponents* max = NULL;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<URLMatcherConditionSet::ID>::iterator id = matching_ids.begin();
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       id != matching_ids.end(); ++id) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::map<int, FilterComponents>::const_iterator it = filters_.find(*id);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(it != filters_.end());
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FilterComponents& filter = it->second;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!max || FilterTakesPrecedence(filter, *max))
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max = &filter;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Default to allow.
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!max)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Some of the internal Chrome URLs are not affected by the "*" in the
22103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // blacklist. Note that the "*" is the lowest priority filter possible, so
22203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // any higher priority filter will be applied first.
22303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (max->IsBlacklistWildcard() && BypassBlacklistWildcardForURL(url))
22403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
22503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !max->allow;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t URLBlacklist::Size() const {
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return filters_.size();
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool URLBlacklist::FilterToComponents(SegmentURLCallback segment_url,
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      const std::string& filter,
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      std::string* scheme,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      std::string* host,
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      bool* match_subdomains,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      uint16* port,
240a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                      std::string* path,
241a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                      std::string* query) {
242010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  url::Parsed parsed;
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
24403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (segment_url(filter, &parsed) == url::kFileScheme) {
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::FilePath file_path;
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!net::FileURLToFilePath(GURL(filter), &file_path))
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return false;
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
24903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    *scheme = url::kFileScheme;
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    host->clear();
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *match_subdomains = true;
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *port = 0;
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Special path when the |filter| is 'file://*'.
254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *path = (filter == "file://*") ? "" : file_path.AsUTF8Unsafe();
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(FILE_PATH_USES_WIN_SEPARATORS)
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Separators have to be canonicalized on Windows.
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    std::replace(path->begin(), path->end(), '\\', '/');
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *path = "/" + *path;
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return true;
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!parsed.host.is_nonempty())
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parsed.scheme.is_nonempty())
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scheme->assign(filter, parsed.scheme.begin, parsed.scheme.len);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scheme->clear();
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  host->assign(filter, parsed.host.begin, parsed.host.len);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Special '*' host, matches all hosts.
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*host == "*") {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host->clear();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *match_subdomains = true;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if ((*host)[0] == '.') {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A leading dot in the pattern syntax means that we don't want to match
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // subdomains.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host->erase(0, 1);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *match_subdomains = false;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
282010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    url::RawCanonOutputT<char> output;
283010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    url::CanonHostInfo host_info;
284010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    url::CanonicalizeHostVerbose(filter.c_str(), parsed.host, &output,
285010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                 &host_info);
286010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (host_info.family == url::CanonHostInfo::NEUTRAL) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We want to match subdomains. Add a dot in front to make sure we only
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // match at domain component boundaries.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *host = "." + *host;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *match_subdomains = true;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *match_subdomains = false;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parsed.port.is_nonempty()) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int int_port;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!base::StringToInt(filter.substr(parsed.port.begin, parsed.port.len),
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &int_port)) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (int_port <= 0 || int_port > kuint16max)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *port = int_port;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Match any port.
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *port = 0;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parsed.path.is_nonempty())
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    path->assign(filter, parsed.path.begin, parsed.path.len);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    path->clear();
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (query) {
316a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (parsed.query.is_nonempty())
317a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      query->assign(filter, parsed.query.begin, parsed.query.len);
318a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    else
319a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      query->clear();
320a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
321a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_refptr<URLMatcherConditionSet> URLBlacklist::CreateConditionSet(
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    URLMatcher* url_matcher,
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int id,
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& scheme,
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& host,
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool match_subdomains,
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint16 port,
333a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const std::string& path,
334a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const std::string& query,
335a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    bool allow) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  URLMatcherConditionFactory* condition_factory =
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url_matcher->condition_factory();
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<URLMatcherCondition> conditions;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  conditions.insert(match_subdomains ?
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      condition_factory->CreateHostSuffixPathPrefixCondition(host, path) :
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      condition_factory->CreateHostEqualsPathPrefixCondition(host, path));
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
343a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  std::set<URLQueryElementMatcherCondition> query_conditions;
344a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!query.empty()) {
345a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    ProcessQueryToConditions(
346a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        condition_factory, query, allow, &query_conditions);
347a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
348a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<URLMatcherSchemeFilter> scheme_filter;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!scheme.empty())
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scheme_filter.reset(new URLMatcherSchemeFilter(scheme));
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<URLMatcherPortFilter> port_filter;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (port != 0) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<URLMatcherPortFilter::Range> ranges;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ranges.push_back(URLMatcherPortFilter::CreateRange(port));
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    port_filter.reset(new URLMatcherPortFilter(ranges));
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
360a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return new URLMatcherConditionSet(id,
361a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                    conditions,
362a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                    query_conditions,
363a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                    scheme_filter.Pass(),
364a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                    port_filter.Pass());
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLBlacklist::FilterTakesPrecedence(const FilterComponents& lhs,
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const FilterComponents& rhs) {
37003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // The "*" wildcard is the lowest priority filter.
37103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (rhs.IsBlacklistWildcard())
37203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return true;
37303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (lhs.match_subdomains && !rhs.match_subdomains)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!lhs.match_subdomains && rhs.match_subdomains)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t host_length = lhs.host.length();
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t other_host_length = rhs.host.length();
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host_length != other_host_length)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return host_length > other_host_length;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t path_length = lhs.path.length();
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t other_path_length = rhs.path.length();
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (path_length != other_path_length)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return path_length > other_path_length;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
389a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (lhs.number_of_key_value_pairs != rhs.number_of_key_value_pairs)
390a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return lhs.number_of_key_value_pairs > rhs.number_of_key_value_pairs;
391a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (lhs.allow && !rhs.allow)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)URLBlacklistManager::URLBlacklistManager(
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PrefService* pref_service,
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const scoped_refptr<base::SequencedTaskRunner>& io_task_runner,
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    URLBlacklist::SegmentURLCallback segment_url,
403a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    OverrideBlacklistCallback override_blacklist)
4041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : pref_service_(pref_service),
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      background_task_runner_(background_task_runner),
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      io_task_runner_(io_task_runner),
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      segment_url_(segment_url),
408a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      override_blacklist_(override_blacklist),
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ui_task_runner_(base::MessageLoopProxy::current()),
4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      blacklist_(new URLBlacklist(segment_url)),
4111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ui_weak_ptr_factory_(this),
4121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      io_weak_ptr_factory_(this) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pref_change_registrar_.Init(pref_service_);
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Closure callback = base::Bind(&URLBlacklistManager::ScheduleUpdate,
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      base::Unretained(this));
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pref_change_registrar_.Add(policy_prefs::kUrlBlacklist, callback);
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pref_change_registrar_.Add(policy_prefs::kUrlWhitelist, callback);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start enforcing the policies without a delay when they are present at
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // startup.
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (pref_service_->HasPrefPath(policy_prefs::kUrlBlacklist))
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Update();
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklistManager::ShutdownOnUIThread() {
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel any pending updates, and stop listening for pref change updates.
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui_weak_ptr_factory_.InvalidateWeakPtrs();
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pref_change_registrar_.RemoveAll();
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLBlacklistManager::~URLBlacklistManager() {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklistManager::ScheduleUpdate() {
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel pending updates, if any. This can happen if two preferences that
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // change the blacklist are updated in one message loop cycle. In those cases,
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // only rebuild the blacklist after all the preference updates are processed.
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui_weak_ptr_factory_.InvalidateWeakPtrs();
4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui_task_runner_->PostTask(
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&URLBlacklistManager::Update,
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 ui_weak_ptr_factory_.GetWeakPtr()));
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklistManager::Update() {
4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The preferences can only be read on the UI thread.
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::ListValue> block(
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pref_service_->GetList(policy_prefs::kUrlBlacklist)->DeepCopy());
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::ListValue> allow(
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pref_service_->GetList(policy_prefs::kUrlWhitelist)->DeepCopy());
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Go through the IO thread to grab a WeakPtr to |this|. This is safe from
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // here, since this task will always execute before a potential deletion of
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ProfileIOData on IO.
4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  io_task_runner_->PostTask(FROM_HERE,
4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            base::Bind(&URLBlacklistManager::UpdateOnIO,
4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       base::Unretained(this),
4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       base::Passed(&block),
4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       base::Passed(&allow)));
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklistManager::UpdateOnIO(scoped_ptr<base::ListValue> block,
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     scoped_ptr<base::ListValue> allow) {
4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The URLBlacklist is built on a worker thread. Once it's ready, it is passed
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to the URLBlacklistManager on IO.
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::PostTaskAndReplyWithResult(
4721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      background_task_runner_.get(),
4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FROM_HERE,
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BuildBlacklist,
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Passed(&block),
4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 base::Passed(&allow),
4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 segment_url_),
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&URLBlacklistManager::SetBlacklist,
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 io_weak_ptr_factory_.GetWeakPtr()));
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklistManager::SetBlacklist(scoped_ptr<URLBlacklist> blacklist) {
4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blacklist_ = blacklist.Pass();
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLBlacklistManager::IsURLBlocked(const GURL& url) const {
4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return blacklist_->IsURLBlocked(url);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool URLBlacklistManager::IsRequestBlocked(
493c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const net::URLRequest& request, int* reason) const {
4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if !defined(OS_IOS)
4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(joaodasilva): iOS doesn't set these flags. http://crbug.com/338283
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int filter_flags = net::LOAD_MAIN_FRAME | net::LOAD_SUB_FRAME;
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if ((request.load_flags() & filter_flags) == 0)
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
502a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool block = false;
503c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (override_blacklist_.Run(request.url(), &block, reason))
504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return block;
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
506c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  *reason = net::ERR_BLOCKED_BY_ADMINISTRATOR;
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return IsURLBlocked(request.url());
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid URLBlacklistManager::RegisterProfilePrefs(
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    user_prefs::PrefRegistrySyncable* registry) {
5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  registry->RegisterListPref(policy_prefs::kUrlBlacklist,
514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  registry->RegisterListPref(policy_prefs::kUrlWhitelist,
516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace policy
520