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

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