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

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

Issue 664263002: Restructure SDCH layering to allow more separation (observer/1->[0,n] (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Incorporated comments. Created 6 years, 1 month 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
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/base/sdch_observer.h"
14 #include "net/url_request/url_request_http_job.h" 15 #include "net/url_request/url_request_http_job.h"
15 16
16 namespace { 17 namespace {
17 18
18 void StripTrailingDot(GURL* gurl) { 19 void StripTrailingDot(GURL* gurl) {
19 std::string host(gurl->host()); 20 std::string host(gurl->host());
20 21
21 if (host.empty()) 22 if (host.empty())
22 return; 23 return;
23 24
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 } 240 }
240 241
241 // static 242 // static
242 bool SdchManager::Dictionary::DomainMatch(const GURL& gurl, 243 bool SdchManager::Dictionary::DomainMatch(const GURL& gurl,
243 const std::string& restriction) { 244 const std::string& restriction) {
244 // TODO(jar): This is not precisely a domain match definition. 245 // TODO(jar): This is not precisely a domain match definition.
245 return gurl.DomainIs(restriction.data(), restriction.size()); 246 return gurl.DomainIs(restriction.data(), restriction.size());
246 } 247 }
247 248
248 //------------------------------------------------------------------------------ 249 //------------------------------------------------------------------------------
249 SdchManager::SdchManager() 250 SdchManager::SdchManager() {
250 : fetches_count_for_testing_(0) { 251 DCHECK(thread_checker_.CalledOnValidThread());
251 DCHECK(CalledOnValidThread());
252 } 252 }
253 253
254 SdchManager::~SdchManager() { 254 SdchManager::~SdchManager() {
255 DCHECK(CalledOnValidThread()); 255 DCHECK(thread_checker_.CalledOnValidThread());
256 while (!dictionaries_.empty()) { 256 while (!dictionaries_.empty()) {
257 DictionaryMap::iterator it = dictionaries_.begin(); 257 DictionaryMap::iterator it = dictionaries_.begin();
258 dictionaries_.erase(it->first); 258 dictionaries_.erase(it->first);
259 } 259 }
260 } 260 }
261 261
262 void SdchManager::ClearData() { 262 void SdchManager::ClearData() {
263 blacklisted_domains_.clear(); 263 blacklisted_domains_.clear();
264 allow_latency_experiment_.clear(); 264 allow_latency_experiment_.clear();
265 if (fetcher_.get())
266 fetcher_->Cancel();
267 265
268 // Note that this may result in not having dictionaries we've advertised 266 // Note that this may result in not having dictionaries we've advertised
269 // for incoming responses. The window is relatively small (as ClearData() 267 // for incoming responses. The window is relatively small (as ClearData()
270 // is not expected to be called frequently), so we rely on meta-refresh 268 // is not expected to be called frequently), so we rely on meta-refresh
271 // to handle this case. 269 // to handle this case.
272 dictionaries_.clear(); 270 dictionaries_.clear();
271
272 FOR_EACH_OBSERVER(SdchObserver, observers_, OnClearDictionaries(this));
273 } 273 }
274 274
275 // static 275 // static
276 void SdchManager::SdchErrorRecovery(ProblemCodes problem) { 276 void SdchManager::SdchErrorRecovery(ProblemCodes problem) {
277 UMA_HISTOGRAM_ENUMERATION("Sdch3.ProblemCodes_4", problem, MAX_PROBLEM_CODE); 277 UMA_HISTOGRAM_ENUMERATION("Sdch3.ProblemCodes_4", problem, MAX_PROBLEM_CODE);
278 } 278 }
279 279
280 void SdchManager::set_sdch_fetcher(scoped_ptr<SdchFetcher> fetcher) {
281 DCHECK(CalledOnValidThread());
282 fetcher_ = fetcher.Pass();
283 }
284
285 // static 280 // static
286 void SdchManager::EnableSdchSupport(bool enabled) { 281 void SdchManager::EnableSdchSupport(bool enabled) {
287 g_sdch_enabled_ = enabled; 282 g_sdch_enabled_ = enabled;
288 } 283 }
289 284
290 // static 285 // static
291 void SdchManager::EnableSecureSchemeSupport(bool enabled) { 286 void SdchManager::EnableSecureSchemeSupport(bool enabled) {
292 g_secure_scheme_supported_ = enabled; 287 g_secure_scheme_supported_ = enabled;
293 } 288 }
294 289
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 340
346 int SdchManager::BlacklistDomainExponential(const std::string& domain) { 341 int SdchManager::BlacklistDomainExponential(const std::string& domain) {
347 std::string domain_lower(base::StringToLowerASCII(domain)); 342 std::string domain_lower(base::StringToLowerASCII(domain));
348 343
349 if (blacklisted_domains_.end() == blacklisted_domains_.find(domain_lower)) 344 if (blacklisted_domains_.end() == blacklisted_domains_.find(domain_lower))
350 return 0; 345 return 0;
351 return blacklisted_domains_[domain_lower].exponential_count; 346 return blacklisted_domains_[domain_lower].exponential_count;
352 } 347 }
353 348
354 bool SdchManager::IsInSupportedDomain(const GURL& url) { 349 bool SdchManager::IsInSupportedDomain(const GURL& url) {
355 DCHECK(CalledOnValidThread()); 350 DCHECK(thread_checker_.CalledOnValidThread());
356 if (!g_sdch_enabled_ ) 351 if (!g_sdch_enabled_ )
357 return false; 352 return false;
358 353
359 if (!secure_scheme_supported() && url.SchemeIsSecure()) 354 if (!secure_scheme_supported() && url.SchemeIsSecure())
360 return false; 355 return false;
361 356
362 if (blacklisted_domains_.empty()) 357 if (blacklisted_domains_.empty())
363 return true; 358 return true;
364 359
365 DomainBlacklistInfo::iterator it = 360 DomainBlacklistInfo::iterator it =
366 blacklisted_domains_.find(base::StringToLowerASCII(url.host())); 361 blacklisted_domains_.find(base::StringToLowerASCII(url.host()));
367 if (blacklisted_domains_.end() == it || it->second.count == 0) 362 if (blacklisted_domains_.end() == it || it->second.count == 0)
368 return true; 363 return true;
369 364
370 UMA_HISTOGRAM_ENUMERATION("Sdch3.BlacklistReason", it->second.reason, 365 UMA_HISTOGRAM_ENUMERATION("Sdch3.BlacklistReason", it->second.reason,
371 MAX_PROBLEM_CODE); 366 MAX_PROBLEM_CODE);
372 SdchErrorRecovery(DOMAIN_BLACKLIST_INCLUDES_TARGET); 367 SdchErrorRecovery(DOMAIN_BLACKLIST_INCLUDES_TARGET);
373 368
374 int count = it->second.count - 1; 369 int count = it->second.count - 1;
375 if (count > 0) { 370 if (count > 0) {
376 it->second.count = count; 371 it->second.count = count;
377 } else { 372 } else {
378 it->second.count = 0; 373 it->second.count = 0;
379 it->second.reason = MIN_PROBLEM_CODE; 374 it->second.reason = MIN_PROBLEM_CODE;
380 } 375 }
381 376
382 return false; 377 return false;
383 } 378 }
384 379
385 void SdchManager::FetchDictionary(const GURL& request_url, 380 void SdchManager::OnGetDictionary(const GURL& request_url,
386 const GURL& dictionary_url) { 381 const GURL& dictionary_url) {
387 DCHECK(CalledOnValidThread()); 382 if (!CanFetchDictionary(request_url, dictionary_url))
388 if (CanFetchDictionary(request_url, dictionary_url) && fetcher_.get()) { 383 return;
389 ++fetches_count_for_testing_; 384
390 fetcher_->Schedule(dictionary_url); 385 FOR_EACH_OBSERVER(SdchObserver,
391 } 386 observers_,
387 OnGetDictionary(this, request_url, dictionary_url));
392 } 388 }
393 389
394 bool SdchManager::CanFetchDictionary(const GURL& referring_url, 390 bool SdchManager::CanFetchDictionary(const GURL& referring_url,
395 const GURL& dictionary_url) const { 391 const GURL& dictionary_url) const {
396 DCHECK(CalledOnValidThread()); 392 DCHECK(thread_checker_.CalledOnValidThread());
397 /* The user agent may retrieve a dictionary from the dictionary URL if all of 393 /* The user agent may retrieve a dictionary from the dictionary URL if all of
398 the following are true: 394 the following are true:
399 1 The dictionary URL host name matches the referrer URL host name and 395 1 The dictionary URL host name matches the referrer URL host name and
400 scheme. 396 scheme.
401 2 The dictionary URL host name domain matches the parent domain of the 397 2 The dictionary URL host name domain matches the parent domain of the
402 referrer URL host name 398 referrer URL host name
403 3 The parent domain of the referrer URL host name is not a top level 399 3 The parent domain of the referrer URL host name is not a top level
404 domain 400 domain
405 4 The dictionary URL is not an HTTPS URL.
406 */ 401 */
407 // Item (1) above implies item (2). Spec should be updated. 402 // Item (1) above implies item (2). Spec should be updated.
408 // I take "host name match" to be "is identical to" 403 // I take "host name match" to be "is identical to"
409 if (referring_url.host() != dictionary_url.host() || 404 if (referring_url.host() != dictionary_url.host() ||
410 referring_url.scheme() != dictionary_url.scheme()) { 405 referring_url.scheme() != dictionary_url.scheme()) {
411 SdchErrorRecovery(DICTIONARY_LOAD_ATTEMPT_FROM_DIFFERENT_HOST); 406 SdchErrorRecovery(DICTIONARY_LOAD_ATTEMPT_FROM_DIFFERENT_HOST);
412 return false; 407 return false;
413 } 408 }
414 if (!secure_scheme_supported() && referring_url.SchemeIsSecure()) { 409 if (!secure_scheme_supported() && referring_url.SchemeIsSecure()) {
415 SdchErrorRecovery(DICTIONARY_SELECTED_FOR_SSL); 410 SdchErrorRecovery(DICTIONARY_SELECTED_FOR_SSL);
416 return false; 411 return false;
417 } 412 }
418 413
419 // TODO(jar): Remove this failsafe conservative hack which is more restrictive 414 // TODO(jar): Remove this failsafe conservative hack which is more restrictive
420 // than current SDCH spec when needed, and justified by security audit. 415 // than current SDCH spec when needed, and justified by security audit.
421 if (!referring_url.SchemeIsHTTPOrHTTPS()) { 416 if (!referring_url.SchemeIsHTTPOrHTTPS()) {
422 SdchErrorRecovery(DICTIONARY_SELECTED_FROM_NON_HTTP); 417 SdchErrorRecovery(DICTIONARY_SELECTED_FROM_NON_HTTP);
423 return false; 418 return false;
424 } 419 }
425 420
426 return true; 421 return true;
427 } 422 }
428 423
429 void SdchManager::GetVcdiffDictionary( 424 void SdchManager::GetVcdiffDictionary(
430 const std::string& server_hash, 425 const std::string& server_hash,
431 const GURL& referring_url, 426 const GURL& referring_url,
432 scoped_refptr<Dictionary>* dictionary) { 427 scoped_refptr<Dictionary>* dictionary) {
433 DCHECK(CalledOnValidThread()); 428 DCHECK(thread_checker_.CalledOnValidThread());
434 *dictionary = NULL; 429 *dictionary = NULL;
435 DictionaryMap::iterator it = dictionaries_.find(server_hash); 430 DictionaryMap::iterator it = dictionaries_.find(server_hash);
436 if (it == dictionaries_.end()) { 431 if (it == dictionaries_.end()) {
437 return; 432 return;
438 } 433 }
439 scoped_refptr<Dictionary> matching_dictionary = it->second; 434 scoped_refptr<Dictionary> matching_dictionary = it->second;
440 if (!IsInSupportedDomain(referring_url)) 435 if (!IsInSupportedDomain(referring_url))
441 return; 436 return;
442 if (!matching_dictionary->CanUse(referring_url)) 437 if (!matching_dictionary->CanUse(referring_url))
443 return; 438 return;
444 *dictionary = matching_dictionary; 439 *dictionary = matching_dictionary;
445 } 440 }
446 441
447 // TODO(jar): If we have evictions from the dictionaries_, then we need to 442 // TODO(jar): If we have evictions from the dictionaries_, then we need to
448 // change this interface to return a list of reference counted Dictionary 443 // change this interface to return a list of reference counted Dictionary
449 // instances that can be used if/when a server specifies one. 444 // instances that can be used if/when a server specifies one.
450 void SdchManager::GetAvailDictionaryList(const GURL& target_url, 445 void SdchManager::GetAvailDictionaryList(const GURL& target_url,
451 std::string* list) { 446 std::string* list) {
452 DCHECK(CalledOnValidThread()); 447 DCHECK(thread_checker_.CalledOnValidThread());
453 int count = 0; 448 int count = 0;
454 for (DictionaryMap::iterator it = dictionaries_.begin(); 449 for (DictionaryMap::iterator it = dictionaries_.begin();
455 it != dictionaries_.end(); ++it) { 450 it != dictionaries_.end(); ++it) {
456 if (!IsInSupportedDomain(target_url)) 451 if (!IsInSupportedDomain(target_url))
457 continue; 452 continue;
458 if (!it->second->CanAdvertise(target_url)) 453 if (!it->second->CanAdvertise(target_url))
459 continue; 454 continue;
460 ++count; 455 ++count;
461 if (!list->empty()) 456 if (!list->empty())
462 list->append(","); 457 list->append(",");
(...skipping 16 matching lines...) Expand all
479 UrlSafeBase64Encode(second_48_bits, server_hash); 474 UrlSafeBase64Encode(second_48_bits, server_hash);
480 475
481 DCHECK_EQ(server_hash->length(), 8u); 476 DCHECK_EQ(server_hash->length(), 8u);
482 DCHECK_EQ(client_hash->length(), 8u); 477 DCHECK_EQ(client_hash->length(), 8u);
483 } 478 }
484 479
485 //------------------------------------------------------------------------------ 480 //------------------------------------------------------------------------------
486 // Methods for supporting latency experiments. 481 // Methods for supporting latency experiments.
487 482
488 bool SdchManager::AllowLatencyExperiment(const GURL& url) const { 483 bool SdchManager::AllowLatencyExperiment(const GURL& url) const {
489 DCHECK(CalledOnValidThread()); 484 DCHECK(thread_checker_.CalledOnValidThread());
490 return allow_latency_experiment_.end() != 485 return allow_latency_experiment_.end() !=
491 allow_latency_experiment_.find(url.host()); 486 allow_latency_experiment_.find(url.host());
492 } 487 }
493 488
494 void SdchManager::SetAllowLatencyExperiment(const GURL& url, bool enable) { 489 void SdchManager::SetAllowLatencyExperiment(const GURL& url, bool enable) {
495 DCHECK(CalledOnValidThread()); 490 DCHECK(thread_checker_.CalledOnValidThread());
496 if (enable) { 491 if (enable) {
497 allow_latency_experiment_.insert(url.host()); 492 allow_latency_experiment_.insert(url.host());
498 return; 493 return;
499 } 494 }
500 ExperimentSet::iterator it = allow_latency_experiment_.find(url.host()); 495 ExperimentSet::iterator it = allow_latency_experiment_.find(url.host());
501 if (allow_latency_experiment_.end() == it) 496 if (allow_latency_experiment_.end() == it)
502 return; // It was already erased, or never allowed. 497 return; // It was already erased, or never allowed.
503 SdchErrorRecovery(LATENCY_TEST_DISALLOWED); 498 SdchErrorRecovery(LATENCY_TEST_DISALLOWED);
504 allow_latency_experiment_.erase(it); 499 allow_latency_experiment_.erase(it);
505 } 500 }
506 501
502 void SdchManager::AddObserver(SdchObserver* observer) {
503 observers_.AddObserver(observer);
504 }
505
506 void SdchManager::RemoveObserver(SdchObserver* observer) {
507 observers_.RemoveObserver(observer);
508 }
509
507 void SdchManager::AddSdchDictionary(const std::string& dictionary_text, 510 void SdchManager::AddSdchDictionary(const std::string& dictionary_text,
508 const GURL& dictionary_url) { 511 const GURL& dictionary_url) {
509 DCHECK(CalledOnValidThread()); 512 DCHECK(thread_checker_.CalledOnValidThread());
510 std::string client_hash; 513 std::string client_hash;
511 std::string server_hash; 514 std::string server_hash;
512 GenerateHash(dictionary_text, &client_hash, &server_hash); 515 GenerateHash(dictionary_text, &client_hash, &server_hash);
513 if (dictionaries_.find(server_hash) != dictionaries_.end()) { 516 if (dictionaries_.find(server_hash) != dictionaries_.end()) {
514 SdchErrorRecovery(DICTIONARY_ALREADY_LOADED); 517 SdchErrorRecovery(DICTIONARY_ALREADY_LOADED);
515 return; // Already loaded. 518 return; // Already loaded.
516 } 519 }
517 520
518 std::string domain, path; 521 std::string domain, path;
519 std::set<int> ports; 522 std::set<int> ports;
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 void SdchManager::UrlSafeBase64Encode(const std::string& input, 617 void SdchManager::UrlSafeBase64Encode(const std::string& input,
615 std::string* output) { 618 std::string* output) {
616 // Since this is only done during a dictionary load, and hashes are only 8 619 // Since this is only done during a dictionary load, and hashes are only 8
617 // characters, we just do the simple fixup, rather than rewriting the encoder. 620 // characters, we just do the simple fixup, rather than rewriting the encoder.
618 base::Base64Encode(input, output); 621 base::Base64Encode(input, output);
619 std::replace(output->begin(), output->end(), '+', '-'); 622 std::replace(output->begin(), output->end(), '+', '-');
620 std::replace(output->begin(), output->end(), '/', '_'); 623 std::replace(output->begin(), output->end(), '/', '_');
621 } 624 }
622 625
623 } // namespace net 626 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698