1 // Copyright 2013 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.
5 #include "base/command_line.h"
6 #include "base/prefs/pref_service.h"
7 #include "base/run_loop.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/tabs/tab_strip_model.h"
12 #include "chrome/common/chrome_switches.h"
13 #include "chrome/common/pref_names.h"
14 #include "chrome/common/prefetch_messages.h"
15 #include "chrome/test/base/in_process_browser_test.h"
16 #include "chrome/test/base/ui_test_utils.h"
17 #include "content/public/browser/render_frame_host.h"
18 #include "content/public/browser/web_contents.h"
19 #include "content/public/test/browser_test_utils.h"
20 #include "net/url_request/url_request_filter.h"
21 #include "net/url_request/url_request_job.h"
23 using content::BrowserThread;
27 const char kPrefetchPage[] = "files/prerender/simple_prefetch.html";
29 class PrefetchBrowserTestBase : public InProcessBrowserTest {
31 explicit PrefetchBrowserTestBase(bool do_predictive_networking,
32 bool do_prefetch_field_trial)
33 : do_predictive_networking_(do_predictive_networking),
34 do_prefetch_field_trial_(do_prefetch_field_trial) {}
36 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
37 if (do_prefetch_field_trial_) {
38 command_line->AppendSwitchASCII(switches::kForceFieldTrials,
39 "Prefetch/ExperimentDisabled/");
41 command_line->AppendSwitchASCII(switches::kForceFieldTrials,
42 "Prefetch/ExperimentEnabled/");
46 virtual void SetUpOnMainThread() OVERRIDE {
47 browser()->profile()->GetPrefs()->SetBoolean(
48 prefs::kNetworkPredictionEnabled, do_predictive_networking_);
51 bool RunPrefetchExperiment(bool expect_success, Browser* browser) {
52 CHECK(test_server()->Start());
53 GURL url = test_server()->GetURL(kPrefetchPage);
55 const base::string16 expected_title =
56 expect_success ? base::ASCIIToUTF16("link onload")
57 : base::ASCIIToUTF16("link onerror");
58 content::TitleWatcher title_watcher(
59 browser->tab_strip_model()->GetActiveWebContents(), expected_title);
60 ui_test_utils::NavigateToURL(browser, url);
61 return expected_title == title_watcher.WaitAndGetTitle();
65 bool do_predictive_networking_;
66 bool do_prefetch_field_trial_;
69 class PrefetchBrowserTestPredictionOnExpOn : public PrefetchBrowserTestBase {
71 PrefetchBrowserTestPredictionOnExpOn()
72 : PrefetchBrowserTestBase(true, true) {}
75 class PrefetchBrowserTestPredictionOnExpOff : public PrefetchBrowserTestBase {
77 PrefetchBrowserTestPredictionOnExpOff()
78 : PrefetchBrowserTestBase(true, false) {}
81 class PrefetchBrowserTestPredictionOffExpOn : public PrefetchBrowserTestBase {
83 PrefetchBrowserTestPredictionOffExpOn()
84 : PrefetchBrowserTestBase(false, true) {}
87 class PrefetchBrowserTestPredictionOffExpOff : public PrefetchBrowserTestBase {
89 PrefetchBrowserTestPredictionOffExpOff()
90 : PrefetchBrowserTestBase(false, false) {}
93 // URLRequestJob (and associated handler) which hangs.
94 class HangingURLRequestJob : public net::URLRequestJob {
96 HangingURLRequestJob(net::URLRequest* request,
97 net::NetworkDelegate* network_delegate)
98 : net::URLRequestJob(request, network_delegate) {}
100 // net::URLRequestJob implementation
101 virtual void Start() OVERRIDE {}
104 virtual ~HangingURLRequestJob() {}
106 DISALLOW_COPY_AND_ASSIGN(HangingURLRequestJob);
109 class HangingRequestInterceptor : public net::URLRequestInterceptor {
111 explicit HangingRequestInterceptor(const base::Closure& callback)
112 : callback_(callback) {}
114 virtual ~HangingRequestInterceptor() {}
116 virtual net::URLRequestJob* MaybeInterceptRequest(
117 net::URLRequest* request,
118 net::NetworkDelegate* network_delegate) const OVERRIDE {
119 if (!callback_.is_null())
120 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback_);
121 return new HangingURLRequestJob(request, network_delegate);
125 base::Closure callback_;
128 void CreateHangingRequestInterceptorOnIO(const GURL& url,
129 base::Closure callback) {
130 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
131 scoped_ptr<net::URLRequestInterceptor> never_respond_handler(
132 new HangingRequestInterceptor(callback));
133 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
134 url, never_respond_handler.Pass());
137 // Privacy option is on, experiment is on. Prefetch should succeed.
138 IN_PROC_BROWSER_TEST_F(PrefetchBrowserTestPredictionOnExpOn, PredOnExpOn) {
139 EXPECT_TRUE(RunPrefetchExperiment(false, browser()));
142 // Privacy option is on, experiment is off. Prefetch should be dropped.
143 IN_PROC_BROWSER_TEST_F(PrefetchBrowserTestPredictionOnExpOff, PredOnExpOff) {
144 EXPECT_TRUE(RunPrefetchExperiment(true, browser()));
147 // Privacy option is off, experiment is on. Prefetch should be dropped.
148 IN_PROC_BROWSER_TEST_F(PrefetchBrowserTestPredictionOffExpOn, PredOffExpOn) {
149 EXPECT_TRUE(RunPrefetchExperiment(false, browser()));
152 // Privacy option is off, experiment is off. Prefetch should be dropped.
153 IN_PROC_BROWSER_TEST_F(PrefetchBrowserTestPredictionOffExpOff, PredOffExpOff) {
154 EXPECT_TRUE(RunPrefetchExperiment(false, browser()));
157 // Bug 339909: When in incognito mode the browser crashed due to an
158 // uninitialized preference member. Verify that it no longer does.
159 IN_PROC_BROWSER_TEST_F(PrefetchBrowserTestPredictionOnExpOff, IncognitoTest) {
160 Profile* incognito_profile = browser()->profile()->GetOffTheRecordProfile();
161 Browser* incognito_browser = new Browser(
162 Browser::CreateParams(incognito_profile, browser()->host_desktop_type()));
164 // Navigate just to have a tab in this window, otherwise there is no
165 // WebContents for the incognito browser.
166 ui_test_utils::OpenURLOffTheRecord(browser()->profile(), GURL("about:blank"));
168 EXPECT_TRUE(RunPrefetchExperiment(true, incognito_browser));
171 // This test will verify the following:
172 // - that prefetches from the browser are actually launched
173 // - if a prefetch is in progress, but the originating renderer is destroyed,
174 // that the pending prefetch request is cleaned up cleanly and does not
175 // result in a crash.
176 IN_PROC_BROWSER_TEST_F(PrefetchBrowserTestPredictionOnExpOff,
177 PrefetchFromBrowser) {
178 const GURL kHangingUrl("http://hanging-url.com");
180 BrowserThread::PostTask(BrowserThread::IO,
182 base::Bind(&CreateHangingRequestInterceptorOnIO,
184 loop_.QuitClosure()));
185 ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
186 content::RenderFrameHost* rfh =
187 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame();
188 rfh->Send(new PrefetchMsg_Prefetch(rfh->GetRoutingID(), kHangingUrl));