url_blacklist_manager.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
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" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/user_prefs/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" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using url_matcher::URLMatcher; 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using url_matcher::URLMatcherCondition; 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using url_matcher::URLMatcherConditionFactory; 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using url_matcher::URLMatcherConditionSet; 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using url_matcher::URLMatcherPortFilter; 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using url_matcher::URLMatcherSchemeFilter; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace policy { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kFileScheme[] = "file"; 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum filters per policy. Filters over this index are ignored. 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMaxFiltersPerPolicy = 1000; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A task that builds the blacklist on a background thread. 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<URLBlacklist> BuildBlacklist( 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> block, 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> allow, 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) URLBlacklist::SegmentURLCallback segment_url) { 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<URLBlacklist> blacklist(new URLBlacklist(segment_url)); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blacklist->Block(block.get()); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blacklist->Allow(allow.get()); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return blacklist.Pass(); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct URLBlacklist::FilterComponents { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilterComponents() : port(0), match_subdomains(true), allow(true) {} 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~FilterComponents() {} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string scheme; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string host; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16 port; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string path; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool match_subdomains; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool allow; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)URLBlacklist::URLBlacklist(SegmentURLCallback segment_url) 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : segment_url_(segment_url), id_(0), url_matcher_(new URLMatcher) {} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)URLBlacklist::~URLBlacklist() {} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklist::AddFilters(bool allow, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::ListValue* list) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLMatcherConditionSet::Vector all_conditions; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size = std::min(kMaxFiltersPerPolicy, list->GetSize()); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < size; ++i) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string pattern; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = list->GetString(i, &pattern); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(success); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilterComponents components; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) components.allow = allow; 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!FilterToComponents(segment_url_, pattern, &components.scheme, 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &components.host, &components.match_subdomains, 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &components.port, &components.path)) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Invalid pattern " << pattern; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) all_conditions.push_back( 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateConditionSet(url_matcher_.get(), ++id_, components.scheme, 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) components.host, components.match_subdomains, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) components.port, components.path)); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filters_[id_] = components; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_matcher_->AddConditionSets(all_conditions); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklist::Block(const base::ListValue* filters) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddFilters(false, filters); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklist::Allow(const base::ListValue* filters) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddFilters(true, filters); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLBlacklist::IsURLBlocked(const GURL& url) const { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<URLMatcherConditionSet::ID> matching_ids = 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_matcher_->MatchURL(url); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilterComponents* max = NULL; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<URLMatcherConditionSet::ID>::iterator id = matching_ids.begin(); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) id != matching_ids.end(); ++id) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<int, FilterComponents>::const_iterator it = filters_.find(*id); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(it != filters_.end()); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilterComponents& filter = it->second; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!max || FilterTakesPrecedence(filter, *max)) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max = &filter; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default to allow. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!max) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !max->allow; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t URLBlacklist::Size() const { 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return filters_.size(); 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool URLBlacklist::FilterToComponents(SegmentURLCallback segment_url, 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& filter, 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* scheme, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* host, 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool* match_subdomains, 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16* port, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* path) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_parse::Parsed parsed; 138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (segment_url(filter, &parsed) == kFileScheme) { 140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FilePath file_path; 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!net::FileURLToFilePath(GURL(filter), &file_path)) 142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *scheme = kFileScheme; 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) host->clear(); 146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *match_subdomains = true; 147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *port = 0; 148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Special path when the |filter| is 'file://*'. 149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *path = (filter == "file://*") ? "" : file_path.AsUTF8Unsafe(); 150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(FILE_PATH_USES_WIN_SEPARATORS) 151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Separators have to be canonicalized on Windows. 152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::replace(path->begin(), path->end(), '\\', '/'); 153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *path = "/" + *path; 154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif 155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return true; 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!parsed.host.is_nonempty()) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parsed.scheme.is_nonempty()) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheme->assign(filter, parsed.scheme.begin, parsed.scheme.len); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheme->clear(); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->assign(filter, parsed.host.begin, parsed.host.len); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Special '*' host, matches all hosts. 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*host == "*") { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->clear(); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *match_subdomains = true; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if ((*host)[0] == '.') { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A leading dot in the pattern syntax means that we don't want to match 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // subdomains. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host->erase(0, 1); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *match_subdomains = false; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_canon::RawCanonOutputT<char> output; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_canon::CanonHostInfo host_info; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_canon::CanonicalizeHostVerbose(filter.c_str(), parsed.host, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &output, &host_info); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (host_info.family == url_canon::CanonHostInfo::NEUTRAL) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We want to match subdomains. Add a dot in front to make sure we only 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // match at domain component boundaries. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *host = "." + *host; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *match_subdomains = true; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *match_subdomains = false; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parsed.port.is_nonempty()) { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int int_port; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base::StringToInt(filter.substr(parsed.port.begin, parsed.port.len), 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &int_port)) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (int_port <= 0 || int_port > kuint16max) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *port = int_port; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Match any port. 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *port = 0; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parsed.path.is_nonempty()) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path->assign(filter, parsed.path.begin, parsed.path.len); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path->clear(); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_refptr<URLMatcherConditionSet> URLBlacklist::CreateConditionSet( 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) URLMatcher* url_matcher, 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int id, 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& scheme, 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& host, 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool match_subdomains, 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16 port, 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& path) { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLMatcherConditionFactory* condition_factory = 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_matcher->condition_factory(); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<URLMatcherCondition> conditions; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) conditions.insert(match_subdomains ? 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) condition_factory->CreateHostSuffixPathPrefixCondition(host, path) : 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) condition_factory->CreateHostEqualsPathPrefixCondition(host, path)); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<URLMatcherSchemeFilter> scheme_filter; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!scheme.empty()) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheme_filter.reset(new URLMatcherSchemeFilter(scheme)); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<URLMatcherPortFilter> port_filter; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port != 0) { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<URLMatcherPortFilter::Range> ranges; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ranges.push_back(URLMatcherPortFilter::CreateRange(port)); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port_filter.reset(new URLMatcherPortFilter(ranges)); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new URLMatcherConditionSet(id, conditions, 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheme_filter.Pass(), port_filter.Pass()); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLBlacklist::FilterTakesPrecedence(const FilterComponents& lhs, 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilterComponents& rhs) { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lhs.match_subdomains && !rhs.match_subdomains) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!lhs.match_subdomains && rhs.match_subdomains) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t host_length = lhs.host.length(); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t other_host_length = rhs.host.length(); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (host_length != other_host_length) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return host_length > other_host_length; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t path_length = lhs.path.length(); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t other_path_length = rhs.path.length(); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path_length != other_path_length) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return path_length > other_path_length; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lhs.allow && !rhs.allow) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)URLBlacklistManager::URLBlacklistManager( 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PrefService* pref_service, 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<base::SequencedTaskRunner>& background_task_runner, 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<base::SequencedTaskRunner>& io_task_runner, 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) URLBlacklist::SegmentURLCallback segment_url, 273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OverrideBlacklistCallback override_blacklist) 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : ui_weak_ptr_factory_(this), 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pref_service_(pref_service), 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) background_task_runner_(background_task_runner), 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) io_task_runner_(io_task_runner), 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) segment_url_(segment_url), 279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) override_blacklist_(override_blacklist), 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) io_weak_ptr_factory_(this), 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui_task_runner_(base::MessageLoopProxy::current()), 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blacklist_(new URLBlacklist(segment_url)) { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pref_change_registrar_.Init(pref_service_); 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Closure callback = base::Bind(&URLBlacklistManager::ScheduleUpdate, 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this)); 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pref_change_registrar_.Add(policy_prefs::kUrlBlacklist, callback); 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pref_change_registrar_.Add(policy_prefs::kUrlWhitelist, callback); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start enforcing the policies without a delay when they are present at 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // startup. 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (pref_service_->HasPrefPath(policy_prefs::kUrlBlacklist)) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Update(); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklistManager::ShutdownOnUIThread() { 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cancel any pending updates, and stop listening for pref change updates. 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui_weak_ptr_factory_.InvalidateWeakPtrs(); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pref_change_registrar_.RemoveAll(); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLBlacklistManager::~URLBlacklistManager() { 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklistManager::ScheduleUpdate() { 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cancel pending updates, if any. This can happen if two preferences that 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // change the blacklist are updated in one message loop cycle. In those cases, 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // only rebuild the blacklist after all the preference updates are processed. 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui_weak_ptr_factory_.InvalidateWeakPtrs(); 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui_task_runner_->PostTask( 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&URLBlacklistManager::Update, 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui_weak_ptr_factory_.GetWeakPtr())); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklistManager::Update() { 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The preferences can only be read on the UI thread. 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::ListValue> block( 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pref_service_->GetList(policy_prefs::kUrlBlacklist)->DeepCopy()); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::ListValue> allow( 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pref_service_->GetList(policy_prefs::kUrlWhitelist)->DeepCopy()); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Go through the IO thread to grab a WeakPtr to |this|. This is safe from 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // here, since this task will always execute before a potential deletion of 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ProfileIOData on IO. 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) io_task_runner_->PostTask(FROM_HERE, 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&URLBlacklistManager::UpdateOnIO, 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Unretained(this), 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&block), 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&allow))); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklistManager::UpdateOnIO(scoped_ptr<base::ListValue> block, 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::ListValue> allow) { 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The URLBlacklist is built on a worker thread. Once it's ready, it is passed 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to the URLBlacklistManager on IO. 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::PostTaskAndReplyWithResult( 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) background_task_runner_, 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&BuildBlacklist, 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Passed(&block), 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Passed(&allow), 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) segment_url_), 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&URLBlacklistManager::SetBlacklist, 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_weak_ptr_factory_.GetWeakPtr())); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLBlacklistManager::SetBlacklist(scoped_ptr<URLBlacklist> blacklist) { 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blacklist_ = blacklist.Pass(); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLBlacklistManager::IsURLBlocked(const GURL& url) const { 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return blacklist_->IsURLBlocked(url); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool URLBlacklistManager::IsRequestBlocked( 363c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const net::URLRequest& request, int* reason) const { 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); 3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if !defined(OS_IOS) 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(joaodasilva): iOS doesn't set these flags. http://crbug.com/338283 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int filter_flags = net::LOAD_MAIN_FRAME | net::LOAD_SUB_FRAME; 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((request.load_flags() & filter_flags) == 0) 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 372a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool block = false; 373c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (override_blacklist_.Run(request.url(), &block, reason)) 374a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return block; 375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 376c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch *reason = net::ERR_BLOCKED_BY_ADMINISTRATOR; 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return IsURLBlocked(request.url()); 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid URLBlacklistManager::RegisterProfilePrefs( 382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user_prefs::PrefRegistrySyncable* registry) { 3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) registry->RegisterListPref(policy_prefs::kUrlBlacklist, 384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) registry->RegisterListPref(policy_prefs::kUrlWhitelist, 386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace policy 390