Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/policy/url_blacklist_manager.h" | 5 #include "chrome/browser/policy/url_blacklist_manager.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
| 10 #include "base/string_number_conversions.h" | 10 #include "base/string_number_conversions.h" |
| 11 #include "base/values.h" | 11 #include "base/values.h" |
| 12 #include "chrome/browser/net/url_fixer_upper.h" | 12 #include "chrome/browser/net/url_fixer_upper.h" |
| 13 #include "chrome/browser/prefs/pref_service.h" | 13 #include "chrome/browser/prefs/pref_service.h" |
| 14 #include "chrome/common/chrome_notification_types.h" | 14 #include "chrome/common/chrome_notification_types.h" |
| 15 #include "chrome/common/pref_names.h" | 15 #include "chrome/common/pref_names.h" |
| 16 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" |
| 17 #include "content/public/browser/notification_details.h" | 17 #include "content/public/browser/notification_details.h" |
| 18 #include "content/public/browser/notification_source.h" | 18 #include "content/public/browser/notification_source.h" |
| 19 #include "googleurl/src/gurl.h" | 19 #include "googleurl/src/gurl.h" |
| 20 | 20 |
| 21 using content::BrowserThread; | 21 using content::BrowserThread; |
| 22 using extensions::URLMatcher; | |
| 23 using extensions::URLMatcherCondition; | |
| 24 using extensions::URLMatcherConditionFactory; | |
| 25 using extensions::URLMatcherConditionSet; | |
| 26 using extensions::URLMatcherPortFilter; | |
| 27 using extensions::URLMatcherSchemeFilter; | |
| 22 | 28 |
| 23 namespace policy { | 29 namespace policy { |
| 24 | 30 |
| 25 namespace { | 31 namespace { |
| 26 | 32 |
| 27 // Maximum filters per policy. Filters over this index are ignored. | 33 // Maximum filters per policy. Filters over this index are ignored. |
| 28 const size_t kMaxFiltersPerPolicy = 100; | 34 const size_t kMaxFiltersPerPolicy = 100; |
| 29 | 35 |
| 30 typedef std::vector<std::string> StringVector; | 36 const char* kStandardSchemes[] = { |
| 37 "http", | |
| 38 "https", | |
| 39 "file", | |
| 40 "ftp", | |
| 41 "gopher", | |
| 42 "ws", | |
| 43 "wss" | |
| 44 }; | |
| 31 | 45 |
| 32 StringVector* ListValueToStringVector(const base::ListValue* list) { | 46 bool IsStandardScheme(const std::string& scheme) { |
| 33 StringVector* vector = new StringVector; | 47 for (size_t i = 0; i < arraysize(kStandardSchemes); ++i) { |
| 34 | 48 if (scheme == kStandardSchemes[i]) |
| 35 if (list == NULL) | 49 return true; |
| 36 return vector; | |
| 37 | |
| 38 vector->reserve(list->GetSize()); | |
| 39 std::string s; | |
| 40 for (base::ListValue::const_iterator it = list->begin(); | |
| 41 it != list->end() && vector->size() < kMaxFiltersPerPolicy; ++it) { | |
| 42 if ((*it)->GetAsString(&s)) | |
| 43 vector->push_back(s); | |
| 44 } | 50 } |
| 45 | 51 return false; |
| 46 return vector; | |
| 47 } | 52 } |
| 48 | 53 |
| 49 // A task that builds the blacklist on the FILE thread. Takes ownership | 54 // A task that builds the blacklist on the FILE thread. |
| 50 // of |block| and |allow| but not of |blacklist|. | 55 scoped_ptr<URLBlacklist> BuildBlacklist(scoped_ptr<base::ListValue> block, |
| 51 void BuildBlacklist(URLBlacklist* blacklist, | 56 scoped_ptr<base::ListValue> allow) { |
| 52 StringVector* block, | |
| 53 StringVector* allow) { | |
| 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 57 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 55 | 58 |
| 56 scoped_ptr<StringVector> scoped_block(block); | 59 scoped_ptr<URLBlacklist> blacklist(new URLBlacklist); |
| 57 scoped_ptr<StringVector> scoped_allow(allow); | 60 blacklist->Block(block.get()); |
| 58 | 61 blacklist->Allow(allow.get()); |
| 59 for (StringVector::iterator it = block->begin(); it != block->end(); ++it) { | 62 return blacklist.Pass(); |
| 60 blacklist->Block(*it); | |
| 61 } | |
| 62 for (StringVector::iterator it = allow->begin(); it != allow->end(); ++it) { | |
| 63 blacklist->Allow(*it); | |
| 64 } | |
| 65 } | |
| 66 | |
| 67 // A task that owns the URLBlacklist, and passes it to the URLBlacklistManager | |
| 68 // on the IO thread, if the URLBlacklistManager still exists. | |
| 69 void SetBlacklistOnIO(base::WeakPtr<URLBlacklistManager> blacklist_manager, | |
| 70 URLBlacklist* blacklist) { | |
| 71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 72 if (blacklist_manager) { | |
| 73 blacklist_manager->SetBlacklist(blacklist); | |
| 74 } else { | |
| 75 delete blacklist; | |
| 76 } | |
| 77 } | 63 } |
| 78 | 64 |
| 79 } // namespace | 65 } // namespace |
| 80 | 66 |
| 81 struct URLBlacklist::PathFilter { | 67 struct URLBlacklist::FilterComponents { |
| 82 explicit PathFilter(const std::string& path, uint16 port, bool match) | 68 FilterComponents() : match_subdomains(true), allow(true) {} |
| 83 : path_prefix(path), | 69 ~FilterComponents() {} |
| 84 port(port), | |
| 85 blocked_schemes(0), | |
| 86 allowed_schemes(0), | |
| 87 match_subdomains(match) {} | |
| 88 | 70 |
| 89 std::string path_prefix; | 71 std::string scheme; |
| 72 std::string host; | |
| 90 uint16 port; | 73 uint16 port; |
| 91 uint8 blocked_schemes; | 74 std::string path; |
| 92 uint8 allowed_schemes; | |
| 93 bool match_subdomains; | 75 bool match_subdomains; |
| 76 bool allow; | |
| 94 }; | 77 }; |
| 95 | 78 |
| 96 URLBlacklist::URLBlacklist() { | 79 URLBlacklist::URLBlacklist() : id_(0), |
| 80 url_matcher_(new URLMatcher) { | |
| 97 } | 81 } |
| 98 | 82 |
| 99 URLBlacklist::~URLBlacklist() { | 83 URLBlacklist::~URLBlacklist() { |
| 100 STLDeleteValues(&host_filters_); | |
| 101 } | 84 } |
| 102 | 85 |
| 103 void URLBlacklist::Block(const std::string& filter) { | 86 void URLBlacklist::AddFilters(bool allow, |
| 104 AddFilter(filter, true); | 87 const base::ListValue* list) { |
| 88 URLMatcherConditionSet::Vector all_conditions; | |
| 89 size_t size = std::min(kMaxFiltersPerPolicy, list->GetSize()); | |
| 90 for (size_t i = 0; i < size; ++i) { | |
| 91 std::string pattern; | |
| 92 bool success = list->GetString(i, &pattern); | |
| 93 DCHECK(success); | |
| 94 FilterComponents components; | |
| 95 components.allow = allow; | |
| 96 if (!FilterToComponents(pattern, &components.scheme, &components.host, | |
| 97 &components.match_subdomains, &components.port, | |
| 98 &components.path)) { | |
| 99 LOG(ERROR) << "Invalid pattern " << pattern; | |
| 100 continue; | |
| 101 } | |
| 102 | |
| 103 all_conditions.push_back( | |
| 104 CreateConditionSet(url_matcher_.get(), ++id_, components.scheme, | |
| 105 components.host, components.match_subdomains, | |
| 106 components.port, components.path)); | |
| 107 filters_[id_] = components; | |
| 108 } | |
| 109 url_matcher_->AddConditionSets(all_conditions); | |
| 105 } | 110 } |
| 106 | 111 |
| 107 void URLBlacklist::Allow(const std::string& filter) { | 112 void URLBlacklist::Block(const base::ListValue* filters) { |
| 108 AddFilter(filter, false); | 113 AddFilters(false, filters); |
| 114 } | |
| 115 | |
| 116 void URLBlacklist::Allow(const base::ListValue* filters) { | |
| 117 AddFilters(true, filters); | |
| 109 } | 118 } |
| 110 | 119 |
| 111 bool URLBlacklist::IsURLBlocked(const GURL& url) const { | 120 bool URLBlacklist::IsURLBlocked(const GURL& url) const { |
| 112 SchemeFlag flag = SCHEME_ALL; | 121 if (!HasStandardScheme(url)) |
| 113 if (!SchemeToFlag(url.scheme(), &flag)) { | |
| 114 // Not a scheme that can be filtered. | |
| 115 return false; | 122 return false; |
| 123 | |
| 124 std::set<URLMatcherConditionSet::ID> matching_ids = | |
| 125 url_matcher_->MatchURL(url); | |
| 126 | |
| 127 const FilterComponents* max = NULL; | |
| 128 for (std::set<URLMatcherConditionSet::ID>::iterator id = matching_ids.begin(); | |
| 129 id != matching_ids.end(); ++id) { | |
| 130 std::map<int, FilterComponents>::const_iterator it = filters_.find(*id); | |
| 131 DCHECK(it != filters_.end()); | |
| 132 const FilterComponents& filter = it->second; | |
| 133 if (!max || FilterTakesPrecedence(filter, *max)) | |
| 134 max = &filter; | |
| 116 } | 135 } |
| 117 | 136 |
| 118 std::string host(url.host()); | 137 // Default to allow. |
| 119 int int_port = url.EffectiveIntPort(); | 138 if (!max) |
| 120 const uint16 port = int_port > 0 ? int_port : 0; | 139 return false; |
| 121 const std::string& path = url.path(); | |
| 122 | 140 |
| 123 // The first iteration through the loop will be an exact host match. | 141 return !max->allow; |
| 124 // Subsequent iterations are subdomain matches, and some filters don't apply | |
| 125 // to those. | |
| 126 bool is_matching_subdomains = false; | |
| 127 const bool host_is_ip = url.HostIsIPAddress(); | |
| 128 while (1) { | |
| 129 HostFilterTable::const_iterator host_filter = host_filters_.find(host); | |
| 130 if (host_filter != host_filters_.end()) { | |
| 131 const PathFilterList* list = host_filter->second; | |
| 132 size_t longest_length = 0; | |
| 133 bool is_blocked = false; | |
| 134 bool has_match = false; | |
| 135 bool has_exact_host_match = false; | |
| 136 for (PathFilterList::const_iterator it = list->begin(); | |
| 137 it != list->end(); ++it) { | |
| 138 // Filters that apply to an exact hostname only take precedence over | |
| 139 // filters that can apply to subdomains too. | |
| 140 // E.g. ".google.com" filters take priority over "google.com". | |
| 141 if (has_exact_host_match && it->match_subdomains) | |
| 142 continue; | |
| 143 | |
| 144 // Skip if filter doesn't apply to subdomains, and this is a subdomain. | |
| 145 if (is_matching_subdomains && !it->match_subdomains) | |
| 146 continue; | |
| 147 | |
| 148 if (it->port != 0 && it->port != port) | |
| 149 continue; | |
| 150 | |
| 151 // Skip if the filter doesn't apply to the scheme. | |
| 152 if ((it->allowed_schemes & flag) == 0 && | |
| 153 (it->blocked_schemes & flag) == 0) | |
| 154 continue; | |
| 155 | |
| 156 // If this match can't be longer than the current match, skip it. | |
| 157 // For same size matches, the first rule to match takes precedence. | |
| 158 // If this is an exact host match, it can be actually shorter than | |
| 159 // a previous, non-exact match. | |
| 160 if ((has_match && it->path_prefix.length() <= longest_length) && | |
| 161 (has_exact_host_match || it->match_subdomains)) { | |
| 162 continue; | |
| 163 } | |
| 164 | |
| 165 // Skip if the filter's |path_prefix| is not a prefix of |path|. | |
| 166 if (path.compare(0, it->path_prefix.length(), it->path_prefix) != 0) | |
| 167 continue; | |
| 168 | |
| 169 // This is the best match so far. | |
| 170 has_match = true; | |
| 171 has_exact_host_match = !it->match_subdomains; | |
| 172 longest_length = it->path_prefix.length(); | |
| 173 // If both blocked and allowed bits are set, allowed takes precedence. | |
| 174 is_blocked = !(it->allowed_schemes & flag); | |
| 175 } | |
| 176 // If a match was found, return its decision. | |
| 177 if (has_match) | |
| 178 return is_blocked; | |
| 179 } | |
| 180 | |
| 181 // Quit after trying the empty string (corresponding to host '*'). | |
| 182 // Also skip subdomain matching for IP addresses. | |
| 183 if (host.empty() || host_is_ip) | |
| 184 break; | |
| 185 | |
| 186 // No match found for this host. Try a subdomain match, by removing the | |
| 187 // leftmost subdomain from the hostname. | |
| 188 is_matching_subdomains = true; | |
| 189 size_t i = host.find('.'); | |
| 190 if (i != std::string::npos) | |
| 191 ++i; | |
| 192 host.erase(0, i); | |
| 193 } | |
| 194 | |
| 195 // Default is to allow. | |
| 196 return false; | |
| 197 } | 142 } |
| 198 | 143 |
| 199 // static | 144 // static |
| 200 bool URLBlacklist::SchemeToFlag(const std::string& scheme, SchemeFlag* flag) { | 145 bool URLBlacklist::HasStandardScheme(const GURL& url) { |
| 201 if (scheme.empty()) { | 146 return IsStandardScheme(url.scheme()); |
| 202 *flag = SCHEME_ALL; | |
| 203 } else if (scheme == "http") { | |
| 204 *flag = SCHEME_HTTP; | |
| 205 } else if (scheme == "https") { | |
| 206 *flag = SCHEME_HTTPS; | |
| 207 } else if (scheme == "ftp") { | |
| 208 *flag = SCHEME_FTP; | |
| 209 } else if (scheme == "ws") { | |
| 210 *flag = SCHEME_WS; | |
| 211 } else if (scheme == "wss") { | |
| 212 *flag = SCHEME_WSS; | |
| 213 } else { | |
| 214 return false; | |
| 215 } | |
| 216 return true; | |
| 217 } | 147 } |
| 218 | 148 |
| 219 // static | 149 // static |
| 220 bool URLBlacklist::FilterToComponents(const std::string& filter, | 150 bool URLBlacklist::FilterToComponents(const std::string& filter, |
| 221 std::string* scheme, | 151 std::string* scheme, |
| 222 std::string* host, | 152 std::string* host, |
| 223 uint16* port, | 153 bool* match_subdomains, |
| 224 std::string* path) { | 154 uint16* port, |
| 155 std::string* path) { | |
| 225 url_parse::Parsed parsed; | 156 url_parse::Parsed parsed; |
| 226 URLFixerUpper::SegmentURL(filter, &parsed); | 157 URLFixerUpper::SegmentURL(filter, &parsed); |
| 227 | 158 |
| 228 if (!parsed.host.is_nonempty()) | 159 if (!parsed.host.is_nonempty()) |
| 229 return false; | 160 return false; |
| 230 | 161 |
| 231 if (parsed.scheme.is_nonempty()) | 162 if (parsed.scheme.is_nonempty()) |
| 232 scheme->assign(filter, parsed.scheme.begin, parsed.scheme.len); | 163 scheme->assign(filter, parsed.scheme.begin, parsed.scheme.len); |
| 233 else | 164 else |
| 234 scheme->clear(); | 165 scheme->clear(); |
| 235 | 166 |
| 236 host->assign(filter, parsed.host.begin, parsed.host.len); | 167 host->assign(filter, parsed.host.begin, parsed.host.len); |
| 237 // Special '*' host, matches all hosts. | 168 // Special '*' host, matches all hosts. |
| 238 if (*host == "*") | 169 if (*host == "*") { |
| 239 host->clear(); | 170 host->clear(); |
| 171 *match_subdomains = true; | |
| 172 } else if ((*host)[0] == '.') { | |
| 173 // A leading dot in the pattern syntax means that we don't want to match | |
| 174 // subdomains. | |
| 175 host->erase(0, 1); | |
| 176 *match_subdomains = false; | |
| 177 } else { | |
| 178 url_canon::RawCanonOutputT<char> output; | |
| 179 url_canon::CanonHostInfo host_info; | |
| 180 url_canon::CanonicalizeHostVerbose(filter.c_str(), parsed.host, | |
| 181 &output, &host_info); | |
| 182 if (host_info.family == url_canon::CanonHostInfo::NEUTRAL) { | |
| 183 // We want to match subdomains. Add a dot in front to make sure we only | |
| 184 // match at domain component boundaries. | |
| 185 *host = "." + *host; | |
| 186 *match_subdomains = true; | |
| 187 } else { | |
| 188 *match_subdomains = false; | |
| 189 } | |
| 190 } | |
| 240 | 191 |
| 241 if (parsed.port.is_nonempty()) { | 192 if (parsed.port.is_nonempty()) { |
| 242 int int_port; | 193 int int_port; |
| 243 if (!base::StringToInt(filter.substr(parsed.port.begin, parsed.port.len), | 194 if (!base::StringToInt(filter.substr(parsed.port.begin, parsed.port.len), |
| 244 &int_port)) { | 195 &int_port)) { |
| 245 return false; | 196 return false; |
| 246 } | 197 } |
| 247 if (int_port <= 0 || int_port > kuint16max) | 198 if (int_port <= 0 || int_port > kuint16max) |
| 248 return false; | 199 return false; |
| 249 *port = int_port; | 200 *port = int_port; |
| 250 } else { | 201 } else { |
| 251 // Match any port. | 202 // Match any port. |
| 252 *port = 0; | 203 *port = 0; |
| 253 } | 204 } |
| 254 | 205 |
| 255 if (parsed.path.is_nonempty()) | 206 if (parsed.path.is_nonempty()) |
| 256 path->assign(filter, parsed.path.begin, parsed.path.len); | 207 path->assign(filter, parsed.path.begin, parsed.path.len); |
| 257 else | 208 else |
| 258 path->clear(); | 209 path->clear(); |
| 259 | 210 |
| 211 if (!scheme->empty() && !IsStandardScheme(*scheme)) | |
| 212 return false; | |
| 213 | |
| 260 return true; | 214 return true; |
| 261 } | 215 } |
| 262 | 216 |
| 263 void URLBlacklist::AddFilter(const std::string& filter, bool block) { | 217 // static |
| 264 std::string scheme; | 218 scoped_refptr<extensions::URLMatcherConditionSet> |
| 265 std::string host; | 219 URLBlacklist::CreateConditionSet( |
| 266 uint16 port; | 220 extensions::URLMatcher* url_matcher, |
| 267 std::string path; | 221 int id, |
| 268 if (!FilterToComponents(filter, &scheme, &host, &port, &path)) { | 222 const std::string& scheme, |
| 269 LOG(WARNING) << "Invalid filter, ignoring: " << filter; | 223 const std::string& host, |
| 270 return; | 224 bool match_subdomains, |
| 225 uint16 port, | |
| 226 const std::string& path) { | |
| 227 URLMatcherConditionFactory* condition_factory = | |
| 228 url_matcher->condition_factory(); | |
| 229 std::set<URLMatcherCondition> conditions; | |
| 230 conditions.insert(match_subdomains ? | |
| 231 condition_factory->CreateHostSuffixPathPrefixCondition(host, path) : | |
| 232 condition_factory->CreateHostEqualsPathPrefixCondition(host, path)); | |
| 233 | |
| 234 scoped_ptr<URLMatcherSchemeFilter> scheme_filter; | |
| 235 if (!scheme.empty()) | |
| 236 scheme_filter.reset(new URLMatcherSchemeFilter(scheme)); | |
| 237 | |
| 238 scoped_ptr<URLMatcherPortFilter> port_filter; | |
| 239 if (port != 0) { | |
| 240 std::vector<URLMatcherPortFilter::Range> ranges; | |
| 241 ranges.push_back(URLMatcherPortFilter::CreateRange(port)); | |
| 242 port_filter.reset(new URLMatcherPortFilter(ranges)); | |
| 271 } | 243 } |
| 272 | 244 |
| 273 SchemeFlag flag; | 245 return new URLMatcherConditionSet(id, conditions, |
| 274 if (!SchemeToFlag(scheme, &flag)) { | 246 scheme_filter.Pass(), port_filter.Pass()); |
| 275 LOG(WARNING) << "Unsupported scheme in filter, ignoring filter: " << filter; | 247 } |
| 276 return; | |
| 277 } | |
| 278 | 248 |
| 279 bool match_subdomains = true; | 249 // static |
| 280 // Special syntax to disable subdomain matching. | 250 bool URLBlacklist::FilterTakesPrecedence(const FilterComponents& lhs, |
| 281 if (!host.empty() && host[0] == '.') { | 251 const FilterComponents& rhs) { |
| 282 host.erase(0, 1); | 252 if (lhs.match_subdomains && !rhs.match_subdomains) |
| 283 match_subdomains = false; | 253 return false; |
| 284 } | 254 if (!lhs.match_subdomains && rhs.match_subdomains) |
| 255 return true; | |
| 285 | 256 |
| 286 // Try to find an existing PathFilter with the same path prefix, port and | 257 size_t host_length = lhs.host.length(); |
| 287 // match_subdomains value. | 258 size_t other_host_length = rhs.host.length(); |
| 288 PathFilterList* list; | 259 if (host_length < other_host_length) |
| 289 HostFilterTable::iterator host_filter = host_filters_.find(host); | 260 return false; |
| 290 if (host_filter == host_filters_.end()) { | 261 if (host_length > other_host_length) |
| 291 list = new PathFilterList; | 262 return true; |
|
Joao da Silva
2012/07/16 11:26:43
Suggestion:
if (host_length != other_host_length)
Bernhard Bauer
2012/07/16 11:31:58
Done.
| |
| 292 host_filters_[host] = list; | |
| 293 } else { | |
| 294 list = host_filter->second; | |
| 295 } | |
| 296 PathFilterList::iterator it; | |
| 297 for (it = list->begin(); it != list->end(); ++it) { | |
| 298 if (it->port == port && it->match_subdomains == match_subdomains && | |
| 299 it->path_prefix == path) { | |
| 300 break; | |
| 301 } | |
| 302 } | |
| 303 PathFilter* path_filter; | |
| 304 if (it == list->end()) { | |
| 305 list->push_back(PathFilter(path, port, match_subdomains)); | |
| 306 path_filter = &list->back(); | |
| 307 } else { | |
| 308 path_filter = &(*it); | |
| 309 } | |
| 310 | 263 |
| 311 if (block) { | 264 size_t path_length = lhs.path.length(); |
| 312 path_filter->blocked_schemes |= flag; | 265 size_t other_path_length = rhs.path.length(); |
| 313 } else { | 266 if (path_length < other_path_length) |
| 314 path_filter->allowed_schemes |= flag; | 267 return false; |
| 315 } | 268 if (path_length > other_path_length) |
| 269 return true; | |
| 270 | |
| 271 if (lhs.allow && !rhs.allow) | |
| 272 return true; | |
| 273 | |
| 274 return false; | |
| 316 } | 275 } |
| 317 | 276 |
| 318 URLBlacklistManager::URLBlacklistManager(PrefService* pref_service) | 277 URLBlacklistManager::URLBlacklistManager(PrefService* pref_service) |
| 319 : ALLOW_THIS_IN_INITIALIZER_LIST(ui_weak_ptr_factory_(this)), | 278 : ALLOW_THIS_IN_INITIALIZER_LIST(ui_weak_ptr_factory_(this)), |
| 320 pref_service_(pref_service), | 279 pref_service_(pref_service), |
| 321 ALLOW_THIS_IN_INITIALIZER_LIST(io_weak_ptr_factory_(this)), | 280 ALLOW_THIS_IN_INITIALIZER_LIST(io_weak_ptr_factory_(this)), |
| 322 blacklist_(new URLBlacklist) { | 281 blacklist_(new URLBlacklist) { |
| 323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 282 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 324 | 283 |
| 325 pref_change_registrar_.Init(pref_service_); | 284 pref_change_registrar_.Init(pref_service_); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 364 MessageLoop::current()->PostTask( | 323 MessageLoop::current()->PostTask( |
| 365 FROM_HERE, | 324 FROM_HERE, |
| 366 base::Bind(&URLBlacklistManager::Update, | 325 base::Bind(&URLBlacklistManager::Update, |
| 367 ui_weak_ptr_factory_.GetWeakPtr())); | 326 ui_weak_ptr_factory_.GetWeakPtr())); |
| 368 } | 327 } |
| 369 | 328 |
| 370 void URLBlacklistManager::Update() { | 329 void URLBlacklistManager::Update() { |
| 371 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 330 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 372 | 331 |
| 373 // The preferences can only be read on the UI thread. | 332 // The preferences can only be read on the UI thread. |
| 374 StringVector* block = | 333 scoped_ptr<base::ListValue> block( |
| 375 ListValueToStringVector(pref_service_->GetList(prefs::kUrlBlacklist)); | 334 pref_service_->GetList(prefs::kUrlBlacklist)->DeepCopy()); |
| 376 StringVector* allow = | 335 scoped_ptr<base::ListValue> allow( |
| 377 ListValueToStringVector(pref_service_->GetList(prefs::kUrlWhitelist)); | 336 pref_service_->GetList(prefs::kUrlWhitelist)->DeepCopy()); |
| 378 | 337 |
| 379 // Go through the IO thread to grab a WeakPtr to |this|. This is safe from | 338 // Go through the IO thread to grab a WeakPtr to |this|. This is safe from |
| 380 // here, since this task will always execute before a potential deletion of | 339 // here, since this task will always execute before a potential deletion of |
| 381 // ProfileIOData on IO. | 340 // ProfileIOData on IO. |
| 382 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 341 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 383 base::Bind(&URLBlacklistManager::UpdateOnIO, | 342 base::Bind(&URLBlacklistManager::UpdateOnIO, |
| 384 base::Unretained(this), block, allow)); | 343 base::Unretained(this), |
| 344 base::Passed(&block), | |
| 345 base::Passed(&allow))); | |
| 385 } | 346 } |
| 386 | 347 |
| 387 void URLBlacklistManager::UpdateOnIO(StringVector* block, StringVector* allow) { | 348 void URLBlacklistManager::UpdateOnIO(scoped_ptr<base::ListValue> block, |
| 349 scoped_ptr<base::ListValue> allow) { | |
| 388 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 350 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 389 URLBlacklist* blacklist = new URLBlacklist; | |
| 390 // The URLBlacklist is built on the FILE thread. Once it's ready, it is passed | 351 // The URLBlacklist is built on the FILE thread. Once it's ready, it is passed |
| 391 // to the URLBlacklistManager on IO. | 352 // to the URLBlacklistManager on IO. |
| 392 // |blacklist|, |block| and |allow| can leak on the unlikely event of a | 353 BrowserThread::PostTaskAndReplyWithResult( |
| 393 // policy update and shutdown happening at the same time. | 354 BrowserThread::FILE, FROM_HERE, |
| 394 BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE, | 355 base::Bind(&BuildBlacklist, |
| 395 base::Bind(&BuildBlacklist, | 356 base::Passed(&block), |
| 396 blacklist, block, allow), | 357 base::Passed(&allow)), |
| 397 base::Bind(&SetBlacklistOnIO, | 358 base::Bind(&URLBlacklistManager::SetBlacklist, |
| 398 io_weak_ptr_factory_.GetWeakPtr(), | 359 io_weak_ptr_factory_.GetWeakPtr())); |
| 399 blacklist)); | |
| 400 } | 360 } |
| 401 | 361 |
| 402 void URLBlacklistManager::SetBlacklist(URLBlacklist* blacklist) { | 362 void URLBlacklistManager::SetBlacklist(scoped_ptr<URLBlacklist> blacklist) { |
| 403 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 404 blacklist_.reset(blacklist); | 364 blacklist_ = blacklist.Pass(); |
| 405 } | 365 } |
| 406 | 366 |
| 407 bool URLBlacklistManager::IsURLBlocked(const GURL& url) const { | 367 bool URLBlacklistManager::IsURLBlocked(const GURL& url) const { |
| 408 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 368 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 409 return blacklist_->IsURLBlocked(url); | 369 return blacklist_->IsURLBlocked(url); |
| 410 } | 370 } |
| 411 | 371 |
| 412 // static | 372 // static |
| 413 void URLBlacklistManager::RegisterPrefs(PrefService* pref_service) { | 373 void URLBlacklistManager::RegisterPrefs(PrefService* pref_service) { |
| 414 pref_service->RegisterListPref(prefs::kUrlBlacklist, | 374 pref_service->RegisterListPref(prefs::kUrlBlacklist, |
| 415 PrefService::UNSYNCABLE_PREF); | 375 PrefService::UNSYNCABLE_PREF); |
| 416 pref_service->RegisterListPref(prefs::kUrlWhitelist, | 376 pref_service->RegisterListPref(prefs::kUrlWhitelist, |
| 417 PrefService::UNSYNCABLE_PREF); | 377 PrefService::UNSYNCABLE_PREF); |
| 418 } | 378 } |
| 419 | 379 |
| 420 } // namespace policy | 380 } // namespace policy |
| OLD | NEW |