1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
9 #include "base/command_line.h"
10 #include "base/files/file_path.h"
11 #include "base/memory/ref_counted_memory.h"
12 #include "base/memory/scoped_vector.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/path_service.h"
15 #include "base/prefs/pref_service.h"
16 #include "base/run_loop.h"
17 #include "base/strings/string_util.h"
18 #include "base/strings/stringprintf.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/test/test_timeouts.h"
21 #include "base/values.h"
22 #include "chrome/browser/browsing_data/browsing_data_helper.h"
23 #include "chrome/browser/browsing_data/browsing_data_remover.h"
24 #include "chrome/browser/chrome_content_browser_client.h"
25 #include "chrome/browser/chrome_notification_types.h"
26 #include "chrome/browser/content_settings/host_content_settings_map.h"
27 #include "chrome/browser/extensions/api/web_navigation/web_navigation_api.h"
28 #include "chrome/browser/extensions/extension_apitest.h"
29 #include "chrome/browser/external_protocol/external_protocol_handler.h"
30 #include "chrome/browser/favicon/favicon_tab_helper.h"
31 #include "chrome/browser/prerender/prerender_contents.h"
32 #include "chrome/browser/prerender/prerender_handle.h"
33 #include "chrome/browser/prerender/prerender_link_manager.h"
34 #include "chrome/browser/prerender/prerender_link_manager_factory.h"
35 #include "chrome/browser/prerender/prerender_manager.h"
36 #include "chrome/browser/prerender/prerender_manager_factory.h"
37 #include "chrome/browser/profiles/profile.h"
38 #include "chrome/browser/profiles/profile_io_data.h"
39 #include "chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h"
40 #include "chrome/browser/safe_browsing/database_manager.h"
41 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
42 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
43 #include "chrome/browser/task_manager/task_manager.h"
44 #include "chrome/browser/task_manager/task_manager_browsertest_util.h"
45 #include "chrome/browser/ui/browser.h"
46 #include "chrome/browser/ui/browser_commands.h"
47 #include "chrome/browser/ui/browser_finder.h"
48 #include "chrome/browser/ui/browser_navigator.h"
49 #include "chrome/browser/ui/browser_window.h"
50 #include "chrome/browser/ui/tabs/tab_strip_model.h"
51 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
52 #include "chrome/common/chrome_paths.h"
53 #include "chrome/common/chrome_switches.h"
54 #include "chrome/common/extensions/extension_constants.h"
55 #include "chrome/common/pref_names.h"
56 #include "chrome/test/base/in_process_browser_test.h"
57 #include "chrome/test/base/test_switches.h"
58 #include "chrome/test/base/ui_test_utils.h"
59 #include "chrome/test/base/uma_histogram_helper.h"
60 #include "content/public/browser/browser_message_filter.h"
61 #include "content/public/browser/devtools_agent_host.h"
62 #include "content/public/browser/devtools_client_host.h"
63 #include "content/public/browser/devtools_manager.h"
64 #include "content/public/browser/navigation_controller.h"
65 #include "content/public/browser/navigation_entry.h"
66 #include "content/public/browser/notification_service.h"
67 #include "content/public/browser/render_process_host.h"
68 #include "content/public/browser/render_view_host.h"
69 #include "content/public/browser/site_instance.h"
70 #include "content/public/browser/web_contents.h"
71 #include "content/public/browser/web_contents_observer.h"
72 #include "content/public/common/url_constants.h"
73 #include "content/public/test/browser_test_utils.h"
74 #include "content/public/test/test_navigation_observer.h"
75 #include "content/public/test/test_utils.h"
76 #include "content/test/net/url_request_mock_http_job.h"
77 #include "extensions/common/switches.h"
78 #include "grit/generated_resources.h"
79 #include "net/base/escape.h"
80 #include "net/cert/x509_certificate.h"
81 #include "net/dns/mock_host_resolver.h"
82 #include "net/ssl/client_cert_store.h"
83 #include "net/ssl/ssl_cert_request_info.h"
84 #include "net/url_request/url_request_context.h"
85 #include "net/url_request/url_request_context_getter.h"
86 #include "net/url_request/url_request_filter.h"
87 #include "net/url_request/url_request_job.h"
88 #include "ui/base/l10n/l10n_util.h"
91 using content::BrowserThread
;
92 using content::DevToolsAgentHost
;
93 using content::DevToolsClientHost
;
94 using content::DevToolsManager
;
95 using content::NavigationController
;
96 using content::OpenURLParams
;
97 using content::Referrer
;
98 using content::RenderViewHost
;
99 using content::RenderWidgetHost
;
100 using content::TestNavigationObserver
;
101 using content::WebContents
;
102 using content::WebContentsObserver
;
104 // Prerender tests work as follows:
106 // A page with a prefetch link to the test page is loaded. Once prerendered,
107 // its Javascript function DidPrerenderPass() is called, which returns true if
108 // the page behaves as expected when prerendered.
110 // The prerendered page is then displayed on a tab. The Javascript function
111 // DidDisplayPass() is called, and returns true if the page behaved as it
112 // should while being displayed.
114 namespace prerender
{
118 // Constants used in the test HTML files.
119 const char* kReadyTitle
= "READY";
120 const char* kPassTitle
= "PASS";
122 std::string
CreateClientRedirect(const std::string
& dest_url
) {
123 const char* const kClientRedirectBase
= "client-redirect?";
124 return kClientRedirectBase
+ net::EscapeQueryParamValue(dest_url
, false);
127 std::string
CreateServerRedirect(const std::string
& dest_url
) {
128 const char* const kServerRedirectBase
= "server-redirect?";
129 return kServerRedirectBase
+ net::EscapeQueryParamValue(dest_url
, false);
132 // Clears the specified data using BrowsingDataRemover.
133 void ClearBrowsingData(Browser
* browser
, int remove_mask
) {
134 BrowsingDataRemover
* remover
=
135 BrowsingDataRemover::CreateForUnboundedRange(browser
->profile());
136 remover
->Remove(remove_mask
, BrowsingDataHelper::UNPROTECTED_WEB
);
137 // BrowsingDataRemover deletes itself.
140 // Returns true if the prerender is expected to abort on its own, before
141 // attempting to swap it.
142 bool ShouldAbortPrerenderBeforeSwap(FinalStatus status
) {
144 case FINAL_STATUS_USED
:
145 case FINAL_STATUS_WINDOW_OPENER
:
146 case FINAL_STATUS_APP_TERMINATING
:
147 case FINAL_STATUS_CACHE_OR_HISTORY_CLEARED
:
148 // We'll crash the renderer after it's loaded.
149 case FINAL_STATUS_RENDERER_CRASHED
:
150 case FINAL_STATUS_CANCELLED
:
151 case FINAL_STATUS_DEVTOOLS_ATTACHED
:
152 case FINAL_STATUS_PAGE_BEING_CAPTURED
:
153 case FINAL_STATUS_NAVIGATION_UNCOMMITTED
:
154 case FINAL_STATUS_WOULD_HAVE_BEEN_USED
:
161 // Convenience function to wait for a title. Handles the case when the
162 // WebContents already has the expected title.
163 void WaitForASCIITitle(WebContents
* web_contents
,
164 const char* expected_title_ascii
) {
165 base::string16 expected_title
= base::ASCIIToUTF16(expected_title_ascii
);
166 if (web_contents
->GetTitle() == expected_title
)
168 content::TitleWatcher
title_watcher(web_contents
, expected_title
);
169 EXPECT_EQ(expected_title
, title_watcher
.WaitAndGetTitle());
172 // Waits for the destruction of a RenderProcessHost's IPC channel.
173 // Used to make sure the PrerenderLinkManager's OnChannelClosed function has
174 // been called, before checking its state.
175 class ChannelDestructionWatcher
{
177 ChannelDestructionWatcher() : channel_destroyed_(false) {
180 ~ChannelDestructionWatcher() {
183 void WatchChannel(content::RenderProcessHost
* host
) {
184 host
->AddFilter(new DestructionMessageFilter(this));
187 void WaitForChannelClose() {
189 EXPECT_TRUE(channel_destroyed_
);
193 // When destroyed, calls ChannelDestructionWatcher::OnChannelDestroyed.
194 // Ignores all messages.
195 class DestructionMessageFilter
: public content::BrowserMessageFilter
{
197 explicit DestructionMessageFilter(ChannelDestructionWatcher
* watcher
)
198 : watcher_(watcher
) {
202 virtual ~DestructionMessageFilter() {
203 content::BrowserThread::PostTask(
204 content::BrowserThread::UI
, FROM_HERE
,
205 base::Bind(&ChannelDestructionWatcher::OnChannelDestroyed
,
206 base::Unretained(watcher_
)));
209 virtual bool OnMessageReceived(const IPC::Message
& message
,
210 bool* message_was_ok
) OVERRIDE
{
214 ChannelDestructionWatcher
* watcher_
;
216 DISALLOW_COPY_AND_ASSIGN(DestructionMessageFilter
);
219 void OnChannelDestroyed() {
220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
222 EXPECT_FALSE(channel_destroyed_
);
223 channel_destroyed_
= true;
227 bool channel_destroyed_
;
228 base::RunLoop run_loop_
;
230 DISALLOW_COPY_AND_ASSIGN(ChannelDestructionWatcher
);
233 // A navigation observer to wait on either a new load or a swap of a
234 // WebContents. On swap, if the new WebContents is still loading, wait for that
235 // load to complete as well. Note that the load must begin after the observer is
237 class NavigationOrSwapObserver
: public WebContentsObserver
,
238 public TabStripModelObserver
{
240 // Waits for either a new load or a swap of |tab_strip_model|'s active
242 NavigationOrSwapObserver(TabStripModel
* tab_strip_model
,
243 WebContents
* web_contents
)
244 : WebContentsObserver(web_contents
),
245 tab_strip_model_(tab_strip_model
),
246 did_start_loading_(false),
247 number_of_loads_(1) {
248 CHECK_NE(TabStripModel::kNoTab
,
249 tab_strip_model
->GetIndexOfWebContents(web_contents
));
250 tab_strip_model_
->AddObserver(this);
253 // Waits for either |number_of_loads| loads or a swap of |tab_strip_model|'s
254 // active WebContents.
255 NavigationOrSwapObserver(TabStripModel
* tab_strip_model
,
256 WebContents
* web_contents
,
258 : WebContentsObserver(web_contents
),
259 tab_strip_model_(tab_strip_model
),
260 did_start_loading_(false),
261 number_of_loads_(number_of_loads
) {
262 CHECK_NE(TabStripModel::kNoTab
,
263 tab_strip_model
->GetIndexOfWebContents(web_contents
));
264 tab_strip_model_
->AddObserver(this);
267 virtual ~NavigationOrSwapObserver() {
268 tab_strip_model_
->RemoveObserver(this);
275 // WebContentsObserver implementation:
276 virtual void DidStartLoading(RenderViewHost
* render_view_host
) OVERRIDE
{
277 did_start_loading_
= true;
279 virtual void DidStopLoading(RenderViewHost
* render_view_host
) OVERRIDE
{
280 if (!did_start_loading_
)
283 if (number_of_loads_
== 0)
287 // TabStripModelObserver implementation:
288 virtual void TabReplacedAt(TabStripModel
* tab_strip_model
,
289 WebContents
* old_contents
,
290 WebContents
* new_contents
,
291 int index
) OVERRIDE
{
292 if (old_contents
!= web_contents())
294 // Switch to observing the new WebContents.
295 Observe(new_contents
);
296 if (new_contents
->IsLoading()) {
297 // If the new WebContents is still loading, wait for it to complete. Only
298 // one load post-swap is supported.
299 did_start_loading_
= true;
300 number_of_loads_
= 1;
307 TabStripModel
* tab_strip_model_
;
308 bool did_start_loading_
;
309 int number_of_loads_
;
313 // Waits for a new tab to open and a navigation or swap in it.
314 class NewTabNavigationOrSwapObserver
{
316 NewTabNavigationOrSwapObserver()
318 chrome::NOTIFICATION_TAB_ADDED
,
319 base::Bind(&NewTabNavigationOrSwapObserver::OnTabAdded
,
320 base::Unretained(this))) {
321 // Watch for NOTIFICATION_TAB_ADDED. Add a callback so that the
322 // NavigationOrSwapObserver can be attached synchronously and no events are
327 new_tab_observer_
.Wait();
328 swap_observer_
->Wait();
331 bool OnTabAdded(const content::NotificationSource
& source
,
332 const content::NotificationDetails
& details
) {
335 WebContents
* new_tab
= content::Details
<WebContents
>(details
).ptr();
336 // Get the TabStripModel. Assume this is attached to a Browser.
337 TabStripModel
* tab_strip_model
=
338 static_cast<Browser
*>(new_tab
->GetDelegate())->tab_strip_model();
339 swap_observer_
.reset(new NavigationOrSwapObserver(tab_strip_model
,
345 content::WindowedNotificationObserver new_tab_observer_
;
346 scoped_ptr
<NavigationOrSwapObserver
> swap_observer_
;
349 // PrerenderContents that stops the UI message loop on DidStopLoading().
350 class TestPrerenderContents
: public PrerenderContents
{
352 TestPrerenderContents(
353 PrerenderManager
* prerender_manager
,
356 const content::Referrer
& referrer
,
358 FinalStatus expected_final_status
)
359 : PrerenderContents(prerender_manager
, profile
, url
,
360 referrer
, origin
, PrerenderManager::kNoExperiment
),
361 expected_final_status_(expected_final_status
),
362 new_render_view_host_(NULL
),
365 should_be_shown_(expected_final_status
== FINAL_STATUS_USED
),
366 skip_final_checks_(false) {
369 virtual ~TestPrerenderContents() {
370 if (skip_final_checks_
)
373 if (expected_final_status_
== FINAL_STATUS_MAX
) {
374 EXPECT_EQ(MATCH_COMPLETE_REPLACEMENT
, match_complete_status());
376 EXPECT_EQ(expected_final_status_
, final_status()) <<
377 " when testing URL " << prerender_url().path() <<
378 " (Expected: " << NameFromFinalStatus(expected_final_status_
) <<
379 ", Actual: " << NameFromFinalStatus(final_status()) << ")";
381 // Prerendering RenderViewHosts should be hidden before the first
382 // navigation, so this should be happen for every PrerenderContents for
383 // which a RenderViewHost is created, regardless of whether or not it's
385 if (new_render_view_host_
)
386 EXPECT_TRUE(was_hidden_
);
388 // A used PrerenderContents will only be destroyed when we swap out
389 // WebContents, at the end of a navigation caused by a call to
390 // NavigateToURLImpl().
391 if (final_status() == FINAL_STATUS_USED
)
392 EXPECT_TRUE(new_render_view_host_
);
394 EXPECT_EQ(should_be_shown_
, was_shown_
);
397 virtual void RenderProcessGone(base::TerminationStatus status
) OVERRIDE
{
398 // On quit, it's possible to end up here when render processes are closed
399 // before the PrerenderManager is destroyed. As a result, it's possible to
400 // get either FINAL_STATUS_APP_TERMINATING or FINAL_STATUS_RENDERER_CRASHED
403 // It's also possible for this to be called after we've been notified of
404 // app termination, but before we've been deleted, which is why the second
406 if (expected_final_status_
== FINAL_STATUS_APP_TERMINATING
&&
407 final_status() != expected_final_status_
) {
408 expected_final_status_
= FINAL_STATUS_RENDERER_CRASHED
;
411 PrerenderContents::RenderProcessGone(status
);
414 virtual bool CheckURL(const GURL
& url
) OVERRIDE
{
415 // Prevent FINAL_STATUS_UNSUPPORTED_SCHEME when navigating to about:crash in
416 // the PrerenderRendererCrash test.
417 if (url
.spec() != content::kChromeUICrashURL
)
418 return PrerenderContents::CheckURL(url
);
422 // For tests that open the prerender in a new background tab, the RenderView
423 // will not have been made visible when the PrerenderContents is destroyed
424 // even though it is used.
425 void set_should_be_shown(bool value
) { should_be_shown_
= value
; }
427 // For tests which do not know whether the prerender will be used.
428 void set_skip_final_checks(bool value
) { skip_final_checks_
= value
; }
430 FinalStatus
expected_final_status() const { return expected_final_status_
; }
433 virtual void OnRenderViewHostCreated(
434 RenderViewHost
* new_render_view_host
) OVERRIDE
{
435 // Used to make sure the RenderViewHost is hidden and, if used,
436 // subsequently shown.
437 notification_registrar().Add(
439 content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED
,
440 content::Source
<RenderWidgetHost
>(new_render_view_host
));
442 new_render_view_host_
= new_render_view_host
;
444 PrerenderContents::OnRenderViewHostCreated(new_render_view_host
);
447 virtual void Observe(int type
,
448 const content::NotificationSource
& source
,
449 const content::NotificationDetails
& details
) OVERRIDE
{
451 content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED
) {
452 EXPECT_EQ(new_render_view_host_
,
453 content::Source
<RenderWidgetHost
>(source
).ptr());
454 bool is_visible
= *content::Details
<bool>(details
).ptr();
458 } else if (is_visible
&& was_hidden_
) {
459 // Once hidden, a prerendered RenderViewHost should only be shown after
460 // being removed from the PrerenderContents for display.
461 EXPECT_FALSE(GetRenderViewHost());
466 PrerenderContents::Observe(type
, source
, details
);
469 FinalStatus expected_final_status_
;
471 // The RenderViewHost created for the prerender, if any.
472 RenderViewHost
* new_render_view_host_
;
473 // Set to true when the prerendering RenderWidget is hidden.
475 // Set to true when the prerendering RenderWidget is shown, after having been
478 // Expected final value of was_shown_. Defaults to true for
479 // FINAL_STATUS_USED, and false otherwise.
480 bool should_be_shown_
;
481 // If true, |expected_final_status_| and other shutdown checks are skipped.
482 bool skip_final_checks_
;
485 // A handle to a TestPrerenderContents whose lifetime is under the caller's
486 // control. A PrerenderContents may be destroyed at any point. This allows
487 // tracking the final status, etc.
488 class TestPrerender
: public PrerenderContents::Observer
,
489 public base::SupportsWeakPtr
<TestPrerender
> {
494 expected_number_of_loads_(0) {
496 virtual ~TestPrerender() {
498 contents_
->RemoveObserver(this);
501 TestPrerenderContents
* contents() const { return contents_
; }
502 int number_of_loads() const { return number_of_loads_
; }
504 void WaitForCreate() { create_loop_
.Run(); }
505 void WaitForStart() { start_loop_
.Run(); }
506 void WaitForStop() { stop_loop_
.Run(); }
508 // Waits for |number_of_loads()| to be at least |expected_number_of_loads| OR
509 // for the prerender to stop running (just to avoid a timeout if the prerender
510 // dies). Note: this does not assert equality on the number of loads; the
511 // caller must do it instead.
512 void WaitForLoads(int expected_number_of_loads
) {
513 DCHECK(!load_waiter_
);
514 DCHECK(!expected_number_of_loads_
);
515 if (number_of_loads_
< expected_number_of_loads
) {
516 load_waiter_
.reset(new base::RunLoop
);
517 expected_number_of_loads_
= expected_number_of_loads
;
519 load_waiter_
.reset();
520 expected_number_of_loads_
= 0;
522 EXPECT_LE(expected_number_of_loads
, number_of_loads_
);
525 void OnPrerenderCreated(TestPrerenderContents
* contents
) {
527 contents_
= contents
;
528 contents_
->AddObserver(this);
532 // PrerenderContents::Observer implementation:
533 virtual void OnPrerenderStart(PrerenderContents
* contents
) OVERRIDE
{
537 virtual void OnPrerenderStopLoading(PrerenderContents
* contents
) OVERRIDE
{
539 if (load_waiter_
&& number_of_loads_
>= expected_number_of_loads_
)
540 load_waiter_
->Quit();
543 virtual void OnPrerenderStop(PrerenderContents
* contents
) OVERRIDE
{
547 // If there is a WaitForLoads call and it has yet to see the expected number
548 // of loads, stop the loop so the test fails instead of timing out.
550 load_waiter_
->Quit();
553 virtual void OnPrerenderCreatedMatchCompleteReplacement(
554 PrerenderContents
* contents
, PrerenderContents
* replacement
) OVERRIDE
{
558 TestPrerenderContents
* contents_
;
559 int number_of_loads_
;
561 int expected_number_of_loads_
;
562 scoped_ptr
<base::RunLoop
> load_waiter_
;
564 base::RunLoop create_loop_
;
565 base::RunLoop start_loop_
;
566 base::RunLoop stop_loop_
;
568 DISALLOW_COPY_AND_ASSIGN(TestPrerender
);
571 // PrerenderManager that uses TestPrerenderContents.
572 class TestPrerenderContentsFactory
: public PrerenderContents::Factory
{
574 TestPrerenderContentsFactory() {}
576 virtual ~TestPrerenderContentsFactory() {
577 EXPECT_TRUE(expected_contents_queue_
.empty());
580 scoped_ptr
<TestPrerender
> ExpectPrerenderContents(FinalStatus final_status
) {
581 scoped_ptr
<TestPrerender
> handle(new TestPrerender());
582 expected_contents_queue_
.push_back(
583 ExpectedContents(final_status
, handle
->AsWeakPtr()));
584 return handle
.Pass();
587 virtual PrerenderContents
* CreatePrerenderContents(
588 PrerenderManager
* prerender_manager
,
591 const content::Referrer
& referrer
,
593 uint8 experiment_id
) OVERRIDE
{
594 ExpectedContents expected
;
595 if (!expected_contents_queue_
.empty()) {
596 expected
= expected_contents_queue_
.front();
597 expected_contents_queue_
.pop_front();
599 VLOG(1) << "Creating prerender contents for " << url
.path() <<
600 " with expected final status " << expected
.final_status
;
601 VLOG(1) << expected_contents_queue_
.size() << " left in the queue.";
602 TestPrerenderContents
* contents
=
603 new TestPrerenderContents(prerender_manager
,
604 profile
, url
, referrer
, origin
,
605 expected
.final_status
);
607 expected
.handle
->OnPrerenderCreated(contents
);
612 struct ExpectedContents
{
613 ExpectedContents() : final_status(FINAL_STATUS_MAX
) { }
614 ExpectedContents(FinalStatus final_status
,
615 const base::WeakPtr
<TestPrerender
>& handle
)
616 : final_status(final_status
),
620 FinalStatus final_status
;
621 base::WeakPtr
<TestPrerender
> handle
;
624 std::deque
<ExpectedContents
> expected_contents_queue_
;
627 #if defined(FULL_SAFE_BROWSING)
628 // A SafeBrowsingDatabaseManager implementation that returns a fixed result for
630 class FakeSafeBrowsingDatabaseManager
: public SafeBrowsingDatabaseManager
{
632 explicit FakeSafeBrowsingDatabaseManager(SafeBrowsingService
* service
)
633 : SafeBrowsingDatabaseManager(service
),
634 threat_type_(SB_THREAT_TYPE_SAFE
) { }
636 // Called on the IO thread to check if the given url is safe or not. If we
637 // can synchronously determine that the url is safe, CheckUrl returns true.
638 // Otherwise it returns false, and "client" is called asynchronously with the
639 // result when it is ready.
640 // Returns true, indicating a SAFE result, unless the URL is the fixed URL
641 // specified by the user, and the user-specified result is not SAFE
642 // (in which that result will be communicated back via a call into the
643 // client, and false will be returned).
644 // Overrides SafeBrowsingService::CheckBrowseUrl.
645 virtual bool CheckBrowseUrl(const GURL
& gurl
, Client
* client
) OVERRIDE
{
646 if (gurl
!= url_
|| threat_type_
== SB_THREAT_TYPE_SAFE
)
649 BrowserThread::PostTask(
650 BrowserThread::IO
, FROM_HERE
,
651 base::Bind(&FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone
,
652 this, gurl
, client
));
656 void SetThreatTypeForUrl(const GURL
& url
, SBThreatType threat_type
) {
658 threat_type_
= threat_type
;
662 virtual ~FakeSafeBrowsingDatabaseManager() {}
664 void OnCheckBrowseURLDone(const GURL
& gurl
, Client
* client
) {
665 std::vector
<SBThreatType
> expected_threats
;
666 expected_threats
.push_back(SB_THREAT_TYPE_URL_MALWARE
);
667 expected_threats
.push_back(SB_THREAT_TYPE_URL_PHISHING
);
668 SafeBrowsingDatabaseManager::SafeBrowsingCheck
sb_check(
669 std::vector
<GURL
>(1, gurl
),
670 std::vector
<SBFullHash
>(),
672 safe_browsing_util::MALWARE
,
674 sb_check
.url_results
[0] = threat_type_
;
675 client
->OnSafeBrowsingResult(sb_check
);
679 SBThreatType threat_type_
;
680 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingDatabaseManager
);
683 class FakeSafeBrowsingService
: public SafeBrowsingService
{
685 FakeSafeBrowsingService() { }
687 // Returned pointer has the same lifespan as the database_manager_ refcounted
689 FakeSafeBrowsingDatabaseManager
* fake_database_manager() {
690 return fake_database_manager_
;
694 virtual ~FakeSafeBrowsingService() { }
696 virtual SafeBrowsingDatabaseManager
* CreateDatabaseManager() OVERRIDE
{
697 fake_database_manager_
= new FakeSafeBrowsingDatabaseManager(this);
698 return fake_database_manager_
;
702 FakeSafeBrowsingDatabaseManager
* fake_database_manager_
;
704 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService
);
707 // Factory that creates FakeSafeBrowsingService instances.
708 class TestSafeBrowsingServiceFactory
: public SafeBrowsingServiceFactory
{
710 TestSafeBrowsingServiceFactory() :
711 most_recent_service_(NULL
) { }
712 virtual ~TestSafeBrowsingServiceFactory() { }
714 virtual SafeBrowsingService
* CreateSafeBrowsingService() OVERRIDE
{
715 most_recent_service_
= new FakeSafeBrowsingService();
716 return most_recent_service_
;
719 FakeSafeBrowsingService
* most_recent_service() const {
720 return most_recent_service_
;
724 FakeSafeBrowsingService
* most_recent_service_
;
728 class FakeDevToolsClientHost
: public DevToolsClientHost
{
730 FakeDevToolsClientHost() {}
731 virtual ~FakeDevToolsClientHost() {}
732 virtual void InspectedContentsClosing() OVERRIDE
{}
733 virtual void DispatchOnInspectorFrontend(const std::string
& msg
) OVERRIDE
{}
734 virtual void ReplacedWithAnotherClient() OVERRIDE
{}
737 class RestorePrerenderMode
{
739 RestorePrerenderMode() : prev_mode_(PrerenderManager::GetMode()) {
742 ~RestorePrerenderMode() { PrerenderManager::SetMode(prev_mode_
); }
744 PrerenderManager::PrerenderManagerMode prev_mode_
;
747 // URLRequestJob (and associated handler) which hangs.
748 class HangingURLRequestJob
: public net::URLRequestJob
{
750 HangingURLRequestJob(net::URLRequest
* request
,
751 net::NetworkDelegate
* network_delegate
)
752 : net::URLRequestJob(request
, network_delegate
) {
755 virtual void Start() OVERRIDE
{}
758 virtual ~HangingURLRequestJob() {}
761 class HangingFirstRequestProtocolHandler
762 : public net::URLRequestJobFactory::ProtocolHandler
{
764 HangingFirstRequestProtocolHandler(const base::FilePath
& file
,
765 base::Closure callback
)
770 virtual ~HangingFirstRequestProtocolHandler() {}
772 virtual net::URLRequestJob
* MaybeCreateJob(
773 net::URLRequest
* request
,
774 net::NetworkDelegate
* network_delegate
) const OVERRIDE
{
777 BrowserThread::PostTask(
778 BrowserThread::UI
, FROM_HERE
, callback_
);
779 return new HangingURLRequestJob(request
, network_delegate
);
781 return new content::URLRequestMockHTTPJob(request
, network_delegate
, file_
);
785 base::FilePath file_
;
786 base::Closure callback_
;
787 mutable bool first_run_
;
790 // Makes |url| never respond on the first load, and then with the contents of
791 // |file| afterwards. When the first load has been scheduled, runs |callback| on
793 void CreateHangingFirstRequestProtocolHandlerOnIO(const GURL
& url
,
794 const base::FilePath
& file
,
795 base::Closure callback
) {
796 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
797 scoped_ptr
<net::URLRequestJobFactory::ProtocolHandler
> never_respond_handler(
798 new HangingFirstRequestProtocolHandler(file
, callback
));
799 net::URLRequestFilter::GetInstance()->AddUrlProtocolHandler(
800 url
, never_respond_handler
.Pass());
803 // Wrapper over URLRequestMockHTTPJob that exposes extra callbacks.
804 class MockHTTPJob
: public content::URLRequestMockHTTPJob
{
806 MockHTTPJob(net::URLRequest
* request
,
807 net::NetworkDelegate
* delegate
,
808 const base::FilePath
& file
)
809 : content::URLRequestMockHTTPJob(request
, delegate
, file
) {
812 void set_start_callback(const base::Closure
& start_callback
) {
813 start_callback_
= start_callback
;
816 virtual void Start() OVERRIDE
{
817 if (!start_callback_
.is_null())
818 start_callback_
.Run();
819 content::URLRequestMockHTTPJob::Start();
823 virtual ~MockHTTPJob() {}
825 base::Closure start_callback_
;
828 // Dummy counter class to live on the UI thread for counting requests.
829 class RequestCounter
: public base::SupportsWeakPtr
<RequestCounter
> {
831 RequestCounter() : count_(0), expected_count_(-1) {}
832 int count() const { return count_
; }
834 void RequestStarted() {
836 if (loop_
&& count_
== expected_count_
)
840 void WaitForCount(int expected_count
) {
842 ASSERT_EQ(-1, expected_count_
);
843 if (count_
< expected_count
) {
844 expected_count_
= expected_count
;
845 loop_
.reset(new base::RunLoop
);
847 expected_count_
= -1;
851 EXPECT_EQ(expected_count
, count_
);
856 scoped_ptr
<base::RunLoop
> loop_
;
859 // Protocol handler which counts the number of requests that start.
860 class CountingProtocolHandler
861 : public net::URLRequestJobFactory::ProtocolHandler
{
863 CountingProtocolHandler(const base::FilePath
& file
,
864 const base::WeakPtr
<RequestCounter
>& counter
)
867 weak_factory_(this) {
869 virtual ~CountingProtocolHandler() {}
871 virtual net::URLRequestJob
* MaybeCreateJob(
872 net::URLRequest
* request
,
873 net::NetworkDelegate
* network_delegate
) const OVERRIDE
{
874 MockHTTPJob
* job
= new MockHTTPJob(request
, network_delegate
, file_
);
875 job
->set_start_callback(base::Bind(&CountingProtocolHandler::RequestStarted
,
876 weak_factory_
.GetWeakPtr()));
880 void RequestStarted() {
881 BrowserThread::PostTask(
882 BrowserThread::UI
, FROM_HERE
,
883 base::Bind(&RequestCounter::RequestStarted
, counter_
));
887 base::FilePath file_
;
888 base::WeakPtr
<RequestCounter
> counter_
;
889 mutable base::WeakPtrFactory
<CountingProtocolHandler
> weak_factory_
;
892 // Makes |url| respond to requests with the contents of |file|, counting the
893 // number that start in |counter|.
894 void CreateCountingProtocolHandlerOnIO(
896 const base::FilePath
& file
,
897 const base::WeakPtr
<RequestCounter
>& counter
) {
898 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
899 scoped_ptr
<net::URLRequestJobFactory::ProtocolHandler
> protocol_handler(
900 new CountingProtocolHandler(file
, counter
));
901 net::URLRequestFilter::GetInstance()->AddUrlProtocolHandler(
902 url
, protocol_handler
.Pass());
905 // Makes |url| respond to requests with the contents of |file|.
906 void CreateMockProtocolHandlerOnIO(const GURL
& url
,
907 const base::FilePath
& file
) {
908 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
909 net::URLRequestFilter::GetInstance()->AddUrlProtocolHandler(
910 url
, content::URLRequestMockHTTPJob::CreateProtocolHandlerForSingleFile(
914 // A ContentBrowserClient that cancels all prerenderers on OpenURL.
915 class TestContentBrowserClient
: public chrome::ChromeContentBrowserClient
{
917 TestContentBrowserClient() {}
918 virtual ~TestContentBrowserClient() {}
920 // chrome::ChromeContentBrowserClient implementation.
921 virtual bool ShouldAllowOpenURL(content::SiteInstance
* site_instance
,
922 const GURL
& url
) OVERRIDE
{
923 PrerenderManagerFactory::GetForProfile(
924 Profile::FromBrowserContext(site_instance
->GetBrowserContext()))
925 ->CancelAllPrerenders();
926 return chrome::ChromeContentBrowserClient::ShouldAllowOpenURL(site_instance
,
931 DISALLOW_COPY_AND_ASSIGN(TestContentBrowserClient
);
934 // A ContentBrowserClient that forces cross-process navigations.
935 class SwapProcessesContentBrowserClient
936 : public chrome::ChromeContentBrowserClient
{
938 SwapProcessesContentBrowserClient() {}
939 virtual ~SwapProcessesContentBrowserClient() {}
941 // chrome::ChromeContentBrowserClient implementation.
942 virtual bool ShouldSwapProcessesForRedirect(
943 content::ResourceContext
* resource_context
,
944 const GURL
& current_url
,
945 const GURL
& new_url
) OVERRIDE
{
950 DISALLOW_COPY_AND_ASSIGN(SwapProcessesContentBrowserClient
);
953 // An ExternalProtocolHandler that blocks everything and asserts it never is
955 class NeverRunsExternalProtocolHandlerDelegate
956 : public ExternalProtocolHandler::Delegate
{
958 // ExternalProtocolHandler::Delegate implementation.
959 virtual ShellIntegration::DefaultProtocolClientWorker
* CreateShellWorker(
960 ShellIntegration::DefaultWebClientObserver
* observer
,
961 const std::string
& protocol
) OVERRIDE
{
963 // This will crash, but it shouldn't get this far with BlockState::BLOCK
967 virtual ExternalProtocolHandler::BlockState
GetBlockState(
968 const std::string
& scheme
) OVERRIDE
{
969 // Block everything and fail the test.
971 return ExternalProtocolHandler::BLOCK
;
973 virtual void BlockRequest() OVERRIDE
{ }
974 virtual void RunExternalProtocolDialog(const GURL
& url
,
975 int render_process_host_id
,
976 int routing_id
) OVERRIDE
{
979 virtual void LaunchUrlWithoutSecurityCheck(const GURL
& url
) OVERRIDE
{
982 virtual void FinishedProcessingCheck() OVERRIDE
{
987 base::FilePath
GetTestPath(const std::string
& file_name
) {
988 return ui_test_utils::GetTestFilePath(
989 base::FilePath(FILE_PATH_LITERAL("prerender")),
990 base::FilePath().AppendASCII(file_name
));
995 // Many of these tests are flaky. See http://crbug.com/249179
996 class PrerenderBrowserTest
: virtual public InProcessBrowserTest
{
998 PrerenderBrowserTest()
999 : autostart_test_server_(true),
1000 prerender_contents_factory_(NULL
),
1001 #if defined(FULL_SAFE_BROWSING)
1002 safe_browsing_factory_(new TestSafeBrowsingServiceFactory()),
1004 call_javascript_(true),
1005 check_load_events_(true),
1006 loader_path_("files/prerender/prerender_loader.html"),
1007 explicitly_set_browser_(NULL
) {}
1009 virtual ~PrerenderBrowserTest() {}
1011 content::SessionStorageNamespace
* GetSessionStorageNamespace() const {
1012 WebContents
* web_contents
= GetActiveWebContents();
1015 return web_contents
->GetController().GetDefaultSessionStorageNamespace();
1018 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE
{
1019 #if defined(FULL_SAFE_BROWSING)
1020 SafeBrowsingService::RegisterFactory(safe_browsing_factory_
.get());
1024 virtual void TearDownInProcessBrowserTestFixture() OVERRIDE
{
1025 #if defined(FULL_SAFE_BROWSING)
1026 SafeBrowsingService::RegisterFactory(NULL
);
1030 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
1031 command_line
->AppendSwitchASCII(switches::kPrerenderMode
,
1032 switches::kPrerenderModeSwitchValueEnabled
);
1033 #if defined(OS_MACOSX)
1034 // The plugins directory isn't read by default on the Mac, so it needs to be
1035 // explicitly registered.
1036 base::FilePath app_dir
;
1037 PathService::Get(chrome::DIR_APP
, &app_dir
);
1038 command_line
->AppendSwitchPath(
1039 switches::kExtraPluginDir
,
1040 app_dir
.Append(FILE_PATH_LITERAL("plugins")));
1042 command_line
->AppendSwitch(switches::kAlwaysAuthorizePlugins
);
1045 virtual void SetUpOnMainThread() OVERRIDE
{
1046 current_browser()->profile()->GetPrefs()->SetBoolean(
1047 prefs::kPromptForDownload
, false);
1048 IncreasePrerenderMemory();
1049 if (autostart_test_server_
)
1050 ASSERT_TRUE(test_server()->Start());
1051 ChromeResourceDispatcherHostDelegate::
1052 SetExternalProtocolHandlerDelegateForTesting(
1053 &external_protocol_handler_delegate_
);
1055 PrerenderManager
* prerender_manager
= GetPrerenderManager();
1056 ASSERT_TRUE(prerender_manager
);
1057 prerender_manager
->mutable_config().rate_limit_enabled
= false;
1058 ASSERT_TRUE(prerender_contents_factory_
== NULL
);
1059 prerender_contents_factory_
= new TestPrerenderContentsFactory
;
1060 prerender_manager
->SetPrerenderContentsFactory(prerender_contents_factory_
);
1063 // Convenience function to get the currently active WebContents in
1064 // current_browser().
1065 WebContents
* GetActiveWebContents() const {
1066 return current_browser()->tab_strip_model()->GetActiveWebContents();
1069 // Overload for a single expected final status
1070 scoped_ptr
<TestPrerender
> PrerenderTestURL(
1071 const std::string
& html_file
,
1072 FinalStatus expected_final_status
,
1073 int expected_number_of_loads
) {
1074 GURL url
= test_server()->GetURL(html_file
);
1075 return PrerenderTestURL(url
,
1076 expected_final_status
,
1077 expected_number_of_loads
);
1080 ScopedVector
<TestPrerender
> PrerenderTestURL(
1081 const std::string
& html_file
,
1082 const std::vector
<FinalStatus
>& expected_final_status_queue
,
1083 int expected_number_of_loads
) {
1084 GURL url
= test_server()->GetURL(html_file
);
1085 return PrerenderTestURLImpl(url
,
1086 expected_final_status_queue
,
1087 expected_number_of_loads
);
1090 scoped_ptr
<TestPrerender
> PrerenderTestURL(
1092 FinalStatus expected_final_status
,
1093 int expected_number_of_loads
) {
1094 std::vector
<FinalStatus
> expected_final_status_queue(
1095 1, expected_final_status
);
1096 std::vector
<TestPrerender
*> prerenders
;
1097 PrerenderTestURLImpl(url
,
1098 expected_final_status_queue
,
1099 expected_number_of_loads
).release(&prerenders
);
1100 CHECK_EQ(1u, prerenders
.size());
1101 return scoped_ptr
<TestPrerender
>(prerenders
[0]);
1104 void NavigateToDestURL() const {
1105 NavigateToDestURLWithDisposition(CURRENT_TAB
, true);
1108 // Opens the url in a new tab, with no opener.
1109 void NavigateToDestURLWithDisposition(
1110 WindowOpenDisposition disposition
,
1111 bool expect_swap_to_succeed
) const {
1112 NavigateToURLWithParams(
1113 content::OpenURLParams(dest_url_
, Referrer(), disposition
,
1114 content::PAGE_TRANSITION_TYPED
, false),
1115 expect_swap_to_succeed
);
1118 void NavigateToURL(const std::string
& dest_html_file
) const {
1119 NavigateToURLWithDisposition(dest_html_file
, CURRENT_TAB
, true);
1122 void NavigateToURLWithDisposition(const std::string
& dest_html_file
,
1123 WindowOpenDisposition disposition
,
1124 bool expect_swap_to_succeed
) const {
1125 GURL dest_url
= test_server()->GetURL(dest_html_file
);
1126 NavigateToURLWithDisposition(dest_url
, disposition
, expect_swap_to_succeed
);
1129 void NavigateToURLWithDisposition(const GURL
& dest_url
,
1130 WindowOpenDisposition disposition
,
1131 bool expect_swap_to_succeed
) const {
1132 NavigateToURLWithParams(
1133 content::OpenURLParams(dest_url
, Referrer(), disposition
,
1134 content::PAGE_TRANSITION_TYPED
, false),
1135 expect_swap_to_succeed
);
1138 void NavigateToURLWithParams(const content::OpenURLParams
& params
,
1139 bool expect_swap_to_succeed
) const {
1140 NavigateToURLImpl(params
, expect_swap_to_succeed
);
1143 void OpenDestURLViaClick() const {
1144 OpenURLViaClick(dest_url_
);
1147 void OpenURLViaClick(const GURL
& url
) const {
1148 OpenURLWithJSImpl("Click", url
, GURL(), false);
1151 void OpenDestURLViaClickTarget() const {
1152 OpenURLWithJSImpl("ClickTarget", dest_url_
, GURL(), true);
1155 void OpenDestURLViaClickPing(const GURL
& ping_url
) const {
1156 OpenURLWithJSImpl("ClickPing", dest_url_
, ping_url
, false);
1159 void OpenDestURLViaClickNewWindow() const {
1160 OpenURLWithJSImpl("ShiftClick", dest_url_
, GURL(), true);
1163 void OpenDestURLViaClickNewForegroundTab() const {
1164 #if defined(OS_MACOSX)
1165 OpenURLWithJSImpl("MetaShiftClick", dest_url_
, GURL(), true);
1167 OpenURLWithJSImpl("CtrlShiftClick", dest_url_
, GURL(), true);
1171 void OpenDestURLViaClickNewBackgroundTab() const {
1172 #if defined(OS_MACOSX)
1173 OpenURLWithJSImpl("MetaClick", dest_url_
, GURL(), true);
1175 OpenURLWithJSImpl("CtrlClick", dest_url_
, GURL(), true);
1179 void OpenDestURLViaWindowOpen() const {
1180 OpenURLWithJSImpl("WindowOpen", dest_url_
, GURL(), true);
1183 void RemoveLinkElement(int i
) const {
1184 GetActiveWebContents()->GetRenderViewHost()->ExecuteJavascriptInWebFrame(
1186 base::ASCIIToUTF16(base::StringPrintf("RemoveLinkElement(%d)", i
)));
1189 void ClickToNextPageAfterPrerender() {
1190 TestNavigationObserver
nav_observer(GetActiveWebContents());
1191 RenderViewHost
* render_view_host
=
1192 GetActiveWebContents()->GetRenderViewHost();
1193 render_view_host
->ExecuteJavascriptInWebFrame(
1195 base::ASCIIToUTF16("ClickOpenLink()"));
1196 nav_observer
.Wait();
1199 void NavigateToNextPageAfterPrerender() const {
1200 ui_test_utils::NavigateToURL(
1202 test_server()->GetURL("files/prerender/prerender_page.html"));
1205 // Called after the prerendered page has been navigated to and then away from.
1206 // Navigates back through the history to the prerendered page.
1207 void GoBackToPrerender() {
1208 TestNavigationObserver
back_nav_observer(GetActiveWebContents());
1209 chrome::GoBack(current_browser(), CURRENT_TAB
);
1210 back_nav_observer
.Wait();
1211 bool original_prerender_page
= false;
1212 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
1213 GetActiveWebContents(),
1214 "window.domAutomationController.send(IsOriginalPrerenderPage())",
1215 &original_prerender_page
));
1216 EXPECT_TRUE(original_prerender_page
);
1219 // Goes back to the page that was active before the prerender was swapped
1220 // in. This must be called when the prerendered page is the current page
1221 // in the active tab.
1222 void GoBackToPageBeforePrerender() {
1223 WebContents
* tab
= GetActiveWebContents();
1225 EXPECT_FALSE(tab
->IsLoading());
1226 TestNavigationObserver
back_nav_observer(tab
);
1227 chrome::GoBack(current_browser(), CURRENT_TAB
);
1228 back_nav_observer
.Wait();
1230 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
1232 "window.domAutomationController.send(DidBackToOriginalPagePass())",
1234 EXPECT_TRUE(js_result
);
1237 bool UrlIsInPrerenderManager(const std::string
& html_file
) const {
1238 return UrlIsInPrerenderManager(test_server()->GetURL(html_file
));
1241 bool UrlIsInPrerenderManager(const GURL
& url
) const {
1242 return GetPrerenderManager()->FindPrerenderData(
1243 url
, GetSessionStorageNamespace()) != NULL
;
1246 void UseHttpsSrcServer() {
1247 if (https_src_server_
)
1249 https_src_server_
.reset(
1250 new net::SpawnedTestServer(
1251 net::SpawnedTestServer::TYPE_HTTPS
,
1252 net::SpawnedTestServer::kLocalhost
,
1253 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))));
1254 CHECK(https_src_server_
->Start());
1257 void DisableJavascriptCalls() {
1258 call_javascript_
= false;
1261 void DisableLoadEventCheck() {
1262 check_load_events_
= false;
1265 TaskManagerModel
* GetModel() const {
1266 return TaskManager::GetInstance()->model();
1269 PrerenderManager
* GetPrerenderManager() const {
1270 PrerenderManager
* prerender_manager
=
1271 PrerenderManagerFactory::GetForProfile(current_browser()->profile());
1272 return prerender_manager
;
1275 const PrerenderLinkManager
* GetPrerenderLinkManager() const {
1276 PrerenderLinkManager
* prerender_link_manager
=
1277 PrerenderLinkManagerFactory::GetForProfile(
1278 current_browser()->profile());
1279 return prerender_link_manager
;
1282 int GetPrerenderEventCount(int index
, const std::string
& type
) const {
1284 std::string expression
= base::StringPrintf(
1285 "window.domAutomationController.send("
1286 " GetPrerenderEventCount(%d, '%s'))", index
, type
.c_str());
1288 CHECK(content::ExecuteScriptAndExtractInt(
1289 GetActiveWebContents(), expression
, &event_count
));
1293 bool DidReceivePrerenderStartEventForLinkNumber(int index
) const {
1294 return GetPrerenderEventCount(index
, "webkitprerenderstart") > 0;
1297 int GetPrerenderLoadEventCountForLinkNumber(int index
) const {
1298 return GetPrerenderEventCount(index
, "webkitprerenderload");
1301 int GetPrerenderDomContentLoadedEventCountForLinkNumber(int index
) const {
1302 return GetPrerenderEventCount(index
, "webkitprerenderdomcontentloaded");
1305 bool DidReceivePrerenderStopEventForLinkNumber(int index
) const {
1306 return GetPrerenderEventCount(index
, "webkitprerenderstop") > 0;
1309 void WaitForPrerenderEventCount(int index
,
1310 const std::string
& type
,
1313 std::string expression
= base::StringPrintf(
1314 "WaitForPrerenderEventCount(%d, '%s', %d,"
1315 " window.domAutomationController.send.bind("
1316 " window.domAutomationController, 0))",
1317 index
, type
.c_str(), count
);
1319 CHECK(content::ExecuteScriptAndExtractInt(
1320 GetActiveWebContents(), expression
, &dummy
));
1324 bool HadPrerenderEventErrors() const {
1325 bool had_prerender_event_errors
;
1326 CHECK(content::ExecuteScriptAndExtractBool(
1327 GetActiveWebContents(),
1328 "window.domAutomationController.send(Boolean("
1329 " hadPrerenderEventErrors))",
1330 &had_prerender_event_errors
));
1331 return had_prerender_event_errors
;
1334 // Asserting on this can result in flaky tests. PrerenderHandles are
1335 // removed from the PrerenderLinkManager when the prerender is canceled from
1336 // the browser, when the prerenders are cancelled from the renderer process,
1337 // or the channel for the renderer process is closed on the IO thread. In the
1338 // last case, the code must be careful to wait for the channel to close, as it
1339 // is done asynchronously after swapping out the old process. See
1340 // ChannelDestructionWatcher.
1341 bool IsEmptyPrerenderLinkManager() const {
1342 return GetPrerenderLinkManager()->IsEmpty();
1345 size_t GetLinkPrerenderCount() const {
1346 return GetPrerenderLinkManager()->prerenders_
.size();
1349 size_t GetRunningLinkPrerenderCount() const {
1350 return GetPrerenderLinkManager()->CountRunningPrerenders();
1353 // Returns length of |prerender_manager_|'s history, or -1 on failure.
1354 int GetHistoryLength() const {
1355 scoped_ptr
<base::DictionaryValue
> prerender_dict(
1356 static_cast<base::DictionaryValue
*>(
1357 GetPrerenderManager()->GetAsValue()));
1358 if (!prerender_dict
.get())
1360 base::ListValue
* history_list
;
1361 if (!prerender_dict
->GetList("history", &history_list
))
1363 return static_cast<int>(history_list
->GetSize());
1366 #if defined(FULL_SAFE_BROWSING)
1367 FakeSafeBrowsingDatabaseManager
* GetFakeSafeBrowsingDatabaseManager() {
1368 return safe_browsing_factory_
->most_recent_service()->
1369 fake_database_manager();
1373 TestPrerenderContents
* GetPrerenderContentsFor(const GURL
& url
) const {
1374 PrerenderManager::PrerenderData
* prerender_data
=
1375 GetPrerenderManager()->FindPrerenderData(url
, NULL
);
1376 return static_cast<TestPrerenderContents
*>(
1377 prerender_data
? prerender_data
->contents() : NULL
);
1380 void SetLoaderHostOverride(const std::string
& host
) {
1381 loader_host_override_
= host
;
1382 host_resolver()->AddRule(host
, "127.0.0.1");
1385 void set_loader_path(const std::string
& path
) {
1386 loader_path_
= path
;
1389 void set_loader_query_and_fragment(const std::string
& query_and_fragment
) {
1390 loader_query_and_fragment_
= query_and_fragment
;
1393 GURL
GetCrossDomainTestUrl(const std::string
& path
) {
1394 static const std::string secondary_domain
= "www.foo.com";
1395 host_resolver()->AddRule(secondary_domain
, "127.0.0.1");
1396 std::string
url_str(base::StringPrintf(
1398 secondary_domain
.c_str(),
1399 test_server()->host_port_pair().port(),
1401 return GURL(url_str
);
1404 void set_browser(Browser
* browser
) {
1405 explicitly_set_browser_
= browser
;
1408 Browser
* current_browser() const {
1409 return explicitly_set_browser_
? explicitly_set_browser_
: browser();
1412 const GURL
& dest_url() const {
1416 void IncreasePrerenderMemory() {
1417 // Increase the memory allowed in a prerendered page above normal settings.
1418 // Debug build bots occasionally run against the default limit, and tests
1419 // were failing because the prerender was canceled due to memory exhaustion.
1420 // http://crbug.com/93076
1421 GetPrerenderManager()->mutable_config().max_bytes
= 1000 * 1024 * 1024;
1424 bool DidPrerenderPass(WebContents
* web_contents
) const {
1425 bool prerender_test_result
= false;
1426 if (!content::ExecuteScriptAndExtractBool(
1428 "window.domAutomationController.send(DidPrerenderPass())",
1429 &prerender_test_result
))
1431 return prerender_test_result
;
1434 bool DidDisplayPass(WebContents
* web_contents
) const {
1435 bool display_test_result
= false;
1436 if (!content::ExecuteScriptAndExtractBool(
1438 "window.domAutomationController.send(DidDisplayPass())",
1439 &display_test_result
))
1441 return display_test_result
;
1444 scoped_ptr
<TestPrerender
> ExpectPrerender(FinalStatus expected_final_status
) {
1445 return prerender_contents_factory_
->ExpectPrerenderContents(
1446 expected_final_status
);
1449 void AddPrerender(const GURL
& url
, int index
) {
1450 std::string javascript
= base::StringPrintf(
1451 "AddPrerender('%s', %d)", url
.spec().c_str(), index
);
1452 RenderViewHost
* render_view_host
=
1453 GetActiveWebContents()->GetRenderViewHost();
1454 render_view_host
->ExecuteJavascriptInWebFrame(
1455 base::string16(), base::ASCIIToUTF16(javascript
));
1459 bool autostart_test_server_
;
1462 // TODO(davidben): Remove this altogether so the tests don't globally assume
1463 // only one prerender.
1464 TestPrerenderContents
* GetPrerenderContents() const {
1465 return GetPrerenderContentsFor(dest_url_
);
1468 ScopedVector
<TestPrerender
> PrerenderTestURLImpl(
1469 const GURL
& prerender_url
,
1470 const std::vector
<FinalStatus
>& expected_final_status_queue
,
1471 int expected_number_of_loads
) {
1472 dest_url_
= prerender_url
;
1474 std::vector
<net::SpawnedTestServer::StringPair
> replacement_text
;
1475 replacement_text
.push_back(
1476 make_pair("REPLACE_WITH_PRERENDER_URL", prerender_url
.spec()));
1477 std::string replacement_path
;
1478 CHECK(net::SpawnedTestServer::GetFilePathWithReplacements(
1481 &replacement_path
));
1483 const net::SpawnedTestServer
* src_server
= test_server();
1484 if (https_src_server_
)
1485 src_server
= https_src_server_
.get();
1486 GURL loader_url
= src_server
->GetURL(replacement_path
+
1487 loader_query_and_fragment_
);
1489 GURL::Replacements loader_replacements
;
1490 if (!loader_host_override_
.empty())
1491 loader_replacements
.SetHostStr(loader_host_override_
);
1492 loader_url
= loader_url
.ReplaceComponents(loader_replacements
);
1494 VLOG(1) << "Running test with queue length " <<
1495 expected_final_status_queue
.size();
1496 CHECK(!expected_final_status_queue
.empty());
1497 ScopedVector
<TestPrerender
> prerenders
;
1498 for (size_t i
= 0; i
< expected_final_status_queue
.size(); i
++) {
1499 prerenders
.push_back(
1500 prerender_contents_factory_
->ExpectPrerenderContents(
1501 expected_final_status_queue
[i
]).release());
1504 FinalStatus expected_final_status
= expected_final_status_queue
.front();
1506 // Navigate to the loader URL and then wait for the first prerender to be
1508 ui_test_utils::NavigateToURL(current_browser(), loader_url
);
1509 prerenders
[0]->WaitForCreate();
1510 prerenders
[0]->WaitForLoads(expected_number_of_loads
);
1512 if (ShouldAbortPrerenderBeforeSwap(expected_final_status
)) {
1513 // The prerender will abort on its own. Assert it does so correctly.
1514 prerenders
[0]->WaitForStop();
1515 EXPECT_FALSE(prerenders
[0]->contents());
1516 EXPECT_TRUE(DidReceivePrerenderStopEventForLinkNumber(0));
1518 // Otherwise, check that it prerendered correctly.
1519 TestPrerenderContents
* prerender_contents
= prerenders
[0]->contents();
1521 CHECK_NE(static_cast<PrerenderContents
*>(NULL
), prerender_contents
);
1522 EXPECT_EQ(FINAL_STATUS_MAX
, prerender_contents
->final_status());
1523 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
1525 if (call_javascript_
) {
1526 // Check if page behaves as expected while in prerendered state.
1527 EXPECT_TRUE(DidPrerenderPass(prerender_contents
->prerender_contents()));
1531 // Test that the referring page received the right start and load events.
1532 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
1533 if (check_load_events_
) {
1534 EXPECT_EQ(expected_number_of_loads
, prerenders
[0]->number_of_loads());
1535 EXPECT_EQ(expected_number_of_loads
,
1536 GetPrerenderLoadEventCountForLinkNumber(0));
1538 EXPECT_FALSE(HadPrerenderEventErrors());
1540 return prerenders
.Pass();
1543 void NavigateToURLImpl(const content::OpenURLParams
& params
,
1544 bool expect_swap_to_succeed
) const {
1545 ASSERT_NE(static_cast<PrerenderManager
*>(NULL
), GetPrerenderManager());
1546 // Make sure in navigating we have a URL to use in the PrerenderManager.
1547 ASSERT_NE(static_cast<PrerenderContents
*>(NULL
), GetPrerenderContents());
1549 WebContents
* web_contents
= GetPrerenderContents()->prerender_contents();
1551 // Navigate and wait for either the load to finish normally or for a swap to
1553 // TODO(davidben): The only handles CURRENT_TAB navigations, which is the
1554 // only case tested or prerendered right now.
1555 CHECK_EQ(CURRENT_TAB
, params
.disposition
);
1556 NavigationOrSwapObserver
swap_observer(current_browser()->tab_strip_model(),
1557 GetActiveWebContents());
1558 WebContents
* target_web_contents
= current_browser()->OpenURL(params
);
1559 swap_observer
.Wait();
1561 if (web_contents
&& expect_swap_to_succeed
) {
1562 EXPECT_EQ(web_contents
, target_web_contents
);
1563 if (call_javascript_
)
1564 EXPECT_TRUE(DidDisplayPass(web_contents
));
1568 // Opens the prerendered page using javascript functions in the loader
1569 // page. |javascript_function_name| should be a 0 argument function which is
1570 // invoked. |new_web_contents| is true if the navigation is expected to
1571 // happen in a new WebContents via OpenURL.
1572 void OpenURLWithJSImpl(const std::string
& javascript_function_name
,
1574 const GURL
& ping_url
,
1575 bool new_web_contents
) const {
1576 WebContents
* web_contents
= GetActiveWebContents();
1577 RenderViewHost
* render_view_host
=
1578 GetActiveWebContents()->GetRenderViewHost();
1579 // Extra arguments in JS are ignored.
1580 std::string javascript
= base::StringPrintf(
1581 "%s('%s', '%s')", javascript_function_name
.c_str(),
1582 url
.spec().c_str(), ping_url
.spec().c_str());
1584 if (new_web_contents
) {
1585 NewTabNavigationOrSwapObserver observer
;
1586 render_view_host
->ExecuteJavascriptInWebFrame(
1587 base::string16(), base::ASCIIToUTF16(javascript
));
1590 NavigationOrSwapObserver
observer(current_browser()->tab_strip_model(),
1592 render_view_host
->ExecuteJavascriptInWebFrame(
1593 base::string16(), base::ASCIIToUTF16(javascript
));
1598 TestPrerenderContentsFactory
* prerender_contents_factory_
;
1599 #if defined(FULL_SAFE_BROWSING)
1600 scoped_ptr
<TestSafeBrowsingServiceFactory
> safe_browsing_factory_
;
1602 NeverRunsExternalProtocolHandlerDelegate external_protocol_handler_delegate_
;
1604 scoped_ptr
<net::SpawnedTestServer
> https_src_server_
;
1605 bool call_javascript_
;
1606 bool check_load_events_
;
1607 std::string loader_host_override_
;
1608 std::string loader_path_
;
1609 std::string loader_query_and_fragment_
;
1610 Browser
* explicitly_set_browser_
;
1613 // Checks that a page is correctly prerendered in the case of a
1614 // <link rel=prerender> tag and then loaded into a tab in response to a
1616 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderPage
) {
1617 UMAHistogramHelper histograms
;
1619 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED
, 1);
1620 EXPECT_EQ(1, GetPrerenderDomContentLoadedEventCountForLinkNumber(0));
1622 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLT", 1);
1623 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0);
1624 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLTMatchedComplete", 0);
1625 histograms
.ExpectTotalCount("Prerender.websame_PrerenderNotSwappedInPLT", 1);
1627 ChannelDestructionWatcher channel_close_watcher
;
1628 channel_close_watcher
.WatchChannel(
1629 GetActiveWebContents()->GetRenderProcessHost());
1630 NavigateToDestURL();
1631 channel_close_watcher
.WaitForChannelClose();
1634 histograms
.ExpectTotalCount("Prerender.websame_PerceivedPLT", 1);
1635 histograms
.ExpectTotalCount("Prerender.websame_PerceivedPLTMatched", 1);
1636 histograms
.ExpectTotalCount(
1637 "Prerender.websame_PerceivedPLTMatchedComplete", 1);
1639 ASSERT_TRUE(IsEmptyPrerenderLinkManager());
1642 // Checks that cross-domain prerenders emit the correct histograms.
1643 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderPageCrossDomain
) {
1644 UMAHistogramHelper histograms
;
1646 PrerenderTestURL(GetCrossDomainTestUrl("files/prerender/prerender_page.html"),
1647 FINAL_STATUS_USED
, 1);
1649 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLT", 1);
1650 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0);
1651 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLTMatchedComplete", 0);
1652 histograms
.ExpectTotalCount("Prerender.webcross_PrerenderNotSwappedInPLT", 1);
1654 NavigateToDestURL();
1656 histograms
.ExpectTotalCount("Prerender.webcross_PerceivedPLT", 1);
1657 histograms
.ExpectTotalCount("Prerender.webcross_PerceivedPLTMatched", 1);
1658 histograms
.ExpectTotalCount(
1659 "Prerender.webcross_PerceivedPLTMatchedComplete", 1);
1662 // Checks that pending prerenders launch and receive proper event treatment.
1663 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderPagePending
) {
1664 scoped_ptr
<TestPrerender
> prerender
=
1665 PrerenderTestURL("files/prerender/prerender_page_pending.html",
1666 FINAL_STATUS_USED
, 1);
1668 // Navigate to the prerender.
1669 scoped_ptr
<TestPrerender
> prerender2
= ExpectPrerender(FINAL_STATUS_USED
);
1670 NavigateToDestURL();
1671 // Abort early if the original prerender didn't swap, so as not to hang.
1672 ASSERT_FALSE(prerender
->contents());
1674 // Wait for the new prerender to be ready.
1675 prerender2
->WaitForStart();
1676 prerender2
->WaitForLoads(1);
1678 const GURL prerender_page_url
=
1679 test_server()->GetURL("files/prerender/prerender_page.html");
1680 EXPECT_FALSE(IsEmptyPrerenderLinkManager());
1681 EXPECT_NE(static_cast<TestPrerenderContents
*>(NULL
),
1682 GetPrerenderContentsFor(prerender_page_url
));
1684 // Now navigate to our target page.
1685 NavigationOrSwapObserver
swap_observer(current_browser()->tab_strip_model(),
1686 GetActiveWebContents());
1687 ui_test_utils::NavigateToURLWithDisposition(
1688 current_browser(), prerender_page_url
, CURRENT_TAB
,
1689 ui_test_utils::BROWSER_TEST_NONE
);
1690 swap_observer
.Wait();
1692 EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1695 // Checks that pending prerenders which are canceled before they are launched
1696 // never get started.
1697 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderPageRemovesPending
) {
1698 PrerenderTestURL("files/prerender/prerender_page_removes_pending.html",
1699 FINAL_STATUS_USED
, 1);
1701 ChannelDestructionWatcher channel_close_watcher
;
1702 channel_close_watcher
.WatchChannel(
1703 GetActiveWebContents()->GetRenderProcessHost());
1704 NavigateToDestURL();
1705 channel_close_watcher
.WaitForChannelClose();
1707 EXPECT_FALSE(DidReceivePrerenderStartEventForLinkNumber(1));
1708 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
1709 EXPECT_FALSE(HadPrerenderEventErrors());
1710 // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive*
1711 // calls did a thread/process hop to the renderer which insured pending
1712 // renderer events have arrived.
1713 ASSERT_TRUE(IsEmptyPrerenderLinkManager());
1716 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderPageRemovingLink
) {
1717 scoped_ptr
<TestPrerender
> prerender
=
1718 PrerenderTestURL("files/prerender/prerender_page.html",
1719 FINAL_STATUS_CANCELLED
, 1);
1721 // No ChannelDestructionWatcher is needed here, since prerenders in the
1722 // PrerenderLinkManager should be deleted by removing the links, rather than
1723 // shutting down the renderer process.
1724 RemoveLinkElement(0);
1725 prerender
->WaitForStop();
1727 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
1728 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
1729 EXPECT_FALSE(HadPrerenderEventErrors());
1730 // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive*
1731 // calls did a thread/process hop to the renderer which insured pending
1732 // renderer events have arrived.
1733 EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1736 IN_PROC_BROWSER_TEST_F(
1737 PrerenderBrowserTest
, PrerenderPageRemovingLinkWithTwoLinks
) {
1738 GetPrerenderManager()->mutable_config().max_link_concurrency
= 2;
1739 GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher
= 2;
1741 set_loader_query_and_fragment("?links_to_insert=2");
1742 scoped_ptr
<TestPrerender
> prerender
=
1743 PrerenderTestURL("files/prerender/prerender_page.html",
1744 FINAL_STATUS_CANCELLED
, 1);
1745 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
1746 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
1747 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
1748 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
1750 RemoveLinkElement(0);
1751 RemoveLinkElement(1);
1752 prerender
->WaitForStop();
1754 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
1755 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
1756 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
1757 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
1758 EXPECT_FALSE(HadPrerenderEventErrors());
1759 // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive*
1760 // calls did a thread/process hop to the renderer which insured pending
1761 // renderer events have arrived.
1762 EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1765 IN_PROC_BROWSER_TEST_F(
1766 PrerenderBrowserTest
, PrerenderPageRemovingLinkWithTwoLinksOneLate
) {
1767 GetPrerenderManager()->mutable_config().max_link_concurrency
= 2;
1768 GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher
= 2;
1770 GURL url
= test_server()->GetURL("files/prerender/prerender_page.html");
1771 scoped_ptr
<TestPrerender
> prerender
=
1772 PrerenderTestURL(url
, FINAL_STATUS_CANCELLED
, 1);
1774 // Add a second prerender for the same link. It reuses the prerender, so only
1775 // the start event fires here.
1776 AddPrerender(url
, 1);
1777 WaitForPrerenderEventCount(1, "webkitprerenderstart", 1);
1778 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
1779 EXPECT_EQ(0, GetPrerenderLoadEventCountForLinkNumber(1));
1780 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
1782 RemoveLinkElement(0);
1783 RemoveLinkElement(1);
1784 prerender
->WaitForStop();
1786 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
1787 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
1788 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
1789 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
1790 EXPECT_FALSE(HadPrerenderEventErrors());
1791 // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive*
1792 // calls did a thread/process hop to the renderer which insured pending
1793 // renderer events have arrived.
1794 EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1797 IN_PROC_BROWSER_TEST_F(
1798 PrerenderBrowserTest
,
1799 PrerenderPageRemovingLinkWithTwoLinksRemovingOne
) {
1800 GetPrerenderManager()->mutable_config().max_link_concurrency
= 2;
1801 GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher
= 2;
1802 set_loader_query_and_fragment("?links_to_insert=2");
1803 PrerenderTestURL("files/prerender/prerender_page.html",
1804 FINAL_STATUS_USED
, 1);
1805 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
1806 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
1807 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
1808 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
1810 RemoveLinkElement(0);
1811 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
1812 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
1813 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
1814 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
1815 EXPECT_FALSE(HadPrerenderEventErrors());
1816 // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive*
1817 // calls did a thread/process hop to the renderer which insured pending
1818 // renderer events have arrived.
1819 EXPECT_FALSE(IsEmptyPrerenderLinkManager());
1821 ChannelDestructionWatcher channel_close_watcher
;
1822 channel_close_watcher
.WatchChannel(
1823 GetActiveWebContents()->GetRenderProcessHost());
1824 NavigateToDestURL();
1825 channel_close_watcher
.WaitForChannelClose();
1827 EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1830 // Checks that the visibility API works.
1831 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderVisibility
) {
1832 PrerenderTestURL("files/prerender/prerender_visibility.html",
1835 NavigateToDestURL();
1838 // Checks that the prerendering of a page is canceled correctly if we try to
1839 // swap it in before it commits.
1840 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderNoCommitNoSwap
) {
1841 // Navigate to a page that triggers a prerender for a URL that never commits.
1842 const GURL
kNoCommitUrl("http://never-respond.example.com");
1843 base::FilePath
file(GetTestPath("prerender_page.html"));
1845 base::RunLoop prerender_start_loop
;
1846 BrowserThread::PostTask(
1847 BrowserThread::IO
, FROM_HERE
,
1848 base::Bind(&CreateHangingFirstRequestProtocolHandlerOnIO
,
1849 kNoCommitUrl
, file
, prerender_start_loop
.QuitClosure()));
1850 DisableJavascriptCalls();
1851 PrerenderTestURL(kNoCommitUrl
,
1852 FINAL_STATUS_NAVIGATION_UNCOMMITTED
,
1854 // Wait for the hanging request to be scheduled.
1855 prerender_start_loop
.Run();
1857 // Navigate to the URL, but assume the contents won't be swapped in.
1858 NavigateToDestURLWithDisposition(CURRENT_TAB
, false);
1861 // Checks that client redirects don't add alias URLs until after they commit.
1862 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderNoCommitNoSwap2
) {
1863 // Navigate to a page that then navigates to a URL that never commits.
1864 const GURL
kNoCommitUrl("http://never-respond.example.com");
1865 base::FilePath
file(GetTestPath("prerender_page.html"));
1867 base::RunLoop prerender_start_loop
;
1868 BrowserThread::PostTask(
1869 BrowserThread::IO
, FROM_HERE
,
1870 base::Bind(&CreateHangingFirstRequestProtocolHandlerOnIO
,
1871 kNoCommitUrl
, file
, prerender_start_loop
.QuitClosure()));
1872 DisableJavascriptCalls();
1873 PrerenderTestURL(CreateClientRedirect(kNoCommitUrl
.spec()),
1874 FINAL_STATUS_APP_TERMINATING
, 1);
1875 // Wait for the hanging request to be scheduled.
1876 prerender_start_loop
.Run();
1878 // Navigating to the second URL should not swap.
1879 NavigateToURLWithDisposition(kNoCommitUrl
, CURRENT_TAB
, false);
1882 // Checks that the prerendering of a page is canceled correctly when a
1883 // Javascript alert is called.
1884 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderAlertBeforeOnload
) {
1885 PrerenderTestURL("files/prerender/prerender_alert_before_onload.html",
1886 FINAL_STATUS_JAVASCRIPT_ALERT
,
1890 // Checks that the prerendering of a page is canceled correctly when a
1891 // Javascript alert is called.
1892 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderAlertAfterOnload
) {
1893 PrerenderTestURL("files/prerender/prerender_alert_after_onload.html",
1894 FINAL_STATUS_JAVASCRIPT_ALERT
,
1898 // Checks that plugins are not loaded while a page is being preloaded, but
1899 // are loaded when the page is displayed.
1900 #if defined(USE_AURA) && !defined(OS_WIN)
1901 // http://crbug.com/103496
1902 #define MAYBE_PrerenderDelayLoadPlugin DISABLED_PrerenderDelayLoadPlugin
1903 #elif defined(OS_MACOSX)
1904 // http://crbug.com/100514
1905 #define MAYBE_PrerenderDelayLoadPlugin DISABLED_PrerenderDelayLoadPlugin
1906 #elif defined(OS_WIN) && defined(ARCH_CPU_X86_64)
1907 // TODO(jschuh): Failing plugin tests. crbug.com/244653
1908 #define MAYBE_PrerenderDelayLoadPlugin DISABLED_PrerenderDelayLoadPlugin
1909 #elif defined(OS_LINUX)
1910 // http://crbug.com/306715
1911 #define MAYBE_PrerenderDelayLoadPlugin DISABLED_PrerenderDelayLoadPlugin
1913 #define MAYBE_PrerenderDelayLoadPlugin PrerenderDelayLoadPlugin
1915 // http://crbug.com/306715
1916 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, MAYBE_PrerenderDelayLoadPlugin
) {
1917 PrerenderTestURL("files/prerender/plugin_delay_load.html",
1920 NavigateToDestURL();
1923 // Checks that plugins are not loaded on prerendering pages when click-to-play
1925 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderClickToPlay
) {
1926 // Enable click-to-play.
1927 HostContentSettingsMap
* content_settings_map
=
1928 current_browser()->profile()->GetHostContentSettingsMap();
1929 content_settings_map
->SetDefaultContentSetting(
1930 CONTENT_SETTINGS_TYPE_PLUGINS
, CONTENT_SETTING_ASK
);
1932 PrerenderTestURL("files/prerender/prerender_plugin_click_to_play.html",
1935 NavigateToDestURL();
1938 // Checks that we don't load a NaCl plugin when NaCl is disabled.
1939 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderNaClPluginDisabled
) {
1940 PrerenderTestURL("files/prerender/prerender_plugin_nacl_disabled.html",
1943 NavigateToDestURL();
1946 // Run this check again. When we try to load aa ppapi plugin, the
1947 // "loadstart" event is asynchronously posted to a message loop.
1948 // It's possible that earlier call could have been run before the
1949 // the "loadstart" event was posted.
1950 // TODO(mmenke): While this should reliably fail on regressions, the
1951 // reliability depends on the specifics of ppapi plugin
1952 // loading. It would be great if we could avoid that.
1953 EXPECT_TRUE(DidDisplayPass(GetActiveWebContents()));
1956 // Checks that plugins in an iframe are not loaded while a page is
1957 // being preloaded, but are loaded when the page is displayed.
1958 #if defined(USE_AURA) && !defined(OS_WIN)
1959 // http://crbug.com/103496
1960 #define MAYBE_PrerenderIframeDelayLoadPlugin \
1961 DISABLED_PrerenderIframeDelayLoadPlugin
1962 #elif defined(OS_MACOSX)
1963 // http://crbug.com/100514
1964 #define MAYBE_PrerenderIframeDelayLoadPlugin \
1965 DISABLED_PrerenderIframeDelayLoadPlugin
1966 #elif defined(OS_WIN) && defined(ARCH_CPU_X86_64)
1967 // TODO(jschuh): Failing plugin tests. crbug.com/244653
1968 #define MAYBE_PrerenderIframeDelayLoadPlugin \
1969 DISABLED_PrerenderIframeDelayLoadPlugin
1971 #define MAYBE_PrerenderIframeDelayLoadPlugin PrerenderIframeDelayLoadPlugin
1973 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
1974 MAYBE_PrerenderIframeDelayLoadPlugin
) {
1975 PrerenderTestURL("files/prerender/prerender_iframe_plugin_delay_load.html",
1978 NavigateToDestURL();
1981 // Renders a page that contains a prerender link to a page that contains an
1982 // iframe with a source that requires http authentication. This should not
1983 // prerender successfully.
1984 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderHttpAuthentication
) {
1985 PrerenderTestURL("files/prerender/prerender_http_auth_container.html",
1986 FINAL_STATUS_AUTH_NEEDED
,
1990 // Checks that client-issued redirects work with prerendering.
1991 // This version navigates to the page which issues the redirection, rather
1992 // than the final destination page.
1993 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
1994 PrerenderClientRedirectNavigateToFirst
) {
1995 PrerenderTestURL(CreateClientRedirect("files/prerender/prerender_page.html"),
1998 NavigateToDestURL();
2001 // Checks that client-issued redirects work with prerendering.
2002 // This version navigates to the final destination page, rather than the
2003 // page which does the redirection.
2004 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2005 PrerenderClientRedirectNavigateToSecond
) {
2006 PrerenderTestURL(CreateClientRedirect("files/prerender/prerender_page.html"),
2009 NavigateToURL("files/prerender/prerender_page.html");
2012 // Checks that redirects with location.replace do not cancel a prerender and
2013 // and swap when navigating to the first page.
2014 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2015 PrerenderLocationReplaceNavigateToFirst
) {
2016 PrerenderTestURL("files/prerender/prerender_location_replace.html",
2019 NavigateToDestURL();
2022 // Checks that redirects with location.replace do not cancel a prerender and
2023 // and swap when navigating to the second.
2024 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2025 PrerenderLocationReplaceNavigateToSecond
) {
2026 PrerenderTestURL("files/prerender/prerender_location_replace.html",
2029 NavigateToURL("files/prerender/prerender_page.html");
2032 // Checks that we get the right PPLT histograms for client redirect prerenders
2033 // and navigations when the referring page is Google.
2034 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2035 PrerenderLocationReplaceGWSHistograms
) {
2036 DisableJavascriptCalls();
2037 UMAHistogramHelper histograms
;
2039 // The loader page should look like Google.
2040 const std::string
kGoogleDotCom("www.google.com");
2041 SetLoaderHostOverride(kGoogleDotCom
);
2042 set_loader_path("files/prerender/prerender_loader_with_replace_state.html");
2044 GURL dest_url
= GetCrossDomainTestUrl(
2045 "files/prerender/prerender_deferred_image.html");
2047 GURL prerender_url
= test_server()->GetURL(
2048 "files/prerender/prerender_location_replace.html?" +
2049 net::EscapeQueryParamValue(dest_url
.spec(), false) +
2051 GURL::Replacements replacements
;
2052 replacements
.SetHostStr(kGoogleDotCom
);
2053 prerender_url
= prerender_url
.ReplaceComponents(replacements
);
2055 // The prerender will not completely load until after the swap, so wait for a
2056 // title change before calling DidPrerenderPass.
2057 scoped_ptr
<TestPrerender
> prerender
=
2058 PrerenderTestURL(prerender_url
, FINAL_STATUS_USED
, 1);
2059 WaitForASCIITitle(prerender
->contents()->prerender_contents(), kReadyTitle
);
2060 EXPECT_TRUE(DidPrerenderPass(prerender
->contents()->prerender_contents()));
2061 EXPECT_EQ(1, prerender
->number_of_loads());
2064 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLT", 1);
2065 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0);
2066 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLTMatchedComplete", 0);
2067 // Although there is a client redirect, it is dropped from histograms because
2068 // it is a Google URL. The target page itself does not load until after the
2070 histograms
.ExpectTotalCount("Prerender.gws_PrerenderNotSwappedInPLT", 0);
2072 GURL navigate_url
= test_server()->GetURL(
2073 "files/prerender/prerender_location_replace.html?" +
2074 net::EscapeQueryParamValue(dest_url
.spec(), false) +
2076 navigate_url
= navigate_url
.ReplaceComponents(replacements
);
2078 NavigationOrSwapObserver
swap_observer(
2079 current_browser()->tab_strip_model(),
2080 GetActiveWebContents(), 2);
2081 current_browser()->OpenURL(OpenURLParams(
2082 navigate_url
, Referrer(), CURRENT_TAB
,
2083 content::PAGE_TRANSITION_TYPED
, false));
2084 swap_observer
.Wait();
2086 EXPECT_TRUE(DidDisplayPass(GetActiveWebContents()));
2089 histograms
.ExpectTotalCount("Prerender.gws_PrerenderNotSwappedInPLT", 0);
2090 histograms
.ExpectTotalCount("Prerender.gws_PerceivedPLT", 1);
2091 histograms
.ExpectTotalCount("Prerender.gws_PerceivedPLTMatched", 1);
2092 histograms
.ExpectTotalCount(
2093 "Prerender.gws_PerceivedPLTMatchedComplete", 1);
2095 // The client redirect does /not/ count as a miss because it's a Google URL.
2096 histograms
.ExpectTotalCount("Prerender.PerceivedPLTFirstAfterMiss", 0);
2099 // Checks that client-issued redirects work with prerendering.
2100 // This version navigates to the final destination page, rather than the
2101 // page which does the redirection via a mouse click.
2102 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2103 PrerenderClientRedirectNavigateToSecondViaClick
) {
2104 GURL prerender_url
= test_server()->GetURL(
2105 CreateClientRedirect("files/prerender/prerender_page.html"));
2106 GURL destination_url
= test_server()->GetURL(
2107 "files/prerender/prerender_page.html");
2108 PrerenderTestURL(prerender_url
, FINAL_STATUS_USED
, 2);
2109 OpenURLViaClick(destination_url
);
2112 // Checks that a page served over HTTPS is correctly prerendered.
2113 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderHttps
) {
2114 net::SpawnedTestServer
https_server(
2115 net::SpawnedTestServer::TYPE_HTTPS
, net::SpawnedTestServer::kLocalhost
,
2116 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2117 ASSERT_TRUE(https_server
.Start());
2118 GURL https_url
= https_server
.GetURL("files/prerender/prerender_page.html");
2119 PrerenderTestURL(https_url
,
2122 NavigateToDestURL();
2125 // Checks that client-issued redirects within an iframe in a prerendered
2126 // page will not count as an "alias" for the prerendered page.
2127 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2128 PrerenderClientRedirectInIframe
) {
2129 std::string redirect_path
= CreateClientRedirect(
2130 "/files/prerender/prerender_embedded_content.html");
2131 std::vector
<net::SpawnedTestServer::StringPair
> replacement_text
;
2132 replacement_text
.push_back(
2133 std::make_pair("REPLACE_WITH_URL", "/" + redirect_path
));
2134 std::string replacement_path
;
2135 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
2136 "files/prerender/prerender_with_iframe.html",
2138 &replacement_path
));
2139 PrerenderTestURL(replacement_path
, FINAL_STATUS_USED
, 2);
2140 EXPECT_FALSE(UrlIsInPrerenderManager(
2141 "files/prerender/prerender_embedded_content.html"));
2142 NavigateToDestURL();
2145 // Checks that server-issued redirects work with prerendering.
2146 // This version navigates to the page which issues the redirection, rather
2147 // than the final destination page.
2148 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2149 PrerenderServerRedirectNavigateToFirst
) {
2150 PrerenderTestURL(CreateServerRedirect("files/prerender/prerender_page.html"),
2153 NavigateToDestURL();
2156 // Checks that server-issued redirects work with prerendering.
2157 // This version navigates to the final destination page, rather than the
2158 // page which does the redirection.
2159 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2160 PrerenderServerRedirectNavigateToSecond
) {
2161 PrerenderTestURL(CreateServerRedirect("files/prerender/prerender_page.html"),
2164 NavigateToURL("files/prerender/prerender_page.html");
2167 // Checks that server-issued redirects work with prerendering.
2168 // This version navigates to the final destination page, rather than the
2169 // page which does the redirection via a mouse click.
2170 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2171 PrerenderServerRedirectNavigateToSecondViaClick
) {
2172 GURL prerender_url
= test_server()->GetURL(
2173 CreateServerRedirect("files/prerender/prerender_page.html"));
2174 GURL destination_url
= test_server()->GetURL(
2175 "files/prerender/prerender_page.html");
2176 PrerenderTestURL(prerender_url
, FINAL_STATUS_USED
, 1);
2177 OpenURLViaClick(destination_url
);
2180 // Checks that server-issued redirects within an iframe in a prerendered
2181 // page will not count as an "alias" for the prerendered page.
2182 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderServerRedirectInIframe
) {
2183 std::string redirect_path
= CreateServerRedirect(
2184 "/files/prerender/prerender_embedded_content.html");
2185 std::vector
<net::SpawnedTestServer::StringPair
> replacement_text
;
2186 replacement_text
.push_back(
2187 std::make_pair("REPLACE_WITH_URL", "/" + redirect_path
));
2188 std::string replacement_path
;
2189 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
2190 "files/prerender/prerender_with_iframe.html",
2192 &replacement_path
));
2193 PrerenderTestURL(replacement_path
, FINAL_STATUS_USED
, 1);
2194 EXPECT_FALSE(UrlIsInPrerenderManager(
2195 "files/prerender/prerender_embedded_content.html"));
2196 NavigateToDestURL();
2199 // Prerenders a page that contains an automatic download triggered through an
2200 // iframe. This should not prerender successfully.
2201 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderDownloadIframe
) {
2202 PrerenderTestURL("files/prerender/prerender_download_iframe.html",
2203 FINAL_STATUS_DOWNLOAD
,
2207 // Prerenders a page that contains an automatic download triggered through
2208 // Javascript changing the window.location. This should not prerender
2210 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderDownloadLocation
) {
2211 PrerenderTestURL(CreateClientRedirect("files/download-test1.lib"),
2212 FINAL_STATUS_DOWNLOAD
,
2216 // Prerenders a page that contains an automatic download triggered through a
2217 // client-issued redirect. This should not prerender successfully.
2218 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderDownloadClientRedirect
) {
2219 PrerenderTestURL("files/prerender/prerender_download_refresh.html",
2220 FINAL_STATUS_DOWNLOAD
,
2224 // Checks that the referrer is set when prerendering.
2225 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderReferrer
) {
2226 PrerenderTestURL("files/prerender/prerender_referrer.html",
2229 NavigateToDestURL();
2232 // Checks that the referrer is not set when prerendering and the source page is
2234 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2235 PrerenderNoSSLReferrer
) {
2236 UseHttpsSrcServer();
2237 PrerenderTestURL("files/prerender/prerender_no_referrer.html",
2240 NavigateToDestURL();
2243 // Checks that the referrer is set when prerendering is cancelled.
2244 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderCancelReferrer
) {
2245 scoped_ptr
<TestContentBrowserClient
> test_content_browser_client(
2246 new TestContentBrowserClient
);
2247 content::ContentBrowserClient
* original_browser_client
=
2248 content::SetBrowserClientForTesting(test_content_browser_client
.get());
2250 PrerenderTestURL("files/prerender/prerender_referrer.html",
2251 FINAL_STATUS_CANCELLED
,
2253 OpenDestURLViaClick();
2255 EXPECT_TRUE(DidDisplayPass(GetActiveWebContents()));
2257 content::SetBrowserClientForTesting(original_browser_client
);
2260 // Checks that popups on a prerendered page cause cancellation.
2261 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderPopup
) {
2262 PrerenderTestURL("files/prerender/prerender_popup.html",
2263 FINAL_STATUS_CREATE_NEW_WINDOW
,
2267 // Checks that registering a protocol handler causes cancellation.
2268 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderRegisterProtocolHandler
) {
2269 PrerenderTestURL("files/prerender/prerender_register_protocol_handler.html",
2270 FINAL_STATUS_REGISTER_PROTOCOL_HANDLER
,
2274 // Checks that renderers using excessive memory will be terminated.
2275 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderExcessiveMemory
) {
2276 ASSERT_TRUE(GetPrerenderManager());
2277 GetPrerenderManager()->mutable_config().max_bytes
= 30 * 1024 * 1024;
2278 // The excessive memory kill may happen before or after the load event as it
2279 // happens asynchronously with IPC calls. Even if the test does not start
2280 // allocating until after load, the browser process might notice before the
2281 // message gets through. This happens on XP debug bots because they're so
2282 // slow. Instead, don't bother checking the load event count.
2283 DisableLoadEventCheck();
2284 PrerenderTestURL("files/prerender/prerender_excessive_memory.html",
2285 FINAL_STATUS_MEMORY_LIMIT_EXCEEDED
, 0);
2288 // Checks shutdown code while a prerender is active.
2289 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderQuickQuit
) {
2290 DisableJavascriptCalls();
2291 DisableLoadEventCheck();
2292 PrerenderTestURL("files/prerender/prerender_page.html",
2293 FINAL_STATUS_APP_TERMINATING
,
2297 // Checks that we don't prerender in an infinite loop.
2298 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderInfiniteLoop
) {
2299 const char* const kHtmlFileA
= "files/prerender/prerender_infinite_a.html";
2300 const char* const kHtmlFileB
= "files/prerender/prerender_infinite_b.html";
2302 std::vector
<FinalStatus
> expected_final_status_queue
;
2303 expected_final_status_queue
.push_back(FINAL_STATUS_USED
);
2304 expected_final_status_queue
.push_back(FINAL_STATUS_APP_TERMINATING
);
2306 ScopedVector
<TestPrerender
> prerenders
=
2307 PrerenderTestURL(kHtmlFileA
, expected_final_status_queue
, 1);
2308 ASSERT_TRUE(prerenders
[0]->contents());
2309 // Assert that the pending prerender is in there already. This relies on the
2310 // fact that the renderer sends out the AddLinkRelPrerender IPC before sending
2311 // the page load one.
2312 EXPECT_EQ(2U, GetLinkPrerenderCount());
2313 EXPECT_EQ(1U, GetRunningLinkPrerenderCount());
2315 // Next url should be in pending list but not an active entry.
2316 EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileB
));
2318 NavigateToDestURL();
2320 // Make sure the PrerenderContents for the next url is now in the manager and
2321 // not pending. This relies on pending prerenders being resolved in the same
2322 // event loop iteration as OnPrerenderStop.
2323 EXPECT_TRUE(UrlIsInPrerenderManager(kHtmlFileB
));
2324 EXPECT_EQ(1U, GetLinkPrerenderCount());
2325 EXPECT_EQ(1U, GetRunningLinkPrerenderCount());
2328 // Checks that we don't prerender in an infinite loop and multiple links are
2329 // handled correctly.
2330 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2331 PrerenderInfiniteLoopMultiple
) {
2332 const char* const kHtmlFileA
=
2333 "files/prerender/prerender_infinite_a_multiple.html";
2334 const char* const kHtmlFileB
=
2335 "files/prerender/prerender_infinite_b_multiple.html";
2336 const char* const kHtmlFileC
=
2337 "files/prerender/prerender_infinite_c_multiple.html";
2339 // This test is conceptually simplest if concurrency is at two, since we
2340 // don't have to worry about which of kHtmlFileB or kHtmlFileC gets evicted.
2341 GetPrerenderManager()->mutable_config().max_link_concurrency
= 2;
2342 GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher
= 2;
2344 std::vector
<FinalStatus
> expected_final_status_queue
;
2345 expected_final_status_queue
.push_back(FINAL_STATUS_USED
);
2346 expected_final_status_queue
.push_back(FINAL_STATUS_APP_TERMINATING
);
2347 expected_final_status_queue
.push_back(FINAL_STATUS_APP_TERMINATING
);
2349 ScopedVector
<TestPrerender
> prerenders
=
2350 PrerenderTestURL(kHtmlFileA
, expected_final_status_queue
, 1);
2351 ASSERT_TRUE(prerenders
[0]->contents());
2353 // Next url should be in pending list but not an active entry. This relies on
2354 // the fact that the renderer sends out the AddLinkRelPrerender IPC before
2355 // sending the page load one.
2356 EXPECT_EQ(3U, GetLinkPrerenderCount());
2357 EXPECT_EQ(1U, GetRunningLinkPrerenderCount());
2358 EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileB
));
2359 EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileC
));
2361 NavigateToDestURL();
2363 // Make sure the PrerenderContents for the next urls are now in the manager
2364 // and not pending. One and only one of the URLs (the last seen) should be the
2365 // active entry. This relies on pending prerenders being resolved in the same
2366 // event loop iteration as OnPrerenderStop.
2367 bool url_b_is_active_prerender
= UrlIsInPrerenderManager(kHtmlFileB
);
2368 bool url_c_is_active_prerender
= UrlIsInPrerenderManager(kHtmlFileC
);
2369 EXPECT_TRUE(url_b_is_active_prerender
&& url_c_is_active_prerender
);
2370 EXPECT_EQ(2U, GetLinkPrerenderCount());
2371 EXPECT_EQ(2U, GetRunningLinkPrerenderCount());
2374 // Checks that pending prerenders are aborted (and never launched) when launched
2375 // by a prerender that itself gets aborted.
2376 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderAbortPendingOnCancel
) {
2377 const char* const kHtmlFileA
= "files/prerender/prerender_infinite_a.html";
2378 const char* const kHtmlFileB
= "files/prerender/prerender_infinite_b.html";
2380 scoped_ptr
<TestPrerender
> prerender
=
2381 PrerenderTestURL(kHtmlFileA
, FINAL_STATUS_CANCELLED
, 1);
2382 ASSERT_TRUE(prerender
->contents());
2383 // Assert that the pending prerender is in there already. This relies on the
2384 // fact that the renderer sends out the AddLinkRelPrerender IPC before sending
2385 // the page load one.
2386 EXPECT_EQ(2U, GetLinkPrerenderCount());
2387 EXPECT_EQ(1U, GetRunningLinkPrerenderCount());
2389 // Next url should be in pending list but not an active entry.
2390 EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileB
));
2392 // Cancel the prerender.
2393 GetPrerenderManager()->CancelAllPrerenders();
2394 prerender
->WaitForStop();
2396 // All prerenders are now gone.
2397 EXPECT_TRUE(IsEmptyPrerenderLinkManager());
2400 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderTaskManager
) {
2401 // Show the task manager. This populates the model.
2402 chrome::OpenTaskManager(current_browser());
2403 // Wait for the model of task manager to start.
2404 TaskManagerBrowserTestUtil::WaitForWebResourceChange(1);
2406 // Start with two resources.
2407 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED
, 1);
2409 // One of the resources that has a WebContents associated with it should have
2410 // the Prerender prefix.
2411 const base::string16 prefix
=
2412 l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PRERENDER_PREFIX
,
2414 base::string16 prerender_title
;
2415 int num_prerender_tabs
= 0;
2417 TaskManagerModel
* model
= GetModel();
2418 // The task manager caches values. Force the titles to be fresh.
2420 for (int i
= 0; i
< model
->ResourceCount(); ++i
) {
2421 if (model
->GetResourceWebContents(i
)) {
2422 prerender_title
= model
->GetResourceTitle(i
);
2423 if (StartsWith(prerender_title
, prefix
, true))
2424 ++num_prerender_tabs
;
2427 EXPECT_EQ(1, num_prerender_tabs
);
2428 const base::string16 prerender_page_title
=
2429 prerender_title
.substr(prefix
.length());
2431 NavigateToDestURL();
2433 // There should be no tabs with the Prerender prefix.
2434 const base::string16 tab_prefix
=
2435 l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_TAB_PREFIX
, base::string16());
2436 num_prerender_tabs
= 0;
2437 int num_tabs_with_prerender_page_title
= 0;
2439 for (int i
= 0; i
< model
->ResourceCount(); ++i
) {
2440 if (model
->GetResourceWebContents(i
)) {
2441 base::string16 tab_title
= model
->GetResourceTitle(i
);
2442 if (StartsWith(tab_title
, prefix
, true)) {
2443 ++num_prerender_tabs
;
2445 EXPECT_TRUE(StartsWith(tab_title
, tab_prefix
, true));
2447 // The prerender tab should now be a normal tab but the title should be
2448 // the same. Depending on timing, there may be more than one of these.
2449 const base::string16 tab_page_title
=
2450 tab_title
.substr(tab_prefix
.length());
2451 if (prerender_page_title
.compare(tab_page_title
) == 0)
2452 ++num_tabs_with_prerender_page_title
;
2456 EXPECT_EQ(0, num_prerender_tabs
);
2458 // We may have deleted the prerender tab, but the swapped in tab should be
2460 EXPECT_GE(num_tabs_with_prerender_page_title
, 1);
2461 EXPECT_LE(num_tabs_with_prerender_page_title
, 2);
2464 // Checks that audio loads are deferred on prerendering.
2465 // Times out under AddressSanitizer, see http://crbug.com/108402
2466 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, DISABLED_PrerenderHTML5Audio
) {
2467 PrerenderTestURL("files/prerender/prerender_html5_audio.html",
2470 NavigateToDestURL();
2471 WaitForASCIITitle(GetActiveWebContents(), kPassTitle
);
2474 // Checks that audio loads are deferred on prerendering and played back when
2475 // the prerender is swapped in if autoplay is set.
2476 // Periodically fails on chrome-os. See http://crbug.com/145263
2477 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2478 DISABLED_PrerenderHTML5AudioAutoplay
) {
2479 PrerenderTestURL("files/prerender/prerender_html5_audio_autoplay.html",
2482 NavigateToDestURL();
2483 WaitForASCIITitle(GetActiveWebContents(), kPassTitle
);
2486 // Checks that audio loads are deferred on prerendering and played back when
2487 // the prerender is swapped in if js starts playing.
2488 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2489 DISABLED_PrerenderHTML5AudioJsplay
) {
2490 PrerenderTestURL("files/prerender/prerender_html5_audio_jsplay.html",
2493 NavigateToDestURL();
2494 WaitForASCIITitle(GetActiveWebContents(), kPassTitle
);
2497 // Checks that video loads are deferred on prerendering.
2498 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, DISABLED_PrerenderHTML5Video
) {
2499 PrerenderTestURL("files/prerender/prerender_html5_video.html",
2502 NavigateToDestURL();
2503 WaitForASCIITitle(GetActiveWebContents(), kPassTitle
);
2506 // Checks that video tags inserted by javascript are deferred and played
2507 // correctly on swap in.
2508 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2509 DISABLED_PrerenderHTML5VideoJs
) {
2510 PrerenderTestURL("files/prerender/prerender_html5_video_script.html",
2513 NavigateToDestURL();
2514 WaitForASCIITitle(GetActiveWebContents(), kPassTitle
);
2517 // Checks for correct network events by using a busy sleep the javascript.
2518 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2519 DISABLED_PrerenderHTML5VideoNetwork
) {
2520 DisableJavascriptCalls();
2521 scoped_ptr
<TestPrerender
> prerender
=
2522 PrerenderTestURL("files/prerender/prerender_html5_video_network.html",
2525 WaitForASCIITitle(prerender
->contents()->prerender_contents(), kReadyTitle
);
2526 EXPECT_TRUE(DidPrerenderPass(prerender
->contents()->prerender_contents()));
2527 NavigateToDestURL();
2528 WaitForASCIITitle(GetActiveWebContents(), kPassTitle
);
2531 // Checks that scripts can retrieve the correct window size while prerendering.
2532 #if defined(TOOLKIT_VIEWS)
2533 // TODO(beng): Widget hierarchy split causes this to fail http://crbug.com/82363
2534 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, DISABLED_PrerenderWindowSize
) {
2536 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderWindowSize
) {
2538 PrerenderTestURL("files/prerender/prerender_size.html",
2541 NavigateToDestURL();
2544 // Checks that prerenderers will terminate when the RenderView crashes.
2545 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderRendererCrash
) {
2546 scoped_ptr
<TestPrerender
> prerender
=
2547 PrerenderTestURL("files/prerender/prerender_page.html",
2548 FINAL_STATUS_RENDERER_CRASHED
,
2551 // Navigate to about:crash and then wait for the renderer to crash.
2552 ASSERT_TRUE(prerender
->contents());
2553 ASSERT_TRUE(prerender
->contents()->prerender_contents());
2554 prerender
->contents()->prerender_contents()->GetController().
2556 GURL(content::kChromeUICrashURL
),
2557 content::Referrer(),
2558 content::PAGE_TRANSITION_TYPED
,
2560 prerender
->WaitForStop();
2563 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2564 PrerenderPageWithFragment
) {
2565 PrerenderTestURL("files/prerender/prerender_page.html#fragment",
2569 ChannelDestructionWatcher channel_close_watcher
;
2570 channel_close_watcher
.WatchChannel(browser()->tab_strip_model()->
2571 GetActiveWebContents()->GetRenderProcessHost());
2572 NavigateToDestURL();
2573 channel_close_watcher
.WaitForChannelClose();
2575 ASSERT_TRUE(IsEmptyPrerenderLinkManager());
2578 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2579 PrerenderPageWithRedirectedFragment
) {
2581 CreateClientRedirect("files/prerender/prerender_page.html#fragment"),
2585 ChannelDestructionWatcher channel_close_watcher
;
2586 channel_close_watcher
.WatchChannel(browser()->tab_strip_model()->
2587 GetActiveWebContents()->GetRenderProcessHost());
2588 NavigateToDestURL();
2589 channel_close_watcher
.WaitForChannelClose();
2591 ASSERT_TRUE(IsEmptyPrerenderLinkManager());
2594 // Checks that we do not use a prerendered page when navigating from
2595 // the main page to a fragment.
2596 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2597 PrerenderPageNavigateFragment
) {
2598 PrerenderTestURL("files/prerender/no_prerender_page.html",
2599 FINAL_STATUS_APP_TERMINATING
,
2601 NavigateToURLWithDisposition(
2602 "files/prerender/no_prerender_page.html#fragment",
2603 CURRENT_TAB
, false);
2606 // Checks that we do not use a prerendered page when we prerender a fragment
2607 // but navigate to the main page.
2608 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2609 PrerenderFragmentNavigatePage
) {
2610 PrerenderTestURL("files/prerender/no_prerender_page.html#fragment",
2611 FINAL_STATUS_APP_TERMINATING
,
2613 NavigateToURLWithDisposition(
2614 "files/prerender/no_prerender_page.html",
2615 CURRENT_TAB
, false);
2618 // Checks that we do not use a prerendered page when we prerender a fragment
2619 // but navigate to a different fragment on the same page.
2620 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2621 PrerenderFragmentNavigateFragment
) {
2622 PrerenderTestURL("files/prerender/no_prerender_page.html#other_fragment",
2623 FINAL_STATUS_APP_TERMINATING
,
2625 NavigateToURLWithDisposition(
2626 "files/prerender/no_prerender_page.html#fragment",
2627 CURRENT_TAB
, false);
2630 // Checks that we do not use a prerendered page when the page uses a client
2631 // redirect to refresh from a fragment on the same page.
2632 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2633 PrerenderClientRedirectFromFragment
) {
2635 CreateClientRedirect("files/prerender/no_prerender_page.html#fragment"),
2636 FINAL_STATUS_APP_TERMINATING
,
2638 NavigateToURLWithDisposition(
2639 "files/prerender/no_prerender_page.html",
2640 CURRENT_TAB
, false);
2643 // Checks that we do not use a prerendered page when the page uses a client
2644 // redirect to refresh to a fragment on the same page.
2645 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2646 PrerenderClientRedirectToFragment
) {
2648 CreateClientRedirect("files/prerender/no_prerender_page.html"),
2649 FINAL_STATUS_APP_TERMINATING
,
2651 NavigateToURLWithDisposition(
2652 "files/prerender/no_prerender_page.html#fragment",
2653 CURRENT_TAB
, false);
2656 // Checks that we correctly use a prerendered page when the page uses JS to set
2657 // the window.location.hash to a fragment on the same page.
2658 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2659 PrerenderPageChangeFragmentLocationHash
) {
2660 PrerenderTestURL("files/prerender/prerender_fragment_location_hash.html",
2663 NavigateToURL("files/prerender/prerender_fragment_location_hash.html");
2666 // Checks that prerendering a PNG works correctly.
2667 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderImagePng
) {
2668 DisableJavascriptCalls();
2669 PrerenderTestURL("files/prerender/image.png", FINAL_STATUS_USED
, 1);
2670 NavigateToDestURL();
2673 // Checks that prerendering a JPG works correctly.
2674 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderImageJpeg
) {
2675 DisableJavascriptCalls();
2676 PrerenderTestURL("files/prerender/image.jpeg", FINAL_STATUS_USED
, 1);
2677 NavigateToDestURL();
2680 // Checks that a prerender of a CRX will result in a cancellation due to
2682 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderCrx
) {
2683 PrerenderTestURL("files/prerender/extension.crx", FINAL_STATUS_DOWNLOAD
, 0);
2686 // Checks that xhr GET requests allow prerenders.
2687 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderXhrGet
) {
2688 PrerenderTestURL("files/prerender/prerender_xhr_get.html",
2691 NavigateToDestURL();
2694 // Checks that xhr HEAD requests allow prerenders.
2695 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderXhrHead
) {
2696 PrerenderTestURL("files/prerender/prerender_xhr_head.html",
2699 NavigateToDestURL();
2702 // Checks that xhr OPTIONS requests allow prerenders.
2703 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderXhrOptions
) {
2704 PrerenderTestURL("files/prerender/prerender_xhr_options.html",
2707 NavigateToDestURL();
2710 // Checks that xhr TRACE requests allow prerenders.
2711 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderXhrTrace
) {
2712 PrerenderTestURL("files/prerender/prerender_xhr_trace.html",
2715 NavigateToDestURL();
2718 // Checks that xhr POST requests allow prerenders.
2719 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderXhrPost
) {
2720 PrerenderTestURL("files/prerender/prerender_xhr_post.html",
2723 NavigateToDestURL();
2726 // Checks that xhr PUT cancels prerenders.
2727 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderXhrPut
) {
2728 PrerenderTestURL("files/prerender/prerender_xhr_put.html",
2729 FINAL_STATUS_INVALID_HTTP_METHOD
,
2733 // Checks that xhr DELETE cancels prerenders.
2734 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderXhrDelete
) {
2735 PrerenderTestURL("files/prerender/prerender_xhr_delete.html",
2736 FINAL_STATUS_INVALID_HTTP_METHOD
,
2740 // Checks that a top-level page which would trigger an SSL error is canceled.
2741 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderSSLErrorTopLevel
) {
2742 net::SpawnedTestServer::SSLOptions ssl_options
;
2743 ssl_options
.server_certificate
=
2744 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
2745 net::SpawnedTestServer
https_server(
2746 net::SpawnedTestServer::TYPE_HTTPS
, ssl_options
,
2747 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2748 ASSERT_TRUE(https_server
.Start());
2749 GURL https_url
= https_server
.GetURL("files/prerender/prerender_page.html");
2750 PrerenderTestURL(https_url
,
2751 FINAL_STATUS_SSL_ERROR
,
2755 // Checks that an SSL error that comes from a subresource does not cancel
2756 // the page. Non-main-frame requests are simply cancelled if they run into
2758 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderSSLErrorSubresource
) {
2759 net::SpawnedTestServer::SSLOptions ssl_options
;
2760 ssl_options
.server_certificate
=
2761 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
2762 net::SpawnedTestServer
https_server(
2763 net::SpawnedTestServer::TYPE_HTTPS
, ssl_options
,
2764 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2765 ASSERT_TRUE(https_server
.Start());
2766 GURL https_url
= https_server
.GetURL("files/prerender/image.jpeg");
2767 std::vector
<net::SpawnedTestServer::StringPair
> replacement_text
;
2768 replacement_text
.push_back(
2769 std::make_pair("REPLACE_WITH_IMAGE_URL", https_url
.spec()));
2770 std::string replacement_path
;
2771 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
2772 "files/prerender/prerender_with_image.html",
2774 &replacement_path
));
2775 PrerenderTestURL(replacement_path
, FINAL_STATUS_USED
, 1);
2776 NavigateToDestURL();
2779 // Checks that an SSL error that comes from an iframe does not cancel
2780 // the page. Non-main-frame requests are simply cancelled if they run into
2782 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderSSLErrorIframe
) {
2783 net::SpawnedTestServer::SSLOptions ssl_options
;
2784 ssl_options
.server_certificate
=
2785 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME
;
2786 net::SpawnedTestServer
https_server(
2787 net::SpawnedTestServer::TYPE_HTTPS
, ssl_options
,
2788 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2789 ASSERT_TRUE(https_server
.Start());
2790 GURL https_url
= https_server
.GetURL(
2791 "files/prerender/prerender_embedded_content.html");
2792 std::vector
<net::SpawnedTestServer::StringPair
> replacement_text
;
2793 replacement_text
.push_back(
2794 std::make_pair("REPLACE_WITH_URL", https_url
.spec()));
2795 std::string replacement_path
;
2796 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
2797 "files/prerender/prerender_with_iframe.html",
2799 &replacement_path
));
2800 PrerenderTestURL(replacement_path
, FINAL_STATUS_USED
, 1);
2801 NavigateToDestURL();
2804 // Checks that we cancel correctly when window.print() is called.
2805 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderPrint
) {
2806 PrerenderTestURL("files/prerender/prerender_print.html",
2807 FINAL_STATUS_WINDOW_PRINT
,
2811 // Checks that if a page is opened in a new window by javascript and both the
2812 // pages are in the same domain, the prerendered page is not used, due to
2814 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2815 PrerenderSameDomainWindowOpenerWindowOpen
) {
2816 PrerenderTestURL("files/prerender/prerender_page.html",
2817 FINAL_STATUS_WINDOW_OPENER
,
2819 OpenDestURLViaWindowOpen();
2822 // Checks that if a page is opened due to click on a href with target="_blank"
2823 // and both pages are in the same domain the prerendered page is not used, due
2824 // to window.opener.
2825 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2826 PrerenderSameDomainWindowOpenerClickTarget
) {
2827 PrerenderTestURL("files/prerender/prerender_page.html",
2828 FINAL_STATUS_WINDOW_OPENER
,
2830 OpenDestURLViaClickTarget();
2833 class TestClientCertStore
: public net::ClientCertStore
{
2835 TestClientCertStore() {}
2836 virtual ~TestClientCertStore() {}
2838 // net::ClientCertStore:
2839 virtual void GetClientCerts(const net::SSLCertRequestInfo
& cert_request_info
,
2840 net::CertificateList
* selected_certs
,
2841 const base::Closure
& callback
) OVERRIDE
{
2842 *selected_certs
= net::CertificateList(
2843 1, scoped_refptr
<net::X509Certificate
>(
2844 new net::X509Certificate("test", "test", base::Time(), base::Time())));
2849 scoped_ptr
<net::ClientCertStore
> CreateCertStore() {
2850 return scoped_ptr
<net::ClientCertStore
>(new TestClientCertStore
);
2853 // Checks that a top-level page which would normally request an SSL client
2854 // certificate will never be seen since it's an https top-level resource.
2855 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2856 PrerenderSSLClientCertTopLevel
) {
2857 ProfileIOData::FromResourceContext(
2858 current_browser()->profile()->GetResourceContext())->
2859 set_client_cert_store_factory_for_testing(
2860 base::Bind(&CreateCertStore
));
2861 net::SpawnedTestServer::SSLOptions ssl_options
;
2862 ssl_options
.request_client_certificate
= true;
2863 net::SpawnedTestServer
https_server(
2864 net::SpawnedTestServer::TYPE_HTTPS
, ssl_options
,
2865 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2866 ASSERT_TRUE(https_server
.Start());
2867 GURL https_url
= https_server
.GetURL("files/prerender/prerender_page.html");
2868 PrerenderTestURL(https_url
, FINAL_STATUS_SSL_CLIENT_CERTIFICATE_REQUESTED
, 0);
2871 // Checks that an SSL Client Certificate request that originates from a
2872 // subresource will cancel the prerendered page.
2873 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2874 PrerenderSSLClientCertSubresource
) {
2875 ProfileIOData::FromResourceContext(
2876 current_browser()->profile()->GetResourceContext())->
2877 set_client_cert_store_factory_for_testing(
2878 base::Bind(&CreateCertStore
));
2879 net::SpawnedTestServer::SSLOptions ssl_options
;
2880 ssl_options
.request_client_certificate
= true;
2881 net::SpawnedTestServer
https_server(
2882 net::SpawnedTestServer::TYPE_HTTPS
, ssl_options
,
2883 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2884 ASSERT_TRUE(https_server
.Start());
2885 GURL https_url
= https_server
.GetURL("files/prerender/image.jpeg");
2886 std::vector
<net::SpawnedTestServer::StringPair
> replacement_text
;
2887 replacement_text
.push_back(
2888 std::make_pair("REPLACE_WITH_IMAGE_URL", https_url
.spec()));
2889 std::string replacement_path
;
2890 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
2891 "files/prerender/prerender_with_image.html",
2893 &replacement_path
));
2894 PrerenderTestURL(replacement_path
,
2895 FINAL_STATUS_SSL_CLIENT_CERTIFICATE_REQUESTED
,
2899 // Checks that an SSL Client Certificate request that originates from an
2900 // iframe will cancel the prerendered page.
2901 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderSSLClientCertIframe
) {
2902 ProfileIOData::FromResourceContext(
2903 current_browser()->profile()->GetResourceContext())->
2904 set_client_cert_store_factory_for_testing(
2905 base::Bind(&CreateCertStore
));
2906 net::SpawnedTestServer::SSLOptions ssl_options
;
2907 ssl_options
.request_client_certificate
= true;
2908 net::SpawnedTestServer
https_server(
2909 net::SpawnedTestServer::TYPE_HTTPS
, ssl_options
,
2910 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2911 ASSERT_TRUE(https_server
.Start());
2912 GURL https_url
= https_server
.GetURL(
2913 "files/prerender/prerender_embedded_content.html");
2914 std::vector
<net::SpawnedTestServer::StringPair
> replacement_text
;
2915 replacement_text
.push_back(
2916 std::make_pair("REPLACE_WITH_URL", https_url
.spec()));
2917 std::string replacement_path
;
2918 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
2919 "files/prerender/prerender_with_iframe.html",
2921 &replacement_path
));
2922 PrerenderTestURL(replacement_path
,
2923 FINAL_STATUS_SSL_CLIENT_CERTIFICATE_REQUESTED
,
2927 #if defined(FULL_SAFE_BROWSING)
2928 // Ensures that we do not prerender pages with a safe browsing
2930 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderSafeBrowsingTopLevel
) {
2931 GURL url
= test_server()->GetURL("files/prerender/prerender_page.html");
2932 GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl(
2933 url
, SB_THREAT_TYPE_URL_MALWARE
);
2934 PrerenderTestURL("files/prerender/prerender_page.html",
2935 FINAL_STATUS_SAFE_BROWSING
, 0);
2938 // Ensures that server redirects to a malware page will cancel prerenders.
2939 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2940 PrerenderSafeBrowsingServerRedirect
) {
2941 GURL url
= test_server()->GetURL("files/prerender/prerender_page.html");
2942 GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl(
2943 url
, SB_THREAT_TYPE_URL_MALWARE
);
2944 PrerenderTestURL(CreateServerRedirect("files/prerender/prerender_page.html"),
2945 FINAL_STATUS_SAFE_BROWSING
,
2949 // Ensures that client redirects to a malware page will cancel prerenders.
2950 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
2951 PrerenderSafeBrowsingClientRedirect
) {
2952 GURL url
= test_server()->GetURL("files/prerender/prerender_page.html");
2953 GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl(
2954 url
, SB_THREAT_TYPE_URL_MALWARE
);
2955 PrerenderTestURL(CreateClientRedirect("files/prerender/prerender_page.html"),
2956 FINAL_STATUS_SAFE_BROWSING
,
2960 // Ensures that we do not prerender pages which have a malware subresource.
2961 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderSafeBrowsingSubresource
) {
2962 GURL image_url
= test_server()->GetURL("files/prerender/image.jpeg");
2963 GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl(
2964 image_url
, SB_THREAT_TYPE_URL_MALWARE
);
2965 std::vector
<net::SpawnedTestServer::StringPair
> replacement_text
;
2966 replacement_text
.push_back(
2967 std::make_pair("REPLACE_WITH_IMAGE_URL", image_url
.spec()));
2968 std::string replacement_path
;
2969 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
2970 "files/prerender/prerender_with_image.html",
2972 &replacement_path
));
2973 PrerenderTestURL(replacement_path
,
2974 FINAL_STATUS_SAFE_BROWSING
,
2978 // Ensures that we do not prerender pages which have a malware iframe.
2979 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderSafeBrowsingIframe
) {
2980 GURL iframe_url
= test_server()->GetURL(
2981 "files/prerender/prerender_embedded_content.html");
2982 GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl(
2983 iframe_url
, SB_THREAT_TYPE_URL_MALWARE
);
2984 std::vector
<net::SpawnedTestServer::StringPair
> replacement_text
;
2985 replacement_text
.push_back(
2986 std::make_pair("REPLACE_WITH_URL", iframe_url
.spec()));
2987 std::string replacement_path
;
2988 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
2989 "files/prerender/prerender_with_iframe.html",
2991 &replacement_path
));
2992 PrerenderTestURL(replacement_path
,
2993 FINAL_STATUS_SAFE_BROWSING
,
2999 // Checks that a local storage read will not cause prerender to fail.
3000 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderLocalStorageRead
) {
3001 PrerenderTestURL("files/prerender/prerender_localstorage_read.html",
3004 NavigateToDestURL();
3007 // Checks that a local storage write will not cause prerender to fail.
3008 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderLocalStorageWrite
) {
3009 PrerenderTestURL("files/prerender/prerender_localstorage_write.html",
3012 NavigateToDestURL();
3015 // Checks that the favicon is properly loaded on prerender.
3016 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderFavicon
) {
3017 scoped_ptr
<TestPrerender
> prerender
=
3018 PrerenderTestURL("files/prerender/prerender_favicon.html",
3021 NavigateToDestURL();
3023 if (!FaviconTabHelper::FromWebContents(
3024 GetActiveWebContents())->FaviconIsValid()) {
3025 // If the favicon has not been set yet, wait for it to be.
3026 content::WindowedNotificationObserver
favicon_update_watcher(
3027 chrome::NOTIFICATION_FAVICON_UPDATED
,
3028 content::Source
<WebContents
>(GetActiveWebContents()));
3029 favicon_update_watcher
.Wait();
3031 EXPECT_TRUE(FaviconTabHelper::FromWebContents(
3032 GetActiveWebContents())->FaviconIsValid());
3035 // Checks that when a prerendered page is swapped in to a referring page, the
3036 // unload handlers on the referring page are executed.
3037 // Fails about 50% on CrOS, 5-10% on linux, win, mac. http://crbug.com/128986
3038 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, DISABLED_PrerenderUnload
) {
3039 set_loader_path("files/prerender/prerender_loader_with_unload.html");
3040 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED
, 1);
3041 base::string16 expected_title
= base::ASCIIToUTF16("Unloaded");
3042 content::TitleWatcher
title_watcher(
3043 current_browser()->tab_strip_model()->GetActiveWebContents(),
3045 NavigateToDestURL();
3046 EXPECT_EQ(expected_title
, title_watcher
.WaitAndGetTitle());
3049 // Checks that when the history is cleared, prerendering is cancelled and
3050 // prerendering history is cleared.
3051 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderClearHistory
) {
3052 scoped_ptr
<TestPrerender
> prerender
=
3053 PrerenderTestURL("files/prerender/prerender_page.html",
3054 FINAL_STATUS_CACHE_OR_HISTORY_CLEARED
,
3057 base::MessageLoop::current()->PostTask(
3059 base::Bind(&ClearBrowsingData
, current_browser(),
3060 BrowsingDataRemover::REMOVE_HISTORY
));
3061 prerender
->WaitForStop();
3063 // Make sure prerender history was cleared.
3064 EXPECT_EQ(0, GetHistoryLength());
3067 // Disabled due to flakiness: crbug.com/316225
3068 // Checks that when the cache is cleared, prerenders are cancelled but
3069 // prerendering history is not cleared.
3070 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, DISABLED_PrerenderClearCache
) {
3071 scoped_ptr
<TestPrerender
> prerender
=
3072 PrerenderTestURL("files/prerender/prerender_page.html",
3073 FINAL_STATUS_CACHE_OR_HISTORY_CLEARED
,
3076 base::MessageLoop::current()->PostTask(FROM_HERE
,
3077 base::Bind(&ClearBrowsingData
, current_browser(),
3078 BrowsingDataRemover::REMOVE_CACHE
));
3079 prerender
->WaitForStop();
3081 // Make sure prerender history was not cleared. Not a vital behavior, but
3082 // used to compare with PrerenderClearHistory test.
3083 EXPECT_EQ(1, GetHistoryLength());
3086 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderCancelAll
) {
3087 scoped_ptr
<TestPrerender
> prerender
=
3088 PrerenderTestURL("files/prerender/prerender_page.html",
3089 FINAL_STATUS_CANCELLED
,
3092 GetPrerenderManager()->CancelAllPrerenders();
3093 prerender
->WaitForStop();
3095 EXPECT_FALSE(prerender
->contents());
3098 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderEvents
) {
3099 scoped_ptr
<TestPrerender
> prerender
=
3100 PrerenderTestURL("files/prerender/prerender_page.html",
3101 FINAL_STATUS_CANCELLED
, 1);
3103 GetPrerenderManager()->CancelAllPrerenders();
3104 prerender
->WaitForStop();
3106 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
3107 EXPECT_TRUE(DidReceivePrerenderStopEventForLinkNumber(0));
3108 EXPECT_FALSE(HadPrerenderEventErrors());
3111 // Cancels the prerender of a page with its own prerender. The second prerender
3112 // should never be started.
3113 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
3114 PrerenderCancelPrerenderWithPrerender
) {
3115 scoped_ptr
<TestPrerender
> prerender
=
3116 PrerenderTestURL("files/prerender/prerender_infinite_a.html",
3117 FINAL_STATUS_CANCELLED
,
3120 GetPrerenderManager()->CancelAllPrerenders();
3121 prerender
->WaitForStop();
3123 EXPECT_FALSE(prerender
->contents());
3126 // Prerendering and history tests.
3127 // The prerendered page is navigated to in several ways [navigate via
3128 // omnibox, click on link, key-modified click to open in background tab, etc],
3129 // followed by a navigation to another page from the prerendered page, followed
3130 // by a back navigation.
3132 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderNavigateClickGoBack
) {
3133 PrerenderTestURL("files/prerender/prerender_page_with_link.html",
3136 NavigateToDestURL();
3137 ClickToNextPageAfterPrerender();
3138 GoBackToPrerender();
3141 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderNavigateNavigateGoBack
) {
3142 PrerenderTestURL("files/prerender/prerender_page_with_link.html",
3145 NavigateToDestURL();
3146 NavigateToNextPageAfterPrerender();
3147 GoBackToPrerender();
3150 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderClickClickGoBack
) {
3151 PrerenderTestURL("files/prerender/prerender_page_with_link.html",
3154 OpenDestURLViaClick();
3155 ClickToNextPageAfterPrerender();
3156 GoBackToPrerender();
3159 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderClickNavigateGoBack
) {
3160 PrerenderTestURL("files/prerender/prerender_page_with_link.html",
3163 OpenDestURLViaClick();
3164 NavigateToNextPageAfterPrerender();
3165 GoBackToPrerender();
3168 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderClickNewWindow
) {
3169 PrerenderTestURL("files/prerender/prerender_page_with_link.html",
3170 FINAL_STATUS_WINDOW_OPENER
,
3172 OpenDestURLViaClickNewWindow();
3175 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderClickNewForegroundTab
) {
3176 PrerenderTestURL("files/prerender/prerender_page_with_link.html",
3177 FINAL_STATUS_WINDOW_OPENER
,
3179 OpenDestURLViaClickNewForegroundTab();
3182 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderClickNewBackgroundTab
) {
3183 scoped_ptr
<TestPrerender
> prerender
=
3184 PrerenderTestURL("files/prerender/prerender_page_with_link.html",
3185 FINAL_STATUS_WINDOW_OPENER
,
3187 ASSERT_TRUE(prerender
->contents());
3188 prerender
->contents()->set_should_be_shown(false);
3189 OpenDestURLViaClickNewBackgroundTab();
3192 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
3193 NavigateToPrerenderedPageWhenDevToolsAttached
) {
3194 DisableJavascriptCalls();
3195 WebContents
* web_contents
=
3196 current_browser()->tab_strip_model()->GetActiveWebContents();
3197 scoped_refptr
<DevToolsAgentHost
> agent(DevToolsAgentHost::GetOrCreateFor(
3198 web_contents
->GetRenderViewHost()));
3199 DevToolsManager
* manager
= DevToolsManager::GetInstance();
3200 FakeDevToolsClientHost client_host
;
3201 manager
->RegisterDevToolsClientHostFor(agent
.get(), &client_host
);
3202 const char* url
= "files/prerender/prerender_page.html";
3203 PrerenderTestURL(url
, FINAL_STATUS_DEVTOOLS_ATTACHED
, 1);
3204 NavigateToURLWithDisposition(url
, CURRENT_TAB
, false);
3205 manager
->ClientHostClosing(&client_host
);
3208 // Validate that the sessionStorage namespace remains the same when swapping
3209 // in a prerendered page.
3210 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderSessionStorage
) {
3211 set_loader_path("files/prerender/prerender_loader_with_session_storage.html");
3212 PrerenderTestURL(GetCrossDomainTestUrl("files/prerender/prerender_page.html"),
3215 NavigateToDestURL();
3216 GoBackToPageBeforePrerender();
3219 // Checks that the control group works. An XHR PUT cannot be detected in the
3221 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, ControlGroup
) {
3222 RestorePrerenderMode restore_prerender_mode
;
3223 PrerenderManager::SetMode(
3224 PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP
);
3225 DisableJavascriptCalls();
3226 PrerenderTestURL("files/prerender/prerender_xhr_put.html",
3227 FINAL_STATUS_WOULD_HAVE_BEEN_USED
, 0);
3228 NavigateToDestURL();
3231 // Checks that the control group correctly hits WOULD_HAVE_BEEN_USED
3232 // renderer-initiated navigations. (This verifies that the ShouldFork logic
3233 // behaves correctly.)
3234 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, ControlGroupRendererInitiated
) {
3235 RestorePrerenderMode restore_prerender_mode
;
3236 PrerenderManager::SetMode(
3237 PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP
);
3238 DisableJavascriptCalls();
3239 PrerenderTestURL("files/prerender/prerender_xhr_put.html",
3240 FINAL_STATUS_WOULD_HAVE_BEEN_USED
, 0);
3241 OpenDestURLViaClick();
3244 // Make sure that the MatchComplete dummy works in the normal case. Once
3245 // a prerender is cancelled because of a script, a dummy must be created to
3246 // account for the MatchComplete case, and it must have a final status of
3247 // FINAL_STATUS_WOULD_HAVE_BEEN_USED.
3248 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, MatchCompleteDummy
) {
3249 UMAHistogramHelper histograms
;
3251 std::vector
<FinalStatus
> expected_final_status_queue
;
3252 expected_final_status_queue
.push_back(FINAL_STATUS_INVALID_HTTP_METHOD
);
3253 expected_final_status_queue
.push_back(FINAL_STATUS_WOULD_HAVE_BEEN_USED
);
3254 PrerenderTestURL("files/prerender/prerender_xhr_put.html",
3255 expected_final_status_queue
, 1);
3257 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLT", 1);
3258 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0);
3259 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLTMatchedComplete", 0);
3260 histograms
.ExpectTotalCount("Prerender.websame_PrerenderNotSwappedInPLT", 1);
3262 NavigateToDestURL();
3264 histograms
.ExpectTotalCount("Prerender.websame_PerceivedPLT", 1);
3265 histograms
.ExpectTotalCount("Prerender.websame_PerceivedPLTMatched", 0);
3266 histograms
.ExpectTotalCount(
3267 "Prerender.websame_PerceivedPLTMatchedComplete", 1);
3270 // Verify that a navigation that hits a MatchComplete dummy while another is in
3271 // progress does not also classify the previous navigation as a MatchComplete.
3272 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
3273 MatchCompleteDummyCancelNavigation
) {
3274 UMAHistogramHelper histograms
;
3276 // Arrange for a URL to hang.
3277 const GURL
kNoCommitUrl("http://never-respond.example.com");
3278 base::FilePath
file(FILE_PATH_LITERAL(
3279 "chrome/test/data/prerender/prerender_page.html"));
3280 base::RunLoop hang_loop
;
3281 BrowserThread::PostTask(
3282 BrowserThread::IO
, FROM_HERE
,
3283 base::Bind(&CreateHangingFirstRequestProtocolHandlerOnIO
,
3284 kNoCommitUrl
, file
, hang_loop
.QuitClosure()));
3286 // First, fire a prerender that aborts after it completes its load.
3287 std::vector
<FinalStatus
> expected_final_status_queue
;
3288 expected_final_status_queue
.push_back(FINAL_STATUS_INVALID_HTTP_METHOD
);
3289 expected_final_status_queue
.push_back(FINAL_STATUS_WOULD_HAVE_BEEN_USED
);
3290 PrerenderTestURL("files/prerender/prerender_xhr_put.html",
3291 expected_final_status_queue
, 1);
3293 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLT", 1);
3294 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0);
3295 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLTMatchedComplete", 0);
3296 histograms
.ExpectTotalCount("Prerender.websame_PrerenderNotSwappedInPLT", 1);
3298 // Open the hanging URL in a new tab. Wait for both the new tab to open and
3299 // the hanging request to be scheduled.
3300 ui_test_utils::NavigateToURLWithDisposition(
3301 current_browser(), kNoCommitUrl
, NEW_FOREGROUND_TAB
,
3302 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB
);
3305 // Now interrupt that navigation and navigate to the destination URL. This
3306 // should forcibly complete the previous navigation and also complete a
3307 // WOULD_HAVE_BEEN_PRERENDERED navigation.
3308 NavigateToDestURL();
3310 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLT", 2);
3311 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0);
3312 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLTMatchedComplete", 0);
3313 histograms
.ExpectTotalCount("Prerender.websame_PerceivedPLT", 1);
3314 histograms
.ExpectTotalCount("Prerender.websame_PerceivedPLTMatched", 0);
3315 histograms
.ExpectTotalCount(
3316 "Prerender.websame_PerceivedPLTMatchedComplete", 1);
3319 class PrerenderBrowserTestWithNaCl
: public PrerenderBrowserTest
{
3321 PrerenderBrowserTestWithNaCl() {}
3322 virtual ~PrerenderBrowserTestWithNaCl() {}
3324 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
3325 PrerenderBrowserTest::SetUpCommandLine(command_line
);
3326 command_line
->AppendSwitch(switches::kEnableNaCl
);
3330 // Check that NaCl plugins work when enabled, with prerendering.
3331 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithNaCl
,
3332 PrerenderNaClPluginEnabled
) {
3333 #if defined(OS_WIN) && defined(USE_ASH)
3334 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
3335 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests
))
3339 PrerenderTestURL("files/prerender/prerender_plugin_nacl_enabled.html",
3342 NavigateToDestURL();
3344 // To avoid any chance of a race, we have to let the script send its response
3346 WebContents
* web_contents
=
3347 browser()->tab_strip_model()->GetActiveWebContents();
3348 bool display_test_result
= false;
3349 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(web_contents
,
3350 "DidDisplayReallyPass()",
3351 &display_test_result
));
3352 ASSERT_TRUE(display_test_result
);
3355 // Checks that the referrer policy is used when prerendering.
3356 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderReferrerPolicy
) {
3357 set_loader_path("files/prerender/prerender_loader_with_referrer_policy.html");
3358 PrerenderTestURL("files/prerender/prerender_referrer_policy.html",
3361 NavigateToDestURL();
3364 // Checks that the referrer policy is used when prerendering on HTTPS.
3365 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
3366 PrerenderSSLReferrerPolicy
) {
3367 UseHttpsSrcServer();
3368 set_loader_path("files/prerender/prerender_loader_with_referrer_policy.html");
3369 PrerenderTestURL("files/prerender/prerender_referrer_policy.html",
3372 NavigateToDestURL();
3375 // Checks that the referrer policy is used when prerendering is cancelled.
3376 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderCancelReferrerPolicy
) {
3377 scoped_ptr
<TestContentBrowserClient
> test_content_browser_client(
3378 new TestContentBrowserClient
);
3379 content::ContentBrowserClient
* original_browser_client
=
3380 content::SetBrowserClientForTesting(test_content_browser_client
.get());
3382 set_loader_path("files/prerender/prerender_loader_with_referrer_policy.html");
3383 PrerenderTestURL("files/prerender/prerender_referrer_policy.html",
3384 FINAL_STATUS_CANCELLED
,
3386 OpenDestURLViaClick();
3388 bool display_test_result
= false;
3389 WebContents
* web_contents
=
3390 browser()->tab_strip_model()->GetActiveWebContents();
3391 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
3393 "window.domAutomationController.send(DidDisplayPass())",
3394 &display_test_result
));
3395 EXPECT_TRUE(display_test_result
);
3397 content::SetBrowserClientForTesting(original_browser_client
);
3400 // Test interaction of the webNavigation and tabs API with prerender.
3401 class PrerenderBrowserTestWithExtensions
: public PrerenderBrowserTest
,
3402 public ExtensionApiTest
{
3404 PrerenderBrowserTestWithExtensions() {
3405 // The individual tests start the test server through ExtensionApiTest, so
3406 // the port number can be passed through to the extension.
3407 autostart_test_server_
= false;
3410 virtual void SetUp() OVERRIDE
{
3411 PrerenderBrowserTest::SetUp();
3414 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
3415 PrerenderBrowserTest::SetUpCommandLine(command_line
);
3416 ExtensionApiTest::SetUpCommandLine(command_line
);
3419 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE
{
3420 PrerenderBrowserTest::SetUpInProcessBrowserTestFixture();
3421 ExtensionApiTest::SetUpInProcessBrowserTestFixture();
3424 virtual void TearDownInProcessBrowserTestFixture() OVERRIDE
{
3425 PrerenderBrowserTest::TearDownInProcessBrowserTestFixture();
3426 ExtensionApiTest::TearDownInProcessBrowserTestFixture();
3429 virtual void SetUpOnMainThread() OVERRIDE
{
3430 PrerenderBrowserTest::SetUpOnMainThread();
3434 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithExtensions
, WebNavigation
) {
3435 ASSERT_TRUE(StartSpawnedTestServer());
3436 extensions::FrameNavigationState::set_allow_extension_scheme(true);
3438 CommandLine::ForCurrentProcess()->AppendSwitch(
3439 extensions::switches::kAllowLegacyExtensionManifests
);
3441 // Wait for the extension to set itself up and return control to us.
3442 ASSERT_TRUE(RunExtensionTest("webnavigation/prerender")) << message_
;
3444 ResultCatcher catcher
;
3446 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED
, 1);
3448 ChannelDestructionWatcher channel_close_watcher
;
3449 channel_close_watcher
.WatchChannel(browser()->tab_strip_model()->
3450 GetActiveWebContents()->GetRenderProcessHost());
3451 NavigateToDestURL();
3452 channel_close_watcher
.WaitForChannelClose();
3454 ASSERT_TRUE(IsEmptyPrerenderLinkManager());
3455 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
3458 // Fails often on Windows dbg bots. http://crbug.com/177163
3459 #if defined(OS_WIN) && !defined(NDEBUG)
3460 #define MAYBE_TabsApi DISABLED_TabsApi
3462 #define MAYBE_TabsApi TabsApi
3463 #endif // defined(OS_WIN) && !defined(NDEBUG)
3464 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithExtensions
, MAYBE_TabsApi
) {
3465 ASSERT_TRUE(StartSpawnedTestServer());
3466 extensions::FrameNavigationState::set_allow_extension_scheme(true);
3468 // Wait for the extension to set itself up and return control to us.
3469 ASSERT_TRUE(RunExtensionSubtest("tabs/on_replaced", "on_replaced.html"))
3472 ResultCatcher catcher
;
3474 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED
, 1);
3476 ChannelDestructionWatcher channel_close_watcher
;
3477 channel_close_watcher
.WatchChannel(browser()->tab_strip_model()->
3478 GetActiveWebContents()->GetRenderProcessHost());
3479 NavigateToDestURL();
3480 channel_close_watcher
.WaitForChannelClose();
3482 ASSERT_TRUE(IsEmptyPrerenderLinkManager());
3483 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
3486 // Checks that non-http/https/chrome-extension subresource cancels the
3488 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
3489 PrerenderCancelSubresourceUnsupportedScheme
) {
3490 GURL image_url
= GURL("invalidscheme://www.google.com/test.jpg");
3491 std::vector
<net::SpawnedTestServer::StringPair
> replacement_text
;
3492 replacement_text
.push_back(
3493 std::make_pair("REPLACE_WITH_IMAGE_URL", image_url
.spec()));
3494 std::string replacement_path
;
3495 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
3496 "files/prerender/prerender_with_image.html",
3498 &replacement_path
));
3499 PrerenderTestURL(replacement_path
, FINAL_STATUS_UNSUPPORTED_SCHEME
, 0);
3502 // Ensure that about:blank is permitted for any subresource.
3503 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
3504 PrerenderAllowAboutBlankSubresource
) {
3505 GURL image_url
= GURL("about:blank");
3506 std::vector
<net::SpawnedTestServer::StringPair
> replacement_text
;
3507 replacement_text
.push_back(
3508 std::make_pair("REPLACE_WITH_IMAGE_URL", image_url
.spec()));
3509 std::string replacement_path
;
3510 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
3511 "files/prerender/prerender_with_image.html",
3513 &replacement_path
));
3514 PrerenderTestURL(replacement_path
, FINAL_STATUS_USED
, 1);
3515 NavigateToDestURL();
3518 // Checks that non-http/https/chrome-extension subresource cancels the prerender
3520 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
3521 PrerenderCancelSubresourceRedirectUnsupportedScheme
) {
3522 GURL image_url
= test_server()->GetURL(
3523 CreateServerRedirect("invalidscheme://www.google.com/test.jpg"));
3524 std::vector
<net::SpawnedTestServer::StringPair
> replacement_text
;
3525 replacement_text
.push_back(
3526 std::make_pair("REPLACE_WITH_IMAGE_URL", image_url
.spec()));
3527 std::string replacement_path
;
3528 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
3529 "files/prerender/prerender_with_image.html",
3531 &replacement_path
));
3532 PrerenderTestURL(replacement_path
, FINAL_STATUS_UNSUPPORTED_SCHEME
, 0);
3535 // Checks that chrome-extension subresource does not cancel the prerender.
3536 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
3537 PrerenderKeepSubresourceExtensionScheme
) {
3538 GURL image_url
= GURL("chrome-extension://abcdefg/test.jpg");
3539 std::vector
<net::SpawnedTestServer::StringPair
> replacement_text
;
3540 replacement_text
.push_back(
3541 std::make_pair("REPLACE_WITH_IMAGE_URL", image_url
.spec()));
3542 std::string replacement_path
;
3543 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
3544 "files/prerender/prerender_with_image.html",
3546 &replacement_path
));
3547 PrerenderTestURL(replacement_path
, FINAL_STATUS_USED
, 1);
3548 NavigateToDestURL();
3551 // Checks that redirect to chrome-extension subresource does not cancel the
3553 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
3554 PrerenderKeepSubresourceRedirectExtensionScheme
) {
3555 GURL image_url
= test_server()->GetURL(
3556 CreateServerRedirect("chrome-extension://abcdefg/test.jpg"));
3557 std::vector
<net::SpawnedTestServer::StringPair
> replacement_text
;
3558 replacement_text
.push_back(
3559 std::make_pair("REPLACE_WITH_IMAGE_URL", image_url
.spec()));
3560 std::string replacement_path
;
3561 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
3562 "files/prerender/prerender_with_image.html",
3564 &replacement_path
));
3565 PrerenderTestURL(replacement_path
, FINAL_STATUS_USED
, 1);
3566 NavigateToDestURL();
3570 // Checks that non-http/https main page redirects cancel the prerender.
3571 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
3572 PrerenderCancelMainFrameRedirectUnsupportedScheme
) {
3573 GURL url
= test_server()->GetURL(
3574 CreateServerRedirect("invalidscheme://www.google.com/test.html"));
3575 PrerenderTestURL(url
, FINAL_STATUS_UNSUPPORTED_SCHEME
, 0);
3578 // Checks that media source video loads are deferred on prerendering.
3579 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderHTML5MediaSourceVideo
) {
3580 PrerenderTestURL("files/prerender/prerender_html5_video_media_source.html",
3583 NavigateToDestURL();
3584 WaitForASCIITitle(GetActiveWebContents(), kPassTitle
);
3587 // Checks that a prerender that creates an audio stream (via a WebAudioDevice)
3589 // http://crbug.com/261489
3590 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, DISABLED_PrerenderWebAudioDevice
) {
3591 PrerenderTestURL("files/prerender/prerender_web_audio_device.html",
3592 FINAL_STATUS_CREATING_AUDIO_STREAM
, 1);
3595 // Checks that prerenders do not swap in to WebContents being captured.
3596 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderCapturedWebContents
) {
3597 PrerenderTestURL("files/prerender/prerender_page.html",
3598 FINAL_STATUS_PAGE_BEING_CAPTURED
, 1);
3599 WebContents
* web_contents
= GetActiveWebContents();
3600 web_contents
->IncrementCapturerCount(gfx::Size());
3601 NavigateToDestURLWithDisposition(CURRENT_TAB
, false);
3602 web_contents
->DecrementCapturerCount();
3605 // Checks that prerenders are aborted on cross-process navigation from
3606 // a server redirect.
3607 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
3608 PrerenderCrossProcessServerRedirect
) {
3609 // Force everything to be a process swap.
3610 SwapProcessesContentBrowserClient test_browser_client
;
3611 content::ContentBrowserClient
* original_browser_client
=
3612 content::SetBrowserClientForTesting(&test_browser_client
);
3615 CreateServerRedirect("files/prerender/prerender_page.html"),
3616 FINAL_STATUS_OPEN_URL
, 0);
3618 content::SetBrowserClientForTesting(original_browser_client
);
3621 // Checks that URLRequests for prerenders being aborted on cross-process
3622 // navigation from a server redirect are cleaned up, so they don't keep cache
3624 // See http://crbug.com/341134
3625 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
3626 PrerenderCrossProcessServerRedirectNoHang
) {
3627 const char kDestPath
[] = "files/prerender/prerender_page.html";
3628 // Force everything to be a process swap.
3629 SwapProcessesContentBrowserClient test_browser_client
;
3630 content::ContentBrowserClient
* original_browser_client
=
3631 content::SetBrowserClientForTesting(&test_browser_client
);
3633 PrerenderTestURL(CreateServerRedirect(kDestPath
), FINAL_STATUS_OPEN_URL
, 0);
3635 ui_test_utils::NavigateToURL(
3637 test_server()->GetURL(kDestPath
));
3639 content::SetBrowserClientForTesting(original_browser_client
);
3642 // Checks that prerenders are aborted on cross-process navigation from
3643 // a client redirect.
3644 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
3645 PrerenderCrossProcessClientRedirect
) {
3646 // Cross-process navigation logic for renderer-initiated navigations
3647 // is partially controlled by the renderer, namely
3648 // ChromeContentRendererClient. This test instead relies on the Web
3649 // Store triggering such navigations.
3650 std::string webstore_url
= extension_urls::GetWebstoreLaunchURL();
3652 // Mock out requests to the Web Store.
3653 base::FilePath
file(GetTestPath("prerender_page.html"));
3654 BrowserThread::PostTask(
3655 BrowserThread::IO
, FROM_HERE
,
3656 base::Bind(&CreateMockProtocolHandlerOnIO
,
3657 GURL(webstore_url
), file
));
3659 PrerenderTestURL(CreateClientRedirect(webstore_url
),
3660 FINAL_STATUS_OPEN_URL
, 1);
3663 // Checks that canceling a MatchComplete dummy doesn't result in two
3665 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, CancelMatchCompleteDummy
) {
3666 std::vector
<FinalStatus
> expected_final_status_queue
;
3667 expected_final_status_queue
.push_back(FINAL_STATUS_JAVASCRIPT_ALERT
);
3668 expected_final_status_queue
.push_back(FINAL_STATUS_CANCELLED
);
3669 ScopedVector
<TestPrerender
> prerenders
=
3670 PrerenderTestURL("files/prerender/prerender_alert_before_onload.html",
3671 expected_final_status_queue
, 0);
3673 // Cancel the MatchComplete dummy.
3674 GetPrerenderManager()->CancelAllPrerenders();
3675 prerenders
[1]->WaitForStop();
3677 // Check the referring page only got one copy of the event.
3678 EXPECT_FALSE(HadPrerenderEventErrors());
3681 // Checks that a deferred redirect to an image is not loaded until the page is
3682 // visible. Also test the right histogram events are emitted in this case.
3683 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderDeferredImage
) {
3684 DisableJavascriptCalls();
3685 UMAHistogramHelper histograms
;
3687 // The prerender will not completely load until after the swap, so wait for a
3688 // title change before calling DidPrerenderPass.
3689 scoped_ptr
<TestPrerender
> prerender
=
3691 "files/prerender/prerender_deferred_image.html",
3692 FINAL_STATUS_USED
, 0);
3693 WaitForASCIITitle(prerender
->contents()->prerender_contents(), kReadyTitle
);
3694 EXPECT_EQ(1, GetPrerenderDomContentLoadedEventCountForLinkNumber(0));
3695 EXPECT_TRUE(DidPrerenderPass(prerender
->contents()->prerender_contents()));
3696 EXPECT_EQ(0, prerender
->number_of_loads());
3698 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLT", 1);
3699 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0);
3700 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLTMatchedComplete", 0);
3701 histograms
.ExpectTotalCount("Prerender.websame_PrerenderNotSwappedInPLT", 0);
3704 NavigationOrSwapObserver
swap_observer(current_browser()->tab_strip_model(),
3705 GetActiveWebContents());
3706 ui_test_utils::NavigateToURLWithDisposition(
3707 current_browser(), dest_url(), CURRENT_TAB
,
3708 ui_test_utils::BROWSER_TEST_NONE
);
3709 swap_observer
.Wait();
3711 // The prerender never observes the final load.
3712 EXPECT_EQ(0, prerender
->number_of_loads());
3714 // Now check DidDisplayPass.
3715 EXPECT_TRUE(DidDisplayPass(GetActiveWebContents()));
3718 histograms
.ExpectTotalCount("Prerender.websame_PrerenderNotSwappedInPLT", 0);
3719 histograms
.ExpectTotalCount("Prerender.websame_PerceivedPLT", 1);
3720 histograms
.ExpectTotalCount("Prerender.websame_PerceivedPLTMatched", 1);
3721 histograms
.ExpectTotalCount(
3722 "Prerender.websame_PerceivedPLTMatchedComplete", 1);
3725 // Checks that a deferred redirect to an image is not loaded until the
3726 // page is visible, even after another redirect.
3727 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
3728 PrerenderDeferredImageAfterRedirect
) {
3729 DisableJavascriptCalls();
3731 // The prerender will not completely load until after the swap, so wait for a
3732 // title change before calling DidPrerenderPass.
3733 scoped_ptr
<TestPrerender
> prerender
=
3735 "files/prerender/prerender_deferred_image.html",
3736 FINAL_STATUS_USED
, 0);
3737 WaitForASCIITitle(prerender
->contents()->prerender_contents(), kReadyTitle
);
3738 EXPECT_TRUE(DidPrerenderPass(prerender
->contents()->prerender_contents()));
3739 EXPECT_EQ(0, prerender
->number_of_loads());
3742 NavigationOrSwapObserver
swap_observer(current_browser()->tab_strip_model(),
3743 GetActiveWebContents());
3744 ui_test_utils::NavigateToURLWithDisposition(
3745 current_browser(), dest_url(), CURRENT_TAB
,
3746 ui_test_utils::BROWSER_TEST_NONE
);
3747 swap_observer
.Wait();
3749 // The prerender never observes the final load.
3750 EXPECT_EQ(0, prerender
->number_of_loads());
3752 // Now check DidDisplayPass.
3753 EXPECT_TRUE(DidDisplayPass(GetActiveWebContents()));
3756 // Checks that deferred redirects in the main frame are followed.
3757 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderDeferredMainFrame
) {
3758 DisableJavascriptCalls();
3760 "files/prerender/image-deferred.png",
3761 FINAL_STATUS_USED
, 1);
3762 NavigateToDestURL();
3765 // Checks that deferred redirects in the main frame are followed, even
3766 // with a double-redirect.
3767 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
3768 PrerenderDeferredMainFrameAfterRedirect
) {
3769 DisableJavascriptCalls();
3771 CreateServerRedirect("files/prerender/image-deferred.png"),
3772 FINAL_STATUS_USED
, 1);
3773 NavigateToDestURL();
3776 // Checks that deferred redirects in a synchronous XHR abort the
3778 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderDeferredSynchronousXHR
) {
3779 PrerenderTestURL("files/prerender/prerender_deferred_sync_xhr.html",
3780 FINAL_STATUS_BAD_DEFERRED_REDIRECT
, 0);
3781 NavigateToDestURL();
3784 // Checks that prerenders are not swapped for navigations with extra headers.
3785 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderExtraHeadersNoSwap
) {
3786 PrerenderTestURL("files/prerender/prerender_page.html",
3787 FINAL_STATUS_APP_TERMINATING
, 1);
3789 content::OpenURLParams
params(dest_url(), Referrer(), CURRENT_TAB
,
3790 content::PAGE_TRANSITION_TYPED
, false);
3791 params
.extra_headers
= "X-Custom-Header: 42\r\n";
3792 NavigateToURLWithParams(params
, false);
3795 // Checks that prerenders are not swapped for navigations with browser-initiated
3797 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
3798 PrerenderBrowserInitiatedPostNoSwap
) {
3799 PrerenderTestURL("files/prerender/prerender_page.html",
3800 FINAL_STATUS_APP_TERMINATING
, 1);
3802 std::string post_data
= "DATA";
3803 content::OpenURLParams
params(dest_url(), Referrer(), CURRENT_TAB
,
3804 content::PAGE_TRANSITION_TYPED
, false);
3805 params
.uses_post
= true;
3806 params
.browser_initiated_post_data
=
3807 base::RefCountedString::TakeString(&post_data
);
3808 NavigateToURLWithParams(params
, false);
3811 // Checks that the prerendering of a page is canceled correctly when the
3812 // prerendered page tries to make a second navigation entry.
3813 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderNewNavigationEntry
) {
3814 PrerenderTestURL("files/prerender/prerender_new_entry.html",
3815 FINAL_STATUS_NEW_NAVIGATION_ENTRY
,
3819 // Attempt a swap-in in a new tab, verifying that session storage namespace
3821 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderPageNewTab
) {
3822 // Mock out some URLs and count the number of requests to one of them. Both
3823 // prerender_session_storage.html and init_session_storage.html need to be
3824 // mocked so they are same-origin.
3825 const GURL
kInitURL("http://prerender.test/init_session_storage.html");
3826 base::FilePath init_file
= GetTestPath("init_session_storage.html");
3827 BrowserThread::PostTask(
3828 BrowserThread::IO
, FROM_HERE
,
3829 base::Bind(&CreateMockProtocolHandlerOnIO
, kInitURL
, init_file
));
3831 const GURL
kTestURL("http://prerender.test/prerender_session_storage.html");
3832 base::FilePath test_file
= GetTestPath("prerender_session_storage.html");
3833 RequestCounter counter
;
3834 BrowserThread::PostTask(
3835 BrowserThread::IO
, FROM_HERE
,
3836 base::Bind(&CreateCountingProtocolHandlerOnIO
,
3837 kTestURL
, test_file
, counter
.AsWeakPtr()));
3839 PrerenderTestURL(kTestURL
, FINAL_STATUS_USED
, 1);
3841 // Open a new tab to navigate in.
3842 ui_test_utils::NavigateToURLWithDisposition(
3843 current_browser(), kInitURL
, NEW_FOREGROUND_TAB
,
3844 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION
);
3846 // Now navigate in the new tab. Set expect_swap_to_succeed to false because
3847 // the swap does not occur synchronously.
3849 // TODO(davidben): When all swaps become asynchronous, remove the OpenURL
3850 // return value assertion and let this go through the usual successful-swap
3852 NavigateToDestURLWithDisposition(CURRENT_TAB
, false);
3854 // Verify DidDisplayPass manually since the previous call skipped it.
3855 EXPECT_TRUE(DidDisplayPass(
3856 current_browser()->tab_strip_model()->GetActiveWebContents()));
3858 // Only one request to the test URL started.
3860 // TODO(davidben): Re-enable this check when the races in attaching the
3861 // throttle are resolved. http://crbug.com/335835
3862 // EXPECT_EQ(1, counter.count());
3865 // Attempt a swap-in in a new tab, verifying that session storage namespace
3866 // merging works. Unlike the above test, the swap is for a navigation that would
3867 // normally be cross-process.
3868 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderPageNewTabCrossProcess
) {
3869 base::FilePath test_data_dir
;
3870 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_data_dir
));
3872 // Mock out some URLs and count the number of requests to one of them. Both
3873 // prerender_session_storage.html and init_session_storage.html need to be
3874 // mocked so they are same-origin.
3875 const GURL
kInitURL("http://prerender.test/init_session_storage.html");
3876 base::FilePath init_file
= GetTestPath("init_session_storage.html");
3877 BrowserThread::PostTask(
3878 BrowserThread::IO
, FROM_HERE
,
3879 base::Bind(&CreateMockProtocolHandlerOnIO
, kInitURL
, init_file
));
3881 const GURL
kTestURL("http://prerender.test/prerender_session_storage.html");
3882 base::FilePath test_file
= GetTestPath("prerender_session_storage.html");
3883 RequestCounter counter
;
3884 BrowserThread::PostTask(
3885 BrowserThread::IO
, FROM_HERE
,
3886 base::Bind(&CreateCountingProtocolHandlerOnIO
,
3887 kTestURL
, test_file
, counter
.AsWeakPtr()));
3889 PrerenderTestURL(kTestURL
, FINAL_STATUS_USED
, 1);
3891 // Open a new tab to navigate in.
3892 ui_test_utils::NavigateToURLWithDisposition(
3893 current_browser(), kInitURL
, NEW_FOREGROUND_TAB
,
3894 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION
);
3896 // Navigate to about:blank so the next navigation is cross-process.
3897 ui_test_utils::NavigateToURL(current_browser(),
3898 GURL(content::kAboutBlankURL
));
3900 // Now navigate in the new tab. Set expect_swap_to_succeed to false because
3901 // the swap does not occur synchronously.
3903 // TODO(davidben): When all swaps become asynchronous, remove the OpenURL
3904 // return value assertion and let this go through the usual successful-swap
3906 NavigateToDestURLWithDisposition(CURRENT_TAB
, false);
3908 // Verify DidDisplayPass manually since the previous call skipped it.
3909 EXPECT_TRUE(DidDisplayPass(GetActiveWebContents()));
3911 // Only one request to the test URL started.
3913 // TODO(davidben): Re-enable this check when the races in attaching the
3914 // throttle are resolved. http://crbug.com/335835
3915 // EXPECT_EQ(1, counter.count());
3918 // Verify that session storage conflicts don't merge.
3919 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderSessionStorageConflict
) {
3920 PrerenderTestURL("files/prerender/prerender_session_storage_conflict.html",
3921 FINAL_STATUS_APP_TERMINATING
, 1);
3923 // Open a new tab to navigate in.
3924 ui_test_utils::NavigateToURLWithDisposition(
3926 test_server()->GetURL("files/prerender/init_session_storage.html"),
3928 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION
);
3930 // Now navigate in the new tab.
3931 NavigateToDestURLWithDisposition(CURRENT_TAB
, false);
3933 // Verify DidDisplayPass in the new tab.
3934 EXPECT_TRUE(DidDisplayPass(GetActiveWebContents()));
3937 // Checks that prerenders honor |should_replace_current_entry|.
3938 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderReplaceCurrentEntry
) {
3939 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED
, 1);
3941 content::OpenURLParams
params(dest_url(), Referrer(), CURRENT_TAB
,
3942 content::PAGE_TRANSITION_TYPED
, false);
3943 params
.should_replace_current_entry
= true;
3944 NavigateToURLWithParams(params
, false);
3946 const NavigationController
& controller
=
3947 GetActiveWebContents()->GetController();
3948 // First entry is about:blank, second is prerender_page.html.
3949 EXPECT_TRUE(controller
.GetPendingEntry() == NULL
);
3950 EXPECT_EQ(2, controller
.GetEntryCount());
3951 EXPECT_EQ(GURL(content::kAboutBlankURL
),
3952 controller
.GetEntryAtIndex(0)->GetURL());
3953 EXPECT_EQ(dest_url(), controller
.GetEntryAtIndex(1)->GetURL());
3956 // Checks prerender does not hit DCHECKs and behaves properly if two pending
3957 // swaps occur in a row.
3958 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderDoublePendingSwap
) {
3959 GetPrerenderManager()->mutable_config().max_link_concurrency
= 2;
3960 GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher
= 2;
3962 GURL url1
= test_server()->GetURL("files/prerender/prerender_page.html?1");
3963 scoped_ptr
<TestPrerender
> prerender1
=
3964 PrerenderTestURL(url1
, FINAL_STATUS_APP_TERMINATING
, 1);
3966 GURL url2
= test_server()->GetURL("files/prerender/prerender_page.html?2");
3967 scoped_ptr
<TestPrerender
> prerender2
= ExpectPrerender(FINAL_STATUS_USED
);
3968 AddPrerender(url2
, 1);
3969 prerender2
->WaitForStart();
3970 prerender2
->WaitForLoads(1);
3972 // There's no reason the second prerender can't be used, but the swap races
3973 // with didStartProvisionalLoad and didFailProvisionalLoad from the previous
3974 // navigation. The current logic will conservatively fail to swap under such
3975 // races. However, if the renderer is slow enough, it's possible for the
3976 // prerender to still be used, so don't program in either expectation.
3977 ASSERT_TRUE(prerender2
->contents());
3978 prerender2
->contents()->set_skip_final_checks(true);
3980 // Open a new tab to navigate in.
3981 ui_test_utils::NavigateToURLWithDisposition(
3982 current_browser(), GURL(content::kAboutBlankURL
), NEW_FOREGROUND_TAB
,
3983 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION
);
3985 // Fire off two navigations, without running the event loop between them.
3986 NavigationOrSwapObserver
swap_observer(
3987 current_browser()->tab_strip_model(),
3988 GetActiveWebContents(), 2);
3989 current_browser()->OpenURL(OpenURLParams(
3990 url1
, Referrer(), CURRENT_TAB
, content::PAGE_TRANSITION_TYPED
, false));
3991 current_browser()->OpenURL(OpenURLParams(
3992 url2
, Referrer(), CURRENT_TAB
, content::PAGE_TRANSITION_TYPED
, false));
3993 swap_observer
.Wait();
3995 // The WebContents should be on url2. There may be 2 or 3 entries, depending
3996 // on whether the first one managed to complete.
3998 // TODO(davidben): When http://crbug.com/335835 is fixed, the 3 entry case
3999 // shouldn't be possible because it's throttled by the pending swap that
4001 const NavigationController
& controller
=
4002 GetActiveWebContents()->GetController();
4003 EXPECT_TRUE(controller
.GetPendingEntry() == NULL
);
4004 EXPECT_LE(2, controller
.GetEntryCount());
4005 EXPECT_GE(3, controller
.GetEntryCount());
4006 EXPECT_EQ(GURL(content::kAboutBlankURL
),
4007 controller
.GetEntryAtIndex(0)->GetURL());
4008 EXPECT_EQ(url2
, controller
.GetEntryAtIndex(
4009 controller
.GetEntryCount() - 1)->GetURL());
4012 // Verify that pending swaps get aborted on new navigations.
4013 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
,
4014 PrerenderPendingSwapNewNavigation
) {
4015 PrerenderManager::HangSessionStorageMergesForTesting();
4017 PrerenderTestURL("files/prerender/prerender_page.html",
4018 FINAL_STATUS_APP_TERMINATING
, 1);
4020 // Open a new tab to navigate in.
4021 ui_test_utils::NavigateToURLWithDisposition(
4022 current_browser(), GURL(content::kAboutBlankURL
), NEW_FOREGROUND_TAB
,
4023 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION
);
4025 // Navigate to the URL. Wait for DidStartLoading, just so it's definitely
4026 // progressed somewhere.
4027 content::WindowedNotificationObserver
page_load_observer(
4028 content::NOTIFICATION_LOAD_START
,
4029 content::Source
<NavigationController
>(
4030 &GetActiveWebContents()->GetController()));
4031 current_browser()->OpenURL(OpenURLParams(
4032 dest_url(), Referrer(), CURRENT_TAB
,
4033 content::PAGE_TRANSITION_TYPED
, false));
4034 page_load_observer
.Wait();
4036 // Navigate somewhere else. This should succeed and abort the pending swap.
4037 TestNavigationObserver
nav_observer(GetActiveWebContents());
4038 current_browser()->OpenURL(OpenURLParams(
4039 GURL(content::kAboutBlankURL
), Referrer(), CURRENT_TAB
,
4040 content::PAGE_TRANSITION_TYPED
, false));
4041 nav_observer
.Wait();
4044 // Checks that <a ping> requests are not dropped in prerender.
4045 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderPing
) {
4046 // Count hits to a certain URL.
4047 const GURL
kPingURL("http://prerender.test/ping");
4048 base::FilePath empty_file
= ui_test_utils::GetTestFilePath(
4049 base::FilePath(), base::FilePath(FILE_PATH_LITERAL("empty.html")));
4050 RequestCounter ping_counter
;
4051 BrowserThread::PostTask(
4052 BrowserThread::IO
, FROM_HERE
,
4053 base::Bind(&CreateCountingProtocolHandlerOnIO
,
4054 kPingURL
, empty_file
, ping_counter
.AsWeakPtr()));
4056 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED
, 1);
4057 OpenDestURLViaClickPing(kPingURL
);
4059 ping_counter
.WaitForCount(1);
4062 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest
, PrerenderPPLTNormalNavigation
) {
4063 UMAHistogramHelper histograms
;
4065 GURL url
= test_server()->GetURL("files/prerender/prerender_page.html");
4066 ui_test_utils::NavigateToURL(current_browser(), url
);
4068 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLT", 1);
4069 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0);
4070 histograms
.ExpectTotalCount("Prerender.none_PerceivedPLTMatchedComplete", 0);
4073 class PrerenderIncognitoBrowserTest
: public PrerenderBrowserTest
{
4075 virtual void SetUpOnMainThread() OVERRIDE
{
4076 Profile
* normal_profile
= current_browser()->profile();
4077 set_browser(ui_test_utils::OpenURLOffTheRecord(
4078 normal_profile
, GURL("about:blank")));
4079 PrerenderBrowserTest::SetUpOnMainThread();
4083 // Checks that prerendering works in incognito mode.
4084 IN_PROC_BROWSER_TEST_F(PrerenderIncognitoBrowserTest
, PrerenderIncognito
) {
4085 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED
, 1);
4086 NavigateToDestURL();
4089 } // namespace prerender