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 #ifndef CHROME_BROWSER_PRERENDER_PRERENDER_MANAGER_H_ 6 #define CHROME_BROWSER_PRERENDER_PRERENDER_MANAGER_H_ 7 8 #include <list> 9 #include <map> 10 #include <string> 11 #include <utility> 12 #include <vector> 13 14 #include "base/containers/hash_tables.h" 15 #include "base/gtest_prod_util.h" 16 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/scoped_vector.h" 18 #include "base/memory/weak_ptr.h" 19 #include "base/threading/non_thread_safe.h" 20 #include "base/time/time.h" 21 #include "base/timer/timer.h" 22 #include "chrome/browser/history/history_service.h" 23 #include "chrome/browser/media/media_capture_devices_dispatcher.h" 24 #include "chrome/browser/predictors/logged_in_predictor_table.h" 25 #include "chrome/browser/prerender/prerender_config.h" 26 #include "chrome/browser/prerender/prerender_contents.h" 27 #include "chrome/browser/prerender/prerender_events.h" 28 #include "chrome/browser/prerender/prerender_final_status.h" 29 #include "chrome/browser/prerender/prerender_origin.h" 30 #include "chrome/browser/prerender/prerender_tracker.h" 31 #include "components/browser_context_keyed_service/browser_context_keyed_service.h" 32 #include "content/public/browser/notification_observer.h" 33 #include "content/public/browser/notification_registrar.h" 34 #include "content/public/browser/session_storage_namespace.h" 35 #include "content/public/browser/web_contents_observer.h" 36 #include "net/cookies/canonical_cookie.h" 37 #include "net/cookies/cookie_monster.h" 38 #include "url/gurl.h" 39 40 class Profile; 41 class InstantSearchPrerendererTest; 42 struct ChromeCookieDetails; 43 44 namespace base { 45 class DictionaryValue; 46 } 47 48 namespace chrome { 49 struct NavigateParams; 50 } 51 52 namespace content { 53 class WebContents; 54 } 55 56 namespace gfx { 57 class Size; 58 } 59 60 namespace net { 61 class URLRequestContextGetter; 62 } 63 64 #if defined(COMPILER_GCC) 65 66 namespace BASE_HASH_NAMESPACE { 67 template <> 68 struct hash<content::WebContents*> { 69 std::size_t operator()(content::WebContents* value) const { 70 return reinterpret_cast<std::size_t>(value); 71 } 72 }; 73 74 } // namespace BASE_HASH_NAMESPACE 75 76 #endif 77 78 namespace prerender { 79 80 class PrerenderCondition; 81 class PrerenderHandle; 82 class PrerenderHistograms; 83 class PrerenderHistory; 84 class PrerenderLocalPredictor; 85 86 // PrerenderManager is responsible for initiating and keeping prerendered 87 // views of web pages. All methods must be called on the UI thread unless 88 // indicated otherwise. 89 class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>, 90 public base::NonThreadSafe, 91 public content::NotificationObserver, 92 public BrowserContextKeyedService, 93 public MediaCaptureDevicesDispatcher::Observer { 94 public: 95 // NOTE: New values need to be appended, since they are used in histograms. 96 enum PrerenderManagerMode { 97 PRERENDER_MODE_DISABLED = 0, 98 PRERENDER_MODE_ENABLED = 1, 99 PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP = 2, 100 PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP = 3, 101 // Obsolete: PRERENDER_MODE_EXPERIMENT_5MIN_TTL_GROUP = 4, 102 PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP = 5, 103 PRERENDER_MODE_EXPERIMENT_MULTI_PRERENDER_GROUP = 6, 104 PRERENDER_MODE_EXPERIMENT_15MIN_TTL_GROUP = 7, 105 PRERENDER_MODE_MAX 106 }; 107 108 // One or more of these flags must be passed to ClearData() to specify just 109 // what data to clear. See function declaration for more information. 110 enum ClearFlags { 111 CLEAR_PRERENDER_CONTENTS = 0x1 << 0, 112 CLEAR_PRERENDER_HISTORY = 0x1 << 1, 113 CLEAR_MAX = 0x1 << 2 114 }; 115 116 typedef predictors::LoggedInPredictorTable::LoggedInStateMap LoggedInStateMap; 117 118 // ID indicating that no experiment is active. 119 static const uint8 kNoExperiment = 0; 120 121 // Owned by a Profile object for the lifetime of the profile. 122 PrerenderManager(Profile* profile, PrerenderTracker* prerender_tracker); 123 124 virtual ~PrerenderManager(); 125 126 // From BrowserContextKeyedService: 127 virtual void Shutdown() OVERRIDE; 128 129 // Entry points for adding prerenders. 130 131 // Adds a prerender for |url| if valid. |process_id| and |route_id| identify 132 // the RenderView that the prerender request came from. If |size| is empty, a 133 // default from the PrerenderConfig is used. Returns a caller-owned 134 // PrerenderHandle* if the URL was added, NULL if it was not. If the launching 135 // RenderView is itself prerendering, the prerender is added as a pending 136 // prerender. 137 PrerenderHandle* AddPrerenderFromLinkRelPrerender( 138 int process_id, 139 int route_id, 140 const GURL& url, 141 const content::Referrer& referrer, 142 const gfx::Size& size); 143 144 // Adds a prerender for |url| if valid. As the prerender request is coming 145 // from a source without a RenderViewHost (i.e., the omnibox) we don't have a 146 // child or route id, or a referrer. This method uses sensible values for 147 // those. The |session_storage_namespace| matches the namespace of the active 148 // tab at the time the prerender is generated from the omnibox. Returns a 149 // caller-owned PrerenderHandle*, or NULL. 150 PrerenderHandle* AddPrerenderFromOmnibox( 151 const GURL& url, 152 content::SessionStorageNamespace* session_storage_namespace, 153 const gfx::Size& size); 154 155 PrerenderHandle* AddPrerenderFromLocalPredictor( 156 const GURL& url, 157 content::SessionStorageNamespace* session_storage_namespace, 158 const gfx::Size& size); 159 160 PrerenderHandle* AddPrerenderFromExternalRequest( 161 const GURL& url, 162 const content::Referrer& referrer, 163 content::SessionStorageNamespace* session_storage_namespace, 164 const gfx::Size& size); 165 166 // Adds a prerender for Instant Search |url| if valid. The 167 // |session_storage_namespace| matches the namespace of the active tab at the 168 // time the prerender is generated. Returns a caller-owned PrerenderHandle* or 169 // NULL. 170 PrerenderHandle* AddPrerenderForInstant( 171 const GURL& url, 172 content::SessionStorageNamespace* session_storage_namespace, 173 const gfx::Size& size); 174 175 // If |process_id| and |view_id| refer to a running prerender, destroy 176 // it with |final_status|. 177 virtual void DestroyPrerenderForRenderView(int process_id, 178 int view_id, 179 FinalStatus final_status); 180 181 // Cancels all active prerenders. 182 void CancelAllPrerenders(); 183 184 // If |url| matches a valid prerendered page and |params| are compatible, try 185 // to swap it and merge browsing histories. Returns |true| and updates 186 // |params->target_contents| if a prerendered page is swapped in, |false| 187 // otherwise. 188 bool MaybeUsePrerenderedPage(const GURL& url, 189 chrome::NavigateParams* params); 190 191 // Moves a PrerenderContents to the pending delete list from the list of 192 // active prerenders when prerendering should be cancelled. 193 virtual void MoveEntryToPendingDelete(PrerenderContents* entry, 194 FinalStatus final_status); 195 196 // Records the perceived page load time for a page - effectively the time from 197 // when the user navigates to a page to when it finishes loading. The actual 198 // load may have started prior to navigation due to prerender hints. 199 // This must be called on the UI thread. 200 // |fraction_plt_elapsed_at_swap_in| must either be in [0.0, 1.0], or a value 201 // outside that range indicating that it doesn't apply. 202 static void RecordPerceivedPageLoadTime( 203 base::TimeDelta perceived_page_load_time, 204 double fraction_plt_elapsed_at_swap_in, 205 content::WebContents* web_contents, 206 const GURL& url); 207 208 // Records the percentage of pixels of the final page in place at swap-in. 209 void RecordFractionPixelsFinalAtSwapin( 210 content::WebContents* web_contents, 211 double fraction); 212 213 // Set whether prerendering is currently enabled for this manager. 214 // Must be called on the UI thread. 215 // If |enabled| is false, existing prerendered pages will still persist until 216 // they time out, but new ones will not be generated. 217 void set_enabled(bool enabled); 218 219 static PrerenderManagerMode GetMode(); 220 static void SetMode(PrerenderManagerMode mode); 221 static const char* GetModeString(); 222 static bool IsPrerenderingPossible(); 223 static bool ActuallyPrerendering(); 224 static bool IsControlGroup(uint8 experiment_id); 225 static bool IsNoUseGroup(); 226 227 // Query the list of current prerender pages to see if the given web contents 228 // is prerendering a page. The optional parameter |origin| is an output 229 // parameter which, if a prerender is found, is set to the Origin of the 230 // prerender |web_contents|. 231 bool IsWebContentsPrerendering(const content::WebContents* web_contents, 232 Origin* origin) const; 233 234 // Whether the PrerenderManager has an active prerender with the given url and 235 // SessionStorageNamespace associated with the given WebContens. 236 bool HasPrerenderedUrl(GURL url, content::WebContents* web_contents) const; 237 238 // Returns the PrerenderContents object for the given web_contents if it's 239 // used for an active prerender page, otherwise returns NULL. 240 PrerenderContents* GetPrerenderContents( 241 const content::WebContents* web_contents) const; 242 243 // Returns a list of all WebContents being prerendered. 244 const std::vector<content::WebContents*> GetAllPrerenderingContents() const; 245 246 // Maintaining and querying the set of WebContents belonging to this 247 // PrerenderManager that are currently showing prerendered pages. 248 void MarkWebContentsAsPrerendered(content::WebContents* web_contents, 249 Origin origin); 250 void MarkWebContentsAsWouldBePrerendered(content::WebContents* web_contents, 251 Origin origin); 252 void MarkWebContentsAsNotPrerendered(content::WebContents* web_contents); 253 254 // Returns true if |web_contents| was originally a prerender that has since 255 // been swapped in. The optional parameter |origin| is an output parameter 256 // which, if a prerender is found, is set to the Origin of the prerender of 257 // |web_contents|. 258 bool IsWebContentsPrerendered(content::WebContents* web_contents, 259 Origin* origin) const; 260 bool WouldWebContentsBePrerendered(content::WebContents* web_contents, 261 Origin* origin) const; 262 263 // Checks whether |url| has been recently navigated to. 264 bool HasRecentlyBeenNavigatedTo(Origin origin, const GURL& url); 265 266 // Returns true iff the method given is valid for prerendering. 267 static bool IsValidHttpMethod(const std::string& method); 268 269 // Returns true iff the scheme of the URL given is valid for prerendering. 270 static bool DoesURLHaveValidScheme(const GURL& url); 271 272 // Returns true iff the scheme of the subresource URL given is valid for 273 // prerendering. 274 static bool DoesSubresourceURLHaveValidScheme(const GURL& url); 275 276 // Returns a Value object containing the active pages being prerendered, and 277 // a history of pages which were prerendered. The caller is responsible for 278 // deleting the return value. 279 base::DictionaryValue* GetAsValue() const; 280 281 // Clears the data indicated by which bits of clear_flags are set. 282 // 283 // If the CLEAR_PRERENDER_CONTENTS bit is set, all active prerenders are 284 // cancelled and then deleted, and any WebContents queued for destruction are 285 // destroyed as well. 286 // 287 // If the CLEAR_PRERENDER_HISTORY bit is set, the prerender history is 288 // cleared, including any entries newly created by destroying them in 289 // response to the CLEAR_PRERENDER_CONTENTS flag. 290 // 291 // Intended to be used when clearing the cache or history. 292 void ClearData(int clear_flags); 293 294 // Record a final status of a prerendered page in a histogram. 295 // This variation allows specifying whether prerendering had been started 296 // (necessary to flag MatchComplete dummies). 297 void RecordFinalStatusWithMatchCompleteStatus( 298 Origin origin, 299 uint8 experiment_id, 300 PrerenderContents::MatchCompleteStatus mc_status, 301 FinalStatus final_status) const; 302 303 // Record a cookie status histogram (see prerender_histograms.h). 304 void RecordCookieStatus(Origin origin, 305 uint8 experiment_id, 306 int cookie_status) const; 307 308 // content::NotificationObserver 309 virtual void Observe(int type, 310 const content::NotificationSource& source, 311 const content::NotificationDetails& details) OVERRIDE; 312 313 // MediaCaptureDevicesDispatcher::Observer 314 virtual void OnCreatingAudioStream(int render_process_id, 315 int render_view_id) OVERRIDE; 316 317 const Config& config() const { return config_; } 318 Config& mutable_config() { return config_; } 319 320 PrerenderTracker* prerender_tracker() { return prerender_tracker_; } 321 322 // Adds a condition. This is owned by the PrerenderManager. 323 void AddCondition(const PrerenderCondition* condition); 324 325 // Records that some visible tab navigated (or was redirected) to the 326 // provided URL. 327 void RecordNavigation(const GURL& url); 328 329 // Updates the LoggedInPredictor state to reflect that a login has likely 330 // on the URL provided. 331 void RecordLikelyLoginOnURL(const GURL& url); 332 333 // Checks if the LoggedInPredictor shows that the user is likely logged on 334 // to the site for the URL provided. 335 void CheckIfLikelyLoggedInOnURL(const GURL& url, 336 bool* lookup_result, 337 bool* database_was_present, 338 const base::Closure& result_cb); 339 340 void OnHistoryServiceDidQueryURL(Origin origin, 341 uint8 experiment_id, 342 CancelableRequestProvider::Handle handle, 343 bool success, 344 const history::URLRow* url_row, 345 history::VisitVector* visits); 346 347 Profile* profile() const { return profile_; } 348 349 // Classes which will be tested in prerender unit browser tests should use 350 // these methods to get times for comparison, so that the test framework can 351 // mock advancing/retarding time. 352 virtual base::Time GetCurrentTime() const; 353 virtual base::TimeTicks GetCurrentTimeTicks() const; 354 355 scoped_refptr<predictors::LoggedInPredictorTable> 356 logged_in_predictor_table() { 357 return logged_in_predictor_table_; 358 } 359 360 PrerenderLocalPredictor* local_predictor() { 361 return local_predictor_.get(); 362 } 363 364 // Notification that a cookie event happened on a render frame. Will record a 365 // cookie event for a given render frame, if it is being prerendered. 366 // If cookies were sent, all cookies must be supplied in |cookie_list|. 367 static void RecordCookieEvent(int process_id, 368 int render_view_id, 369 const GURL& url, 370 const GURL& frame_url, 371 PrerenderContents::CookieEvent event, 372 const net::CookieList* cookie_list); 373 374 protected: 375 class PendingSwap; 376 class PrerenderData : public base::SupportsWeakPtr<PrerenderData> { 377 public: 378 struct OrderByExpiryTime; 379 380 PrerenderData(PrerenderManager* manager, 381 PrerenderContents* contents, 382 base::TimeTicks expiry_time); 383 384 ~PrerenderData(); 385 386 // Turn this PrerenderData into a Match Complete replacement for itself, 387 // placing the current prerender contents into |to_delete_prerenders_|. 388 void MakeIntoMatchCompleteReplacement(); 389 390 // A new PrerenderHandle has been created for this PrerenderData. 391 void OnHandleCreated(PrerenderHandle* prerender_handle); 392 393 // The launcher associated with a handle is navigating away from the context 394 // that launched this prerender. If the prerender is active, it may stay 395 // alive briefly though, in case we we going through a redirect chain that 396 // will eventually land at it. 397 void OnHandleNavigatedAway(PrerenderHandle* prerender_handle); 398 399 // The launcher associated with a handle has taken explicit action to cancel 400 // this prerender. We may well destroy the prerender in this case if no 401 // other handles continue to track it. 402 void OnHandleCanceled(PrerenderHandle* prerender_handle); 403 404 PrerenderContents* contents() { return contents_.get(); } 405 406 PrerenderContents* ReleaseContents(); 407 408 int handle_count() const { return handle_count_; } 409 410 base::TimeTicks expiry_time() const { return expiry_time_; } 411 void set_expiry_time(base::TimeTicks expiry_time) { 412 expiry_time_ = expiry_time; 413 } 414 415 void ClearPendingSwap(); 416 417 PendingSwap* pending_swap() { return pending_swap_.get(); } 418 void set_pending_swap(PendingSwap* pending_swap) { 419 pending_swap_.reset(pending_swap); 420 } 421 422 private: 423 PrerenderManager* manager_; 424 scoped_ptr<PrerenderContents> contents_; 425 426 // The number of distinct PrerenderHandles created for |this|, including 427 // ones that have called PrerenderData::OnHandleNavigatedAway(), but not 428 // counting the ones that have called PrerenderData::OnHandleCanceled(). For 429 // pending prerenders, this will always be 1, since the PrerenderManager 430 // only merges handles of running prerenders. 431 int handle_count_; 432 433 // After this time, this prerender is no longer fresh, and should be 434 // removed. 435 base::TimeTicks expiry_time_; 436 437 // If a session storage namespace merge is in progress for this object, 438 // we need to keep track of various state associated with it. 439 scoped_ptr<PendingSwap> pending_swap_; 440 441 DISALLOW_COPY_AND_ASSIGN(PrerenderData); 442 }; 443 444 // When a swap can't happen immediately, due to a sesison storage namespace 445 // merge, there will be a pending swap object while the merge is in 446 // progress. It retains all the data needed to do the merge, maintains 447 // throttles for the navigation in the target WebContents that needs to be 448 // delayed, and handles all conditions which would cancel a pending swap. 449 class PendingSwap : public content::WebContentsObserver { 450 public: 451 PendingSwap(PrerenderManager* manager, 452 content::WebContents* target_contents, 453 PrerenderData* prerender_data, 454 const GURL& url, 455 bool should_replace_current_entry); 456 virtual ~PendingSwap(); 457 458 void set_swap_successful(bool swap_successful) { 459 swap_successful_ = swap_successful; 460 } 461 462 void BeginSwap(); 463 464 // content::WebContentsObserver implementation. 465 virtual void ProvisionalChangeToMainFrameUrl( 466 const GURL& url, 467 content::RenderViewHost* render_view_host) OVERRIDE; 468 virtual void DidCommitProvisionalLoadForFrame( 469 int64 frame_id, 470 const base::string16& frame_unique_name, 471 bool is_main_frame, 472 const GURL& validated_url, 473 content::PageTransition transition_type, 474 content::RenderViewHost* render_view_host) OVERRIDE; 475 virtual void RenderViewCreated( 476 content::RenderViewHost* render_view_host) OVERRIDE; 477 virtual void DidFailProvisionalLoad( 478 int64 frame_id, 479 const base::string16& frame_unique_name, 480 bool is_main_frame, 481 const GURL& validated_url, 482 int error_code, 483 const base::string16& error_description, 484 content::RenderViewHost* render_view_host) OVERRIDE; 485 virtual void WebContentsDestroyed(content::WebContents* web_contents) 486 OVERRIDE; 487 488 private: 489 void RecordEvent(PrerenderEvent event) const; 490 491 void OnMergeCompleted(content::SessionStorageNamespace::MergeResult result); 492 void OnMergeTimeout(); 493 494 // Prerender parameters. 495 PrerenderManager* manager_; 496 content::WebContents* target_contents_; 497 PrerenderData* prerender_data_; 498 GURL url_; 499 bool should_replace_current_entry_; 500 501 base::TimeTicks start_time_; 502 std::vector<PrerenderTracker::ChildRouteIdPair> rvh_ids_; 503 base::OneShotTimer<PendingSwap> merge_timeout_; 504 bool swap_successful_; 505 506 base::WeakPtrFactory<PendingSwap> weak_factory_; 507 }; 508 509 void SetPrerenderContentsFactory( 510 PrerenderContents::Factory* prerender_contents_factory); 511 512 // Adds prerenders from the pending Prerenders, called by 513 // PrerenderContents::StartPendingPrerenders. 514 void StartPendingPrerenders( 515 int process_id, 516 ScopedVector<PrerenderContents::PendingPrerenderInfo>* pending_prerenders, 517 content::SessionStorageNamespace* session_storage_namespace); 518 519 // Called by a PrerenderData to signal that the launcher has navigated away 520 // from the context that launched the prerender. A user may have clicked 521 // a link in a page containing a <link rel=prerender> element, or the user 522 // might have committed an omnibox navigation. This is used to possibly 523 // shorten the TTL of the prerendered page. 524 void SourceNavigatedAway(PrerenderData* prerender_data); 525 526 private: 527 friend class ::InstantSearchPrerendererTest; 528 friend class PrerenderBrowserTest; 529 friend class PrerenderContents; 530 friend class PrerenderHandle; 531 friend class UnitTestPrerenderManager; 532 533 class OnCloseWebContentsDeleter; 534 struct NavigationRecord; 535 536 // For each WebContents that is swapped in, we store a 537 // PrerenderedWebContentsData so that we can track the origin of the 538 // prerender. 539 struct PrerenderedWebContentsData { 540 explicit PrerenderedWebContentsData(Origin origin); 541 542 Origin origin; 543 }; 544 545 // In the control group experimental group for each WebContents "not swapped 546 // in" we create a WouldBePrerenderedWebContentsData to the origin of the 547 // "prerender" we did not launch. We also track a state machine to ensure 548 // the histogram reporting tracks what histograms would have done. 549 struct WouldBePrerenderedWebContentsData { 550 // When the WebContents gets a provisional load, we'd like to remove the 551 // WebContents from the map since the new navigation would not have swapped 552 // in a prerender. But the first provisional load after the control 553 // prerender is not "swapped in" is actually to the prerendered location! So 554 // we don't remove the item from the map on the first provisional load, but 555 // we do for subsequent loads. 556 enum State { 557 WAITING_FOR_PROVISIONAL_LOAD, 558 SEEN_PROVISIONAL_LOAD, 559 }; 560 561 explicit WouldBePrerenderedWebContentsData(Origin origin); 562 563 Origin origin; 564 State state; 565 }; 566 567 // Time interval before a new prerender is allowed. 568 static const int kMinTimeBetweenPrerendersMs = 500; 569 570 // Time window for which we record old navigations, in milliseconds. 571 static const int kNavigationRecordWindowMs = 5000; 572 573 void OnCancelPrerenderHandle(PrerenderData* prerender_data); 574 575 // Adds a prerender for |url| from |referrer| initiated from the process 576 // |child_id|. The |origin| specifies how the prerender was added. If |size| 577 // is empty, then PrerenderContents::StartPrerendering will instead use a 578 // default from PrerenderConfig. Returns a PrerenderHandle*, owned by the 579 // caller, or NULL. 580 PrerenderHandle* AddPrerender( 581 Origin origin, 582 int child_id, 583 const GURL& url, 584 const content::Referrer& referrer, 585 const gfx::Size& size, 586 content::SessionStorageNamespace* session_storage_namespace); 587 588 void StartSchedulingPeriodicCleanups(); 589 void StopSchedulingPeriodicCleanups(); 590 591 void EvictOldestPrerendersIfNecessary(); 592 593 // Deletes stale and cancelled prerendered PrerenderContents, as well as 594 // WebContents that have been replaced by prerendered WebContents. 595 // Also identifies and kills PrerenderContents that use too much 596 // resources. 597 void PeriodicCleanup(); 598 599 // Posts a task to call PeriodicCleanup. Results in quicker destruction of 600 // objects. If |this| is deleted before the task is run, the task will 601 // automatically be cancelled. 602 void PostCleanupTask(); 603 604 base::TimeTicks GetExpiryTimeForNewPrerender(Origin origin) const; 605 base::TimeTicks GetExpiryTimeForNavigatedAwayPrerender() const; 606 607 void DeleteOldEntries(); 608 virtual PrerenderContents* CreatePrerenderContents( 609 const GURL& url, 610 const content::Referrer& referrer, 611 Origin origin, 612 uint8 experiment_id); 613 614 // Insures the |active_prerenders_| are sorted by increasing expiry time. Call 615 // after every mutation of active_prerenders_ that can possibly make it 616 // unsorted (e.g. an insert, or changing an expiry time). 617 void SortActivePrerenders(); 618 619 // Finds the active PrerenderData object for a running prerender matching 620 // |url| and |session_storage_namespace|. 621 PrerenderData* FindPrerenderData( 622 const GURL& url, 623 const content::SessionStorageNamespace* session_storage_namespace); 624 625 // If |child_id| and |route_id| correspond to a RenderView that is an active 626 // prerender, returns the PrerenderData object for that prerender. Otherwise, 627 // returns NULL. 628 PrerenderData* FindPrerenderDataForChildAndRoute(int child_id, int route_id); 629 630 // Given the |prerender_contents|, find the iterator in active_prerenders_ 631 // correponding to the given prerender. 632 ScopedVector<PrerenderData>::iterator 633 FindIteratorForPrerenderContents(PrerenderContents* prerender_contents); 634 635 bool DoesRateLimitAllowPrerender(Origin origin) const; 636 637 // Deletes old WebContents that have been replaced by prerendered ones. This 638 // is needed because they're replaced in a callback from the old WebContents, 639 // so cannot immediately be deleted. 640 void DeleteOldWebContents(); 641 642 // Cleans up old NavigationRecord's. 643 void CleanUpOldNavigations(); 644 645 // Arrange for the given WebContents to be deleted asap. If deleter is not 646 // NULL, deletes that as well. 647 void ScheduleDeleteOldWebContents(content::WebContents* tab, 648 OnCloseWebContentsDeleter* deleter); 649 650 // Adds to the history list. 651 void AddToHistory(PrerenderContents* contents); 652 653 // Returns a new Value representing the pages currently being prerendered. The 654 // caller is responsible for delete'ing the return value. 655 base::Value* GetActivePrerendersAsValue() const; 656 657 // Destroys all pending prerenders using FinalStatus. Also deletes them as 658 // well as any swapped out WebContents queued for destruction. 659 // Used both on destruction, and when clearing the browsing history. 660 void DestroyAllContents(FinalStatus final_status); 661 662 // Helper function to destroy a PrerenderContents with the specified 663 // final_status, while at the same time recording that for the MatchComplete 664 // case, that this prerender would have been used. 665 void DestroyAndMarkMatchCompleteAsUsed(PrerenderContents* prerender_contents, 666 FinalStatus final_status); 667 668 // Record a final status of a prerendered page in a histogram. 669 // This is a helper function which will ultimately call 670 // RecordFinalStatusWthMatchCompleteStatus, using MATCH_COMPLETE_DEFAULT. 671 void RecordFinalStatus(Origin origin, 672 uint8 experiment_id, 673 FinalStatus final_status) const; 674 675 // Returns whether prerendering is currently enabled for this manager. 676 // Must be called on the UI thread. 677 bool IsEnabled() const; 678 679 void CookieChanged(ChromeCookieDetails* details); 680 void CookieChangedAnyCookiesLeftLookupResult(const std::string& domain_key, 681 bool cookies_exist); 682 void LoggedInPredictorDataReceived(scoped_ptr<LoggedInStateMap> new_map); 683 684 void RecordEvent(PrerenderContents* contents, PrerenderEvent event) const; 685 686 // Swaps a prerender |prerender_data| for |url| into the tab, replacing 687 // |web_contents|. Returns the new WebContents that was swapped in, or NULL 688 // if a swap-in was not possible. If |should_replace_current_entry| is true, 689 // the current history entry in |web_contents| is replaced. 690 content::WebContents* SwapInternal(const GURL& url, 691 content::WebContents* web_contents, 692 PrerenderData* prerender_data, 693 bool should_replace_current_entry); 694 695 // The configuration. 696 Config config_; 697 698 // Specifies whether prerendering is currently enabled for this 699 // manager. The value can change dynamically during the lifetime 700 // of the PrerenderManager. 701 bool enabled_; 702 703 // The profile that owns this PrerenderManager. 704 Profile* profile_; 705 706 PrerenderTracker* prerender_tracker_; 707 708 // All running prerenders. Sorted by expiry time, in ascending order. 709 ScopedVector<PrerenderData> active_prerenders_; 710 711 // Prerenders awaiting deletion. 712 ScopedVector<PrerenderData> to_delete_prerenders_; 713 714 // List of recent navigations in this profile, sorted by ascending 715 // navigate_time_. 716 std::list<NavigationRecord> navigations_; 717 718 // This map is from all WebContents which are currently displaying a 719 // prerendered page which has already been swapped in to a 720 // PrerenderedWebContentsData for tracking full lifetime information 721 // on prerenders. 722 base::hash_map<content::WebContents*, PrerenderedWebContentsData> 723 prerendered_web_contents_data_; 724 725 // WebContents that would have been swapped out for a prerendered WebContents 726 // if the user was not part of the control group for measurement. When the 727 // WebContents gets a provisional load, the WebContents is removed from 728 // the map since the new navigation would not have swapped in a prerender. 729 // However, one complication exists because the first provisional load after 730 // the WebContents is marked as "Would Have Been Prerendered" is actually to 731 // the prerendered location. So, we need to keep a state around that does 732 // not clear the item from the map on the first provisional load, but does 733 // for subsequent loads. 734 base::hash_map<content::WebContents*, WouldBePrerenderedWebContentsData> 735 would_be_prerendered_map_; 736 737 scoped_ptr<PrerenderContents::Factory> prerender_contents_factory_; 738 739 static PrerenderManagerMode mode_; 740 741 // A count of how many prerenders we do per session. Initialized to 0 then 742 // incremented and emitted to a histogram on each successful prerender. 743 static int prerenders_per_session_count_; 744 745 // RepeatingTimer to perform periodic cleanups of pending prerendered 746 // pages. 747 base::RepeatingTimer<PrerenderManager> repeating_timer_; 748 749 // Track time of last prerender to limit prerender spam. 750 base::TimeTicks last_prerender_start_time_; 751 752 std::list<content::WebContents*> old_web_contents_list_; 753 754 ScopedVector<OnCloseWebContentsDeleter> on_close_web_contents_deleters_; 755 756 scoped_ptr<PrerenderHistory> prerender_history_; 757 758 std::list<const PrerenderCondition*> prerender_conditions_; 759 760 scoped_ptr<PrerenderHistograms> histograms_; 761 762 scoped_ptr<PrerenderLocalPredictor> local_predictor_; 763 764 scoped_refptr<predictors::LoggedInPredictorTable> logged_in_predictor_table_; 765 766 // Here, we keep the logged in predictor state, but potentially a superset 767 // of its actual (database-backed) state, since we do not incorporate 768 // browser data deletion. We do not use this for actual lookups, but only 769 // to query cookie data for domains we know there was a login before. 770 // This is required to avoid a large number of cookie lookups on bulk 771 // deletion of cookies. 772 scoped_ptr<LoggedInStateMap> logged_in_state_; 773 774 content::NotificationRegistrar notification_registrar_; 775 776 CancelableRequestConsumer query_url_consumer_; 777 778 DISALLOW_COPY_AND_ASSIGN(PrerenderManager); 779 }; 780 781 PrerenderManager* FindPrerenderManagerUsingRenderProcessId( 782 int render_process_id); 783 784 } // namespace prerender 785 786 #endif // CHROME_BROWSER_PRERENDER_PRERENDER_MANAGER_H_ 787