Fire an error if a pref used in the UI is missing once all prefs are fetched.
[chromium-blink-merge.git] / chrome / browser / prerender / prerender_resource_throttle_unittest.cc
blobed8798e44cb57d1f4da824b172528d33405883e5
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.
5 #include <set>
6 #include <utility>
8 #include "base/files/file_path.h"
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/run_loop.h"
12 #include "base/threading/sequenced_worker_pool.h"
13 #include "chrome/browser/net/url_request_mock_util.h"
14 #include "chrome/browser/prerender/prerender_contents.h"
15 #include "chrome/browser/prerender/prerender_manager.h"
16 #include "chrome/browser/prerender/prerender_resource_throttle.h"
17 #include "chrome/test/base/testing_browser_process.h"
18 #include "content/public/browser/resource_controller.h"
19 #include "content/public/browser/resource_request_info.h"
20 #include "content/public/test/test_browser_thread.h"
21 #include "ipc/ipc_message.h"
22 #include "net/base/request_priority.h"
23 #include "net/test/url_request/url_request_mock_http_job.h"
24 #include "net/url_request/redirect_info.h"
25 #include "net/url_request/url_request.h"
26 #include "net/url_request/url_request_test_util.h"
27 #include "testing/gtest/include/gtest/gtest.h"
29 using content::BrowserThread;
30 using content::ResourceType;
32 namespace prerender {
34 namespace {
36 class TestPrerenderContents : public PrerenderContents {
37 public:
38 TestPrerenderContents(PrerenderManager* prerender_manager,
39 int child_id, int route_id)
40 : PrerenderContents(prerender_manager, static_cast<Profile*>(NULL),
41 GURL(), content::Referrer(), ORIGIN_NONE,
42 PrerenderManager::kNoExperiment),
43 child_id_(child_id),
44 route_id_(route_id) {
45 PrerenderResourceThrottle::OverridePrerenderContentsForTesting(this);
48 ~TestPrerenderContents() override {
49 if (final_status() == FINAL_STATUS_MAX)
50 SetFinalStatus(FINAL_STATUS_USED);
51 PrerenderResourceThrottle::OverridePrerenderContentsForTesting(NULL);
54 bool GetChildId(int* child_id) const override {
55 *child_id = child_id_;
56 return true;
59 bool GetRouteId(int* route_id) const override {
60 *route_id = route_id_;
61 return true;
64 void Start() {
65 prerendering_has_started_ = true;
66 NotifyPrerenderStart();
69 void Cancel() {
70 Destroy(FINAL_STATUS_CANCELLED);
73 void Use() {
74 PrepareForUse();
77 private:
78 int child_id_;
79 int route_id_;
82 class TestPrerenderManager : public PrerenderManager {
83 public:
84 TestPrerenderManager() : PrerenderManager(nullptr) {
85 mutable_config().rate_limit_enabled = false;
88 // We never allocate our PrerenderContents in PrerenderManager, so we don't
89 // ever want the default pending delete behaviour.
90 void MoveEntryToPendingDelete(PrerenderContents* entry,
91 FinalStatus final_status) override {}
94 class DeferredRedirectDelegate : public net::URLRequest::Delegate,
95 public content::ResourceController {
96 public:
97 DeferredRedirectDelegate()
98 : throttle_(NULL),
99 was_deferred_(false),
100 cancel_called_(false),
101 resume_called_(false) {
104 void SetThrottle(PrerenderResourceThrottle* throttle) {
105 throttle_ = throttle;
106 throttle_->set_controller_for_testing(this);
109 void Run() {
110 run_loop_.reset(new base::RunLoop());
111 run_loop_->Run();
114 bool was_deferred() const { return was_deferred_; }
115 bool cancel_called() const { return cancel_called_; }
116 bool resume_called() const { return resume_called_; }
118 // net::URLRequest::Delegate implementation:
119 void OnReceivedRedirect(net::URLRequest* request,
120 const net::RedirectInfo& redirect_info,
121 bool* defer_redirect) override {
122 // Defer the redirect either way.
123 *defer_redirect = true;
125 // Find out what the throttle would have done.
126 throttle_->WillRedirectRequest(redirect_info, &was_deferred_);
127 run_loop_->Quit();
129 void OnResponseStarted(net::URLRequest* request) override {}
130 void OnReadCompleted(net::URLRequest* request, int bytes_read) override {}
132 // content::ResourceController implementation:
133 void Cancel() override {
134 EXPECT_FALSE(cancel_called_);
135 EXPECT_FALSE(resume_called_);
137 cancel_called_ = true;
138 run_loop_->Quit();
140 void CancelAndIgnore() override { Cancel(); }
141 void CancelWithError(int error_code) override { Cancel(); }
142 void Resume() override {
143 EXPECT_TRUE(was_deferred_);
144 EXPECT_FALSE(cancel_called_);
145 EXPECT_FALSE(resume_called_);
147 resume_called_ = true;
148 run_loop_->Quit();
151 private:
152 scoped_ptr<base::RunLoop> run_loop_;
153 PrerenderResourceThrottle* throttle_;
154 bool was_deferred_;
155 bool cancel_called_;
156 bool resume_called_;
158 DISALLOW_COPY_AND_ASSIGN(DeferredRedirectDelegate);
161 } // namespace
163 class PrerenderResourceThrottleTest : public testing::Test {
164 public:
165 static const int kDefaultChildId = 0;
166 static const int kDefaultRouteId = 100;
168 PrerenderResourceThrottleTest() :
169 ui_thread_(BrowserThread::UI, &message_loop_),
170 io_thread_(BrowserThread::IO, &message_loop_),
171 test_contents_(&prerender_manager_, kDefaultChildId, kDefaultRouteId) {
172 chrome_browser_net::SetUrlRequestMocksEnabled(true);
175 ~PrerenderResourceThrottleTest() override {
176 chrome_browser_net::SetUrlRequestMocksEnabled(false);
178 // Cleanup work so the file IO tasks from URLRequestMockHTTPJob
179 // are gone.
180 content::BrowserThread::GetBlockingPool()->FlushForTesting();
181 RunEvents();
184 TestPrerenderManager* prerender_manager() {
185 return &prerender_manager_;
188 TestPrerenderContents* test_contents() {
189 return &test_contents_;
192 // Runs any tasks queued on either thread.
193 void RunEvents() {
194 message_loop_.RunUntilIdle();
197 private:
198 base::MessageLoopForIO message_loop_;
199 content::TestBrowserThread ui_thread_;
200 content::TestBrowserThread io_thread_;
202 TestPrerenderManager prerender_manager_;
203 TestPrerenderContents test_contents_;
206 // Checks that deferred redirects are throttled and resumed correctly.
207 TEST_F(PrerenderResourceThrottleTest, RedirectResume) {
208 const base::FilePath::CharType kRedirectPath[] =
209 FILE_PATH_LITERAL("prerender/image-deferred.png");
211 test_contents()->Start();
212 RunEvents();
214 // Fake a request.
215 net::TestURLRequestContext url_request_context;
216 DeferredRedirectDelegate delegate;
217 scoped_ptr<net::URLRequest> request(url_request_context.CreateRequest(
218 net::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kRedirectPath)),
219 net::DEFAULT_PRIORITY,
220 &delegate));
221 content::ResourceRequestInfo::AllocateForTesting(
222 request.get(),
223 content::RESOURCE_TYPE_IMAGE,
224 NULL,
225 kDefaultChildId,
226 kDefaultRouteId,
227 MSG_ROUTING_NONE,
228 false, // is_main_frame
229 false, // parent_is_main_frame
230 true, // allow_download
231 true); // is_async
233 // Install a prerender throttle.
234 PrerenderResourceThrottle throttle(request.get());
235 delegate.SetThrottle(&throttle);
237 // Start the request and wait for a redirect.
238 request->Start();
239 delegate.Run();
240 EXPECT_TRUE(delegate.was_deferred());
241 // This calls WillRedirectRequestOnUI().
242 RunEvents();
244 // Display the prerendered RenderView and wait for the throttle to
245 // notice.
246 test_contents()->Use();
247 delegate.Run();
248 EXPECT_TRUE(delegate.resume_called());
249 EXPECT_FALSE(delegate.cancel_called());
252 // Checks that redirects in main frame loads are not deferred.
253 TEST_F(PrerenderResourceThrottleTest, RedirectMainFrame) {
254 const base::FilePath::CharType kRedirectPath[] =
255 FILE_PATH_LITERAL("prerender/image-deferred.png");
257 test_contents()->Start();
258 RunEvents();
260 // Fake a request.
261 net::TestURLRequestContext url_request_context;
262 DeferredRedirectDelegate delegate;
263 scoped_ptr<net::URLRequest> request(url_request_context.CreateRequest(
264 net::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kRedirectPath)),
265 net::DEFAULT_PRIORITY,
266 &delegate));
267 content::ResourceRequestInfo::AllocateForTesting(
268 request.get(),
269 content::RESOURCE_TYPE_MAIN_FRAME,
270 NULL,
271 kDefaultChildId,
272 kDefaultRouteId,
273 MSG_ROUTING_NONE,
274 true, // is_main_frame
275 false, // parent_is_main_frame
276 true, // allow_download
277 true); // is_async
279 // Install a prerender throttle.
280 PrerenderResourceThrottle throttle(request.get());
281 delegate.SetThrottle(&throttle);
283 // Start the request and wait for a redirect. This time, it should
284 // not be deferred.
285 request->Start();
286 delegate.Run();
287 // This calls WillRedirectRequestOnUI().
288 RunEvents();
290 // Cleanup work so the prerender is gone.
291 test_contents()->Cancel();
292 RunEvents();
295 // Checks that attempting to defer a synchronous request aborts the
296 // prerender.
297 TEST_F(PrerenderResourceThrottleTest, RedirectSyncXHR) {
298 const base::FilePath::CharType kRedirectPath[] =
299 FILE_PATH_LITERAL("prerender/image-deferred.png");
301 test_contents()->Start();
302 RunEvents();
304 // Fake a request.
305 net::TestURLRequestContext url_request_context;
306 DeferredRedirectDelegate delegate;
307 scoped_ptr<net::URLRequest> request(url_request_context.CreateRequest(
308 net::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kRedirectPath)),
309 net::DEFAULT_PRIORITY,
310 &delegate));
311 content::ResourceRequestInfo::AllocateForTesting(
312 request.get(),
313 content::RESOURCE_TYPE_XHR,
314 NULL,
315 kDefaultChildId,
316 kDefaultRouteId,
317 MSG_ROUTING_NONE,
318 false, // is_main_frame
319 false, // parent_is_main_frame
320 true, // allow_download
321 false); // is_async
323 // Install a prerender throttle.
324 PrerenderResourceThrottle throttle(request.get());
325 delegate.SetThrottle(&throttle);
327 // Start the request and wait for a redirect.
328 request->Start();
329 delegate.Run();
330 // This calls WillRedirectRequestOnUI().
331 RunEvents();
333 // We should have cancelled the prerender.
334 EXPECT_EQ(FINAL_STATUS_BAD_DEFERRED_REDIRECT,
335 test_contents()->final_status());
337 // Cleanup work so the prerender is gone.
338 test_contents()->Cancel();
339 RunEvents();
342 } // namespace prerender