Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(365)

Side by Side Diff: net/base/sdch_manager.cc

Issue 298063006: Make SdchManager per-profile. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Incorporated comments and changed test name. Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/sdch_manager.h ('k') | net/base/sdch_manager_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "net/base/sdch_manager.h" 5 #include "net/base/sdch_manager.h"
6 6
7 #include "base/base64.h" 7 #include "base/base64.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
12 #include "crypto/sha2.h" 12 #include "crypto/sha2.h"
13 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" 13 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
14 #include "net/url_request/url_request_http_job.h" 14 #include "net/url_request/url_request_http_job.h"
15 15
16 namespace net { 16 namespace net {
17 17
18 //------------------------------------------------------------------------------ 18 //------------------------------------------------------------------------------
19 // static 19 // static
20 const size_t SdchManager::kMaxDictionarySize = 1000000; 20 const size_t SdchManager::kMaxDictionarySize = 1000000;
21 21
22 // static 22 // static
23 const size_t SdchManager::kMaxDictionaryCount = 20; 23 const size_t SdchManager::kMaxDictionaryCount = 20;
24 24
25 // static 25 // static
26 SdchManager* SdchManager::global_ = NULL;
27
28 // static
29 bool SdchManager::g_sdch_enabled_ = true; 26 bool SdchManager::g_sdch_enabled_ = true;
30 27
31 // static 28 // static
32 bool SdchManager::g_secure_scheme_supported_ = false; 29 bool SdchManager::g_secure_scheme_supported_ = false;
33 30
34 //------------------------------------------------------------------------------ 31 //------------------------------------------------------------------------------
35 SdchManager::Dictionary::Dictionary(const std::string& dictionary_text, 32 SdchManager::Dictionary::Dictionary(const std::string& dictionary_text,
36 size_t offset, 33 size_t offset,
37 const std::string& client_hash, 34 const std::string& client_hash,
38 const GURL& gurl, 35 const GURL& gurl,
39 const std::string& domain, 36 const std::string& domain,
40 const std::string& path, 37 const std::string& path,
41 const base::Time& expiration, 38 const base::Time& expiration,
42 const std::set<int>& ports) 39 const std::set<int>& ports)
43 : text_(dictionary_text, offset), 40 : text_(dictionary_text, offset),
44 client_hash_(client_hash), 41 client_hash_(client_hash),
45 url_(gurl), 42 url_(gurl),
46 domain_(domain), 43 domain_(domain),
47 path_(path), 44 path_(path),
48 expiration_(expiration), 45 expiration_(expiration),
49 ports_(ports) { 46 ports_(ports) {
50 } 47 }
51 48
52 SdchManager::Dictionary::~Dictionary() { 49 SdchManager::Dictionary::~Dictionary() {
53 } 50 }
54 51
55 bool SdchManager::Dictionary::CanAdvertise(const GURL& target_url) { 52 bool SdchManager::Dictionary::CanAdvertise(const GURL& target_url) {
56 if (!SdchManager::Global()->IsInSupportedDomain(target_url))
57 return false;
58 /* The specific rules of when a dictionary should be advertised in an 53 /* The specific rules of when a dictionary should be advertised in an
59 Avail-Dictionary header are modeled after the rules for cookie scoping. The 54 Avail-Dictionary header are modeled after the rules for cookie scoping. The
60 terms "domain-match" and "pathmatch" are defined in RFC 2965 [6]. A 55 terms "domain-match" and "pathmatch" are defined in RFC 2965 [6]. A
61 dictionary may be advertised in the Avail-Dictionaries header exactly when 56 dictionary may be advertised in the Avail-Dictionaries header exactly when
62 all of the following are true: 57 all of the following are true:
63 1. The server's effective host name domain-matches the Domain attribute of 58 1. The server's effective host name domain-matches the Domain attribute of
64 the dictionary. 59 the dictionary.
65 2. If the dictionary has a Port attribute, the request port is one of the 60 2. If the dictionary has a Port attribute, the request port is one of the
66 ports listed in the Port attribute. 61 ports listed in the Port attribute.
67 3. The request URI path-matches the path header of the dictionary. 62 3. The request URI path-matches the path header of the dictionary.
(...skipping 17 matching lines...) Expand all
85 } 80 }
86 81
87 //------------------------------------------------------------------------------ 82 //------------------------------------------------------------------------------
88 // Security functions restricting loads and use of dictionaries. 83 // Security functions restricting loads and use of dictionaries.
89 84
90 // static 85 // static
91 bool SdchManager::Dictionary::CanSet(const std::string& domain, 86 bool SdchManager::Dictionary::CanSet(const std::string& domain,
92 const std::string& path, 87 const std::string& path,
93 const std::set<int>& ports, 88 const std::set<int>& ports,
94 const GURL& dictionary_url) { 89 const GURL& dictionary_url) {
95 if (!SdchManager::Global()->IsInSupportedDomain(dictionary_url))
96 return false;
97 /* 90 /*
98 A dictionary is invalid and must not be stored if any of the following are 91 A dictionary is invalid and must not be stored if any of the following are
99 true: 92 true:
100 1. The dictionary has no Domain attribute. 93 1. The dictionary has no Domain attribute.
101 2. The effective host name that derives from the referer URL host name does 94 2. The effective host name that derives from the referer URL host name does
102 not domain-match the Domain attribute. 95 not domain-match the Domain attribute.
103 3. The Domain attribute is a top level domain. 96 3. The Domain attribute is a top level domain.
104 4. The referer URL host is a host domain name (not IP address) and has the 97 4. The referer URL host is a host domain name (not IP address) and has the
105 form HD, where D is the value of the Domain attribute, and H is a string 98 form HD, where D is the value of the Domain attribute, and H is a string
106 that contains one or more dots. 99 that contains one or more dots.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 if (!ports.empty() 136 if (!ports.empty()
144 && 0 == ports.count(dictionary_url.EffectiveIntPort())) { 137 && 0 == ports.count(dictionary_url.EffectiveIntPort())) {
145 SdchErrorRecovery(DICTIONARY_PORT_NOT_MATCHING_SOURCE_URL); 138 SdchErrorRecovery(DICTIONARY_PORT_NOT_MATCHING_SOURCE_URL);
146 return false; 139 return false;
147 } 140 }
148 return true; 141 return true;
149 } 142 }
150 143
151 // static 144 // static
152 bool SdchManager::Dictionary::CanUse(const GURL& referring_url) { 145 bool SdchManager::Dictionary::CanUse(const GURL& referring_url) {
153 if (!SdchManager::Global()->IsInSupportedDomain(referring_url))
154 return false;
155 /* 146 /*
156 1. The request URL's host name domain-matches the Domain attribute of the 147 1. The request URL's host name domain-matches the Domain attribute of the
157 dictionary. 148 dictionary.
158 2. If the dictionary has a Port attribute, the request port is one of the 149 2. If the dictionary has a Port attribute, the request port is one of the
159 ports listed in the Port attribute. 150 ports listed in the Port attribute.
160 3. The request URL path-matches the path attribute of the dictionary. 151 3. The request URL path-matches the path attribute of the dictionary.
161 4. The request is not an HTTPS request. 152 4. The request is not an HTTPS request.
162 We can override (ignore) item (4) only when we have explicitly enabled 153 We can override (ignore) item (4) only when we have explicitly enabled
163 HTTPS support AND dictionary has been acquired over HTTPS. 154 HTTPS support AND dictionary has been acquired over HTTPS.
164 */ 155 */
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 205
215 // static 206 // static
216 bool SdchManager::Dictionary::DomainMatch(const GURL& gurl, 207 bool SdchManager::Dictionary::DomainMatch(const GURL& gurl,
217 const std::string& restriction) { 208 const std::string& restriction) {
218 // TODO(jar): This is not precisely a domain match definition. 209 // TODO(jar): This is not precisely a domain match definition.
219 return gurl.DomainIs(restriction.data(), restriction.size()); 210 return gurl.DomainIs(restriction.data(), restriction.size());
220 } 211 }
221 212
222 //------------------------------------------------------------------------------ 213 //------------------------------------------------------------------------------
223 SdchManager::SdchManager() { 214 SdchManager::SdchManager() {
224 DCHECK(!global_);
225 DCHECK(CalledOnValidThread()); 215 DCHECK(CalledOnValidThread());
226 global_ = this;
227 } 216 }
228 217
229 SdchManager::~SdchManager() { 218 SdchManager::~SdchManager() {
230 DCHECK_EQ(this, global_);
231 DCHECK(CalledOnValidThread()); 219 DCHECK(CalledOnValidThread());
232 while (!dictionaries_.empty()) { 220 while (!dictionaries_.empty()) {
233 DictionaryMap::iterator it = dictionaries_.begin(); 221 DictionaryMap::iterator it = dictionaries_.begin();
234 it->second->Release(); 222 it->second->Release();
235 dictionaries_.erase(it->first); 223 dictionaries_.erase(it->first);
236 } 224 }
237 global_ = NULL;
238 } 225 }
239 226
240 // static 227 // static
241 void SdchManager::Shutdown() {
242 EnableSdchSupport(false);
243 if (!global_ )
244 return;
245 global_->set_sdch_fetcher(NULL);
246 }
247
248 // static
249 SdchManager* SdchManager::Global() {
250 return global_;
251 }
252
253 // static
254 void SdchManager::SdchErrorRecovery(ProblemCodes problem) { 228 void SdchManager::SdchErrorRecovery(ProblemCodes problem) {
255 UMA_HISTOGRAM_ENUMERATION("Sdch3.ProblemCodes_4", problem, MAX_PROBLEM_CODE); 229 UMA_HISTOGRAM_ENUMERATION("Sdch3.ProblemCodes_4", problem, MAX_PROBLEM_CODE);
256 } 230 }
257 231
258 void SdchManager::set_sdch_fetcher(SdchFetcher* fetcher) { 232 void SdchManager::set_sdch_fetcher(SdchFetcher* fetcher) {
259 DCHECK(CalledOnValidThread()); 233 DCHECK(CalledOnValidThread());
260 fetcher_.reset(fetcher); 234 fetcher_.reset(fetcher);
261 } 235 }
262 236
263 // static 237 // static
264 void SdchManager::EnableSdchSupport(bool enabled) { 238 void SdchManager::EnableSdchSupport(bool enabled) {
265 g_sdch_enabled_ = enabled; 239 g_sdch_enabled_ = enabled;
266 } 240 }
267 241
268 // static 242 // static
269 void SdchManager::EnableSecureSchemeSupport(bool enabled) { 243 void SdchManager::EnableSecureSchemeSupport(bool enabled) {
270 g_secure_scheme_supported_ = enabled; 244 g_secure_scheme_supported_ = enabled;
271 } 245 }
272 246
273 // static
274 void SdchManager::BlacklistDomain(const GURL& url) { 247 void SdchManager::BlacklistDomain(const GURL& url) {
275 if (!global_ ) 248 SetAllowLatencyExperiment(url, false);
276 return;
277 global_->SetAllowLatencyExperiment(url, false);
278 249
279 std::string domain(StringToLowerASCII(url.host())); 250 std::string domain(StringToLowerASCII(url.host()));
280 int count = global_->blacklisted_domains_[domain]; 251 int count = blacklisted_domains_[domain];
281 if (count > 0) 252 if (count > 0)
282 return; // Domain is already blacklisted. 253 return; // Domain is already blacklisted.
283 254
284 count = 1 + 2 * global_->exponential_blacklist_count[domain]; 255 count = 1 + 2 * exponential_blacklist_count[domain];
285 if (count > 0) 256 if (count > 0)
286 global_->exponential_blacklist_count[domain] = count; 257 exponential_blacklist_count[domain] = count;
287 else 258 else
288 count = INT_MAX; 259 count = INT_MAX;
289 260
290 global_->blacklisted_domains_[domain] = count; 261 blacklisted_domains_[domain] = count;
291 } 262 }
292 263
293 // static
294 void SdchManager::BlacklistDomainForever(const GURL& url) { 264 void SdchManager::BlacklistDomainForever(const GURL& url) {
295 if (!global_ ) 265 SetAllowLatencyExperiment(url, false);
296 return;
297 global_->SetAllowLatencyExperiment(url, false);
298 266
299 std::string domain(StringToLowerASCII(url.host())); 267 std::string domain(StringToLowerASCII(url.host()));
300 global_->exponential_blacklist_count[domain] = INT_MAX; 268 exponential_blacklist_count[domain] = INT_MAX;
301 global_->blacklisted_domains_[domain] = INT_MAX; 269 blacklisted_domains_[domain] = INT_MAX;
302 } 270 }
303 271
304 // static
305 void SdchManager::ClearBlacklistings() { 272 void SdchManager::ClearBlacklistings() {
306 Global()->blacklisted_domains_.clear(); 273 blacklisted_domains_.clear();
307 Global()->exponential_blacklist_count.clear(); 274 exponential_blacklist_count.clear();
308 } 275 }
309 276
310 // static
311 void SdchManager::ClearDomainBlacklisting(const std::string& domain) { 277 void SdchManager::ClearDomainBlacklisting(const std::string& domain) {
312 Global()->blacklisted_domains_.erase(StringToLowerASCII(domain)); 278 blacklisted_domains_.erase(StringToLowerASCII(domain));
313 } 279 }
314 280
315 // static
316 int SdchManager::BlackListDomainCount(const std::string& domain) { 281 int SdchManager::BlackListDomainCount(const std::string& domain) {
317 if (Global()->blacklisted_domains_.end() == 282 if (blacklisted_domains_.end() == blacklisted_domains_.find(domain))
318 Global()->blacklisted_domains_.find(domain))
319 return 0; 283 return 0;
320 return Global()->blacklisted_domains_[StringToLowerASCII(domain)]; 284 return blacklisted_domains_[StringToLowerASCII(domain)];
321 } 285 }
322 286
323 // static
324 int SdchManager::BlacklistDomainExponential(const std::string& domain) { 287 int SdchManager::BlacklistDomainExponential(const std::string& domain) {
325 if (Global()->exponential_blacklist_count.end() == 288 if (exponential_blacklist_count.end() ==
326 Global()->exponential_blacklist_count.find(domain)) 289 exponential_blacklist_count.find(domain))
327 return 0; 290 return 0;
328 return Global()->exponential_blacklist_count[StringToLowerASCII(domain)]; 291 return exponential_blacklist_count[StringToLowerASCII(domain)];
329 } 292 }
330 293
331 bool SdchManager::IsInSupportedDomain(const GURL& url) { 294 bool SdchManager::IsInSupportedDomain(const GURL& url) {
332 DCHECK(CalledOnValidThread()); 295 DCHECK(CalledOnValidThread());
333 if (!g_sdch_enabled_ ) 296 if (!g_sdch_enabled_ )
334 return false; 297 return false;
335 298
336 if (blacklisted_domains_.empty()) 299 if (blacklisted_domains_.empty())
337 return true; 300 return true;
338 301
339 std::string domain(StringToLowerASCII(url.host())); 302 std::string domain(StringToLowerASCII(url.host()));
340 DomainCounter::iterator it = blacklisted_domains_.find(domain); 303 DomainCounter::iterator it = blacklisted_domains_.find(domain);
341 if (blacklisted_domains_.end() == it) 304 if (blacklisted_domains_.end() == it)
342 return true; 305 return true;
343 306
344 int count = it->second - 1; 307 int count = it->second - 1;
345 if (count > 0) 308 if (count > 0)
346 blacklisted_domains_[domain] = count; 309 blacklisted_domains_[domain] = count;
347 else 310 else
348 blacklisted_domains_.erase(domain); 311 blacklisted_domains_.erase(domain);
349 SdchErrorRecovery(DOMAIN_BLACKLIST_INCLUDES_TARGET); 312 SdchErrorRecovery(DOMAIN_BLACKLIST_INCLUDES_TARGET);
350 return false; 313 return false;
351 } 314 }
352 315
353 void SdchManager::FetchDictionary(const GURL& request_url, 316 void SdchManager::FetchDictionary(const GURL& request_url,
354 const GURL& dictionary_url) { 317 const GURL& dictionary_url) {
355 DCHECK(CalledOnValidThread()); 318 DCHECK(CalledOnValidThread());
356 if (SdchManager::Global()->CanFetchDictionary(request_url, dictionary_url) && 319 if (CanFetchDictionary(request_url, dictionary_url) && fetcher_.get())
357 fetcher_.get())
358 fetcher_->Schedule(dictionary_url); 320 fetcher_->Schedule(dictionary_url);
359 } 321 }
360 322
361 bool SdchManager::CanFetchDictionary(const GURL& referring_url, 323 bool SdchManager::CanFetchDictionary(const GURL& referring_url,
362 const GURL& dictionary_url) const { 324 const GURL& dictionary_url) const {
363 DCHECK(CalledOnValidThread()); 325 DCHECK(CalledOnValidThread());
364 /* The user agent may retrieve a dictionary from the dictionary URL if all of 326 /* The user agent may retrieve a dictionary from the dictionary URL if all of
365 the following are true: 327 the following are true:
366 1 The dictionary URL host name matches the referrer URL host name and 328 1 The dictionary URL host name matches the referrer URL host name and
367 scheme. 329 scheme.
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 if (port >= 0) 420 if (port >= 0)
459 ports.insert(port); 421 ports.insert(port);
460 } 422 }
461 } 423 }
462 424
463 if (line_end >= header_end) 425 if (line_end >= header_end)
464 break; 426 break;
465 line_start = line_end + 1; 427 line_start = line_end + 1;
466 } 428 }
467 429
430 if (!IsInSupportedDomain(dictionary_url))
431 return false;
432
468 if (!Dictionary::CanSet(domain, path, ports, dictionary_url)) 433 if (!Dictionary::CanSet(domain, path, ports, dictionary_url))
469 return false; 434 return false;
470 435
471 // TODO(jar): Remove these hacks to preclude a DOS attack involving piles of 436 // TODO(jar): Remove these hacks to preclude a DOS attack involving piles of
472 // useless dictionaries. We should probably have a cache eviction plan, 437 // useless dictionaries. We should probably have a cache eviction plan,
473 // instead of just blocking additions. For now, with the spec in flux, it 438 // instead of just blocking additions. For now, with the spec in flux, it
474 // is probably not worth doing eviction handling. 439 // is probably not worth doing eviction handling.
475 if (kMaxDictionarySize < dictionary_text.size()) { 440 if (kMaxDictionarySize < dictionary_text.size()) {
476 SdchErrorRecovery(DICTIONARY_IS_TOO_LARGE); 441 SdchErrorRecovery(DICTIONARY_IS_TOO_LARGE);
477 return false; 442 return false;
(...skipping 16 matching lines...) Expand all
494 459
495 void SdchManager::GetVcdiffDictionary(const std::string& server_hash, 460 void SdchManager::GetVcdiffDictionary(const std::string& server_hash,
496 const GURL& referring_url, Dictionary** dictionary) { 461 const GURL& referring_url, Dictionary** dictionary) {
497 DCHECK(CalledOnValidThread()); 462 DCHECK(CalledOnValidThread());
498 *dictionary = NULL; 463 *dictionary = NULL;
499 DictionaryMap::iterator it = dictionaries_.find(server_hash); 464 DictionaryMap::iterator it = dictionaries_.find(server_hash);
500 if (it == dictionaries_.end()) { 465 if (it == dictionaries_.end()) {
501 return; 466 return;
502 } 467 }
503 Dictionary* matching_dictionary = it->second; 468 Dictionary* matching_dictionary = it->second;
469 if (!IsInSupportedDomain(referring_url))
470 return;
504 if (!matching_dictionary->CanUse(referring_url)) 471 if (!matching_dictionary->CanUse(referring_url))
505 return; 472 return;
506 *dictionary = matching_dictionary; 473 *dictionary = matching_dictionary;
507 } 474 }
508 475
509 // TODO(jar): If we have evictions from the dictionaries_, then we need to 476 // TODO(jar): If we have evictions from the dictionaries_, then we need to
510 // change this interface to return a list of reference counted Dictionary 477 // change this interface to return a list of reference counted Dictionary
511 // instances that can be used if/when a server specifies one. 478 // instances that can be used if/when a server specifies one.
512 void SdchManager::GetAvailDictionaryList(const GURL& target_url, 479 void SdchManager::GetAvailDictionaryList(const GURL& target_url,
513 std::string* list) { 480 std::string* list) {
514 DCHECK(CalledOnValidThread()); 481 DCHECK(CalledOnValidThread());
515 int count = 0; 482 int count = 0;
516 for (DictionaryMap::iterator it = dictionaries_.begin(); 483 for (DictionaryMap::iterator it = dictionaries_.begin();
517 it != dictionaries_.end(); ++it) { 484 it != dictionaries_.end(); ++it) {
485 if (!IsInSupportedDomain(target_url))
486 continue;
518 if (!it->second->CanAdvertise(target_url)) 487 if (!it->second->CanAdvertise(target_url))
519 continue; 488 continue;
520 ++count; 489 ++count;
521 if (!list->empty()) 490 if (!list->empty())
522 list->append(","); 491 list->append(",");
523 list->append(it->second->client_hash()); 492 list->append(it->second->client_hash());
524 } 493 }
525 // Watch to see if we have corrupt or numerous dictionaries. 494 // Watch to see if we have corrupt or numerous dictionaries.
526 if (count > 0) 495 if (count > 0)
527 UMA_HISTOGRAM_COUNTS("Sdch3.Advertisement_Count", count); 496 UMA_HISTOGRAM_COUNTS("Sdch3.Advertisement_Count", count);
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 case '/': 547 case '/':
579 (*output)[i] = '_'; 548 (*output)[i] = '_';
580 continue; 549 continue;
581 default: 550 default:
582 continue; 551 continue;
583 } 552 }
584 } 553 }
585 } 554 }
586 555
587 } // namespace net 556 } // namespace net
OLDNEW
« no previous file with comments | « net/base/sdch_manager.h ('k') | net/base/sdch_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698