Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(125)

Side by Side Diff: chrome/browser/prerender/prerender_test_utils.cc

Issue 2309443002: NoState Prefetch: Refactor prerender_browsertests.cc (Closed)
Patch Set: Comment Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/prerender/prerender_test_utils.h ('k') | chrome/test/BUILD.gn » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/prerender/prerender_test_utils.h"
6
7 #include "base/command_line.h"
8 #include "chrome/browser/prerender/prerender_manager.h"
9 #include "chrome/browser/prerender/prerender_manager_factory.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate. h"
12 #include "chrome/browser/safe_browsing/local_database_manager.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/tabs/tab_strip_model.h"
15 #include "chrome/common/pref_names.h"
16 #include "components/prefs/pref_service.h"
17 #include "content/public/browser/notification_details.h"
18 #include "content/public/browser/notification_source.h"
19 #include "content/public/browser/notification_types.h"
20 #include "content/public/browser/render_view_host.h"
21 #include "content/public/common/content_switches.h"
22 #include "content/public/common/url_constants.h"
23 #include "content/public/test/ppapi_test_utils.h"
24 #include "net/url_request/url_request_filter.h"
25 #include "ppapi/shared_impl/ppapi_switches.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27
28 using content::BrowserThread;
29 using content::RenderViewHost;
30
31 namespace prerender {
32
33 namespace test_utils {
34
35 namespace {
36
37 // Wrapper over URLRequestMockHTTPJob that exposes extra callbacks.
38 class MockHTTPJob : public net::URLRequestMockHTTPJob {
39 public:
40 MockHTTPJob(net::URLRequest* request,
41 net::NetworkDelegate* delegate,
42 const base::FilePath& file)
43 : net::URLRequestMockHTTPJob(
44 request,
45 delegate,
46 file,
47 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
48 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)) {}
49
50 void set_start_callback(const base::Closure& start_callback) {
51 start_callback_ = start_callback;
52 }
53
54 void Start() override {
55 if (!start_callback_.is_null())
56 start_callback_.Run();
57 net::URLRequestMockHTTPJob::Start();
58 }
59
60 private:
61 ~MockHTTPJob() override {}
62
63 base::Closure start_callback_;
64 };
65
66 // Protocol handler which counts the number of requests that start.
67 class CountingInterceptor : public net::URLRequestInterceptor {
68 public:
69 CountingInterceptor(const base::FilePath& file,
70 const base::WeakPtr<RequestCounter>& counter)
71 : file_(file), counter_(counter), weak_factory_(this) {}
72 ~CountingInterceptor() override {}
73
74 net::URLRequestJob* MaybeInterceptRequest(
75 net::URLRequest* request,
76 net::NetworkDelegate* network_delegate) const override {
77 MockHTTPJob* job = new MockHTTPJob(request, network_delegate, file_);
78 job->set_start_callback(base::Bind(&CountingInterceptor::RequestStarted,
79 weak_factory_.GetWeakPtr()));
80 return job;
81 }
82
83 void RequestStarted() {
84 content::BrowserThread::PostTask(
85 content::BrowserThread::UI, FROM_HERE,
86 base::Bind(&RequestCounter::RequestStarted, counter_));
87 }
88
89 private:
90 base::FilePath file_;
91 base::WeakPtr<RequestCounter> counter_;
92 mutable base::WeakPtrFactory<CountingInterceptor> weak_factory_;
93 };
94
95 // An ExternalProtocolHandler that blocks everything and asserts it never is
96 // called.
97 class NeverRunsExternalProtocolHandlerDelegate
98 : public ExternalProtocolHandler::Delegate {
99 public:
100 scoped_refptr<shell_integration::DefaultProtocolClientWorker>
101 CreateShellWorker(
102 const shell_integration::DefaultWebClientWorkerCallback& callback,
103 const std::string& protocol) override {
104 NOTREACHED();
105 // This will crash, but it shouldn't get this far with BlockState::BLOCK
106 // anyway.
107 return nullptr;
108 }
109
110 ExternalProtocolHandler::BlockState GetBlockState(
111 const std::string& scheme) override {
112 // Block everything and fail the test.
113 ADD_FAILURE();
114 return ExternalProtocolHandler::BLOCK;
115 }
116
117 void BlockRequest() override {}
118
119 void RunExternalProtocolDialog(const GURL& url,
120 int render_process_host_id,
121 int routing_id,
122 ui::PageTransition page_transition,
123 bool has_user_gesture) override {
124 NOTREACHED();
125 }
126
127 void LaunchUrlWithoutSecurityCheck(const GURL& url) override { NOTREACHED(); }
128
129 void FinishedProcessingCheck() override { NOTREACHED(); }
130 };
131
132 } // namespace
133
134 RequestCounter::RequestCounter() : count_(0), expected_count_(-1) {}
135
136 RequestCounter::~RequestCounter() {}
137
138 void RequestCounter::RequestStarted() {
139 count_++;
140 if (loop_ && count_ == expected_count_)
141 loop_->Quit();
142 }
143
144 void RequestCounter::WaitForCount(int expected_count) {
145 ASSERT_TRUE(!loop_);
146 ASSERT_EQ(-1, expected_count_);
147 if (count_ < expected_count) {
148 expected_count_ = expected_count;
149 loop_.reset(new base::RunLoop);
150 loop_->Run();
151 expected_count_ = -1;
152 loop_.reset();
153 }
154
155 EXPECT_EQ(expected_count, count_);
156 }
157
158 FakeSafeBrowsingDatabaseManager::FakeSafeBrowsingDatabaseManager() {}
159
160 bool FakeSafeBrowsingDatabaseManager::CheckBrowseUrl(const GURL& gurl,
161 Client* client) {
162 if (bad_urls_.find(gurl.spec()) == bad_urls_.end() ||
163 bad_urls_[gurl.spec()] == safe_browsing::SB_THREAT_TYPE_SAFE) {
164 return true;
165 }
166
167 content::BrowserThread::PostTask(
168 content::BrowserThread::IO, FROM_HERE,
169 base::Bind(&FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone, this,
170 gurl, client));
171 return false;
172 }
173
174 bool FakeSafeBrowsingDatabaseManager::IsSupported() const {
175 return true;
176 }
177
178 bool FakeSafeBrowsingDatabaseManager::ChecksAreAlwaysAsync() const {
179 return false;
180 }
181
182 bool FakeSafeBrowsingDatabaseManager::CanCheckResourceType(
183 content::ResourceType /* resource_type */) const {
184 return true;
185 }
186
187 bool FakeSafeBrowsingDatabaseManager::CheckExtensionIDs(
188 const std::set<std::string>& extension_ids,
189 Client* client) {
190 return true;
191 }
192
193 FakeSafeBrowsingDatabaseManager::~FakeSafeBrowsingDatabaseManager() {}
194
195 void FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone(const GURL& gurl,
196 Client* client) {
197 std::vector<safe_browsing::SBThreatType> expected_threats;
198 expected_threats.push_back(safe_browsing::SB_THREAT_TYPE_URL_MALWARE);
199 expected_threats.push_back(safe_browsing::SB_THREAT_TYPE_URL_PHISHING);
200 // TODO(nparker): Replace SafeBrowsingCheck w/ a call to
201 // client->OnCheckBrowseUrlResult()
202 safe_browsing::LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck sb_check(
203 std::vector<GURL>(1, gurl), std::vector<safe_browsing::SBFullHash>(),
204 client, safe_browsing::MALWARE, expected_threats);
205 sb_check.url_results[0] = bad_urls_[gurl.spec()];
206 sb_check.OnSafeBrowsingResult();
207 }
208
209 TestPrerenderContents::TestPrerenderContents(
210 PrerenderManager* prerender_manager,
211 Profile* profile,
212 const GURL& url,
213 const content::Referrer& referrer,
214 Origin origin,
215 FinalStatus expected_final_status)
216 : PrerenderContents(prerender_manager, profile, url, referrer, origin),
217 expected_final_status_(expected_final_status),
218 new_render_view_host_(nullptr),
219 was_hidden_(false),
220 was_shown_(false),
221 should_be_shown_(expected_final_status == FINAL_STATUS_USED),
222 skip_final_checks_(false) {}
223
224 TestPrerenderContents::~TestPrerenderContents() {
225 if (skip_final_checks_)
226 return;
227
228 EXPECT_EQ(expected_final_status_, final_status())
229 << " when testing URL " << prerender_url().path()
230 << " (Expected: " << NameFromFinalStatus(expected_final_status_)
231 << ", Actual: " << NameFromFinalStatus(final_status()) << ")";
232
233 // Prerendering RenderViewHosts should be hidden before the first
234 // navigation, so this should be happen for every PrerenderContents for
235 // which a RenderViewHost is created, regardless of whether or not it's
236 // used.
237 if (new_render_view_host_)
238 EXPECT_TRUE(was_hidden_);
239
240 // A used PrerenderContents will only be destroyed when we swap out
241 // WebContents, at the end of a navigation caused by a call to
242 // NavigateToURLImpl().
243 if (final_status() == FINAL_STATUS_USED)
244 EXPECT_TRUE(new_render_view_host_);
245
246 EXPECT_EQ(should_be_shown_, was_shown_);
247 }
248
249 void TestPrerenderContents::RenderProcessGone(base::TerminationStatus status) {
250 // On quit, it's possible to end up here when render processes are closed
251 // before the PrerenderManager is destroyed. As a result, it's possible to
252 // get either FINAL_STATUS_APP_TERMINATING or FINAL_STATUS_RENDERER_CRASHED
253 // on quit.
254 //
255 // It's also possible for this to be called after we've been notified of
256 // app termination, but before we've been deleted, which is why the second
257 // check is needed.
258 if (expected_final_status_ == FINAL_STATUS_APP_TERMINATING &&
259 final_status() != expected_final_status_) {
260 expected_final_status_ = FINAL_STATUS_RENDERER_CRASHED;
261 }
262
263 PrerenderContents::RenderProcessGone(status);
264 }
265
266 bool TestPrerenderContents::CheckURL(const GURL& url) {
267 // Prevent FINAL_STATUS_UNSUPPORTED_SCHEME when navigating to about:crash in
268 // the PrerenderRendererCrash test.
269 if (url.spec() != content::kChromeUICrashURL)
270 return PrerenderContents::CheckURL(url);
271 return true;
272 }
273
274 void TestPrerenderContents::OnRenderViewHostCreated(
275 RenderViewHost* new_render_view_host) {
276 // Used to make sure the RenderViewHost is hidden and, if used,
277 // subsequently shown.
278 notification_registrar().Add(
279 this, content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
280 content::Source<content::RenderWidgetHost>(
281 new_render_view_host->GetWidget()));
282
283 new_render_view_host_ = new_render_view_host;
284
285 PrerenderContents::OnRenderViewHostCreated(new_render_view_host);
286 }
287
288 void TestPrerenderContents::Observe(
289 int type,
290 const content::NotificationSource& source,
291 const content::NotificationDetails& details) {
292 if (type == content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED) {
293 EXPECT_EQ(new_render_view_host_->GetWidget(),
294 content::Source<content::RenderWidgetHost>(source).ptr());
295 bool is_visible = *content::Details<bool>(details).ptr();
296
297 if (!is_visible) {
298 was_hidden_ = true;
299 } else if (is_visible && was_hidden_) {
300 // Once hidden, a prerendered RenderViewHost should only be shown after
301 // being removed from the PrerenderContents for display.
302 EXPECT_FALSE(GetRenderViewHost());
303 was_shown_ = true;
304 }
305 return;
306 }
307 PrerenderContents::Observe(type, source, details);
308 }
309
310 TestPrerender::TestPrerender()
311 : contents_(nullptr), number_of_loads_(0), expected_number_of_loads_(0) {}
312
313 TestPrerender::~TestPrerender() {
314 if (contents_)
315 contents_->RemoveObserver(this);
316 }
317
318 void TestPrerender::WaitForLoads(int expected_number_of_loads) {
319 DCHECK(!load_waiter_);
320 DCHECK(!expected_number_of_loads_);
321 if (number_of_loads_ < expected_number_of_loads) {
322 load_waiter_.reset(new base::RunLoop);
323 expected_number_of_loads_ = expected_number_of_loads;
324 load_waiter_->Run();
325 load_waiter_.reset();
326 expected_number_of_loads_ = 0;
327 }
328 EXPECT_LE(expected_number_of_loads, number_of_loads_);
329 }
330
331 void TestPrerender::OnPrerenderCreated(TestPrerenderContents* contents) {
332 DCHECK(!contents_);
333 contents_ = contents;
334 contents_->AddObserver(this);
335 create_loop_.Quit();
336 }
337
338 void TestPrerender::OnPrerenderStart(PrerenderContents* contents) {
339 start_loop_.Quit();
340 }
341
342 void TestPrerender::OnPrerenderStopLoading(PrerenderContents* contents) {
343 number_of_loads_++;
344 if (load_waiter_ && number_of_loads_ >= expected_number_of_loads_)
345 load_waiter_->Quit();
346 }
347
348 void TestPrerender::OnPrerenderStop(PrerenderContents* contents) {
349 DCHECK(contents_);
350 contents_ = nullptr;
351 stop_loop_.Quit();
352 // If there is a WaitForLoads call and it has yet to see the expected number
353 // of loads, stop the loop so the test fails instead of timing out.
354 if (load_waiter_)
355 load_waiter_->Quit();
356 }
357
358 TestPrerenderContentsFactory::TestPrerenderContentsFactory() {}
359
360 TestPrerenderContentsFactory::~TestPrerenderContentsFactory() {
361 EXPECT_TRUE(expected_contents_queue_.empty());
362 }
363
364 std::unique_ptr<TestPrerender>
365 TestPrerenderContentsFactory::ExpectPrerenderContents(
366 FinalStatus final_status) {
367 std::unique_ptr<TestPrerender> handle(new TestPrerender());
368 expected_contents_queue_.push_back(
369 ExpectedContents(final_status, handle->AsWeakPtr()));
370 return handle;
371 }
372
373 PrerenderContents* TestPrerenderContentsFactory::CreatePrerenderContents(
374 PrerenderManager* prerender_manager,
375 Profile* profile,
376 const GURL& url,
377 const content::Referrer& referrer,
378 Origin origin) {
379 ExpectedContents expected;
380 if (!expected_contents_queue_.empty()) {
381 expected = expected_contents_queue_.front();
382 expected_contents_queue_.pop_front();
383 }
384 TestPrerenderContents* contents = new TestPrerenderContents(
385 prerender_manager, profile, url, referrer, origin, expected.final_status);
386 if (expected.handle)
387 expected.handle->OnPrerenderCreated(contents);
388 return contents;
389 }
390
391 TestPrerenderContentsFactory::ExpectedContents::ExpectedContents()
392 : final_status(FINAL_STATUS_MAX) {}
393
394 TestPrerenderContentsFactory::ExpectedContents::ExpectedContents(
395 const ExpectedContents& other) = default;
396
397 TestPrerenderContentsFactory::ExpectedContents::ExpectedContents(
398 FinalStatus final_status,
399 const base::WeakPtr<TestPrerender>& handle)
400 : final_status(final_status), handle(handle) {}
401
402 TestPrerenderContentsFactory::ExpectedContents::~ExpectedContents() {}
403
404 PrerenderInProcessBrowserTest::PrerenderInProcessBrowserTest()
405 : external_protocol_handler_delegate_(
406 base::MakeUnique<NeverRunsExternalProtocolHandlerDelegate>()),
407 safe_browsing_factory_(
408 base::MakeUnique<safe_browsing::TestSafeBrowsingServiceFactory>()),
409 prerender_contents_factory_(nullptr),
410 explicitly_set_browser_(nullptr),
411 autostart_test_server_(true) {}
412
413 PrerenderInProcessBrowserTest::~PrerenderInProcessBrowserTest() {}
414
415 void PrerenderInProcessBrowserTest::SetUpCommandLine(
416 base::CommandLine* command_line) {
417 command_line->AppendSwitch(switches::kEnablePepperTesting);
418 command_line->AppendSwitchASCII(switches::kOverridePluginPowerSaverForTesting,
419 "ignore-list");
420 ASSERT_TRUE(ppapi::RegisterPowerSaverTestPlugin(command_line));
421 }
422
423 void PrerenderInProcessBrowserTest::TearDownInProcessBrowserTestFixture() {
424 safe_browsing::SafeBrowsingService::RegisterFactory(nullptr);
425 }
426
427 content::SessionStorageNamespace*
428 PrerenderInProcessBrowserTest::GetSessionStorageNamespace() const {
429 content::WebContents* web_contents = GetActiveWebContents();
430 if (!web_contents)
431 return nullptr;
432 return web_contents->GetController().GetDefaultSessionStorageNamespace();
433 }
434
435 bool PrerenderInProcessBrowserTest::UrlIsInPrerenderManager(
436 const std::string& html_file) const {
437 return UrlIsInPrerenderManager(embedded_test_server()->GetURL(html_file));
438 }
439
440 bool PrerenderInProcessBrowserTest::UrlIsInPrerenderManager(
441 const GURL& url) const {
442 return GetPrerenderManager()->FindPrerenderData(
443 url, GetSessionStorageNamespace()) != nullptr;
444 }
445
446 content::WebContents* PrerenderInProcessBrowserTest::GetActiveWebContents()
447 const {
448 return current_browser()->tab_strip_model()->GetActiveWebContents();
449 }
450
451 PrerenderManager* PrerenderInProcessBrowserTest::GetPrerenderManager() const {
452 return PrerenderManagerFactory::GetForProfile(current_browser()->profile());
453 }
454
455 TestPrerenderContents* PrerenderInProcessBrowserTest::GetPrerenderContentsFor(
456 const GURL& url) const {
457 PrerenderManager::PrerenderData* prerender_data =
458 GetPrerenderManager()->FindPrerenderData(url, nullptr);
459 return static_cast<TestPrerenderContents*>(
460 prerender_data ? prerender_data->contents() : nullptr);
461 }
462
463 std::unique_ptr<TestPrerender> PrerenderInProcessBrowserTest::PrerenderTestURL(
464 const std::string& html_file,
465 FinalStatus expected_final_status,
466 int expected_number_of_loads) {
467 GURL url = embedded_test_server()->GetURL(html_file);
468 return PrerenderTestURL(url, expected_final_status, expected_number_of_loads);
469 }
470
471 ScopedVector<TestPrerender> PrerenderInProcessBrowserTest::PrerenderTestURL(
472 const std::string& html_file,
473 const std::vector<FinalStatus>& expected_final_status_queue,
474 int expected_number_of_loads) {
475 GURL url = embedded_test_server()->GetURL(html_file);
476 return PrerenderTestURLImpl(url, expected_final_status_queue,
477 expected_number_of_loads);
478 }
479
480 std::unique_ptr<TestPrerender> PrerenderInProcessBrowserTest::PrerenderTestURL(
481 const GURL& url,
482 FinalStatus expected_final_status,
483 int expected_number_of_loads) {
484 std::vector<FinalStatus> expected_final_status_queue(1,
485 expected_final_status);
486 std::vector<TestPrerender*> prerenders;
487 PrerenderTestURLImpl(url, expected_final_status_queue,
488 expected_number_of_loads)
489 .release(&prerenders);
490 CHECK_EQ(1u, prerenders.size());
491 return std::unique_ptr<TestPrerender>(prerenders[0]);
492 }
493
494 void PrerenderInProcessBrowserTest::SetUpInProcessBrowserTestFixture() {
495 safe_browsing_factory_->SetTestDatabaseManager(
496 new test_utils::FakeSafeBrowsingDatabaseManager());
497 safe_browsing::SafeBrowsingService::RegisterFactory(
498 safe_browsing_factory_.get());
499 }
500
501 void PrerenderInProcessBrowserTest::SetUpOnMainThread() {
502 // Increase the memory allowed in a prerendered page above normal settings.
503 // Debug build bots occasionally run against the default limit, and tests
504 // were failing because the prerender was canceled due to memory exhaustion.
505 // http://crbug.com/93076
506 GetPrerenderManager()->mutable_config().max_bytes = 2000 * 1024 * 1024;
507
508 current_browser()->profile()->GetPrefs()->SetBoolean(
509 prefs::kPromptForDownload, false);
510 if (autostart_test_server_)
511 ASSERT_TRUE(embedded_test_server()->Start());
512 ChromeResourceDispatcherHostDelegate::
513 SetExternalProtocolHandlerDelegateForTesting(
514 external_protocol_handler_delegate_.get());
515
516 PrerenderManager* prerender_manager = GetPrerenderManager();
517 ASSERT_TRUE(prerender_manager);
518 prerender_manager->mutable_config().rate_limit_enabled = false;
519 ASSERT_FALSE(prerender_contents_factory_);
520 prerender_contents_factory_ = new TestPrerenderContentsFactory;
521 prerender_manager->SetPrerenderContentsFactoryForTest(
522 prerender_contents_factory_);
523 ASSERT_TRUE(safe_browsing_factory_->test_safe_browsing_service());
524 }
525
526 void CreateCountingInterceptorOnIO(
527 const GURL& url,
528 const base::FilePath& file,
529 const base::WeakPtr<RequestCounter>& counter) {
530 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
531 std::unique_ptr<net::URLRequestInterceptor> request_interceptor(
532 new CountingInterceptor(file, counter));
533 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
534 url, std::move(request_interceptor));
535 }
536
537 void CreateMockInterceptorOnIO(const GURL& url, const base::FilePath& file) {
538 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
539 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
540 url, net::URLRequestMockHTTPJob::CreateInterceptorForSingleFile(
541 file, content::BrowserThread::GetBlockingPool()));
542 }
543
544 } // namespace test_utils
545
546 } // namespace prerender
OLDNEW
« no previous file with comments | « chrome/browser/prerender/prerender_test_utils.h ('k') | chrome/test/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698