| 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 "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" |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 | 133 |
| 134 // TODO(jar): Redirects in dictionary fetches might plausibly be problematic, | 134 // TODO(jar): Redirects in dictionary fetches might plausibly be problematic, |
| 135 // and hence the conservative approach is to not allow any redirects (if there | 135 // and hence the conservative approach is to not allow any redirects (if there |
| 136 // were any... then don't allow the dictionary to be set). | 136 // were any... then don't allow the dictionary to be set). |
| 137 | 137 |
| 138 if (domain.empty()) { | 138 if (domain.empty()) { |
| 139 SdchErrorRecovery(DICTIONARY_MISSING_DOMAIN_SPECIFIER); | 139 SdchErrorRecovery(DICTIONARY_MISSING_DOMAIN_SPECIFIER); |
| 140 return false; // Domain is required. | 140 return false; // Domain is required. |
| 141 } | 141 } |
| 142 if (registry_controlled_domains::GetDomainAndRegistry( | 142 if (registry_controlled_domains::GetDomainAndRegistry( |
| 143 domain, | 143 domain, registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES) |
| 144 registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES).empty()) { | 144 .empty()) { |
| 145 SdchErrorRecovery(DICTIONARY_SPECIFIES_TOP_LEVEL_DOMAIN); | 145 SdchErrorRecovery(DICTIONARY_SPECIFIES_TOP_LEVEL_DOMAIN); |
| 146 return false; // domain was a TLD. | 146 return false; // domain was a TLD. |
| 147 } | 147 } |
| 148 if (!Dictionary::DomainMatch(dictionary_url, domain)) { | 148 if (!Dictionary::DomainMatch(dictionary_url, domain)) { |
| 149 SdchErrorRecovery(DICTIONARY_DOMAIN_NOT_MATCHING_SOURCE_URL); | 149 SdchErrorRecovery(DICTIONARY_DOMAIN_NOT_MATCHING_SOURCE_URL); |
| 150 return false; | 150 return false; |
| 151 } | 151 } |
| 152 | 152 |
| 153 std::string referrer_url_host = dictionary_url.host(); | 153 std::string referrer_url_host = dictionary_url.host(); |
| 154 size_t postfix_domain_index = referrer_url_host.rfind(domain); | 154 size_t postfix_domain_index = referrer_url_host.rfind(domain); |
| 155 // See if it is indeed a postfix, or just an internal string. | 155 // See if it is indeed a postfix, or just an internal string. |
| 156 if (referrer_url_host.size() == postfix_domain_index + domain.size()) { | 156 if (referrer_url_host.size() == postfix_domain_index + domain.size()) { |
| 157 // It is a postfix... so check to see if there's a dot in the prefix. | 157 // It is a postfix... so check to see if there's a dot in the prefix. |
| 158 size_t end_of_host_index = referrer_url_host.find_first_of('.'); | 158 size_t end_of_host_index = referrer_url_host.find_first_of('.'); |
| 159 if (referrer_url_host.npos != end_of_host_index && | 159 if (referrer_url_host.npos != end_of_host_index && |
| 160 end_of_host_index < postfix_domain_index) { | 160 end_of_host_index < postfix_domain_index) { |
| 161 SdchErrorRecovery(DICTIONARY_REFERER_URL_HAS_DOT_IN_PREFIX); | 161 SdchErrorRecovery(DICTIONARY_REFERER_URL_HAS_DOT_IN_PREFIX); |
| 162 return false; | 162 return false; |
| 163 } | 163 } |
| 164 } | 164 } |
| 165 | 165 |
| 166 if (!ports.empty() | 166 if (!ports.empty() && 0 == ports.count(dictionary_url.EffectiveIntPort())) { |
| 167 && 0 == ports.count(dictionary_url.EffectiveIntPort())) { | |
| 168 SdchErrorRecovery(DICTIONARY_PORT_NOT_MATCHING_SOURCE_URL); | 167 SdchErrorRecovery(DICTIONARY_PORT_NOT_MATCHING_SOURCE_URL); |
| 169 return false; | 168 return false; |
| 170 } | 169 } |
| 171 return true; | 170 return true; |
| 172 } | 171 } |
| 173 | 172 |
| 174 // static | 173 // static |
| 175 bool SdchManager::Dictionary::CanUse(const GURL& referring_url) { | 174 bool SdchManager::Dictionary::CanUse(const GURL& referring_url) { |
| 176 /* | 175 /* |
| 177 1. The request URL's host name domain-matches the Domain attribute of the | 176 1. The request URL's host name domain-matches the Domain attribute of the |
| 178 dictionary. | 177 dictionary. |
| 179 2. If the dictionary has a Port attribute, the request port is one of the | 178 2. If the dictionary has a Port attribute, the request port is one of the |
| 180 ports listed in the Port attribute. | 179 ports listed in the Port attribute. |
| 181 3. The request URL path-matches the path attribute of the dictionary. | 180 3. The request URL path-matches the path attribute of the dictionary. |
| 182 4. The request is not an HTTPS request. | 181 4. The request is not an HTTPS request. |
| 183 We can override (ignore) item (4) only when we have explicitly enabled | 182 We can override (ignore) item (4) only when we have explicitly enabled |
| 184 HTTPS support AND the dictionary acquisition scheme matches the target | 183 HTTPS support AND the dictionary acquisition scheme matches the target |
| 185 url scheme. | 184 url scheme. |
| 186 */ | 185 */ |
| 187 if (!DomainMatch(referring_url, domain_)) { | 186 if (!DomainMatch(referring_url, domain_)) { |
| 188 SdchErrorRecovery(DICTIONARY_FOUND_HAS_WRONG_DOMAIN); | 187 SdchErrorRecovery(DICTIONARY_FOUND_HAS_WRONG_DOMAIN); |
| 189 return false; | 188 return false; |
| 190 } | 189 } |
| 191 if (!ports_.empty() | 190 if (!ports_.empty() && 0 == ports_.count(referring_url.EffectiveIntPort())) { |
| 192 && 0 == ports_.count(referring_url.EffectiveIntPort())) { | |
| 193 SdchErrorRecovery(DICTIONARY_FOUND_HAS_WRONG_PORT_LIST); | 191 SdchErrorRecovery(DICTIONARY_FOUND_HAS_WRONG_PORT_LIST); |
| 194 return false; | 192 return false; |
| 195 } | 193 } |
| 196 if (path_.size() && !PathMatch(referring_url.path(), path_)) { | 194 if (path_.size() && !PathMatch(referring_url.path(), path_)) { |
| 197 SdchErrorRecovery(DICTIONARY_FOUND_HAS_WRONG_PATH); | 195 SdchErrorRecovery(DICTIONARY_FOUND_HAS_WRONG_PATH); |
| 198 return false; | 196 return false; |
| 199 } | 197 } |
| 200 if (!SdchManager::secure_scheme_supported() && | 198 if (!SdchManager::secure_scheme_supported() && |
| 201 referring_url.SchemeIsSecure()) { | 199 referring_url.SchemeIsSecure()) { |
| 202 SdchErrorRecovery(DICTIONARY_FOUND_HAS_WRONG_SCHEME); | 200 SdchErrorRecovery(DICTIONARY_FOUND_HAS_WRONG_SCHEME); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 blacklist_info->count = INT_MAX; | 310 blacklist_info->count = INT_MAX; |
| 313 blacklist_info->exponential_count = INT_MAX; | 311 blacklist_info->exponential_count = INT_MAX; |
| 314 blacklist_info->reason = blacklist_reason; | 312 blacklist_info->reason = blacklist_reason; |
| 315 } | 313 } |
| 316 | 314 |
| 317 void SdchManager::ClearBlacklistings() { | 315 void SdchManager::ClearBlacklistings() { |
| 318 blacklisted_domains_.clear(); | 316 blacklisted_domains_.clear(); |
| 319 } | 317 } |
| 320 | 318 |
| 321 void SdchManager::ClearDomainBlacklisting(const std::string& domain) { | 319 void SdchManager::ClearDomainBlacklisting(const std::string& domain) { |
| 322 BlacklistInfo* blacklist_info = &blacklisted_domains_[ | 320 BlacklistInfo* blacklist_info = |
| 323 base::StringToLowerASCII(domain)]; | 321 &blacklisted_domains_[base::StringToLowerASCII(domain)]; |
| 324 blacklist_info->count = 0; | 322 blacklist_info->count = 0; |
| 325 blacklist_info->reason = MIN_PROBLEM_CODE; | 323 blacklist_info->reason = MIN_PROBLEM_CODE; |
| 326 } | 324 } |
| 327 | 325 |
| 328 int SdchManager::BlackListDomainCount(const std::string& domain) { | 326 int SdchManager::BlackListDomainCount(const std::string& domain) { |
| 329 std::string domain_lower(base::StringToLowerASCII(domain)); | 327 std::string domain_lower(base::StringToLowerASCII(domain)); |
| 330 | 328 |
| 331 if (blacklisted_domains_.end() == blacklisted_domains_.find(domain_lower)) | 329 if (blacklisted_domains_.end() == blacklisted_domains_.find(domain_lower)) |
| 332 return 0; | 330 return 0; |
| 333 return blacklisted_domains_[domain_lower].count; | 331 return blacklisted_domains_[domain_lower].count; |
| 334 } | 332 } |
| 335 | 333 |
| 336 int SdchManager::BlacklistDomainExponential(const std::string& domain) { | 334 int SdchManager::BlacklistDomainExponential(const std::string& domain) { |
| 337 std::string domain_lower(base::StringToLowerASCII(domain)); | 335 std::string domain_lower(base::StringToLowerASCII(domain)); |
| 338 | 336 |
| 339 if (blacklisted_domains_.end() == blacklisted_domains_.find(domain_lower)) | 337 if (blacklisted_domains_.end() == blacklisted_domains_.find(domain_lower)) |
| 340 return 0; | 338 return 0; |
| 341 return blacklisted_domains_[domain_lower].exponential_count; | 339 return blacklisted_domains_[domain_lower].exponential_count; |
| 342 } | 340 } |
| 343 | 341 |
| 344 bool SdchManager::IsInSupportedDomain(const GURL& url) { | 342 bool SdchManager::IsInSupportedDomain(const GURL& url) { |
| 345 DCHECK(thread_checker_.CalledOnValidThread()); | 343 DCHECK(thread_checker_.CalledOnValidThread()); |
| 346 if (!g_sdch_enabled_ ) | 344 if (!g_sdch_enabled_) |
| 347 return false; | 345 return false; |
| 348 | 346 |
| 349 if (!secure_scheme_supported() && url.SchemeIsSecure()) | 347 if (!secure_scheme_supported() && url.SchemeIsSecure()) |
| 350 return false; | 348 return false; |
| 351 | 349 |
| 352 if (blacklisted_domains_.empty()) | 350 if (blacklisted_domains_.empty()) |
| 353 return true; | 351 return true; |
| 354 | 352 |
| 355 DomainBlacklistInfo::iterator it = | 353 DomainBlacklistInfo::iterator it = |
| 356 blacklisted_domains_.find(base::StringToLowerASCII(url.host())); | 354 blacklisted_domains_.find(base::StringToLowerASCII(url.host())); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 370 } | 368 } |
| 371 | 369 |
| 372 return false; | 370 return false; |
| 373 } | 371 } |
| 374 | 372 |
| 375 void SdchManager::OnGetDictionary(const GURL& request_url, | 373 void SdchManager::OnGetDictionary(const GURL& request_url, |
| 376 const GURL& dictionary_url) { | 374 const GURL& dictionary_url) { |
| 377 if (!CanFetchDictionary(request_url, dictionary_url)) | 375 if (!CanFetchDictionary(request_url, dictionary_url)) |
| 378 return; | 376 return; |
| 379 | 377 |
| 380 FOR_EACH_OBSERVER(SdchObserver, | 378 FOR_EACH_OBSERVER(SdchObserver, observers_, |
| 381 observers_, | |
| 382 OnGetDictionary(this, request_url, dictionary_url)); | 379 OnGetDictionary(this, request_url, dictionary_url)); |
| 383 } | 380 } |
| 384 | 381 |
| 385 bool SdchManager::CanFetchDictionary(const GURL& referring_url, | 382 bool SdchManager::CanFetchDictionary(const GURL& referring_url, |
| 386 const GURL& dictionary_url) const { | 383 const GURL& dictionary_url) const { |
| 387 DCHECK(thread_checker_.CalledOnValidThread()); | 384 DCHECK(thread_checker_.CalledOnValidThread()); |
| 388 /* The user agent may retrieve a dictionary from the dictionary URL if all of | 385 /* The user agent may retrieve a dictionary from the dictionary URL if all of |
| 389 the following are true: | 386 the following are true: |
| 390 1 The dictionary URL host name matches the referrer URL host name and | 387 1 The dictionary URL host name matches the referrer URL host name and |
| 391 scheme. | 388 scheme. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 409 // TODO(jar): Remove this failsafe conservative hack which is more restrictive | 406 // TODO(jar): Remove this failsafe conservative hack which is more restrictive |
| 410 // than current SDCH spec when needed, and justified by security audit. | 407 // than current SDCH spec when needed, and justified by security audit. |
| 411 if (!referring_url.SchemeIsHTTPOrHTTPS()) { | 408 if (!referring_url.SchemeIsHTTPOrHTTPS()) { |
| 412 SdchErrorRecovery(DICTIONARY_SELECTED_FROM_NON_HTTP); | 409 SdchErrorRecovery(DICTIONARY_SELECTED_FROM_NON_HTTP); |
| 413 return false; | 410 return false; |
| 414 } | 411 } |
| 415 | 412 |
| 416 return true; | 413 return true; |
| 417 } | 414 } |
| 418 | 415 |
| 419 void SdchManager::GetVcdiffDictionary( | 416 void SdchManager::GetVcdiffDictionary(const std::string& server_hash, |
| 420 const std::string& server_hash, | 417 const GURL& referring_url, |
| 421 const GURL& referring_url, | 418 scoped_refptr<Dictionary>* dictionary) { |
| 422 scoped_refptr<Dictionary>* dictionary) { | |
| 423 DCHECK(thread_checker_.CalledOnValidThread()); | 419 DCHECK(thread_checker_.CalledOnValidThread()); |
| 424 *dictionary = NULL; | 420 *dictionary = NULL; |
| 425 DictionaryMap::iterator it = dictionaries_.find(server_hash); | 421 DictionaryMap::iterator it = dictionaries_.find(server_hash); |
| 426 if (it == dictionaries_.end()) { | 422 if (it == dictionaries_.end()) { |
| 427 return; | 423 return; |
| 428 } | 424 } |
| 429 scoped_refptr<Dictionary> matching_dictionary = it->second; | 425 scoped_refptr<Dictionary> matching_dictionary = it->second; |
| 430 if (!IsInSupportedDomain(referring_url)) | 426 if (!IsInSupportedDomain(referring_url)) |
| 431 return; | 427 return; |
| 432 if (!matching_dictionary->CanUse(referring_url)) | 428 if (!matching_dictionary->CanUse(referring_url)) |
| (...skipping 19 matching lines...) Expand all Loading... |
| 452 list->append(","); | 448 list->append(","); |
| 453 list->append(it->second->client_hash()); | 449 list->append(it->second->client_hash()); |
| 454 } | 450 } |
| 455 // Watch to see if we have corrupt or numerous dictionaries. | 451 // Watch to see if we have corrupt or numerous dictionaries. |
| 456 if (count > 0) | 452 if (count > 0) |
| 457 UMA_HISTOGRAM_COUNTS("Sdch3.Advertisement_Count", count); | 453 UMA_HISTOGRAM_COUNTS("Sdch3.Advertisement_Count", count); |
| 458 } | 454 } |
| 459 | 455 |
| 460 // static | 456 // static |
| 461 void SdchManager::GenerateHash(const std::string& dictionary_text, | 457 void SdchManager::GenerateHash(const std::string& dictionary_text, |
| 462 std::string* client_hash, std::string* server_hash) { | 458 std::string* client_hash, |
| 459 std::string* server_hash) { |
| 463 char binary_hash[32]; | 460 char binary_hash[32]; |
| 464 crypto::SHA256HashString(dictionary_text, binary_hash, sizeof(binary_hash)); | 461 crypto::SHA256HashString(dictionary_text, binary_hash, sizeof(binary_hash)); |
| 465 | 462 |
| 466 std::string first_48_bits(&binary_hash[0], 6); | 463 std::string first_48_bits(&binary_hash[0], 6); |
| 467 std::string second_48_bits(&binary_hash[6], 6); | 464 std::string second_48_bits(&binary_hash[6], 6); |
| 468 UrlSafeBase64Encode(first_48_bits, client_hash); | 465 UrlSafeBase64Encode(first_48_bits, client_hash); |
| 469 UrlSafeBase64Encode(second_48_bits, server_hash); | 466 UrlSafeBase64Encode(second_48_bits, server_hash); |
| 470 | 467 |
| 471 DCHECK_EQ(server_hash->length(), 8u); | 468 DCHECK_EQ(server_hash->length(), 8u); |
| 472 DCHECK_EQ(client_hash->length(), 8u); | 469 DCHECK_EQ(client_hash->length(), 8u); |
| 473 } | 470 } |
| 474 | 471 |
| 475 //------------------------------------------------------------------------------ | 472 //------------------------------------------------------------------------------ |
| 476 // Methods for supporting latency experiments. | 473 // Methods for supporting latency experiments. |
| 477 | 474 |
| 478 bool SdchManager::AllowLatencyExperiment(const GURL& url) const { | 475 bool SdchManager::AllowLatencyExperiment(const GURL& url) const { |
| 479 DCHECK(thread_checker_.CalledOnValidThread()); | 476 DCHECK(thread_checker_.CalledOnValidThread()); |
| 480 return allow_latency_experiment_.end() != | 477 return allow_latency_experiment_.end() != |
| 481 allow_latency_experiment_.find(url.host()); | 478 allow_latency_experiment_.find(url.host()); |
| 482 } | 479 } |
| 483 | 480 |
| 484 void SdchManager::SetAllowLatencyExperiment(const GURL& url, bool enable) { | 481 void SdchManager::SetAllowLatencyExperiment(const GURL& url, bool enable) { |
| 485 DCHECK(thread_checker_.CalledOnValidThread()); | 482 DCHECK(thread_checker_.CalledOnValidThread()); |
| 486 if (enable) { | 483 if (enable) { |
| 487 allow_latency_experiment_.insert(url.host()); | 484 allow_latency_experiment_.insert(url.host()); |
| 488 return; | 485 return; |
| 489 } | 486 } |
| 490 ExperimentSet::iterator it = allow_latency_experiment_.find(url.host()); | 487 ExperimentSet::iterator it = allow_latency_experiment_.find(url.host()); |
| 491 if (allow_latency_experiment_.end() == it) | 488 if (allow_latency_experiment_.end() == it) |
| 492 return; // It was already erased, or never allowed. | 489 return; // It was already erased, or never allowed. |
| 493 SdchErrorRecovery(LATENCY_TEST_DISALLOWED); | 490 SdchErrorRecovery(LATENCY_TEST_DISALLOWED); |
| 494 allow_latency_experiment_.erase(it); | 491 allow_latency_experiment_.erase(it); |
| 495 } | 492 } |
| 496 | 493 |
| 497 void SdchManager::AddObserver(SdchObserver* observer) { | 494 void SdchManager::AddObserver(SdchObserver* observer) { |
| 498 observers_.AddObserver(observer); | 495 observers_.AddObserver(observer); |
| 499 } | 496 } |
| 500 | 497 |
| 501 void SdchManager::RemoveObserver(SdchObserver* observer) { | 498 void SdchManager::RemoveObserver(SdchObserver* observer) { |
| 502 observers_.RemoveObserver(observer); | 499 observers_.RemoveObserver(observer); |
| 503 } | 500 } |
| 504 | 501 |
| 505 void SdchManager::AddSdchDictionary(const std::string& dictionary_text, | 502 void SdchManager::AddSdchDictionary(const std::string& dictionary_text, |
| 506 const GURL& dictionary_url) { | 503 const GURL& dictionary_url) { |
| 507 DCHECK(thread_checker_.CalledOnValidThread()); | 504 DCHECK(thread_checker_.CalledOnValidThread()); |
| 508 std::string client_hash; | 505 std::string client_hash; |
| 509 std::string server_hash; | 506 std::string server_hash; |
| 510 GenerateHash(dictionary_text, &client_hash, &server_hash); | 507 GenerateHash(dictionary_text, &client_hash, &server_hash); |
| 511 if (dictionaries_.find(server_hash) != dictionaries_.end()) { | 508 if (dictionaries_.find(server_hash) != dictionaries_.end()) { |
| 512 SdchErrorRecovery(DICTIONARY_ALREADY_LOADED); | 509 SdchErrorRecovery(DICTIONARY_ALREADY_LOADED); |
| 513 return; // Already loaded. | 510 return; // Already loaded. |
| 514 } | 511 } |
| 515 | 512 |
| 516 std::string domain, path; | 513 std::string domain, path; |
| 517 std::set<int> ports; | 514 std::set<int> ports; |
| 518 base::Time expiration(base::Time::Now() + base::TimeDelta::FromDays(30)); | 515 base::Time expiration(base::Time::Now() + base::TimeDelta::FromDays(30)); |
| 519 | 516 |
| 520 if (dictionary_text.empty()) { | 517 if (dictionary_text.empty()) { |
| 521 SdchErrorRecovery(DICTIONARY_HAS_NO_TEXT); | 518 SdchErrorRecovery(DICTIONARY_HAS_NO_TEXT); |
| 522 return; // Missing header. | 519 return; // Missing header. |
| 523 } | 520 } |
| 524 | 521 |
| 525 size_t header_end = dictionary_text.find("\n\n"); | 522 size_t header_end = dictionary_text.find("\n\n"); |
| 526 if (std::string::npos == header_end) { | 523 if (std::string::npos == header_end) { |
| 527 SdchErrorRecovery(DICTIONARY_HAS_NO_HEADER); | 524 SdchErrorRecovery(DICTIONARY_HAS_NO_HEADER); |
| 528 return; // Missing header. | 525 return; // Missing header. |
| 529 } | 526 } |
| 530 size_t line_start = 0; // Start of line being parsed. | 527 size_t line_start = 0; // Start of line being parsed. |
| 531 while (1) { | 528 while (1) { |
| 532 size_t line_end = dictionary_text.find('\n', line_start); | 529 size_t line_end = dictionary_text.find('\n', line_start); |
| 533 DCHECK(std::string::npos != line_end); | 530 DCHECK(std::string::npos != line_end); |
| 534 DCHECK_LE(line_end, header_end); | 531 DCHECK_LE(line_end, header_end); |
| 535 | 532 |
| 536 size_t colon_index = dictionary_text.find(':', line_start); | 533 size_t colon_index = dictionary_text.find(':', line_start); |
| 537 if (std::string::npos == colon_index) { | 534 if (std::string::npos == colon_index) { |
| 538 SdchErrorRecovery(DICTIONARY_HEADER_LINE_MISSING_COLON); | 535 SdchErrorRecovery(DICTIONARY_HEADER_LINE_MISSING_COLON); |
| 539 return; // Illegal line missing a colon. | 536 return; // Illegal line missing a colon. |
| 540 } | 537 } |
| 541 | 538 |
| 542 if (colon_index > line_end) | 539 if (colon_index > line_end) |
| 543 break; | 540 break; |
| 544 | 541 |
| 545 size_t value_start = dictionary_text.find_first_not_of(" \t", | 542 size_t value_start = |
| 546 colon_index + 1); | 543 dictionary_text.find_first_not_of(" \t", colon_index + 1); |
| 547 if (std::string::npos != value_start) { | 544 if (std::string::npos != value_start) { |
| 548 if (value_start >= line_end) | 545 if (value_start >= line_end) |
| 549 break; | 546 break; |
| 550 std::string name(dictionary_text, line_start, colon_index - line_start); | 547 std::string name(dictionary_text, line_start, colon_index - line_start); |
| 551 std::string value(dictionary_text, value_start, line_end - value_start); | 548 std::string value(dictionary_text, value_start, line_end - value_start); |
| 552 name = base::StringToLowerASCII(name); | 549 name = base::StringToLowerASCII(name); |
| 553 if (name == "domain") { | 550 if (name == "domain") { |
| 554 domain = value; | 551 domain = value; |
| 555 } else if (name == "path") { | 552 } else if (name == "path") { |
| 556 path = value; | 553 path = value; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 return; | 590 return; |
| 594 } | 591 } |
| 595 if (kMaxDictionaryCount <= dictionaries_.size()) { | 592 if (kMaxDictionaryCount <= dictionaries_.size()) { |
| 596 SdchErrorRecovery(DICTIONARY_COUNT_EXCEEDED); | 593 SdchErrorRecovery(DICTIONARY_COUNT_EXCEEDED); |
| 597 return; | 594 return; |
| 598 } | 595 } |
| 599 | 596 |
| 600 UMA_HISTOGRAM_COUNTS("Sdch3.Dictionary size loaded", dictionary_text.size()); | 597 UMA_HISTOGRAM_COUNTS("Sdch3.Dictionary size loaded", dictionary_text.size()); |
| 601 DVLOG(1) << "Loaded dictionary with client hash " << client_hash | 598 DVLOG(1) << "Loaded dictionary with client hash " << client_hash |
| 602 << " and server hash " << server_hash; | 599 << " and server hash " << server_hash; |
| 603 Dictionary* dictionary = | 600 Dictionary* dictionary = new Dictionary( |
| 604 new Dictionary(dictionary_text, header_end + 2, client_hash, | 601 dictionary_text, header_end + 2, client_hash, dictionary_url_normalized, |
| 605 dictionary_url_normalized, domain, | 602 domain, path, expiration, ports); |
| 606 path, expiration, ports); | |
| 607 dictionaries_[server_hash] = dictionary; | 603 dictionaries_[server_hash] = dictionary; |
| 608 return; | 604 return; |
| 609 } | 605 } |
| 610 | 606 |
| 611 // static | 607 // static |
| 612 void SdchManager::UrlSafeBase64Encode(const std::string& input, | 608 void SdchManager::UrlSafeBase64Encode(const std::string& input, |
| 613 std::string* output) { | 609 std::string* output) { |
| 614 // Since this is only done during a dictionary load, and hashes are only 8 | 610 // Since this is only done during a dictionary load, and hashes are only 8 |
| 615 // characters, we just do the simple fixup, rather than rewriting the encoder. | 611 // characters, we just do the simple fixup, rather than rewriting the encoder. |
| 616 base::Base64Encode(input, output); | 612 base::Base64Encode(input, output); |
| 617 std::replace(output->begin(), output->end(), '+', '-'); | 613 std::replace(output->begin(), output->end(), '+', '-'); |
| 618 std::replace(output->begin(), output->end(), '/', '_'); | 614 std::replace(output->begin(), output->end(), '/', '_'); |
| 619 } | 615 } |
| 620 | 616 |
| 621 } // namespace net | 617 } // namespace net |
| OLD | NEW |