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

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

Issue 642403002: git cl format the first third of the net/base directory (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Nit 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"
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698