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 3 // found in the LICENSE file. 4 5 // A Predictor object is instantiated once in the browser process, and manages 6 // both preresolution of hostnames, as well as TCP/IP preconnection to expected 7 // subresources. 8 // Most hostname lists are provided by the renderer processes, and include URLs 9 // that *might* be used in the near future by the browsing user. One goal of 10 // this class is to cause the underlying DNS structure to lookup a hostname 11 // before it is really needed, and hence reduce latency in the standard lookup 12 // paths. 13 // Subresource relationships are usually acquired from the referrer field in a 14 // navigation. A subresource URL may be associated with a referrer URL. Later 15 // navigations may, if the likelihood of needing the subresource is high enough, 16 // cause this module to speculatively create a TCP/IP connection. If there is 17 // only a low likelihood, then a DNS pre-resolution operation may be performed. 18 19 #ifndef CHROME_BROWSER_NET_PREDICTOR_H_ 20 #define CHROME_BROWSER_NET_PREDICTOR_H_ 21 22 #include <map> 23 #include <queue> 24 #include <set> 25 #include <string> 26 #include <vector> 27 28 #include "base/gtest_prod_util.h" 29 #include "base/memory/scoped_ptr.h" 30 #include "base/memory/weak_ptr.h" 31 #include "chrome/browser/net/prediction_options.h" 32 #include "chrome/browser/net/referrer.h" 33 #include "chrome/browser/net/spdyproxy/proxy_advisor.h" 34 #include "chrome/browser/net/timed_cache.h" 35 #include "chrome/browser/net/url_info.h" 36 #include "chrome/common/net/predictor_common.h" 37 #include "net/base/host_port_pair.h" 38 39 class IOThread; 40 class PrefService; 41 class Profile; 42 class ProfileIOData; 43 44 namespace base { 45 class ListValue; 46 class WaitableEvent; 47 } 48 49 namespace net { 50 class HostResolver; 51 class SSLConfigService; 52 class TransportSecurityState; 53 class URLRequestContextGetter; 54 } 55 56 namespace user_prefs { 57 class PrefRegistrySyncable; 58 } 59 60 namespace chrome_browser_net { 61 62 typedef chrome_common_net::UrlList UrlList; 63 typedef chrome_common_net::NameList NameList; 64 typedef std::map<GURL, UrlInfo> Results; 65 66 // An observer for testing. 67 class PredictorObserver { 68 public: 69 virtual ~PredictorObserver() {} 70 71 virtual void OnPreconnectUrl(const GURL& original_url, 72 const GURL& first_party_for_cookies, 73 UrlInfo::ResolutionMotivation motivation, 74 int count) = 0; 75 }; 76 77 // Predictor is constructed during Profile construction (on the UI thread), 78 // but it is destroyed on the IO thread when ProfileIOData goes away. All of 79 // its core state and functionality happens on the IO thread. The only UI 80 // methods are initialization / shutdown related (including preconnect 81 // initialization), or convenience methods that internally forward calls to 82 // the IO thread. 83 class Predictor { 84 public: 85 // A version number for prefs that are saved. This should be incremented when 86 // we change the format so that we discard old data. 87 static const int kPredictorReferrerVersion; 88 89 // Given that the underlying Chromium resolver defaults to a total maximum of 90 // 8 paralell resolutions, we will avoid any chance of starving navigational 91 // resolutions by limiting the number of paralell speculative resolutions. 92 // This is used in the field trials and testing. 93 // TODO(jar): Move this limitation into the resolver. 94 static const size_t kMaxSpeculativeParallelResolves; 95 96 // To control the congestion avoidance system, we need an estimate of how 97 // many speculative requests may arrive at once. Since we currently only 98 // keep 8 subresource names for each frame, we'll use that as our basis. 99 // Note that when scanning search results lists, we might actually get 10 at 100 // a time, and wikipedia can often supply (during a page scan) upwards of 50. 101 // In those odd cases, we may discard some of the later speculative requests 102 // mistakenly assuming that the resolutions took too long. 103 static const int kTypicalSpeculativeGroupSize; 104 105 // The next constant specifies an amount of queueing delay that is 106 // "too large," and indicative of problems with resolutions (perhaps due to 107 // an overloaded router, or such). When we exceed this delay, congestion 108 // avoidance will kick in and all speculations in the queue will be discarded. 109 static const int kMaxSpeculativeResolveQueueDelayMs; 110 111 // We don't bother learning to preconnect via a GET if the original URL 112 // navigation was so long ago, that a preconnection would have been dropped 113 // anyway. We believe most servers will drop the connection in 10 seconds, so 114 // we currently estimate this time-till-drop at 10 seconds. 115 // TODO(jar): We should do a persistent field trial to validate/optimize this. 116 static const int kMaxUnusedSocketLifetimeSecondsWithoutAGet; 117 118 // |max_concurrent| specifies how many concurrent (parallel) prefetches will 119 // be performed. Host lookups will be issued through |host_resolver|. 120 explicit Predictor(bool preconnect_enabled, bool predictor_enabled); 121 122 virtual ~Predictor(); 123 124 // This function is used to create a predictor. For testing, we can create 125 // a version which does a simpler shutdown. 126 static Predictor* CreatePredictor(bool preconnect_enabled, 127 bool predictor_enabled, 128 bool simple_shutdown); 129 130 static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); 131 132 // ------------- Start UI thread methods. 133 134 virtual void InitNetworkPredictor(PrefService* user_prefs, 135 PrefService* local_state, 136 IOThread* io_thread, 137 net::URLRequestContextGetter* getter, 138 ProfileIOData* profile_io_data); 139 140 // The Omnibox has proposed a given url to the user, and if it is a search 141 // URL, then it also indicates that this is preconnectable (i.e., we could 142 // preconnect to the search server). 143 void AnticipateOmniboxUrl(const GURL& url, bool preconnectable); 144 145 // Preconnect a URL and all of its subresource domains. 146 void PreconnectUrlAndSubresources(const GURL& url, 147 const GURL& first_party_for_cookies); 148 149 static UrlList GetPredictedUrlListAtStartup(PrefService* user_prefs, 150 PrefService* local_state); 151 152 static void set_max_queueing_delay(int max_queueing_delay_ms); 153 154 static void set_max_parallel_resolves(size_t max_parallel_resolves); 155 156 virtual void ShutdownOnUIThread(); 157 158 // ------------- End UI thread methods. 159 160 // ------------- Start IO thread methods. 161 162 // Cancel pending requests and prevent new ones from being made. 163 void Shutdown(); 164 165 // In some circumstances, for privacy reasons, all results should be 166 // discarded. This method gracefully handles that activity. 167 // Destroy all our internal state, which shows what names we've looked up, and 168 // how long each has taken, etc. etc. We also destroy records of suggesses 169 // (cache hits etc.). 170 void DiscardAllResults(); 171 172 // Add hostname(s) to the queue for processing. 173 void ResolveList(const UrlList& urls, 174 UrlInfo::ResolutionMotivation motivation); 175 176 void Resolve(const GURL& url, UrlInfo::ResolutionMotivation motivation); 177 178 // Record details of a navigation so that we can preresolve the host name 179 // ahead of time the next time the users navigates to the indicated host. 180 // Should only be called when urls are distinct, and they should already be 181 // canonicalized to not have a path. 182 void LearnFromNavigation(const GURL& referring_url, const GURL& target_url); 183 184 // When displaying info in about:dns, the following API is called. 185 static void PredictorGetHtmlInfo(Predictor* predictor, std::string* output); 186 187 // Dump HTML table containing list of referrers for about:dns. 188 void GetHtmlReferrerLists(std::string* output); 189 190 // Dump the list of currently known referrer domains and related prefetchable 191 // domains for about:dns. 192 void GetHtmlInfo(std::string* output); 193 194 // Discards any referrer for which all the suggested host names are currently 195 // annotated with negligible expected-use. Scales down (diminishes) the 196 // expected-use of those that remain, so that their use will go down by a 197 // factor each time we trim (moving the referrer closer to being discarded in 198 // a future call). 199 // The task is performed synchronously and completes before returing. 200 void TrimReferrersNow(); 201 202 // Construct a ListValue object that contains all the data in the referrers_ 203 // so that it can be persisted in a pref. 204 void SerializeReferrers(base::ListValue* referral_list); 205 206 // Process a ListValue that contains all the data from a previous reference 207 // list, as constructed by SerializeReferrers(), and add all the identified 208 // values into the current referrer list. 209 void DeserializeReferrers(const base::ListValue& referral_list); 210 211 void DeserializeReferrersThenDelete(base::ListValue* referral_list); 212 213 void DiscardInitialNavigationHistory(); 214 215 void FinalizeInitializationOnIOThread( 216 const std::vector<GURL>& urls_to_prefetch, 217 base::ListValue* referral_list, 218 IOThread* io_thread, 219 ProfileIOData* profile_io_data); 220 221 // During startup, we learn what the first N urls visited are, and then 222 // resolve the associated hosts ASAP during our next startup. 223 void LearnAboutInitialNavigation(const GURL& url); 224 225 // Renderer bundles up list and sends to this browser API via IPC. 226 // TODO(jar): Use UrlList instead to include port and scheme. 227 void DnsPrefetchList(const NameList& hostnames); 228 229 // May be called from either the IO or UI thread and will PostTask 230 // to the IO thread if necessary. 231 void DnsPrefetchMotivatedList(const UrlList& urls, 232 UrlInfo::ResolutionMotivation motivation); 233 234 // May be called from either the IO or UI thread and will PostTask 235 // to the IO thread if necessary. 236 void SaveStateForNextStartupAndTrim(); 237 238 void SaveDnsPrefetchStateForNextStartupAndTrim( 239 base::ListValue* startup_list, 240 base::ListValue* referral_list, 241 base::WaitableEvent* completion); 242 243 // May be called from either the IO or UI thread and will PostTask 244 // to the IO thread if necessary. 245 void PreconnectUrl(const GURL& url, const GURL& first_party_for_cookies, 246 UrlInfo::ResolutionMotivation motivation, int count); 247 248 void PreconnectUrlOnIOThread(const GURL& url, 249 const GURL& first_party_for_cookies, 250 UrlInfo::ResolutionMotivation motivation, 251 int count); 252 253 // ------------- End IO thread methods. 254 255 // The following methods may be called on either the IO or UI threads. 256 257 // Instigate pre-connection to any URLs, or pre-resolution of related host, 258 // that we predict will be needed after this navigation (typically 259 // more-embedded resources on a page). This method will actually post a task 260 // to do the actual work, so as not to jump ahead of the frame navigation that 261 // instigated this activity. 262 void PredictFrameSubresources(const GURL& url, 263 const GURL& first_party_for_cookies); 264 265 // Put URL in canonical form, including a scheme, host, and port. 266 // Returns GURL::EmptyGURL() if the scheme is not http/https or if the url 267 // cannot be otherwise canonicalized. 268 static GURL CanonicalizeUrl(const GURL& url); 269 270 // Used for testing. 271 void SetHostResolver(net::HostResolver* host_resolver) { 272 host_resolver_ = host_resolver; 273 } 274 // Used for testing. 275 void SetTransportSecurityState( 276 net::TransportSecurityState* transport_security_state) { 277 transport_security_state_ = transport_security_state; 278 } 279 // Used for testing. 280 void SetProxyAdvisor(ProxyAdvisor* proxy_advisor) { 281 proxy_advisor_.reset(proxy_advisor); 282 } 283 // Used for testing. 284 size_t max_concurrent_dns_lookups() const { 285 return max_concurrent_dns_lookups_; 286 } 287 // Used for testing. 288 void SetShutdown(bool shutdown) { 289 shutdown_ = shutdown; 290 } 291 // Used for testing. 292 void SetObserver(PredictorObserver* observer) { 293 observer_ = observer; 294 } 295 296 ProfileIOData* profile_io_data() const { 297 return profile_io_data_; 298 } 299 300 bool preconnect_enabled() const { 301 return preconnect_enabled_; 302 } 303 304 bool predictor_enabled() const { 305 return predictor_enabled_; 306 } 307 308 309 private: 310 FRIEND_TEST_ALL_PREFIXES(PredictorTest, BenefitLookupTest); 311 FRIEND_TEST_ALL_PREFIXES(PredictorTest, ShutdownWhenResolutionIsPendingTest); 312 FRIEND_TEST_ALL_PREFIXES(PredictorTest, SingleLookupTest); 313 FRIEND_TEST_ALL_PREFIXES(PredictorTest, ConcurrentLookupTest); 314 FRIEND_TEST_ALL_PREFIXES(PredictorTest, MassiveConcurrentLookupTest); 315 FRIEND_TEST_ALL_PREFIXES(PredictorTest, PriorityQueuePushPopTest); 316 FRIEND_TEST_ALL_PREFIXES(PredictorTest, PriorityQueueReorderTest); 317 FRIEND_TEST_ALL_PREFIXES(PredictorTest, ReferrerSerializationTrimTest); 318 FRIEND_TEST_ALL_PREFIXES(PredictorTest, SingleLookupTestWithDisabledAdvisor); 319 FRIEND_TEST_ALL_PREFIXES(PredictorTest, SingleLookupTestWithEnabledAdvisor); 320 FRIEND_TEST_ALL_PREFIXES(PredictorTest, TestSimplePreconnectAdvisor); 321 friend class WaitForResolutionHelper; // For testing. 322 323 class LookupRequest; 324 325 // A simple priority queue for handling host names. 326 // Some names that are queued up have |motivation| that requires very rapid 327 // handling. For example, a sub-resource name lookup MUST be done before the 328 // actual sub-resource is fetched. In contrast, a name that was speculatively 329 // noted in a page has to be resolved before the user "gets around to" 330 // clicking on a link. By tagging (with a motivation) each push we make into 331 // this FIFO queue, the queue can re-order the more important names to service 332 // them sooner (relative to some low priority background resolutions). 333 class HostNameQueue { 334 public: 335 HostNameQueue(); 336 ~HostNameQueue(); 337 void Push(const GURL& url, 338 UrlInfo::ResolutionMotivation motivation); 339 bool IsEmpty() const; 340 GURL Pop(); 341 342 private: 343 // The names in the queue that should be serviced (popped) ASAP. 344 std::queue<GURL> rush_queue_; 345 // The names in the queue that should only be serviced when rush_queue is 346 // empty. 347 std::queue<GURL> background_queue_; 348 349 DISALLOW_COPY_AND_ASSIGN(HostNameQueue); 350 }; 351 352 // The InitialObserver monitors navigations made by the network stack. This 353 // is only used to identify startup time resolutions (for re-resolution 354 // during our next process startup). 355 // TODO(jar): Consider preconnecting at startup, which may be faster than 356 // waiting for render process to start and request a connection. 357 class InitialObserver { 358 public: 359 InitialObserver(); 360 ~InitialObserver(); 361 // Recording of when we observed each navigation. 362 typedef std::map<GURL, base::TimeTicks> FirstNavigations; 363 364 // Potentially add a new URL to our startup list. 365 void Append(const GURL& url, Predictor* predictor); 366 367 // Get an HTML version of our current planned first_navigations_. 368 void GetFirstResolutionsHtml(std::string* output); 369 370 // Persist the current first_navigations_ for storage in a list. 371 void GetInitialDnsResolutionList(base::ListValue* startup_list); 372 373 // Discards all initial loading history. 374 void DiscardInitialNavigationHistory() { first_navigations_.clear(); } 375 376 private: 377 // List of the first N URL resolutions observed in this run. 378 FirstNavigations first_navigations_; 379 380 // The number of URLs we'll save for pre-resolving at next startup. 381 static const size_t kStartupResolutionCount = 10; 382 }; 383 384 // A map that is keyed with the host/port that we've learned were the cause 385 // of loading additional URLs. The list of additional targets is held 386 // in a Referrer instance, which is a value in this map. 387 typedef std::map<GURL, Referrer> Referrers; 388 389 // Depending on the expected_subresource_use_, we may either make a TCP/IP 390 // preconnection, or merely pre-resolve the hostname via DNS (or even do 391 // nothing). The following are the threasholds for taking those actions. 392 static const double kPreconnectWorthyExpectedValue; 393 static const double kDNSPreresolutionWorthyExpectedValue; 394 // Referred hosts with a subresource_use_rate_ that are less than the 395 // following threshold will be discarded when we Trim() the list. 396 static const double kDiscardableExpectedValue; 397 // During trimming operation to discard hosts for which we don't have likely 398 // subresources, we multiply the expected_subresource_use_ value by the 399 // following ratio until that value is less than kDiscardableExpectedValue. 400 // This number should always be less than 1, an more than 0. 401 static const double kReferrerTrimRatio; 402 403 // Interval between periodic trimming of our whole referrer list. 404 // We only do a major trimming about once an hour, and then only when the user 405 // is actively browsing. 406 static const int64 kDurationBetweenTrimmingsHours; 407 // Interval between incremental trimmings (to avoid inducing Jank). 408 static const int64 kDurationBetweenTrimmingIncrementsSeconds; 409 // Number of referring URLs processed in an incremental trimming. 410 static const size_t kUrlsTrimmedPerIncrement; 411 412 // Only for testing. Returns true if hostname has been successfully resolved 413 // (name found). 414 bool WasFound(const GURL& url) const { 415 Results::const_iterator it(results_.find(url)); 416 return (it != results_.end()) && 417 it->second.was_found(); 418 } 419 420 // Only for testing. Return how long was the resolution 421 // or UrlInfo::NullDuration() if it hasn't been resolved yet. 422 base::TimeDelta GetResolutionDuration(const GURL& url) { 423 if (results_.find(url) == results_.end()) 424 return UrlInfo::NullDuration(); 425 return results_[url].resolve_duration(); 426 } 427 428 // Only for testing; 429 size_t peak_pending_lookups() const { return peak_pending_lookups_; } 430 431 // If a proxy advisor is defined, let it know that |url| will be prefetched or 432 // preconnected to. Can be called on either UI or IO threads and will post to 433 // the IO thread if necessary, invoking AdviseProxyOnIOThread(). 434 void AdviseProxy(const GURL& url, 435 UrlInfo::ResolutionMotivation motivation, 436 bool is_preconnect); 437 438 // These two members call the appropriate global functions in 439 // prediction_options.cc depending on which thread they are called on. 440 virtual bool CanPrefetchAndPrerender() const; 441 virtual bool CanPreresolveAndPreconnect() const; 442 443 // ------------- Start IO thread methods. 444 445 // Perform actual resolution or preconnection to subresources now. This is 446 // an internal worker method that is reached via a post task from 447 // PredictFrameSubresources(). 448 void PrepareFrameSubresources(const GURL& url, 449 const GURL& first_party_for_cookies); 450 451 // Access method for use by async lookup request to pass resolution result. 452 void OnLookupFinished(LookupRequest* request, const GURL& url, bool found); 453 454 // Underlying method for both async and synchronous lookup to update state. 455 void LookupFinished(LookupRequest* request, 456 const GURL& url, bool found); 457 458 // Queue hostname for resolution. If queueing was done, return the pointer 459 // to the queued instance, otherwise return NULL. If the proxy advisor is 460 // enabled, and |url| is likely to be proxied, the hostname will not be 461 // queued as the browser is not expected to fetch it directly. 462 UrlInfo* AppendToResolutionQueue(const GURL& url, 463 UrlInfo::ResolutionMotivation motivation); 464 465 // Check to see if too much queuing delay has been noted for the given info, 466 // which indicates that there is "congestion" or growing delay in handling the 467 // resolution of names. Rather than letting this congestion potentially grow 468 // without bounds, we abandon our queued efforts at pre-resolutions in such a 469 // case. 470 // To do this, we will recycle |info|, as well as all queued items, back to 471 // the state they had before they were queued up. We can't do anything about 472 // the resolutions we've already sent off for processing on another thread, so 473 // we just let them complete. On a slow system, subject to congestion, this 474 // will greatly reduce the number of resolutions done, but it will assure that 475 // any resolutions that are done, are in a timely and hence potentially 476 // helpful manner. 477 bool CongestionControlPerformed(UrlInfo* info); 478 479 // Take lookup requests from work_queue_ and tell HostResolver to look them up 480 // asynchronously, provided we don't exceed concurrent resolution limit. 481 void StartSomeQueuedResolutions(); 482 483 // Performs trimming similar to TrimReferrersNow(), except it does it as a 484 // series of short tasks by posting continuations again an again until done. 485 void TrimReferrers(); 486 487 // Loads urls_being_trimmed_ from keys of current referrers_. 488 void LoadUrlsForTrimming(); 489 490 // Posts a task to do additional incremental trimming of referrers_. 491 void PostIncrementalTrimTask(); 492 493 // Calls Trim() on some or all of urls_being_trimmed_. 494 // If it does not process all the URLs in that vector, it posts a task to 495 // continue with them shortly (i.e., it yeilds and continues). 496 void IncrementalTrimReferrers(bool trim_all_now); 497 498 // If a proxy advisor is defined, let it know that |url| will be prefetched or 499 // preconnected to. 500 void AdviseProxyOnIOThread(const GURL& url, 501 UrlInfo::ResolutionMotivation motivation, 502 bool is_preconnect); 503 504 // Applies the HSTS redirect for |url|, if any. 505 GURL GetHSTSRedirectOnIOThread(const GURL& url); 506 507 // ------------- End IO thread methods. 508 509 scoped_ptr<InitialObserver> initial_observer_; 510 511 // Reference to URLRequestContextGetter from the Profile which owns the 512 // predictor. Used by Preconnect. 513 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; 514 515 // Status of speculative DNS resolution and speculative TCP/IP connection 516 // feature. This is false if and only if disabled by a command line switch. 517 const bool predictor_enabled_; 518 519 // This is set by InitNetworkPredictor and used for calling 520 // CanPrefetchAndPrerenderUI and CanPreresolveAndPreconnectUI. 521 PrefService* user_prefs_; 522 523 // This is set by InitNetworkPredictor and used for calling 524 // CanPrefetchAndPrerenderIO and CanPreresolveAndPreconnectIO. 525 ProfileIOData* profile_io_data_; 526 527 // work_queue_ holds a list of names we need to look up. 528 HostNameQueue work_queue_; 529 530 // results_ contains information for existing/prior prefetches. 531 Results results_; 532 533 std::set<LookupRequest*> pending_lookups_; 534 535 // For testing, to verify that we don't exceed the limit. 536 size_t peak_pending_lookups_; 537 538 // When true, we don't make new lookup requests. 539 bool shutdown_; 540 541 // The number of concurrent speculative lookups currently allowed to be sent 542 // to the resolver. Any additional lookups will be queued to avoid exceeding 543 // this value. The queue is a priority queue that will accelerate 544 // sub-resource speculation, and retard resolutions suggested by page scans. 545 const size_t max_concurrent_dns_lookups_; 546 547 // The maximum queueing delay that is acceptable before we enter congestion 548 // reduction mode, and discard all queued (but not yet assigned) resolutions. 549 const base::TimeDelta max_dns_queue_delay_; 550 551 // The host resolver we warm DNS entries for. 552 net::HostResolver* host_resolver_; 553 554 // The TransportSecurityState instance we query HSTS redirects from. 555 net::TransportSecurityState* transport_security_state_; 556 557 // The SSLConfigService we query SNI support from (used in querying HSTS 558 // redirects). 559 net::SSLConfigService* ssl_config_service_; 560 561 // Are we currently using preconnection, rather than just DNS resolution, for 562 // subresources and omni-box search URLs. 563 // This is false if and only if disabled by a command line switch. 564 const bool preconnect_enabled_; 565 566 // Most recent suggestion from Omnibox provided via AnticipateOmniboxUrl(). 567 std::string last_omnibox_host_; 568 569 // The time when the last preresolve was done for last_omnibox_host_. 570 base::TimeTicks last_omnibox_preresolve_; 571 572 // The number of consecutive requests to AnticipateOmniboxUrl() that suggested 573 // preconnecting (because it was to a search service). 574 int consecutive_omnibox_preconnect_count_; 575 576 // The time when the last preconnection was requested to a search service. 577 base::TimeTicks last_omnibox_preconnect_; 578 579 // For each URL that we might navigate to (that we've "learned about") 580 // we have a Referrer list. Each Referrer list has all hostnames we might 581 // need to pre-resolve or pre-connect to when there is a navigation to the 582 // orginial hostname. 583 Referrers referrers_; 584 585 // List of URLs in referrers_ currently being trimmed (scaled down to 586 // eventually be aged out of use). 587 std::vector<GURL> urls_being_trimmed_; 588 589 // A time after which we need to do more trimming of referrers. 590 base::TimeTicks next_trim_time_; 591 592 scoped_ptr<ProxyAdvisor> proxy_advisor_; 593 594 // An observer for testing. 595 PredictorObserver* observer_; 596 597 scoped_ptr<base::WeakPtrFactory<Predictor> > weak_factory_; 598 599 DISALLOW_COPY_AND_ASSIGN(Predictor); 600 }; 601 602 // This version of the predictor is used for testing. 603 class SimplePredictor : public Predictor { 604 public: 605 explicit SimplePredictor(bool preconnect_enabled, bool predictor_enabled) 606 : Predictor(preconnect_enabled, predictor_enabled) {} 607 virtual ~SimplePredictor() {} 608 virtual void InitNetworkPredictor( 609 PrefService* user_prefs, 610 PrefService* local_state, 611 IOThread* io_thread, 612 net::URLRequestContextGetter* getter, 613 ProfileIOData* profile_io_data) OVERRIDE; 614 virtual void ShutdownOnUIThread() OVERRIDE; 615 private: 616 // These member functions return True for unittests. 617 virtual bool CanPrefetchAndPrerender() const OVERRIDE; 618 virtual bool CanPreresolveAndPreconnect() const OVERRIDE; 619 }; 620 621 } // namespace chrome_browser_net 622 623 #endif // CHROME_BROWSER_NET_PREDICTOR_H_ 624