diff options
| author | gavinp@chromium.org <gavinp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-18 02:23:52 +0000 | 
|---|---|---|
| committer | gavinp@chromium.org <gavinp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-18 02:23:52 +0000 | 
| commit | 762c724a9bcf0c3d20d63dd1b6d17e4b9d2b68c0 (patch) | |
| tree | 5b08b4e0a35424eb7bf0fda722b9cf8b10d1d03f | |
| parent | bb2b60ac4a5cc1ebde77d71f9022a32e04286d83 (diff) | |
| download | chromium_src-762c724a9bcf0c3d20d63dd1b6d17e4b9d2b68c0.zip chromium_src-762c724a9bcf0c3d20d63dd1b6d17e4b9d2b68c0.tar.gz chromium_src-762c724a9bcf0c3d20d63dd1b6d17e4b9d2b68c0.tar.bz2 | |
Add Start/Stop event signalling on Prerenders.
We've switched to our new event names, we've made sure that the PrerenderHandle and the PrerenderLinkManager are connected, and now, we pass these events into WebKit.
This change depends on the WebKit changes in https://bugs.webkit.org/show_bug.cgi?id=96474 landing first. As well, this CL depends on the earlier work in https://chromiumcodereview.appspot.com/11316311/ , which makes the PrerenderHandle an observer of the PrerenderContents, being landed first. As well, since this code depends on WebPrerender.h changing, it actually needs to be staged carefully between WebKit & Chrome. Careful readers will also observe that this change obsoletes https://chromiumcodereview.appspot.com/10918189/ .
R=mmenke@chromium.org
BUG=None
Review URL: https://chromiumcodereview.appspot.com/11459003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@173625 0039d316-1c4b-4281-b951-d872f2087c98
10 files changed, 333 insertions, 63 deletions
| diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc index 6cc1560..601fa24 100644 --- a/chrome/browser/prerender/prerender_browsertest.cc +++ b/chrome/browser/prerender/prerender_browsertest.cc @@ -744,8 +744,11 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest {      OpenDestURLWithJSImpl("WindowOpen()");    } -  void RemoveLinkElementsAndNavigate() const { -    OpenDestURLWithJSImpl("RemoveLinkElementsAndNavigate()"); +  void RemoveLinkElement(int i) const { +    chrome::GetActiveWebContents(current_browser())->GetRenderViewHost()-> +        ExecuteJavascriptInWebFrame( +            string16(), +            ASCIIToUTF16(base::StringPrintf("RemoveLinkElement(%d)", i)));    }    void ClickToNextPageAfterPrerender() { @@ -850,12 +853,39 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest {      return prerender_link_manager;    } -  // Asserting on this can result in flaky tests.  PrerenderHandles are only -  // removed from the PrerenderLinkManager when the prerenders are cancelled -  // from the renderer process, or the channel for the renderer process is -  // closed on the IO thread.  In the latter case, the code must be careful to -  // wait for the channel to close, as it is done asynchronously after swapping -  // out the old process.  See ChannelDestructionWatcher. +  bool DidReceivePrerenderStartEventForLinkNumber(int index) const { +    bool received_prerender_started; +    std::wstring expression = base::StringPrintf( +        L"window.domAutomationController.send(Boolean(" +            L"receivedPrerenderStartEvents[%d]))", index); + +    CHECK(content::ExecuteJavaScriptAndExtractBool( +        chrome::GetActiveWebContents(current_browser())->GetRenderViewHost(), +        L"", expression, +        &received_prerender_started)); +    return received_prerender_started; +  } + +  bool DidReceivePrerenderStopEventForLinkNumber(int index) const { +    bool received_prerender_stopped; +    std::wstring expression = base::StringPrintf( +        L"window.domAutomationController.send(Boolean(" +            L"receivedPrerenderStopEvents[%d]))", index); + +    CHECK(content::ExecuteJavaScriptAndExtractBool( +        chrome::GetActiveWebContents(current_browser())->GetRenderViewHost(), +        L"", expression, +        &received_prerender_stopped)); +    return received_prerender_stopped; +  } + +  // Asserting on this can result in flaky tests.  PrerenderHandles are +  // removed from the PrerenderLinkManager when the prerender is canceled from +  // the browser, when the prerenders are cancelled from the renderer process, +  // or the channel for the renderer process is closed on the IO thread.  In the +  // last case, the code must be careful to wait for the channel to close, as it +  // is done asynchronously after swapping out the old process.  See +  // ChannelDestructionWatcher.    bool IsEmptyPrerenderLinkManager() const {      return GetPrerenderLinkManager()->IsEmpty();    } @@ -879,14 +909,18 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest {    }  #endif -  TestPrerenderContents* GetPrerenderContents() const { +  TestPrerenderContents* GetPrerenderContentsFor(const GURL& url) const {      PrerenderManager::PrerenderData* prerender_data =          GetPrerenderManager()->FindPrerenderData( -            dest_url_, GetSessionStorageNamespace()); +            url, GetSessionStorageNamespace());      return static_cast<TestPrerenderContents*>(          prerender_data ? prerender_data->contents() : NULL);    } +  TestPrerenderContents* GetPrerenderContents() const { +    return GetPrerenderContentsFor(dest_url_); +  } +    void set_loader_path(const std::string& path) {      loader_path_ = path;    } @@ -994,7 +1028,7 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest {      TestPrerenderContents* prerender_contents = GetPrerenderContents();      if (ShouldRenderPrerenderedPageCorrectly(expected_final_status)) { -      ASSERT_TRUE(prerender_contents != NULL); +      ASSERT_NE(static_cast<PrerenderContents*>(NULL), prerender_contents);        EXPECT_EQ(FINAL_STATUS_MAX, prerender_contents->final_status());        if (call_javascript_ && expected_number_of_loads > 0) { @@ -1022,9 +1056,9 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest {    void NavigateToURLImpl(const GURL& dest_url,                           WindowOpenDisposition disposition) const { -    ASSERT_TRUE(GetPrerenderManager() != NULL); +    ASSERT_NE(static_cast<PrerenderManager*>(NULL), GetPrerenderManager());      // Make sure in navigating we have a URL to use in the PrerenderManager. -    ASSERT_TRUE(GetPrerenderContents() != NULL); +    ASSERT_NE(static_cast<PrerenderContents*>(NULL), GetPrerenderContents());      // If opening the page in a background tab, it won't be shown when swapped      // in. @@ -1055,7 +1089,7 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest {          ui_test_utils::BROWSER_TEST_NONE);      // Make sure the PrerenderContents found earlier was used or removed. -    EXPECT_TRUE(GetPrerenderContents() == NULL); +    EXPECT_EQ(static_cast<PrerenderContents*>(NULL), GetPrerenderContents());      if (call_javascript_ && web_contents) {        if (page_load_observer.get()) @@ -1076,7 +1110,7 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest {    void OpenDestURLWithJSImpl(const std::string& javascript_function_name)        const {      TestPrerenderContents* prerender_contents = GetPrerenderContents(); -    ASSERT_TRUE(prerender_contents != NULL); +    ASSERT_NE(static_cast<PrerenderContents*>(NULL), prerender_contents);      RenderViewHost* render_view_host =          chrome::GetActiveWebContents(current_browser())->GetRenderViewHost(); @@ -1085,8 +1119,8 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest {          string16(), ASCIIToUTF16(javascript_function_name));      if (prerender_contents->quit_message_loop_on_destruction()) { -    // Run message loop until the prerender contents is destroyed. -    content::RunMessageLoop(); +      // Run message loop until the prerender contents is destroyed. +      content::RunMessageLoop();      } else {        // We don't expect to pick up a running prerender, so instead        // observe one navigation. @@ -1127,26 +1161,106 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPage) {    ASSERT_TRUE(IsEmptyPrerenderLinkManager());  } +// Checks that pending prerenders launch and receive proper event treatment. +IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPagePending) { +  std::deque<FinalStatus> expected_final_status_queue; +  expected_final_status_queue.push_back(FINAL_STATUS_USED); +  expected_final_status_queue.push_back(FINAL_STATUS_USED); +  PrerenderTestURL("files/prerender/prerender_page_pending.html", +                   expected_final_status_queue, 1); + +  ChannelDestructionWatcher first_channel_close_watcher; + +  first_channel_close_watcher.WatchChannel( +    chrome::GetActiveWebContents(browser())->GetRenderProcessHost()); +  NavigateToDestURL(); +  // NavigateToDestURL doesn't run a message loop. Normally that's fine, but in +  // this case, we need the pending prerenders to start. +  content::RunMessageLoop(); +  first_channel_close_watcher.WaitForChannelClose(); + +  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0)); +  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0)); + +  const GURL prerender_page_url = +      test_server()->GetURL("files/prerender/prerender_page.html"); +  EXPECT_FALSE(IsEmptyPrerenderLinkManager()); +  EXPECT_NE(static_cast<TestPrerenderContents*>(NULL), +            GetPrerenderContentsFor(prerender_page_url)); + +  // Now navigate to our target page. +  ChannelDestructionWatcher second_channel_close_watcher; +  second_channel_close_watcher.WatchChannel( +    chrome::GetActiveWebContents(browser())->GetRenderProcessHost()); +  ui_test_utils::NavigateToURLWithDisposition( +      current_browser(), prerender_page_url, CURRENT_TAB, +      ui_test_utils::BROWSER_TEST_NONE); +  second_channel_close_watcher.WaitForChannelClose(); + +  EXPECT_TRUE(IsEmptyPrerenderLinkManager()); +} + +// Checks that pending prerenders which are canceled before they are launched +// never get started. +IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageRemovesPending) { +  PrerenderTestURL("files/prerender/prerender_page_removes_pending.html", +                   FINAL_STATUS_USED, 1); + +  ChannelDestructionWatcher channel_close_watcher; +  channel_close_watcher.WatchChannel( +      chrome::GetActiveWebContents(browser())->GetRenderProcessHost()); +  NavigateToDestURL(); +  channel_close_watcher.WaitForChannelClose(); + +  EXPECT_FALSE(DidReceivePrerenderStartEventForLinkNumber(1)); +  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); +  // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive* +  // calls did a thread/process hop to the renderer which insured pending +  // renderer events have arrived. +  ASSERT_TRUE(IsEmptyPrerenderLinkManager()); +} +  IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageRemovingLink) {    set_loader_path("files/prerender/prerender_loader_removing_links.html"); -  set_loader_query_and_fragment("?links_to_insert=1&links_to_remove=1"); +  set_loader_query_and_fragment("?links_to_insert=1");    PrerenderTestURL("files/prerender/prerender_page.html",                     FINAL_STATUS_CANCELLED, 1); +  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0)); +  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0)); +    // No ChannelDestructionWatcher is needed here, since prerenders in the    // PrerenderLinkManager should be deleted by removing the links, rather than    // shutting down the renderer process. -  RemoveLinkElementsAndNavigate(); -  ASSERT_TRUE(IsEmptyPrerenderLinkManager()); +  RemoveLinkElement(0); +  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0)); +  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0)); +  // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive* +  // calls did a thread/process hop to the renderer which insured pending +  // renderer events have arrived. +  EXPECT_TRUE(IsEmptyPrerenderLinkManager());  }  IN_PROC_BROWSER_TEST_F(      PrerenderBrowserTest, PrerenderPageRemovingLinkWithTwoLinks) {    set_loader_path("files/prerender/prerender_loader_removing_links.html"); -  set_loader_query_and_fragment("?links_to_insert=2&links_to_remove=2"); +  set_loader_query_and_fragment("?links_to_insert=2");    PrerenderTestURL("files/prerender/prerender_page.html",                     FINAL_STATUS_CANCELLED, 1); -  RemoveLinkElementsAndNavigate(); -  ASSERT_TRUE(IsEmptyPrerenderLinkManager()); +  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0)); +  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0)); +  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); +  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); + +  RemoveLinkElement(0); +  RemoveLinkElement(1); +  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0)); +  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0)); +  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); +  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); +  // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive* +  // calls did a thread/process hop to the renderer which insured pending +  // renderer events have arrived. +  EXPECT_TRUE(IsEmptyPrerenderLinkManager());  }  #if defined(OS_WIN) @@ -1161,19 +1275,31 @@ IN_PROC_BROWSER_TEST_F(      PrerenderBrowserTest,      MAYBE_PrerenderPageRemovingLinkWithTwoLinksRemovingOne) {    set_loader_path("files/prerender/prerender_loader_removing_links.html"); -  set_loader_query_and_fragment("?links_to_insert=2&links_to_remove=1"); +  set_loader_query_and_fragment("?links_to_insert=2");    PrerenderTestURL("files/prerender/prerender_page.html",                     FINAL_STATUS_USED, 1); -  RemoveLinkElementsAndNavigate(); -} +  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0)); +  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0)); +  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); +  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); + +  RemoveLinkElement(0); +  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0)); +  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0)); +  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); +  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); +  // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive* +  // calls did a thread/process hop to the renderer which insured pending +  // renderer events have arrived. +  EXPECT_FALSE(IsEmptyPrerenderLinkManager()); -IN_PROC_BROWSER_TEST_F( -    PrerenderBrowserTest, PrerenderPageRemovingLinkWithOneLinkRemovingTwo) { -  set_loader_path("files/prerender/prerender_loader_removing_links.html"); -  set_loader_query_and_fragment("?links_to_insert=1&links_to_remove=2"); -  PrerenderTestURL("files/prerender/prerender_page.html", -                   FINAL_STATUS_CANCELLED, 1); -  RemoveLinkElementsAndNavigate(); +  ChannelDestructionWatcher channel_close_watcher; +  channel_close_watcher.WatchChannel( +      chrome::GetActiveWebContents(browser())->GetRenderProcessHost()); +  NavigateToDestURL(); +  channel_close_watcher.WaitForChannelClose(); + +  EXPECT_TRUE(IsEmptyPrerenderLinkManager());  }  // Checks that prerendering works in incognito mode. @@ -2272,12 +2398,25 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCancelAll) {                     1);    // Post a task to cancel all the prerenders.    MessageLoop::current()->PostTask( -      FROM_HERE, -      base::Bind(&CancelAllPrerenders, GetPrerenderManager())); +      FROM_HERE, base::Bind(&CancelAllPrerenders, GetPrerenderManager()));    content::RunMessageLoop();    EXPECT_TRUE(GetPrerenderContents() == NULL);  } +IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderEvents) { +  PrerenderTestURL("files/prerender/prerender_page.html", +                   FINAL_STATUS_CANCELLED, 1); +  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0)); +  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0)); + +  MessageLoop::current()->PostTask( +      FROM_HERE, base::Bind(&CancelAllPrerenders, GetPrerenderManager())); +  content::RunMessageLoop(); + +  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0)); +  EXPECT_TRUE(DidReceivePrerenderStopEventForLinkNumber(0)); +} +  // Prerendering and history tests.  // The prerendered page is navigated to in several ways [navigate via  // omnibox, click on link, key-modified click to open in background tab, etc], diff --git a/chrome/browser/prerender/prerender_link_manager.cc b/chrome/browser/prerender/prerender_link_manager.cc index ea45012..da68f89 100644 --- a/chrome/browser/prerender/prerender_link_manager.cc +++ b/chrome/browser/prerender/prerender_link_manager.cc @@ -98,7 +98,9 @@ void PrerenderLinkManager::OnCancelPrerender(int child_id, int prerender_id) {      DVLOG(5) << "... canceling a prerender that doesn't exist.";      return;    } -  PrerenderHandle* prerender_handle = id_to_handle_iter->second; + +  scoped_ptr<PrerenderHandle> prerender_handle(id_to_handle_iter->second); +  ids_to_handle_map_.erase(id_to_handle_iter);    prerender_handle->OnCancel();    // Because OnCancel() can remove the prerender from the map, we need to diff --git a/chrome/renderer/prerender/prerender_dispatcher.cc b/chrome/renderer/prerender/prerender_dispatcher.cc index 013ca9a..d9c4b93 100644 --- a/chrome/renderer/prerender/prerender_dispatcher.cc +++ b/chrome/renderer/prerender/prerender_dispatcher.cc @@ -34,10 +34,16 @@ bool PrerenderDispatcher::IsPrerenderURL(const GURL& url) const {  void PrerenderDispatcher::OnPrerenderStart(int prerender_id) {    DCHECK_NE(0u, prerenders_.count(prerender_id)); -  std::map<int, GURL>::iterator it = prerenders_.find(prerender_id); -  const GURL& url = it->second; -  running_prerender_urls_.insert( -      std::multimap<GURL, int>::value_type(url, prerender_id)); +  std::map<int, WebPrerender>::iterator it = prerenders_.find(prerender_id); + +  WebPrerender& prerender = it->second; + +  // The prerender should only be null in unit tests. +  if (prerender.isNull()) +    return; + +  prerender.didStartPrerender(); +  OnPrerenderAddAlias(prerender_id, prerender.url());  }  void PrerenderDispatcher::OnPrerenderAddAlias(int prerender_id, @@ -49,6 +55,11 @@ void PrerenderDispatcher::OnPrerenderAddAlias(int prerender_id,  void PrerenderDispatcher::OnPrerenderStop(int prerender_id) {    DCHECK_NE(0u, prerenders_.count(prerender_id)); +  WebPrerender& prerender = prerenders_[prerender_id]; + +  // The prerender should only be null in unit tests. +  if (!prerender.isNull()) +    prerender.didStopPrerender();    // TODO(cbentzel): We'd also want to send the map of active prerenders when    // creating a new render process, so the Add/Remove go relative to that. @@ -81,25 +92,26 @@ bool PrerenderDispatcher::OnControlMessageReceived(    return handled;  } -void PrerenderDispatcher::add(const WebKit::WebPrerender& prerender) { +void PrerenderDispatcher::add(const WebPrerender& prerender) {    const PrerenderExtraData& extra_data =        PrerenderExtraData::FromPrerender(prerender); -  prerenders_[extra_data.prerender_id()] = prerender.url(); +  prerenders_[extra_data.prerender_id()] = prerender;    content::RenderThread::Get()->Send(new PrerenderHostMsg_AddLinkRelPrerender(        extra_data.prerender_id(), GURL(prerender.url()), -      content::Referrer(GURL(prerender.referrer()), prerender.referrerPolicy()), +      content::Referrer(GURL(prerender.referrer()), +                        prerender.referrerPolicy()),        extra_data.size(), extra_data.render_view_route_id()));  } -void PrerenderDispatcher::cancel(const WebKit::WebPrerender& prerender) { +void PrerenderDispatcher::cancel(const WebPrerender& prerender) {    const PrerenderExtraData& extra_data =        PrerenderExtraData::FromPrerender(prerender);    content::RenderThread::Get()->Send(        new PrerenderHostMsg_CancelLinkRelPrerender(extra_data.prerender_id()));  } -void PrerenderDispatcher::abandon(const WebKit::WebPrerender& prerender) { +void PrerenderDispatcher::abandon(const WebPrerender& prerender) {    const PrerenderExtraData& extra_data =        PrerenderExtraData::FromPrerender(prerender);    content::RenderThread::Get()->Send( diff --git a/chrome/renderer/prerender/prerender_dispatcher.h b/chrome/renderer/prerender/prerender_dispatcher.h index 1c981169..9d63639 100644 --- a/chrome/renderer/prerender/prerender_dispatcher.h +++ b/chrome/renderer/prerender/prerender_dispatcher.h @@ -10,6 +10,7 @@  #include "base/compiler_specific.h"  #include "base/memory/scoped_ptr.h"  #include "content/public/renderer/render_process_observer.h" +#include "third_party/WebKit/Source/Platform/chromium/public/WebPrerender.h"  #include "third_party/WebKit/Source/Platform/chromium/public/WebPrerenderingSupport.h"  class GURL; @@ -45,9 +46,7 @@ class PrerenderDispatcher : public content::RenderProcessObserver,    virtual void abandon(const WebKit::WebPrerender& prerender) OVERRIDE;    // From WebKit, prerender elements launched by renderers in our process. -  // TODO(gavinp): Store a WebKit::WebPrerender* here once the WebKit API -  // updates to allow this. -  std::map<int, GURL> prerenders_; +  std::map<int, WebKit::WebPrerender> prerenders_;    // From the browser process, which prerenders are running, indexed by URL.    // Updated by the browser processes as aliases are discovered. diff --git a/chrome/renderer/prerender/prerender_dispatcher_unittest.cc b/chrome/renderer/prerender/prerender_dispatcher_unittest.cc index b46a537..e46cc94 100644 --- a/chrome/renderer/prerender/prerender_dispatcher_unittest.cc +++ b/chrome/renderer/prerender/prerender_dispatcher_unittest.cc @@ -36,15 +36,16 @@ class PrerenderDispatcherTest : public testing::Test {      return prerender_dispatcher_.IsPrerenderURL(url);    } -  const std::map<int, GURL>& prerenders() const { +  const std::map<int, WebPrerender>& prerenders() const {      return prerender_dispatcher_.prerenders_;    }    int StartPrerender(const GURL& url) {      DCHECK_EQ(0u, prerender_dispatcher_.prerenders_.count(g_next_prerender_id)); -    prerender_dispatcher_.prerenders_[g_next_prerender_id] = url; +    prerender_dispatcher_.prerenders_[g_next_prerender_id] = WebPrerender();      prerender_dispatcher_.OnPrerenderStart(g_next_prerender_id); +    prerender_dispatcher_.OnPrerenderAddAlias(g_next_prerender_id, url);      return g_next_prerender_id++;    } diff --git a/chrome/test/data/prerender/prerender_loader.html b/chrome/test/data/prerender/prerender_loader.html index 9fed87a..abd3875 100644 --- a/chrome/test/data/prerender/prerender_loader.html +++ b/chrome/test/data/prerender/prerender_loader.html @@ -3,6 +3,17 @@  <title>Preloader</title>  <script> +  var receivedPrerenderStartEvents = []; +  var receivedPrerenderStopEvents = []; + +  function PrerenderStartHandler() { +    receivedPrerenderStartEvents[0] = true; +  } + +  function PrerenderStopHandler() { +    receivedPrerenderStopEvents[0] = true; +  } +    function Click() {      var eventObject = document.createEvent('MouseEvents');      eventObject.initMouseEvent('click'); @@ -63,7 +74,10 @@  </head>  <body>  <script> -  document.write('<link rel="prerender" href="REPLACE_WITH_PRERENDER_URL"/>'); +  document.write('<link id="theprerender" rel="prerender" href="REPLACE_WITH_PRERENDER_URL"/>'); +  prerender = document.getElementById('theprerender'); +  prerender.addEventListener('webkitprerenderstart', PrerenderStartHandler, false); +  prerender.addEventListener('webkitprerenderstop', PrerenderStopHandler, false);  </script>  <a target="_blank" id="toClickTarget"     href="REPLACE_WITH_DESTINATION_URL">Link To click in new window</a> diff --git a/chrome/test/data/prerender/prerender_loader_removing_links.html b/chrome/test/data/prerender/prerender_loader_removing_links.html index 08d4037..e318869 100644 --- a/chrome/test/data/prerender/prerender_loader_removing_links.html +++ b/chrome/test/data/prerender/prerender_loader_removing_links.html @@ -11,27 +11,39 @@ function ExtractGetParameterBadlyAndInsecurely(param, defaultValue) {    return defaultValue;  } -var linksToInsert = ExtractGetParameterBadlyAndInsecurely('links_to_insert', 1); -var linksToRemove = ExtractGetParameterBadlyAndInsecurely('links_to_remove', 1); +var numLinksToInsert = +    ExtractGetParameterBadlyAndInsecurely('links_to_insert', 1); -function RemoveLinkElementsAndNavigate() { -  for (var i = 1; i <= linksToRemove; ++i) { -    var link = document.getElementById('prerenderElement' + i); -    link.parentElement.removeChild(link); -  } -  document.location = 'REPLACE_WITH_DESTINATION_URL'; +var receivedPrerenderStartEvents = []; +var receivedPrerenderStopEvents = []; + +function PrerenderStartHandlerForLink(index) { +  receivedPrerenderStartEvents[index] = true; +} + +function PrerenderStopHandlerForLink(index) { +  receivedPrerenderStopEvents[index] = true;  } -</script> +function RemoveLinkElement(index) { +  var link = document.getElementById('prerenderElement' + index); +  link.parentElement.removeChild(link); +} +</script>  </head>  <body>  <script> -for (var i = 1; i <= linksToInsert; ++i) { +for (var i = 0; i < numLinksToInsert; ++i) {    document.write(        '<link id="prerenderElement' + i +        '" rel="prerender" href="REPLACE_WITH_PRERENDER_URL"/>'); +  var link = document.getElementById('prerenderElement' + i); +  link.addEventListener('webkitprerenderstart', +                        PrerenderStartHandlerForLink.bind(null, i), false); +  link.addEventListener('webkitprerenderstop', +                        PrerenderStopHandlerForLink.bind(null, i), false);  }  </script> -<a href="REPLACE_WITH_DESTINATION_URL">Link To Click</a> +<a id="toClick" href="REPLACE_WITH_DESTINATION_URL">Link To Click For First Prerender</a>  </body>  </html> diff --git a/chrome/test/data/prerender/prerender_page.html b/chrome/test/data/prerender/prerender_page.html index 57ea613..06cd6f4 100644 --- a/chrome/test/data/prerender/prerender_page.html +++ b/chrome/test/data/prerender/prerender_page.html @@ -8,7 +8,6 @@ This test checks to make sure that a prerendered page is loaded.  <script>  var pageWasPrerendered = false; -// Make sure plugin was not loaded while prerendering.  function DidPrerenderPass() {    pageWasPrerendered = true;    return true; diff --git a/chrome/test/data/prerender/prerender_page_pending.html b/chrome/test/data/prerender/prerender_page_pending.html new file mode 100644 index 0000000..01f8b08 --- /dev/null +++ b/chrome/test/data/prerender/prerender_page_pending.html @@ -0,0 +1,44 @@ +<html> +<!--  +This test checks to make sure that pending prerenders start at page launch, +but not earlier. +--> +<link id=thePrerender rel=prerender href="prerender_page.html" /> +<head> +<title>Prerender Page</title> + +<script> +var pageWasPrerendered = false; + +var receivedPrerenderStartEvents = []; +var receivedPrerenderStopEvents = []; + +function PrerenderStartHandlerForLink(index) { +  receivedPrerenderStartEvents[index] = true; +} + +function PrerenderStopHandlerForLink(index) { +  receivedPrerenderStopEvents[index] = true; +} + +function DidPrerenderPass() { +  pageWasPrerendered = true; +  return !receivedPrerenderStartEvents[0] && !receivedPrerenderStopEvents[0]; +} + +// Make sure DidPrerenderPass() was called first.  Otherwise, the page was +// most likely reloaded instead of using the prerendered page. +function DidDisplayPass() { +  return pageWasPrerendered; +} + +var link = document.getElementById('thePrerender'); +link.addEventListener('webkitprerenderstart', +                      PrerenderStartHandlerForLink.bind(null, 0), false); +link.addEventListener('webkitprerenderstop', +                      PrerenderStopHandlerForLink.bind(null, 0), false); +</script> + +</head> +<body></body> +</html> diff --git a/chrome/test/data/prerender/prerender_page_removes_pending.html b/chrome/test/data/prerender/prerender_page_removes_pending.html new file mode 100644 index 0000000..e6797c4 --- /dev/null +++ b/chrome/test/data/prerender/prerender_page_removes_pending.html @@ -0,0 +1,48 @@ +<html> +<!--  +This test checks to make sure that pending prerenders which are canceled +while pending never start. +--> +<link id=thePrerender rel=prerender href="does_not_exist.html" /> +<head> +<title>Prerender Page</title> + +<script> +var pageWasPrerendered = false; + +var receivedPrerenderStartEvents = []; +var receivedPrerenderStopEvents = []; + +function PrerenderStartHandlerForLink(index) { +  receivedPrerenderStartEvents[index] = true; +} + +function PrerenderStopHandlerForLink(index) { +  receivedPrerenderStopEvents[index] = true; +} + +function DidPrerenderPass() { +  pageWasPrerendered = true; +  var link = document.getElementById('thePrerender'); +  if (link) +    link.parentElement.removeChild(link) +  return !receivedPrerenderStartEvents[0] && !receivedPrerenderStopEvents[0]; +} + +// Make sure DidPrerenderPass() was called first.  Otherwise, the page was +// most likely reloaded instead of using the prerendered page. +function DidDisplayPass() { +  return pageWasPrerendered && !receivedPrerenderStartEvents[0] && +         !receivedPrerenderStopEvents[0]; +} + +var link = document.getElementById('thePrerender'); +link.addEventListener('webkitprerenderstart', +                      PrerenderStartHandlerForLink.bind(null, 0), false); +link.addEventListener('webkitprerenderstop', +                      PrerenderStopHandlerForLink.bind(null, 0), false); +</script> + +</head> +<body></body> +</html> | 
