url_blacklist_manager.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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"
23a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "url/url_parse.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using url_matcher::URLMatcher;
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using url_matcher::URLMatcherCondition;
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using url_matcher::URLMatcherConditionFactory;
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using url_matcher::URLMatcherConditionSet;
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using url_matcher::URLMatcherPortFilter;
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using url_matcher::URLMatcherSchemeFilter;
31a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochusing url_matcher::URLQueryElementMatcherCondition;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace policy {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kFileScheme[] = "file";
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum filters per policy. Filters over this index are ignored.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMaxFiltersPerPolicy = 1000;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A task that builds the blacklist on a background thread.
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<URLBlacklist> BuildBlacklist(
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::ListValue> block,
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::ListValue> allow,
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    URLBlacklist::SegmentURLCallback segment_url) {
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<URLBlacklist> blacklist(new URLBlacklist(segment_url));
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blacklist->Block(block.get());
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blacklist->Allow(allow.get());
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return blacklist.Pass();
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Tokenise the parameter |query| and add appropriate query element matcher
54a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// conditions to the |query_conditions|.
55a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid ProcessQueryToConditions(
56a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    url_matcher::URLMatcherConditionFactory* condition_factory,
57a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const std::string& query,
58a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    bool allow,
59a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    std::set<URLQueryElementMatcherCondition>* query_conditions) {
60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  url::Component query_left = url::MakeRange(0, query.length());
61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  url::Component key;
62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  url::Component value;
63a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Depending on the filter type being black-list or white-list, the matcher
64a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // choose any or every match. The idea is a URL should be black-listed if
65a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // there is any occurrence of the key value pair. It should be white-listed
66a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // only if every occurrence of the key is followed by the value. This avoids
67a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // situations such as a user appending a white-listed video parameter in the
68a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // end of the query and watching a video of his choice (the last parameter is
69a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // ignored by some web servers like youtube's).
70a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  URLQueryElementMatcherCondition::Type match_type =
71a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      allow ? URLQueryElementMatcherCondition::MATCH_ALL
72a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            : URLQueryElementMatcherCondition::MATCH_ANY;
73a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
74a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  while (ExtractQueryKeyValue(query.data(), &query_left, &key, &value)) {
75a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    URLQueryElementMatcherCondition::QueryElementType query_element_type =
76a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        value.len ? URLQueryElementMatcherCondition::ELEMENT_TYPE_KEY_VALUE
77a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                  : URLQueryElementMatcherCondition::ELEMENT_TYPE_KEY;
78a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    URLQueryElementMatcherCondition::QueryValueMatchType query_value_match_type;
79a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (!value.len && key.len && query[key.end() - 1] == '*') {
80a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      --key.len;
81a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      query_value_match_type =
82a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          URLQueryElementMatcherCondition::QUERY_VALUE_MATCH_PREFIX;
83a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    } else if (value.len && query[value.end() - 1] == '*') {
84a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      --value.len;
85a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      query_value_match_type =
86a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          URLQueryElementMatcherCondition::QUERY_VALUE_MATCH_PREFIX;
87a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    } else {
88a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      query_value_match_type =
89a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          URLQueryElementMatcherCondition::QUERY_VALUE_MATCH_EXACT;
90a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
91a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    query_conditions->insert(
92a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        URLQueryElementMatcherCondition(query.substr(key.begin, key.len),
93a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                        query.substr(value.begin, value.len),
94a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                        query_value_match_type,
95a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                        query_element_type,
96a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                        match_type,
97a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                        condition_factory));
98a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
99a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
100a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct URLBlacklist::FilterComponents {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FilterComponents() : port(0), match_subdomains(true), allow(true) {}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~FilterComponents() {}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string scheme;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string host;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint16 port;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string path;
111a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  std::string query;
112a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  int number_of_key_value_pairs;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool match_subdomains;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool allow;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)URLBlacklist::URLBlacklist(SegmentURLCallback segment_url)
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : segment_url_(segment_url), id_(0), url_matcher_(new URLMatcher) {}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)URLBlacklist::~URLBlacklist() {}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklist::AddFilters(bool allow,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const base::ListValue* list) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  URLMatcherConditionSet::Vector all_conditions;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t size = std::min(kMaxFiltersPerPolicy, list->GetSize());
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < size; ++i) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string pattern;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success = list->GetString(i, &pattern);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(success);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FilterComponents components;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    components.allow = allow;
132a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (!FilterToComponents(segment_url_,
133a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            pattern,
134a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            &components.scheme,
135a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            &components.host,
136a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            &components.match_subdomains,
137a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            &components.port,
138a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            &components.path,
139a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            &components.query)) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Invalid pattern " << pattern;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
144a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    scoped_refptr<URLMatcherConditionSet> condition_set =
145a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        CreateConditionSet(url_matcher_.get(),
146a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           ++id_,
147a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           components.scheme,
148a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           components.host,
149a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           components.match_subdomains,
150a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           components.port,
151a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           components.path,
152a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           components.query,
153a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           allow);
154a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    components.number_of_key_value_pairs =
155a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        condition_set->query_conditions().size();
156a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    all_conditions.push_back(condition_set);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    filters_[id_] = components;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_matcher_->AddConditionSets(all_conditions);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklist::Block(const base::ListValue* filters) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddFilters(false, filters);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklist::Allow(const base::ListValue* filters) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddFilters(true, filters);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLBlacklist::IsURLBlocked(const GURL& url) const {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<URLMatcherConditionSet::ID> matching_ids =
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url_matcher_->MatchURL(url);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FilterComponents* max = NULL;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<URLMatcherConditionSet::ID>::iterator id = matching_ids.begin();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       id != matching_ids.end(); ++id) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::map<int, FilterComponents>::const_iterator it = filters_.find(*id);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(it != filters_.end());
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const FilterComponents& filter = it->second;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!max || FilterTakesPrecedence(filter, *max))
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max = &filter;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Default to allow.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!max)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !max->allow;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t URLBlacklist::Size() const {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return filters_.size();
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool URLBlacklist::FilterToComponents(SegmentURLCallback segment_url,
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      const std::string& filter,
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      std::string* scheme,
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      std::string* host,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      bool* match_subdomains,
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      uint16* port,
202a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                      std::string* path,
203a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                      std::string* query) {
204010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  url::Parsed parsed;
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (segment_url(filter, &parsed) == kFileScheme) {
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::FilePath file_path;
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!net::FileURLToFilePath(GURL(filter), &file_path))
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return false;
210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *scheme = kFileScheme;
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    host->clear();
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *match_subdomains = true;
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *port = 0;
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Special path when the |filter| is 'file://*'.
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *path = (filter == "file://*") ? "" : file_path.AsUTF8Unsafe();
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(FILE_PATH_USES_WIN_SEPARATORS)
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Separators have to be canonicalized on Windows.
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    std::replace(path->begin(), path->end(), '\\', '/');
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *path = "/" + *path;
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return true;
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!parsed.host.is_nonempty())
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parsed.scheme.is_nonempty())
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scheme->assign(filter, parsed.scheme.begin, parsed.scheme.len);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scheme->clear();
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  host->assign(filter, parsed.host.begin, parsed.host.len);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Special '*' host, matches all hosts.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*host == "*") {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host->clear();
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *match_subdomains = true;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if ((*host)[0] == '.') {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A leading dot in the pattern syntax means that we don't want to match
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // subdomains.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host->erase(0, 1);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *match_subdomains = false;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
244010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    url::RawCanonOutputT<char> output;
245010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    url::CanonHostInfo host_info;
246010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    url::CanonicalizeHostVerbose(filter.c_str(), parsed.host, &output,
247010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                 &host_info);
248010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (host_info.family == url::CanonHostInfo::NEUTRAL) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We want to match subdomains. Add a dot in front to make sure we only
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // match at domain component boundaries.
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *host = "." + *host;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *match_subdomains = true;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *match_subdomains = false;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parsed.port.is_nonempty()) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int int_port;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!base::StringToInt(filter.substr(parsed.port.begin, parsed.port.len),
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &int_port)) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (int_port <= 0 || int_port > kuint16max)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *port = int_port;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Match any port.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *port = 0;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parsed.path.is_nonempty())
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    path->assign(filter, parsed.path.begin, parsed.path.len);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    path->clear();
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
277a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (query) {
278a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (parsed.query.is_nonempty())
279a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      query->assign(filter, parsed.query.begin, parsed.query.len);
280a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    else
281a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      query->clear();
282a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
283a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_refptr<URLMatcherConditionSet> URLBlacklist::CreateConditionSet(
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    URLMatcher* url_matcher,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int id,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& scheme,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& host,
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool match_subdomains,
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint16 port,
295a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const std::string& path,
296a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const std::string& query,
297a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    bool allow) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  URLMatcherConditionFactory* condition_factory =
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url_matcher->condition_factory();
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<URLMatcherCondition> conditions;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  conditions.insert(match_subdomains ?
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      condition_factory->CreateHostSuffixPathPrefixCondition(host, path) :
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      condition_factory->CreateHostEqualsPathPrefixCondition(host, path));
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  std::set<URLQueryElementMatcherCondition> query_conditions;
306a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (!query.empty()) {
307a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    ProcessQueryToConditions(
308a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        condition_factory, query, allow, &query_conditions);
309a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
310a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<URLMatcherSchemeFilter> scheme_filter;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!scheme.empty())
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scheme_filter.reset(new URLMatcherSchemeFilter(scheme));
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<URLMatcherPortFilter> port_filter;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (port != 0) {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<URLMatcherPortFilter::Range> ranges;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ranges.push_back(URLMatcherPortFilter::CreateRange(port));
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    port_filter.reset(new URLMatcherPortFilter(ranges));
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
322a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return new URLMatcherConditionSet(id,
323a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                    conditions,
324a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                    query_conditions,
325a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                    scheme_filter.Pass(),
326a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                    port_filter.Pass());
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLBlacklist::FilterTakesPrecedence(const FilterComponents& lhs,
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const FilterComponents& rhs) {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (lhs.match_subdomains && !rhs.match_subdomains)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!lhs.match_subdomains && rhs.match_subdomains)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t host_length = lhs.host.length();
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t other_host_length = rhs.host.length();
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host_length != other_host_length)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return host_length > other_host_length;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t path_length = lhs.path.length();
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t other_path_length = rhs.path.length();
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (path_length != other_path_length)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return path_length > other_path_length;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
347a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (lhs.number_of_key_value_pairs != rhs.number_of_key_value_pairs)
348a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return lhs.number_of_key_value_pairs > rhs.number_of_key_value_pairs;
349a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (lhs.allow && !rhs.allow)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)URLBlacklistManager::URLBlacklistManager(
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PrefService* pref_service,
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const scoped_refptr<base::SequencedTaskRunner>& io_task_runner,
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    URLBlacklist::SegmentURLCallback segment_url,
361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    OverrideBlacklistCallback override_blacklist)
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : ui_weak_ptr_factory_(this),
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pref_service_(pref_service),
3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      background_task_runner_(background_task_runner),
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      io_task_runner_(io_task_runner),
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      segment_url_(segment_url),
367a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      override_blacklist_(override_blacklist),
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      io_weak_ptr_factory_(this),
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ui_task_runner_(base::MessageLoopProxy::current()),
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      blacklist_(new URLBlacklist(segment_url)) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pref_change_registrar_.Init(pref_service_);
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Closure callback = base::Bind(&URLBlacklistManager::ScheduleUpdate,
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      base::Unretained(this));
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pref_change_registrar_.Add(policy_prefs::kUrlBlacklist, callback);
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pref_change_registrar_.Add(policy_prefs::kUrlWhitelist, callback);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start enforcing the policies without a delay when they are present at
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // startup.
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (pref_service_->HasPrefPath(policy_prefs::kUrlBlacklist))
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Update();
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklistManager::ShutdownOnUIThread() {
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel any pending updates, and stop listening for pref change updates.
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui_weak_ptr_factory_.InvalidateWeakPtrs();
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pref_change_registrar_.RemoveAll();
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLBlacklistManager::~URLBlacklistManager() {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklistManager::ScheduleUpdate() {
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel pending updates, if any. This can happen if two preferences that
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // change the blacklist are updated in one message loop cycle. In those cases,
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // only rebuild the blacklist after all the preference updates are processed.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui_weak_ptr_factory_.InvalidateWeakPtrs();
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ui_task_runner_->PostTask(
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&URLBlacklistManager::Update,
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 ui_weak_ptr_factory_.GetWeakPtr()));
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklistManager::Update() {
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The preferences can only be read on the UI thread.
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::ListValue> block(
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pref_service_->GetList(policy_prefs::kUrlBlacklist)->DeepCopy());
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::ListValue> allow(
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      pref_service_->GetList(policy_prefs::kUrlWhitelist)->DeepCopy());
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Go through the IO thread to grab a WeakPtr to |this|. This is safe from
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // here, since this task will always execute before a potential deletion of
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ProfileIOData on IO.
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  io_task_runner_->PostTask(FROM_HERE,
4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            base::Bind(&URLBlacklistManager::UpdateOnIO,
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       base::Unretained(this),
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       base::Passed(&block),
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       base::Passed(&allow)));
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklistManager::UpdateOnIO(scoped_ptr<base::ListValue> block,
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     scoped_ptr<base::ListValue> allow) {
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The URLBlacklist is built on a worker thread. Once it's ready, it is passed
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to the URLBlacklistManager on IO.
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::PostTaskAndReplyWithResult(
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      background_task_runner_,
4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FROM_HERE,
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BuildBlacklist,
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Passed(&block),
4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 base::Passed(&allow),
4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 segment_url_),
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&URLBlacklistManager::SetBlacklist,
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 io_weak_ptr_factory_.GetWeakPtr()));
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklistManager::SetBlacklist(scoped_ptr<URLBlacklist> blacklist) {
4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blacklist_ = blacklist.Pass();
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLBlacklistManager::IsURLBlocked(const GURL& url) const {
4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return blacklist_->IsURLBlocked(url);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool URLBlacklistManager::IsRequestBlocked(
451c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const net::URLRequest& request, int* reason) const {
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if !defined(OS_IOS)
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(joaodasilva): iOS doesn't set these flags. http://crbug.com/338283
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int filter_flags = net::LOAD_MAIN_FRAME | net::LOAD_SUB_FRAME;
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if ((request.load_flags() & filter_flags) == 0)
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
460a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool block = false;
461c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (override_blacklist_.Run(request.url(), &block, reason))
462a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return block;
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
464c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  *reason = net::ERR_BLOCKED_BY_ADMINISTRATOR;
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return IsURLBlocked(request.url());
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid URLBlacklistManager::RegisterProfilePrefs(
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    user_prefs::PrefRegistrySyncable* registry) {
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  registry->RegisterListPref(policy_prefs::kUrlBlacklist,
472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  registry->RegisterListPref(policy_prefs::kUrlWhitelist,
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace policy
478