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

Side by Side Diff: net/http/http_server_properties_impl.cc

Issue 1216703002: Implement multiple alternative services per origin. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 5 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
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/http/http_server_properties_impl.h" 5 #include "net/http/http_server_properties_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/location.h" 8 #include "base/location.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 return; 46 return;
47 // Add the entries from persisted data. 47 // Add the entries from persisted data.
48 for (std::vector<std::string>::reverse_iterator it = spdy_servers->rbegin(); 48 for (std::vector<std::string>::reverse_iterator it = spdy_servers->rbegin();
49 it != spdy_servers->rend(); ++it) { 49 it != spdy_servers->rend(); ++it) {
50 spdy_servers_map_.Put(*it, support_spdy); 50 spdy_servers_map_.Put(*it, support_spdy);
51 } 51 }
52 } 52 }
53 53
54 void HttpServerPropertiesImpl::InitializeAlternativeServiceServers( 54 void HttpServerPropertiesImpl::InitializeAlternativeServiceServers(
55 AlternativeServiceMap* alternative_service_map) { 55 AlternativeServiceMap* alternative_service_map) {
56 // Keep all the broken ones since those don't get persisted. 56 for (AlternativeServiceMap::iterator map_it =
57 for (AlternativeServiceMap::iterator it = alternative_service_map_.begin(); 57 alternative_service_map_.begin();
58 it != alternative_service_map_.end();) { 58 map_it != alternative_service_map_.end();) {
59 AlternativeService alternative_service(it->second.alternative_service); 59 for (AlternativeServiceInfoVector::iterator it = map_it->second.begin();
60 if (alternative_service.host.empty()) { 60 it != map_it->second.end();) {
61 alternative_service.host = it->first.host(); 61 // Keep all the broken ones since those do not get persisted.
62 AlternativeService alternative_service(it->alternative_service);
63 if (alternative_service.host.empty()) {
64 alternative_service.host = map_it->first.host();
65 }
66 if (IsAlternativeServiceBroken(alternative_service)) {
67 ++it;
68 continue;
69 }
70 it = map_it->second.erase(it);
62 } 71 }
63 if (IsAlternativeServiceBroken(alternative_service)) { 72 if (map_it->second.empty()) {
64 ++it; 73 RemoveCanonicalHost(map_it->first);
65 } else { 74 map_it = alternative_service_map_.Erase(map_it);
66 it = alternative_service_map_.Erase(it); 75 continue;
76 }
77 ++map_it;
78 }
79
80 // Add the entries from persisted data.
81 for (AlternativeServiceMap::reverse_iterator input_it =
82 alternative_service_map->rbegin();
83 input_it != alternative_service_map->rend(); ++input_it) {
84 AlternativeServiceMap::iterator output_it =
85 alternative_service_map_.Peek(input_it->first);
86 if (output_it == alternative_service_map_.end()) {
87 // There is no value in alternative_service_map_ for input_it->first:
88 // inserting in AlternativeServiceVectorInfo.
89 alternative_service_map_.Put(input_it->first, input_it->second);
90 continue;
91 }
92 // There are some broken alternative services in alternative_service_map_
93 // for input_it->first: appending AlternativeServiceInfo one by one.
94 for (const AlternativeServiceInfo& alternative_service_info :
95 input_it->second) {
96 output_it->second.push_back(alternative_service_info);
67 } 97 }
68 } 98 }
69 99
70 // Add the entries from persisted data.
71 for (AlternativeServiceMap::reverse_iterator it =
72 alternative_service_map->rbegin();
73 it != alternative_service_map->rend(); ++it) {
74 alternative_service_map_.Put(it->first, it->second);
75 }
76
77 // Attempt to find canonical servers. 100 // Attempt to find canonical servers.
78 uint16 canonical_ports[] = { 80, 443 }; 101 uint16 canonical_ports[] = { 80, 443 };
79 for (size_t i = 0; i < canonical_suffixes_.size(); ++i) { 102 for (size_t i = 0; i < canonical_suffixes_.size(); ++i) {
80 std::string canonical_suffix = canonical_suffixes_[i]; 103 std::string canonical_suffix = canonical_suffixes_[i];
81 for (size_t j = 0; j < arraysize(canonical_ports); ++j) { 104 for (size_t j = 0; j < arraysize(canonical_ports); ++j) {
82 HostPortPair canonical_host(canonical_suffix, canonical_ports[j]); 105 HostPortPair canonical_host(canonical_suffix, canonical_ports[j]);
83 // If we already have a valid canonical server, we're done. 106 // If we already have a valid canonical server, we're done.
84 if (ContainsKey(canonical_host_to_origin_map_, canonical_host) && 107 if (ContainsKey(canonical_host_to_origin_map_, canonical_host) &&
85 (alternative_service_map_.Peek( 108 (alternative_service_map_.Peek(
86 canonical_host_to_origin_map_[canonical_host]) != 109 canonical_host_to_origin_map_[canonical_host]) !=
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 181
159 bool HttpServerPropertiesImpl::SupportsRequestPriority( 182 bool HttpServerPropertiesImpl::SupportsRequestPriority(
160 const HostPortPair& host_port_pair) { 183 const HostPortPair& host_port_pair) {
161 DCHECK(CalledOnValidThread()); 184 DCHECK(CalledOnValidThread());
162 if (host_port_pair.host().empty()) 185 if (host_port_pair.host().empty())
163 return false; 186 return false;
164 187
165 if (GetSupportsSpdy(host_port_pair)) 188 if (GetSupportsSpdy(host_port_pair))
166 return true; 189 return true;
167 190
168 const AlternativeService alternative_service = 191 const AlternativeServiceVector alternative_service_vector =
169 GetAlternativeService(host_port_pair); 192 GetAlternativeServices(host_port_pair);
170 return alternative_service.protocol == QUIC; 193 for (const AlternativeService& alternative_service :
194 alternative_service_vector) {
195 if (alternative_service.protocol == QUIC) {
196 return true;
197 }
198 }
199 return false;
171 } 200 }
172 201
173 bool HttpServerPropertiesImpl::GetSupportsSpdy( 202 bool HttpServerPropertiesImpl::GetSupportsSpdy(
174 const HostPortPair& host_port_pair) { 203 const HostPortPair& host_port_pair) {
175 DCHECK(CalledOnValidThread()); 204 DCHECK(CalledOnValidThread());
176 if (host_port_pair.host().empty()) 205 if (host_port_pair.host().empty())
177 return false; 206 return false;
178 207
179 SpdyServerHostPortMap::iterator spdy_host_port = 208 SpdyServerHostPortMap::iterator spdy_host_port =
180 spdy_servers_map_.Get(host_port_pair.ToString()); 209 spdy_servers_map_.Get(host_port_pair.ToString());
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 // suffix. 258 // suffix.
230 for (size_t i = 0; i < canonical_suffixes_.size(); ++i) { 259 for (size_t i = 0; i < canonical_suffixes_.size(); ++i) {
231 std::string canonical_suffix = canonical_suffixes_[i]; 260 std::string canonical_suffix = canonical_suffixes_[i];
232 if (base::EndsWith(host, canonical_suffixes_[i], false)) { 261 if (base::EndsWith(host, canonical_suffixes_[i], false)) {
233 return canonical_suffix; 262 return canonical_suffix;
234 } 263 }
235 } 264 }
236 return std::string(); 265 return std::string();
237 } 266 }
238 267
239 AlternativeService HttpServerPropertiesImpl::GetAlternativeService( 268 AlternativeServiceVector HttpServerPropertiesImpl::GetAlternativeServices(
240 const HostPortPair& origin) { 269 const HostPortPair& origin) {
270 // Copy alternative services with probability greater than or equal to the
271 // threshold into |alternative_services_above_threshold|.
272 AlternativeServiceVector alternative_services_above_threshold;
241 AlternativeServiceMap::const_iterator it = 273 AlternativeServiceMap::const_iterator it =
242 alternative_service_map_.Get(origin); 274 alternative_service_map_.Get(origin);
243 if (it != alternative_service_map_.end()) { 275 if (it != alternative_service_map_.end()) {
244 if (it->second.probability < alternative_service_probability_threshold_) { 276 for (const AlternativeServiceInfo& alternative_service_info : it->second) {
245 return AlternativeService(); 277 if (alternative_service_info.probability <
278 alternative_service_probability_threshold_) {
279 continue;
280 }
281 AlternativeService alternative_service(
282 alternative_service_info.alternative_service);
283 if (alternative_service.host.empty()) {
284 alternative_service.host = origin.host();
285 }
286 alternative_services_above_threshold.push_back(alternative_service);
246 } 287 }
247 AlternativeService alternative_service(it->second.alternative_service); 288 return alternative_services_above_threshold;
248 if (alternative_service.host.empty()) {
249 alternative_service.host = origin.host();
250 }
251 return alternative_service;
252 } 289 }
253 290
254 CanonicalHostMap::const_iterator canonical = GetCanonicalHost(origin); 291 CanonicalHostMap::const_iterator canonical = GetCanonicalHost(origin);
255 if (canonical == canonical_host_to_origin_map_.end()) { 292 if (canonical == canonical_host_to_origin_map_.end()) {
256 return AlternativeService(); 293 return AlternativeServiceVector();
257 } 294 }
258 it = alternative_service_map_.Get(canonical->second); 295 it = alternative_service_map_.Get(canonical->second);
259 if (it == alternative_service_map_.end()) { 296 if (it == alternative_service_map_.end()) {
260 return AlternativeService(); 297 return AlternativeServiceVector();
261 } 298 }
262 if (it->second.probability < alternative_service_probability_threshold_) { 299 for (const AlternativeServiceInfo& alternative_service_info : it->second) {
263 return AlternativeService(); 300 if (alternative_service_info.probability <
301 alternative_service_probability_threshold_) {
302 continue;
303 }
304 AlternativeService alternative_service(
305 alternative_service_info.alternative_service);
306 if (alternative_service.host.empty()) {
307 alternative_service.host = canonical->second.host();
308 if (IsAlternativeServiceBroken(alternative_service)) {
309 continue;
310 }
311 alternative_service.host = origin.host();
312 } else if (IsAlternativeServiceBroken(alternative_service)) {
313 continue;
314 }
315 alternative_services_above_threshold.push_back(alternative_service);
264 } 316 }
265 AlternativeService alternative_service(it->second.alternative_service); 317 return alternative_services_above_threshold;
266 if (alternative_service.host.empty()) {
267 alternative_service.host = canonical->second.host();
268 }
269 if (IsAlternativeServiceBroken(alternative_service)) {
270 RemoveCanonicalHost(canonical->second);
271 return AlternativeService();
272 }
273 // Empty hostname: if alternative service for with hostname of canonical host
274 // is not broken, then return alternative service with hostname of origin.
275 if (it->second.alternative_service.host.empty()) {
276 alternative_service.host = origin.host();
277 }
278 return alternative_service;
279 } 318 }
280 319
281 void HttpServerPropertiesImpl::SetAlternativeService( 320 void HttpServerPropertiesImpl::AddAlternativeService(
282 const HostPortPair& origin, 321 const HostPortPair& origin,
283 const AlternativeService& alternative_service, 322 const AlternativeService& alternative_service,
284 double alternative_probability) { 323 double alternative_probability) {
285 const AlternativeServiceInfo alternative_service_info( 324 DCHECK(IsAlternateProtocolValid(alternative_service.protocol));
286 alternative_service, alternative_probability); 325
287 AlternativeServiceMap::const_iterator it = 326 if (GetAlternateProtocolIterator(origin) == alternative_service_map_.end() &&
288 GetAlternateProtocolIterator(origin);
289 if (it == alternative_service_map_.end() &&
290 alternative_probability >= alternative_service_probability_threshold_) { 327 alternative_probability >= alternative_service_probability_threshold_) {
291 // TODO(rch): Consider the case where multiple requests are started 328 // TODO(rch): Consider the case where multiple requests are started
292 // before the first completes. In this case, only one of the jobs 329 // before the first completes. In this case, only one of the jobs
293 // would reach this code, whereas all of them should should have. 330 // would reach this code, whereas all of them should should have.
294 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_MAPPING_MISSING); 331 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_MAPPING_MISSING);
295 } 332 }
296 333
297 alternative_service_map_.Put(origin, alternative_service_info); 334 const AlternativeServiceInfo alternative_service_info(
335 alternative_service, alternative_probability);
336 AlternativeServiceMap::iterator map_it = alternative_service_map_.Get(origin);
337 if (map_it == alternative_service_map_.end()) {
338 alternative_service_map_.Put(
339 origin,
340 AlternativeServiceInfoVector(/*size=*/1, alternative_service_info));
341 } else {
342 AlternativeServiceInfoVector& existing_alternative_service_info_vector =
343 map_it->second;
344 AlternativeServiceInfoVector::iterator it;
345 for (it = existing_alternative_service_info_vector.begin();
346 it != existing_alternative_service_info_vector.end(); ++it) {
347 if (*it == alternative_service_info) {
348 // Alternative service info is identical to an existing one.
349 return;
350 }
351 if (it->alternative_service == alternative_service) {
352 // Different info (for example, probability) for existing alternative
353 // service: change alternative_service_info.
354 *it = alternative_service_info;
355 break;
356 }
357 }
358 if (it == existing_alternative_service_info_vector.end()) {
359 existing_alternative_service_info_vector.push_back(
360 alternative_service_info);
361 }
362 }
298 363
299 // If this host ends with a canonical suffix, then set it as the 364 // If this host ends with a canonical suffix, then set it as the
300 // canonical host. 365 // canonical host.
301 for (size_t i = 0; i < canonical_suffixes_.size(); ++i) { 366 for (size_t i = 0; i < canonical_suffixes_.size(); ++i) {
302 std::string canonical_suffix = canonical_suffixes_[i]; 367 std::string canonical_suffix = canonical_suffixes_[i];
303 if (base::EndsWith(origin.host(), canonical_suffixes_[i], false)) { 368 if (base::EndsWith(origin.host(), canonical_suffixes_[i], false)) {
304 HostPortPair canonical_host(canonical_suffix, origin.port()); 369 HostPortPair canonical_host(canonical_suffix, origin.port());
305 canonical_host_to_origin_map_[canonical_host] = origin; 370 canonical_host_to_origin_map_[canonical_host] = origin;
306 break; 371 break;
307 } 372 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 } 421 }
357 422
358 void HttpServerPropertiesImpl::ConfirmAlternativeService( 423 void HttpServerPropertiesImpl::ConfirmAlternativeService(
359 const AlternativeService& alternative_service) { 424 const AlternativeService& alternative_service) {
360 if (alternative_service.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL) 425 if (alternative_service.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL)
361 return; 426 return;
362 broken_alternative_services_.erase(alternative_service); 427 broken_alternative_services_.erase(alternative_service);
363 recently_broken_alternative_services_.erase(alternative_service); 428 recently_broken_alternative_services_.erase(alternative_service);
364 } 429 }
365 430
366 void HttpServerPropertiesImpl::ClearAlternativeService( 431 void HttpServerPropertiesImpl::ClearAlternativeServices(
367 const HostPortPair& origin) { 432 const HostPortPair& origin) {
368 RemoveCanonicalHost(origin); 433 RemoveCanonicalHost(origin);
369 434
370 AlternativeServiceMap::iterator it = alternative_service_map_.Peek(origin); 435 AlternativeServiceMap::iterator it = alternative_service_map_.Peek(origin);
371 if (it == alternative_service_map_.end()) { 436 if (it == alternative_service_map_.end()) {
372 return; 437 return;
373 } 438 }
374 alternative_service_map_.Erase(it); 439 alternative_service_map_.Erase(it);
375 } 440 }
376 441
377 const AlternativeServiceMap& HttpServerPropertiesImpl::alternative_service_map() 442 const AlternativeServiceMap& HttpServerPropertiesImpl::alternative_service_map()
378 const { 443 const {
379 return alternative_service_map_; 444 return alternative_service_map_;
380 } 445 }
381 446
382 scoped_ptr<base::Value> 447 scoped_ptr<base::Value>
383 HttpServerPropertiesImpl::GetAlternativeServiceInfoAsValue() 448 HttpServerPropertiesImpl::GetAlternativeServiceInfoAsValue()
384 const { 449 const {
385 scoped_ptr<base::ListValue> dict_list(new base::ListValue()); 450 scoped_ptr<base::ListValue> dict_list(new base::ListValue);
386 for (const auto& alternative_service_map_item : alternative_service_map_) { 451 for (const auto& alternative_service_map_item : alternative_service_map_) {
452 scoped_ptr<base::ListValue> alternative_service_list(new base::ListValue);
387 const HostPortPair& host_port_pair = alternative_service_map_item.first; 453 const HostPortPair& host_port_pair = alternative_service_map_item.first;
388 const AlternativeServiceInfo& alternative_service_info = 454 for (const AlternativeServiceInfo& alternative_service_info :
389 alternative_service_map_item.second; 455 alternative_service_map_item.second) {
390 std::string alternative_service_string(alternative_service_info.ToString()); 456 std::string alternative_service_string(
391 AlternativeService alternative_service( 457 alternative_service_info.ToString());
392 alternative_service_info.alternative_service); 458 AlternativeService alternative_service(
393 if (alternative_service.host.empty()) { 459 alternative_service_info.alternative_service);
394 alternative_service.host = host_port_pair.host(); 460 if (alternative_service.host.empty()) {
461 alternative_service.host = host_port_pair.host();
462 }
463 if (IsAlternativeServiceBroken(alternative_service)) {
464 alternative_service_string.append(" (broken)");
465 }
466 alternative_service_list->Append(
467 new base::StringValue(alternative_service_string));
395 } 468 }
396 if (IsAlternativeServiceBroken(alternative_service)) { 469 if (alternative_service_list->empty())
397 alternative_service_string.append(" (broken)"); 470 continue;
398 }
399
400 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); 471 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
401 dict->SetString("host_port_pair", host_port_pair.ToString()); 472 dict->SetString("host_port_pair", host_port_pair.ToString());
402 dict->SetString("alternative_service", alternative_service_string); 473 dict->Set("alternative_services",
474 scoped_ptr<base::Value>(alternative_service_list.Pass()));
403 dict_list->Append(dict.Pass()); 475 dict_list->Append(dict.Pass());
404 } 476 }
405 return dict_list.Pass(); 477 return dict_list.Pass();
406 } 478 }
407 479
408 const SettingsMap& HttpServerPropertiesImpl::GetSpdySettings( 480 const SettingsMap& HttpServerPropertiesImpl::GetSpdySettings(
409 const HostPortPair& host_port_pair) { 481 const HostPortPair& host_port_pair) {
410 SpdySettingsMap::iterator it = spdy_settings_map_.Get(host_port_pair); 482 SpdySettingsMap::iterator it = spdy_settings_map_.Get(host_port_pair);
411 if (it == spdy_settings_map_.end()) { 483 if (it == spdy_settings_map_.end()) {
412 CR_DEFINE_STATIC_LOCAL(SettingsMap, kEmptySettingsMap, ()); 484 CR_DEFINE_STATIC_LOCAL(SettingsMap, kEmptySettingsMap, ());
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 if (canonical == canonical_host_to_origin_map_.end()) { 580 if (canonical == canonical_host_to_origin_map_.end()) {
509 return alternative_service_map_.end(); 581 return alternative_service_map_.end();
510 } 582 }
511 583
512 const HostPortPair canonical_host_port = canonical->second; 584 const HostPortPair canonical_host_port = canonical->second;
513 it = alternative_service_map_.Get(canonical_host_port); 585 it = alternative_service_map_.Get(canonical_host_port);
514 if (it == alternative_service_map_.end()) { 586 if (it == alternative_service_map_.end()) {
515 return alternative_service_map_.end(); 587 return alternative_service_map_.end();
516 } 588 }
517 589
518 const AlternativeService alternative_service( 590 for (const AlternativeServiceInfo& alternative_service_info : it->second) {
519 it->second.alternative_service.protocol, canonical_host_port.host(), 591 AlternativeService alternative_service(
520 it->second.alternative_service.port); 592 alternative_service_info.alternative_service);
521 if (!IsAlternativeServiceBroken(alternative_service)) { 593 if (alternative_service.host.empty()) {
522 return it; 594 alternative_service.host = canonical_host_port.host();
595 }
596 if (!IsAlternativeServiceBroken(alternative_service)) {
597 return it;
598 }
523 } 599 }
524 600
525 RemoveCanonicalHost(canonical_host_port); 601 RemoveCanonicalHost(canonical_host_port);
526 return alternative_service_map_.end(); 602 return alternative_service_map_.end();
527 } 603 }
528 604
529 HttpServerPropertiesImpl::CanonicalHostMap::const_iterator 605 HttpServerPropertiesImpl::CanonicalHostMap::const_iterator
530 HttpServerPropertiesImpl::GetCanonicalHost(HostPortPair server) const { 606 HttpServerPropertiesImpl::GetCanonicalHost(HostPortPair server) const {
531 for (size_t i = 0; i < canonical_suffixes_.size(); ++i) { 607 for (size_t i = 0; i < canonical_suffixes_.size(); ++i) {
532 std::string canonical_suffix = canonical_suffixes_[i]; 608 std::string canonical_suffix = canonical_suffixes_[i];
(...skipping 23 matching lines...) Expand all
556 while (!broken_alternative_services_.empty()) { 632 while (!broken_alternative_services_.empty()) {
557 BrokenAlternativeServices::iterator it = 633 BrokenAlternativeServices::iterator it =
558 broken_alternative_services_.begin(); 634 broken_alternative_services_.begin();
559 if (now < it->second) { 635 if (now < it->second) {
560 break; 636 break;
561 } 637 }
562 638
563 const AlternativeService alternative_service = it->first; 639 const AlternativeService alternative_service = it->first;
564 broken_alternative_services_.erase(it); 640 broken_alternative_services_.erase(it);
565 // TODO(bnc): Make sure broken alternative services are not in the mapping. 641 // TODO(bnc): Make sure broken alternative services are not in the mapping.
566 ClearAlternativeService( 642 ClearAlternativeServices(
567 HostPortPair(alternative_service.host, alternative_service.port)); 643 HostPortPair(alternative_service.host, alternative_service.port));
568 } 644 }
569 ScheduleBrokenAlternateProtocolMappingsExpiration(); 645 ScheduleBrokenAlternateProtocolMappingsExpiration();
570 } 646 }
571 647
572 void 648 void
573 HttpServerPropertiesImpl::ScheduleBrokenAlternateProtocolMappingsExpiration() { 649 HttpServerPropertiesImpl::ScheduleBrokenAlternateProtocolMappingsExpiration() {
574 if (broken_alternative_services_.empty()) { 650 if (broken_alternative_services_.empty()) {
575 return; 651 return;
576 } 652 }
577 base::TimeTicks now = base::TimeTicks::Now(); 653 base::TimeTicks now = base::TimeTicks::Now();
578 base::TimeTicks when = broken_alternative_services_.front().second; 654 base::TimeTicks when = broken_alternative_services_.front().second;
579 base::TimeDelta delay = when > now ? when - now : base::TimeDelta(); 655 base::TimeDelta delay = when > now ? when - now : base::TimeDelta();
580 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( 656 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
581 FROM_HERE, 657 FROM_HERE,
582 base::Bind( 658 base::Bind(
583 &HttpServerPropertiesImpl::ExpireBrokenAlternateProtocolMappings, 659 &HttpServerPropertiesImpl::ExpireBrokenAlternateProtocolMappings,
584 weak_ptr_factory_.GetWeakPtr()), 660 weak_ptr_factory_.GetWeakPtr()),
585 delay); 661 delay);
586 } 662 }
587 663
588 } // namespace net 664 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698