15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prerender/prerender_contents.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <functional>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/favicon/favicon_tab_helper.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_tab_helper.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_types.h"
167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "chrome/browser/prerender/prerender_field_trial.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prerender/prerender_final_status.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prerender/prerender_handle.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prerender/prerender_manager.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prerender/prerender_render_view_host_observer.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prerender/prerender_tracker.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_tab_contents.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/prerender_messages.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_child_process_host.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/resource_request_details.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/session_storage_namespace.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents_delegate.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents_view.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/favicon_url.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DownloadItem;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::OpenURLParams;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderViewHost;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::ResourceRedirectDetails;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::SessionStorageNamespace;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace prerender {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PrerenderContentsFactoryImpl : public PrerenderContents::Factory {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual PrerenderContents* CreatePrerenderContents(
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PrerenderManager* prerender_manager, Profile* profile,
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const GURL& url, const content::Referrer& referrer,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Origin origin, uint8 experiment_id) OVERRIDE {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return new PrerenderContents(prerender_manager, profile,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 url, referrer, origin, experiment_id);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// WebContentsDelegateImpl -----------------------------------------------------
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class PrerenderContents::WebContentsDelegateImpl
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public content::WebContentsDelegate {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit WebContentsDelegateImpl(PrerenderContents* prerender_contents)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : prerender_contents_(prerender_contents) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // content::WebContentsDelegate implementation:
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual WebContents* OpenURLFromTab(WebContents* source,
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const OpenURLParams& params) OVERRIDE {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |OpenURLFromTab| is typically called when a frame performs a navigation
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // that requires the browser to perform the transition instead of WebKit.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Examples include prerendering a site that redirects to an app URL,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // or if --enable-strict-site-isolation is specified and the prerendered
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // frame redirects to a different origin.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(cbentzel): Consider supporting this if it is a common case during
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // prerenders.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prerender_contents_->Destroy(FINAL_STATUS_OPEN_URL);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void CanDownload(
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      RenderViewHost* render_view_host,
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      int request_id,
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const std::string& request_method,
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const base::Callback<void(bool)>& callback) OVERRIDE {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prerender_contents_->Destroy(FINAL_STATUS_DOWNLOAD);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cancel the download.
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.Run(false);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool ShouldCreateWebContents(
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebContents* web_contents,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int route_id,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WindowContainerType window_container_type,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const string16& frame_name,
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const GURL& target_url,
98a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      const content::Referrer& referrer,
997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      WindowOpenDisposition disposition,
100a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      const WebKit::WebWindowFeatures& features,
101a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      bool user_gesture,
102a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      bool opener_suppressed) OVERRIDE {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Since we don't want to permit child windows that would have a
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // window.opener property, terminate prerendering.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prerender_contents_->Destroy(FINAL_STATUS_CREATE_NEW_WINDOW);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cancel the popup.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool OnGoToEntryOffset(int offset) OVERRIDE {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This isn't allowed because the history merge operation
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // does not work if there are renderer issued challenges.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(cbentzel): Cancel in this case? May not need to do
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // since render-issued offset navigations are not guaranteed,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // but indicates that the page cares about the history.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void JSOutOfMemory(WebContents* tab) OVERRIDE {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prerender_contents_->Destroy(FINAL_STATUS_JS_OUT_OF_MEMORY);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool ShouldSuppressDialogs() OVERRIDE {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We still want to show the user the message when they navigate to this
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // page, so cancel this prerender.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prerender_contents_->Destroy(FINAL_STATUS_JAVASCRIPT_ALERT);
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Always suppress JavaScript messages if they're triggered by a page being
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // prerendered.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RegisterProtocolHandler(WebContents* web_contents,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const std::string& protocol,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const GURL& url,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const string16& title,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       bool user_gesture) OVERRIDE {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(mmenke): Consider supporting this if it is a common case during
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // prerenders.
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prerender_contents_->Destroy(FINAL_STATUS_REGISTER_PROTOCOL_HANDLER);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrerenderContents* prerender_contents_;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PrerenderContents::Observer::OnPrerenderStopLoading(
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PrerenderContents* contents) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PrerenderContents::Observer::OnPrerenderCreatedMatchCompleteReplacement(
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PrerenderContents* contents, PrerenderContents* replacement) {
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PrerenderContents::Observer::Observer() {
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PrerenderContents::Observer::~Observer() {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrerenderContents::PendingPrerenderInfo::PendingPrerenderInfo(
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::WeakPtr<PrerenderHandle> weak_prerender_handle,
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Origin origin,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::Referrer& referrer,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& size)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : weak_prerender_handle(weak_prerender_handle),
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      origin(origin),
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url(url),
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      referrer(referrer),
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size(size) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrerenderContents::PendingPrerenderInfo::~PendingPrerenderInfo() {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PrerenderContents::AddPendingPrerender(
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<PendingPrerenderInfo> pending_prerender_info) {
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_prerenders_.push_back(pending_prerender_info.release());
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PrerenderContents::PrepareForUse() {
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NotifyPrerenderStop();
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SessionStorageNamespace* session_storage_namespace = NULL;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (prerender_contents_) {
186ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // TODO(ajwong): This does not correctly handle storage for isolated apps.
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    session_storage_namespace = prerender_contents_->
188ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        GetController().GetDefaultSessionStorageNamespace();
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prerender_manager_->StartPendingPrerenders(
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      child_id_, &pending_prerenders_, session_storage_namespace);
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_prerenders_.clear();
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrerenderContents::PrerenderContents(
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrerenderManager* prerender_manager,
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile,
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::Referrer& referrer,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Origin origin,
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8 experiment_id)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : prerendering_has_started_(false),
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prerender_manager_(prerender_manager),
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prerender_url_(url),
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      referrer_(referrer),
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_(profile),
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      page_id_(0),
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_storage_namespace_id_(-1),
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_stopped_loading_(false),
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_finished_loading_(false),
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      final_status_(FINAL_STATUS_MAX),
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      match_complete_status_(MATCH_COMPLETE_DEFAULT),
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prerendering_has_been_cancelled_(false),
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      child_id_(-1),
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      route_id_(-1),
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      origin_(origin),
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      experiment_id_(experiment_id),
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      creator_child_id_(-1) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(prerender_manager != NULL);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PrerenderContents* PrerenderContents::CreateMatchCompleteReplacement() {
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PrerenderContents* new_contents = prerender_manager_->CreatePrerenderContents(
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      prerender_url(), referrer(), origin(), experiment_id());
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  new_contents->load_start_time_ = load_start_time_;
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  new_contents->session_storage_namespace_id_ = session_storage_namespace_id_;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  new_contents->set_match_complete_status(
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PrerenderContents::MATCH_COMPLETE_REPLACEMENT_PENDING);
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const bool did_init = new_contents->Init();
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(did_init);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(alias_urls_.front(), new_contents->alias_urls_.front());
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(1u, new_contents->alias_urls_.size());
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  new_contents->alias_urls_ = alias_urls_;
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  new_contents->set_match_complete_status(
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PrerenderContents::MATCH_COMPLETE_REPLACEMENT);
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NotifyPrerenderCreatedMatchCompleteReplacement(new_contents);
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return new_contents;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrerenderContents::Init() {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return AddAliasURL(prerender_url_);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrerenderContents::Factory* PrerenderContents::CreateFactory() {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new PrerenderContentsFactoryImpl();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderContents::StartPrerendering(
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int creator_child_id,
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Size& size,
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SessionStorageNamespace* session_storage_namespace) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(profile_ != NULL);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!size.IsEmpty());
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!prerendering_has_started_);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(prerender_contents_.get() == NULL);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(-1, creator_child_id_);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(size_.IsEmpty());
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(1U, alias_urls_.size());
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  creator_child_id_ = creator_child_id;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_storage_namespace_id_ = session_storage_namespace->id();
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_ = size;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(load_start_time_.is_null());
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  load_start_time_ = base::TimeTicks::Now();
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Everything after this point sets up the WebContents object and associated
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RenderView for the prerender page. Don't do this for members of the
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // control group.
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (prerender_manager_->IsControlGroup(experiment_id()))
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (origin_ == ORIGIN_LOCAL_PREDICTOR &&
2777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      IsLocalPredictorPrerenderAlwaysControlEnabled()) {
2787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
2797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prerendering_has_started_ = true;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prerender_contents_.reset(CreateWebContents(session_storage_namespace));
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BrowserTabContents::AttachTabHelpers(prerender_contents_.get());
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_ANDROID)
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Delay icon fetching until the contents are getting swapped in
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to conserve network usage in mobile devices.
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FaviconTabHelper::FromWebContents(
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      prerender_contents_.get())->set_should_fetch_icons(false);
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // defined(OS_ANDROID)
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebContentsObserver::Observe(prerender_contents_.get());
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  web_contents_delegate_.reset(new WebContentsDelegateImpl(this));
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prerender_contents_.get()->SetDelegate(web_contents_delegate_.get());
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the size of the prerender WebContents.
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prerender_contents_->GetView()->SizeContents(size_);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register as an observer of the RenderViewHost so we get messages.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_view_host_observer_.reset(
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new PrerenderRenderViewHostObserver(this, GetRenderViewHostMutable()));
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  child_id_ = GetRenderViewHost()->GetProcess()->GetID();
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  route_id_ = GetRenderViewHost()->GetRoutingID();
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register this with the ResourceDispatcherHost as a prerender
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RenderViewHost. This must be done before the Navigate message to catch all
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // resource requests, but as it is on the same thread as the Navigate message
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (IO) there is no race condition.
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddObserver(prerender_manager()->prerender_tracker());
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NotifyPrerenderStart();
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Close ourselves when the application is shutting down.
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              content::NotificationService::AllSources());
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register for our parent profile to shutdown, so we can shut ourselves down
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as well (should only be called for OTR profiles, as we should receive
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // APP_TERMINATING before non-OTR profiles are destroyed).
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(tburkard): figure out if this is needed.
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              content::Source<Profile>(profile_));
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register to inform new RenderViews that we're prerendering.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_registrar_.Add(
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this, content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED,
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::Source<WebContents>(prerender_contents_.get()));
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register for redirect notifications sourced from |this|.
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_registrar_.Add(
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this, content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::Source<WebContents>(prerender_contents_.get()));
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Transfer over the user agent override.
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prerender_contents_.get()->SetUserAgentOverride(
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prerender_manager_->config().user_agent_override);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NavigationController::LoadURLParams load_url_params(
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prerender_url_);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  load_url_params.referrer = referrer_;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  load_url_params.transition_type = (origin_ == ORIGIN_OMNIBOX ?
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::PAGE_TRANSITION_TYPED : content::PAGE_TRANSITION_LINK);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  load_url_params.override_user_agent =
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prerender_manager_->config().is_overriding_user_agent ?
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NavigationController::UA_OVERRIDE_TRUE :
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NavigationController::UA_OVERRIDE_FALSE;
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prerender_contents_.get()->GetController().LoadURLWithParams(load_url_params);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrerenderContents::GetChildId(int* child_id) const {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(child_id);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(child_id_, -1);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *child_id = child_id_;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return child_id_ != -1;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrerenderContents::GetRouteId(int* route_id) const {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(route_id);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(route_id_, -1);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *route_id = route_id_;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return route_id_ != -1;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PrerenderContents::SetFinalStatus(FinalStatus final_status) {
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(final_status >= FINAL_STATUS_USED && final_status < FINAL_STATUS_MAX);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(final_status_ == FINAL_STATUS_MAX);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  final_status_ = final_status;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrerenderContents::~PrerenderContents() {
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_NE(FINAL_STATUS_MAX, final_status());
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      prerendering_has_been_cancelled() || final_status() == FINAL_STATUS_USED);
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_NE(ORIGIN_MAX, origin());
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prerender_manager_->RecordFinalStatusWithMatchCompleteStatus(
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      origin(), experiment_id(), match_complete_status(), final_status());
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Broadcast the removal of aliases.
38090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (content::RenderProcessHost::iterator host_iterator =
38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)           content::RenderProcessHost::AllHostsIterator();
38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       !host_iterator.IsAtEnd();
38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       host_iterator.Advance()) {
38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    content::RenderProcessHost* host = host_iterator.GetCurrentValue();
38590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    host->Send(new PrerenderMsg_OnPrerenderRemoveAliases(alias_urls_));
38690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
38790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we still have a WebContents, clean up anything we need to and then
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // destroy it.
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prerender_contents_.get())
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete ReleasePrerenderContents();
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PrerenderContents::AddObserver(Observer* observer) {
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(FINAL_STATUS_MAX, final_status_);
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observer_list_.AddObserver(observer);
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PrerenderContents::RemoveObserver(Observer* observer) {
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observer_list_.RemoveObserver(observer);
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderContents::Observe(int type,
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const content::NotificationSource& source,
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const content::NotificationDetails& details) {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_PROFILE_DESTROYED:
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Destroy(FINAL_STATUS_PROFILE_DESTROYED);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case chrome::NOTIFICATION_APP_TERMINATING:
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Destroy(FINAL_STATUS_APP_TERMINATING);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT: {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // RESOURCE_RECEIVED_REDIRECT can come for any resource on a page.
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If it's a redirect on the top-level resource, the name needs
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // to be remembered for future matching, and if it redirects to
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // an https resource, it needs to be canceled. If a subresource
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // is redirected, nothing changes.
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK_EQ(content::Source<WebContents>(source).ptr(),
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                prerender_contents_.get());
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ResourceRedirectDetails* resource_redirect_details =
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Details<ResourceRedirectDetails>(details).ptr();
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK(resource_redirect_details);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (resource_redirect_details->resource_type ==
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ResourceType::MAIN_FRAME) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!AddAliasURL(resource_redirect_details->new_url))
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED: {
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (prerender_contents_.get()) {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(content::Source<WebContents>(source).ptr(),
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  prerender_contents_.get());
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Details<RenderViewHost> new_render_view_host(details);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        OnRenderViewHostCreated(new_render_view_host.ptr());
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // When a new RenderView is created for a prerendering WebContents,
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // tell the new RenderView it's being used for prerendering before any
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // navigations occur.  Note that this is always triggered before the
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // first navigation, so there's no need to send the message just after
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // the WebContents is created.
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new_render_view_host->Send(
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            new PrerenderMsg_SetIsPrerendering(
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                new_render_view_host->GetRoutingID(),
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                true));
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Make sure the size of the RenderViewHost has been passed to the new
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // RenderView.  Otherwise, the size may not be sent until the
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // RenderViewReady event makes it from the render process to the UI
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // thread of the browser process.  When the RenderView receives its
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // size, is also sets itself to be visible, which would then break the
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // visibility API.
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new_render_view_host->WasResized();
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        prerender_contents_->WasHidden();
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Unexpected notification sent.";
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderContents::OnRenderViewHostCreated(
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RenderViewHost* new_render_view_host) {
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t PrerenderContents::pending_prerender_count() const {
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return pending_prerenders_.size();
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebContents* PrerenderContents::CreateWebContents(
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionStorageNamespace* session_storage_namespace) {
480ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // TODO(ajwong): Remove the temporary map once prerendering is aware of
481ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // multiple session storage namespaces per tab.
482ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  content::SessionStorageNamespaceMap session_storage_namespace_map;
483ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  session_storage_namespace_map[std::string()] = session_storage_namespace;
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return WebContents::CreateWithSessionStorage(
485ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      WebContents::CreateParams(profile_), session_storage_namespace_map);
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PrerenderContents::NotifyPrerenderStart() {
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(FINAL_STATUS_MAX, final_status_);
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observer_list_, OnPrerenderStart(this));
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PrerenderContents::NotifyPrerenderStopLoading() {
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observer_list_, OnPrerenderStopLoading(this));
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PrerenderContents::NotifyPrerenderStop() {
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_NE(FINAL_STATUS_MAX, final_status_);
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observer_list_, OnPrerenderStop(this));
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observer_list_.Clear();
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PrerenderContents::NotifyPrerenderCreatedMatchCompleteReplacement(
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PrerenderContents* replacement) {
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observer_list_,
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    OnPrerenderCreatedMatchCompleteReplacement(this,
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                               replacement));
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PrerenderContents::DidUpdateFaviconURL(
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 page_id,
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<content::FaviconURL>& urls) {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "PrerenderContents::OnUpdateFaviconURL" << icon_url_;
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::vector<content::FaviconURL>::const_iterator it = urls.begin();
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != urls.end(); ++it) {
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (it->icon_type == content::FaviconURL::FAVICON) {
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      icon_url_ = it->icon_url;
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << icon_url_;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrerenderContents::AddAliasURL(const GURL& url) {
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool http = url.SchemeIs(chrome::kHttpScheme);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool https = url.SchemeIs(chrome::kHttpsScheme);
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!http && !https) {
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(MATCH_COMPLETE_REPLACEMENT_PENDING, match_complete_status_);
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Destroy(FINAL_STATUS_UNSUPPORTED_SCHEME);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (https && !prerender_manager_->config().https_allowed) {
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(MATCH_COMPLETE_REPLACEMENT_PENDING, match_complete_status_);
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Destroy(FINAL_STATUS_HTTPS);
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (match_complete_status_ != MATCH_COMPLETE_REPLACEMENT_PENDING &&
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prerender_manager_->HasRecentlyBeenNavigatedTo(origin(), url)) {
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Destroy(FINAL_STATUS_RECENTLY_VISITED);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  alias_urls_.push_back(url);
54490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
54590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (content::RenderProcessHost::iterator host_iterator =
54690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)           content::RenderProcessHost::AllHostsIterator();
54790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       !host_iterator.IsAtEnd();
54890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       host_iterator.Advance()) {
54990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    content::RenderProcessHost* host = host_iterator.GetCurrentValue();
55090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    host->Send(new PrerenderMsg_OnPrerenderAddAlias(url));
55190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
55290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrerenderContents::Matches(
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SessionStorageNamespace* session_storage_namespace) const {
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (session_storage_namespace &&
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      session_storage_namespace_id_ != session_storage_namespace->id()) {
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::count_if(alias_urls_.begin(), alias_urls_.end(),
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       std::bind2nd(std::equal_to<GURL>(), url)) != 0;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid PrerenderContents::RenderProcessGone(base::TerminationStatus status) {
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Destroy(FINAL_STATUS_RENDERER_CRASHED);
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderContents::DidStopLoading(
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::RenderViewHost* render_view_host) {
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  has_stopped_loading_ = true;
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NotifyPrerenderStopLoading();
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderContents::DidStartProvisionalLoadForFrame(
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 frame_id,
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 parent_frame_id,
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_main_frame,
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& validated_url,
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_error_page,
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool is_iframe_srcdoc,
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RenderViewHost* render_view_host) {
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_main_frame) {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!AddAliasURL(validated_url))
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Usually, this event fires if the user clicks or enters a new URL.
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Neither of these can happen in the case of an invisible prerender.
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // So the cause is: Some JavaScript caused a new URL to be loaded.  In that
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // case, the spinner would start again in the browser, so we must reset
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // has_stopped_loading_ so that the spinner won't be stopped.
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_stopped_loading_ = false;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_finished_loading_ = false;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderContents::DidFinishLoad(int64 frame_id,
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const GURL& validated_url,
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      bool is_main_frame,
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      RenderViewHost* render_view_host) {
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_main_frame)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_finished_loading_ = true;
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderContents::Destroy(FinalStatus final_status) {
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_NE(final_status, FINAL_STATUS_USED);
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prerendering_has_been_cancelled_)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (child_id_ != -1 && route_id_ != -1) {
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cancel the prerender in the PrerenderTracker.  This is needed
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // because destroy may be called directly from the UI thread without calling
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TryCancel().  This is difficult to completely avoid, since prerendering
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // can be cancelled before a RenderView is created.
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool is_cancelled = prerender_manager()->prerender_tracker()->TryCancel(
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        child_id_, route_id_, final_status);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(is_cancelled);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A different final status may have been set already from another thread.
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If so, use it instead.
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!prerender_manager()->prerender_tracker()->
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            GetFinalStatus(child_id_, route_id_, &final_status)) {
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetFinalStatus(final_status);
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prerendering_has_been_cancelled_ = true;
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prerender_manager_->AddToHistory(this);
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prerender_manager_->MoveEntryToPendingDelete(this, final_status);
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!prerender_manager_->IsControlGroup(experiment_id()) &&
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (prerendering_has_started() ||
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       match_complete_status() == MATCH_COMPLETE_REPLACEMENT)) {
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NotifyPrerenderStop();
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We may destroy the PrerenderContents before we have initialized the
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RenderViewHost. Otherwise set the Observer's PrerenderContents to NULL to
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // avoid any more messages being sent.
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (render_view_host_observer_)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    render_view_host_observer_->set_prerender_contents(NULL);
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::ProcessMetrics* PrerenderContents::MaybeGetProcessMetrics() {
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (process_metrics_.get() == NULL) {
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If a PrenderContents hasn't started prerending, don't be fully formed.
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!GetRenderViewHost() || !GetRenderViewHost()->GetProcess())
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::ProcessHandle handle = GetRenderViewHost()->GetProcess()->GetHandle();
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (handle == base::kNullProcessHandle)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle));
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        handle,
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::BrowserChildProcessHost::GetPortProvider()));
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return process_metrics_.get();
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderContents::DestroyWhenUsingTooManyResources() {
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ProcessMetrics* metrics = MaybeGetProcessMetrics();
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (metrics == NULL)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t private_bytes, shared_bytes;
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (metrics->GetMemoryBytes(&private_bytes, &shared_bytes) &&
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      private_bytes > prerender_manager_->config().max_bytes) {
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Destroy(FINAL_STATUS_MEMORY_LIMIT_EXCEEDED);
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebContents* PrerenderContents::ReleasePrerenderContents() {
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prerender_contents_->SetDelegate(NULL);
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  render_view_host_observer_.reset();
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::WebContentsObserver::Observe(NULL);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return prerender_contents_.release();
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RenderViewHost* PrerenderContents::GetRenderViewHostMutable() {
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return const_cast<RenderViewHost*>(GetRenderViewHost());
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const RenderViewHost* PrerenderContents::GetRenderViewHost() const {
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!prerender_contents_.get())
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return prerender_contents_->GetRenderViewHost();
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrerenderContents::DidNavigate(
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const history::HistoryAddPageArgs& add_page_args) {
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  add_page_vector_.push_back(add_page_args);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PrerenderContents::CommitHistory(WebContents* tab) {
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HistoryTabHelper* history_tab_helper = HistoryTabHelper::FromWebContents(tab);
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < add_page_vector_.size(); ++i)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    history_tab_helper->UpdateHistoryForNavigation(add_page_vector_[i]);
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Value* PrerenderContents::GetAsValue() const {
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!prerender_contents_.get())
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* dict_value = new DictionaryValue();
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict_value->SetString("url", prerender_url_.spec());
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks current_time = base::TimeTicks::Now();
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta duration = current_time - load_start_time_;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict_value->SetInteger("duration", duration.InSeconds());
716868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  dict_value->SetBoolean("is_loaded", prerender_contents_ &&
717868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      !prerender_contents_->IsLoading());
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dict_value;
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PrerenderContents::IsCrossSiteNavigationPending() const {
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!prerender_contents_)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (prerender_contents_->GetSiteInstance() !=
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          prerender_contents_->GetPendingSiteInstance());
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace prerender
730