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

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

Issue 2309443002: NoState Prefetch: Refactor prerender_browsertests.cc (Closed)
Patch Set: comments/rebase 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
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 "ppapi/shared_impl/ppapi_switches.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26
27 using content::BrowserThread;
28 using content::RenderViewHost;
29
30 namespace prerender {
31
32 namespace test_utils {
33
34 namespace {
35
36 // Wrapper over URLRequestMockHTTPJob that exposes extra callbacks.
37 class MockHTTPJob : public net::URLRequestMockHTTPJob {
38 public:
39 MockHTTPJob(net::URLRequest* request,
40 net::NetworkDelegate* delegate,
41 const base::FilePath& file)
42 : net::URLRequestMockHTTPJob(
43 request,
44 delegate,
45 file,
46 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
47 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)) {}
48
49 void set_start_callback(const base::Closure& start_callback) {
50 start_callback_ = start_callback;
51 }
52
53 void Start() override {
54 if (!start_callback_.is_null())
55 start_callback_.Run();
56 net::URLRequestMockHTTPJob::Start();
57 }
58
59 private:
60 ~MockHTTPJob() override {}
61
62 base::Closure start_callback_;
63 };
64
65 // Protocol handler which counts the number of requests that start.
66 class CountingInterceptor : public net::URLRequestInterceptor {
67 public:
68 CountingInterceptor(const base::FilePath& file,
69 const base::WeakPtr<RequestCounter>& counter)
70 : file_(file), counter_(counter), weak_factory_(this) {}
71 ~CountingInterceptor() override {}
72
73 net::URLRequestJob* MaybeInterceptRequest(
74 net::URLRequest* request,
75 net::NetworkDelegate* network_delegate) const override {
76 MockHTTPJob* job = new MockHTTPJob(request, network_delegate, file_);
77 job->set_start_callback(base::Bind(&CountingInterceptor::RequestStarted,
78 weak_factory_.GetWeakPtr()));
79 return job;
80 }
81
82 void RequestStarted() {
83 content::BrowserThread::PostTask(
84 content::BrowserThread::UI, FROM_HERE,
85 base::Bind(&RequestCounter::RequestStarted, counter_));
86 }
87
88 private:
89 base::FilePath file_;
90 base::WeakPtr<RequestCounter> counter_;
91 mutable base::WeakPtrFactory<CountingInterceptor> weak_factory_;
92 };
93
94 // An ExternalProtocolHandler that blocks everything and asserts it never is
95 // called.
96 class NeverRunsExternalProtocolHandlerDelegate
97 : public ExternalProtocolHandler::Delegate {
98 public:
99 scoped_refptr<shell_integration::DefaultProtocolClientWorker>
100 CreateShellWorker(
101 const shell_integration::DefaultWebClientWorkerCallback& callback,
102 const std::string& protocol) override {
103 NOTREACHED();
104 // This will crash, but it shouldn't get this far with BlockState::BLOCK
105 // anyway.
106 return nullptr;
107 }
108
109 ExternalProtocolHandler::BlockState GetBlockState(
110 const std::string& scheme) override {
111 // Block everything and fail the test.
112 ADD_FAILURE();
113 return ExternalProtocolHandler::BLOCK;
114 }
115
116 void BlockRequest() override {}
117
118 void RunExternalProtocolDialog(const GURL& url,
119 int render_process_host_id,
120 int routing_id,
121 ui::PageTransition page_transition,
122 bool has_user_gesture) override {
123 NOTREACHED();
124 }
125
126 void LaunchUrlWithoutSecurityCheck(const GURL& url) override { NOTREACHED(); }
127
128 void FinishedProcessingCheck() override { NOTREACHED(); }
129 };
130
131 } // namespace
132
133 RequestCounter::RequestCounter() : count_(0), expected_count_(-1) {}
134
135 RequestCounter::~RequestCounter() {}
136
137 void RequestCounter::RequestStarted() {
138 count_++;
139 if (loop_ && count_ == expected_count_)
140 loop_->Quit();
141 }
142
143 void RequestCounter::WaitForCount(int expected_count) {
144 ASSERT_TRUE(!loop_);
145 ASSERT_EQ(-1, expected_count_);
146 if (count_ < expected_count) {
147 expected_count_ = expected_count;
148 loop_.reset(new base::RunLoop);
149 loop_->Run();
150 expected_count_ = -1;
151 loop_.reset();
152 }
153
154 EXPECT_EQ(expected_count, count_);
155 }
156
157 FakeSafeBrowsingDatabaseManager::FakeSafeBrowsingDatabaseManager() {}
158
159 bool FakeSafeBrowsingDatabaseManager::CheckBrowseUrl(const GURL& gurl,
160 Client* client) {
161 if (bad_urls_.find(gurl.spec()) == bad_urls_.end() ||
162 bad_urls_[gurl.spec()] == safe_browsing::SB_THREAT_TYPE_SAFE) {
163 return true;
164 }
165
166 content::BrowserThread::PostTask(
167 content::BrowserThread::IO, FROM_HERE,
168 base::Bind(&FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone, this,
169 gurl, client));
170 return false;
171 }
172
173 bool FakeSafeBrowsingDatabaseManager::IsSupported() const {
174 return true;
175 }
176
177 bool FakeSafeBrowsingDatabaseManager::ChecksAreAlwaysAsync() const {
178 return false;
179 }
180
181 bool FakeSafeBrowsingDatabaseManager::CanCheckResourceType(
182 content::ResourceType /* resource_type */) const {
183 return true;
184 }
185
186 bool FakeSafeBrowsingDatabaseManager::CheckExtensionIDs(
187 const std::set<std::string>& extension_ids,
188 Client* client) {
189 return true;
190 }
191
192 FakeSafeBrowsingDatabaseManager::~FakeSafeBrowsingDatabaseManager() {}
193
194 void FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone(const GURL& gurl,
195 Client* client) {
196 std::vector<safe_browsing::SBThreatType> expected_threats;
197 expected_threats.push_back(safe_browsing::SB_THREAT_TYPE_URL_MALWARE);
198 expected_threats.push_back(safe_browsing::SB_THREAT_TYPE_URL_PHISHING);
199 // TODO(nparker): Replace SafeBrowsingCheck w/ a call to
200 // client->OnCheckBrowseUrlResult()
201 safe_browsing::LocalSafeBrowsingDatabaseManager::SafeBrowsingCheck sb_check(
202 std::vector<GURL>(1, gurl), std::vector<safe_browsing::SBFullHash>(),
203 client, safe_browsing::MALWARE, expected_threats);
204 sb_check.url_results[0] = bad_urls_[gurl.spec()];
205 sb_check.OnSafeBrowsingResult();
206 }
207
208 TestPrerenderContents::TestPrerenderContents(
209 PrerenderManager* prerender_manager,
210 Profile* profile,
211 const GURL& url,
212 const content::Referrer& referrer,
213 Origin origin,
214 FinalStatus expected_final_status)
215 : PrerenderContents(prerender_manager, profile, url, referrer, origin),
216 expected_final_status_(expected_final_status),
217 new_render_view_host_(nullptr),
218 was_hidden_(false),
219 was_shown_(false),
220 should_be_shown_(expected_final_status == FINAL_STATUS_USED),
221 skip_final_checks_(false) {}
222
223 TestPrerenderContents::~TestPrerenderContents() {
224 if (skip_final_checks_)
225 return;
226
227 EXPECT_EQ(expected_final_status_, final_status())
228 << " when testing URL " << prerender_url().path()
229 << " (Expected: " << NameFromFinalStatus(expected_final_status_)
230 << ", Actual: " << NameFromFinalStatus(final_status()) << ")";
231
232 // Prerendering RenderViewHosts should be hidden before the first
233 // navigation, so this should be happen for every PrerenderContents for
234 // which a RenderViewHost is created, regardless of whether or not it's
235 // used.
236 if (new_render_view_host_)
237 EXPECT_TRUE(was_hidden_);
238
239 // A used PrerenderContents will only be destroyed when we swap out
240 // WebContents, at the end of a navigation caused by a call to
241 // NavigateToURLImpl().
242 if (final_status() == FINAL_STATUS_USED)
243 EXPECT_TRUE(new_render_view_host_);
244
245 EXPECT_EQ(should_be_shown_, was_shown_);
246 }
247
248 void TestPrerenderContents::RenderProcessGone(
249 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
424 void PrerenderInProcessBrowserTest::TearDownInProcessBrowserTestFixture() {
425 safe_browsing::SafeBrowsingService::RegisterFactory(nullptr);
426 }
427
428 content::SessionStorageNamespace*
429 PrerenderInProcessBrowserTest::GetSessionStorageNamespace() const {
430 content::WebContents* web_contents = GetActiveWebContents();
431 if (!web_contents)
432 return nullptr;
433 return web_contents->GetController().GetDefaultSessionStorageNamespace();
434 }
435
436 bool PrerenderInProcessBrowserTest::UrlIsInPrerenderManager(
437 const std::string& html_file) const {
438 return UrlIsInPrerenderManager(embedded_test_server()->GetURL(html_file));
439 }
440
441 bool PrerenderInProcessBrowserTest::UrlIsInPrerenderManager(
442 const GURL& url) const {
443 return GetPrerenderManager()->FindPrerenderData(
444 url, GetSessionStorageNamespace()) != nullptr;
445 }
446
447 content::WebContents* PrerenderInProcessBrowserTest::GetActiveWebContents()
448 const {
449 return current_browser()->tab_strip_model()->GetActiveWebContents();
450 }
451
452 PrerenderManager* PrerenderInProcessBrowserTest::GetPrerenderManager() const {
453 return PrerenderManagerFactory::GetForProfile(current_browser()->profile());
454 }
455
456 TestPrerenderContents* PrerenderInProcessBrowserTest::GetPrerenderContentsFor(
457 const GURL& url) const {
458 PrerenderManager::PrerenderData* prerender_data =
459 GetPrerenderManager()->FindPrerenderData(url, nullptr);
460 return static_cast<TestPrerenderContents*>(
461 prerender_data ? prerender_data->contents() : nullptr);
462 }
463
464 std::unique_ptr<TestPrerender> PrerenderInProcessBrowserTest::PrerenderTestURL(
465 const std::string& html_file,
466 FinalStatus expected_final_status,
467 int expected_number_of_loads) {
468 GURL url = embedded_test_server()->GetURL(html_file);
469 return PrerenderTestURL(url, expected_final_status, expected_number_of_loads);
470 }
471
472 ScopedVector<TestPrerender> PrerenderInProcessBrowserTest::PrerenderTestURL(
473 const std::string& html_file,
474 const std::vector<FinalStatus>& expected_final_status_queue,
475 int expected_number_of_loads) {
476 GURL url = embedded_test_server()->GetURL(html_file);
477 return PrerenderTestURLImpl(url, expected_final_status_queue,
478 expected_number_of_loads);
479 }
480
481 std::unique_ptr<TestPrerender> PrerenderInProcessBrowserTest::PrerenderTestURL(
482 const GURL& url,
483 FinalStatus expected_final_status,
484 int expected_number_of_loads) {
485 std::vector<FinalStatus> expected_final_status_queue(1,
486 expected_final_status);
487 std::vector<TestPrerender*> prerenders;
488 PrerenderTestURLImpl(url, expected_final_status_queue,
489 expected_number_of_loads)
490 .release(&prerenders);
pasko 2016/09/05 13:46:27 is this how git cl format performs the formatting?
mattcary 2016/09/06 08:06:20 I've run git cl format. Probably this is clang-for
pasko 2016/09/06 14:40:56 Yes, it is our flavor of clang-format
491 CHECK_EQ(1u, prerenders.size());
492 return std::unique_ptr<TestPrerender>(prerenders[0]);
493 }
494
495 void PrerenderInProcessBrowserTest::SetUpInProcessBrowserTestFixture() {
496 safe_browsing_factory_->SetTestDatabaseManager(
497 new test_utils::FakeSafeBrowsingDatabaseManager());
498 safe_browsing::SafeBrowsingService::RegisterFactory(
499 safe_browsing_factory_.get());
500 }
501
502 void PrerenderInProcessBrowserTest::SetUpOnMainThread() {
503 // Increase the memory allowed in a prerendered page above normal settings.
504 // Debug build bots occasionally run against the default limit, and tests
505 // were failing because the prerender was canceled due to memory exhaustion.
506 // http://crbug.com/93076
507 GetPrerenderManager()->mutable_config().max_bytes = 2000 * 1024 * 1024;
508
509 current_browser()->profile()->GetPrefs()->SetBoolean(
510 prefs::kPromptForDownload, false);
511 if (autostart_test_server_)
512 ASSERT_TRUE(embedded_test_server()->Start());
513 ChromeResourceDispatcherHostDelegate::
514 SetExternalProtocolHandlerDelegateForTesting(
515 external_protocol_handler_delegate_.get());
516
517 PrerenderManager* prerender_manager = GetPrerenderManager();
518 ASSERT_TRUE(prerender_manager);
519 prerender_manager->mutable_config().rate_limit_enabled = false;
520 ASSERT_FALSE(prerender_contents_factory_);
521 prerender_contents_factory_ = new TestPrerenderContentsFactory;
522 prerender_manager->SetPrerenderContentsFactoryForTest(
523 prerender_contents_factory_);
524 ASSERT_TRUE(safe_browsing_factory_->test_safe_browsing_service());
525 }
526
527 void CreateCountingInterceptorOnIO(
528 const GURL& url,
529 const base::FilePath& file,
530 const base::WeakPtr<RequestCounter>& counter) {
531 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
532 std::unique_ptr<net::URLRequestInterceptor> request_interceptor(
533 new CountingInterceptor(file, counter));
534 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
535 url, std::move(request_interceptor));
536 }
537
538 void CreateMockInterceptorOnIO(const GURL& url, const base::FilePath& file) {
539 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
540 net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
541 url,
542 net::URLRequestMockHTTPJob::CreateInterceptorForSingleFile(
543 file, content::BrowserThread::GetBlockingPool()));
544 }
545
546 } // namespace test_utils
547
548 } // namespace prerender
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698