blob: 42a00c8538de5d97159ce39b22bc6940e31ed9ee [file] [log] [blame]
mattcary21521892016-09-08 07:25:591// Copyright (c) 2016 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#ifndef CHROME_BROWSER_PRERENDER_PRERENDER_TEST_UTILS_H_
6#define CHROME_BROWSER_PRERENDER_PRERENDER_TEST_UTILS_H_
7
mattcaryfb7f2b62016-10-17 08:34:358#include <functional>
John Abd-El-Maleka18f97802017-11-27 15:54:149#include <map>
pasko092f08e2016-10-20 13:32:4110#include <memory>
11#include <set>
12#include <string>
13#include <unordered_map>
14#include <vector>
mattcaryfb7f2b62016-10-17 08:34:3515
Brett Wilson275a1372017-09-01 20:27:5416#include "base/containers/circular_deque.h"
mattcary21521892016-09-08 07:25:5917#include "base/memory/weak_ptr.h"
18#include "base/run_loop.h"
Avi Drissman808f72a22018-04-16 21:35:0919#include "base/scoped_observer.h"
John Abd-El-Maleka18f97802017-11-27 15:54:1420#include "base/synchronization/lock.h"
Devlin Cronin626d80c2018-06-01 01:08:3621#include "base/test/metrics/histogram_tester.h"
mattcary21521892016-09-08 07:25:5922#include "chrome/browser/external_protocol/external_protocol_handler.h"
23#include "chrome/browser/prerender/prerender_contents.h"
mattcaryfb7f2b62016-10-17 08:34:3524#include "chrome/browser/prerender/prerender_manager.h"
mattcary21521892016-09-08 07:25:5925#include "chrome/browser/safe_browsing/test_safe_browsing_service.h"
26#include "chrome/test/base/in_process_browser_test.h"
Tim Volodinee45938472017-09-21 10:08:2227#include "components/safe_browsing/db/test_database_manager.h"
mattcary21521892016-09-08 07:25:5928#include "content/public/browser/browser_thread.h"
Avi Drissman808f72a22018-04-16 21:35:0929#include "content/public/browser/render_widget_host_observer.h"
mattcary21521892016-09-08 07:25:5930#include "url/gurl.h"
31
mattcary21521892016-09-08 07:25:5932namespace prerender {
33
34namespace test_utils {
35
mattcary21521892016-09-08 07:25:5936// A SafeBrowsingDatabaseManager implementation that returns a fixed result for
37// a given URL.
38class FakeSafeBrowsingDatabaseManager
39 : public safe_browsing::TestSafeBrowsingDatabaseManager {
40 public:
41 FakeSafeBrowsingDatabaseManager();
42
43 // Called on the IO thread to check if the given url is safe or not. If we
44 // can synchronously determine that the url is safe, CheckUrl returns true.
45 // Otherwise it returns false, and "client" is called asynchronously with the
46 // result when it is ready.
47 // Returns true, indicating a SAFE result, unless the URL is the fixed URL
48 // specified by the user, and the user-specified result is not SAFE
49 // (in which that result will be communicated back via a call into the
50 // client, and false will be returned).
51 // Overrides SafeBrowsingDatabaseManager::CheckBrowseUrl.
ricead852ea42017-06-27 15:10:2052 bool CheckBrowseUrl(const GURL& gurl,
53 const safe_browsing::SBThreatTypeSet& threat_types,
54 Client* client) override;
mattcary21521892016-09-08 07:25:5955
56 void SetThreatTypeForUrl(const GURL& url,
57 safe_browsing::SBThreatType threat_type) {
58 bad_urls_[url.spec()] = threat_type;
59 }
60
61 // These are called when checking URLs, so we implement them.
62 bool IsSupported() const override;
63 bool ChecksAreAlwaysAsync() const override;
64 bool CanCheckResourceType(
65 content::ResourceType /* resource_type */) const override;
66
67 bool CheckExtensionIDs(const std::set<std::string>& extension_ids,
68 Client* client) override;
69
70 private:
71 ~FakeSafeBrowsingDatabaseManager() override;
72
73 void OnCheckBrowseURLDone(const GURL& gurl, Client* client);
74
75 std::unordered_map<std::string, safe_browsing::SBThreatType> bad_urls_;
76 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingDatabaseManager);
77};
78
79// PrerenderContents that stops the UI message loop on DidStopLoading().
Avi Drissman808f72a22018-04-16 21:35:0980class TestPrerenderContents : public PrerenderContents,
81 public content::RenderWidgetHostObserver {
mattcary21521892016-09-08 07:25:5982 public:
83 TestPrerenderContents(PrerenderManager* prerender_manager,
84 Profile* profile,
85 const GURL& url,
86 const content::Referrer& referrer,
Ryan Sturmd154e1e2019-06-01 01:18:5987 const base::Optional<url::Origin>& initiator_origin,
mattcary21521892016-09-08 07:25:5988 Origin origin,
Matthew Cary276256f2018-11-14 10:15:0389 FinalStatus expected_final_status,
90 bool ignore_final_status);
mattcary21521892016-09-08 07:25:5991
92 ~TestPrerenderContents() override;
93
mattcary21521892016-09-08 07:25:5994 bool CheckURL(const GURL& url) override;
95
96 // For tests that open the prerender in a new background tab, the RenderView
97 // will not have been made visible when the PrerenderContents is destroyed
98 // even though it is used.
99 void set_should_be_shown(bool value) { should_be_shown_ = value; }
100
101 // For tests which do not know whether the prerender will be used.
102 void set_skip_final_checks(bool value) { skip_final_checks_ = value; }
103
104 FinalStatus expected_final_status() const { return expected_final_status_; }
105
106 private:
107 void OnRenderViewHostCreated(
108 content::RenderViewHost* new_render_view_host) override;
Avi Drissman808f72a22018-04-16 21:35:09109 void RenderWidgetHostVisibilityChanged(content::RenderWidgetHost* widget_host,
110 bool became_visible) override;
111 void RenderWidgetHostDestroyed(
112 content::RenderWidgetHost* widget_host) override;
mattcary21521892016-09-08 07:25:59113
114 FinalStatus expected_final_status_;
115
Avi Drissman808f72a22018-04-16 21:35:09116 ScopedObserver<content::RenderWidgetHost, content::RenderWidgetHostObserver>
117 observer_;
mattcary21521892016-09-08 07:25:59118 // The RenderViewHost created for the prerender, if any.
119 content::RenderViewHost* new_render_view_host_;
120 // Set to true when the prerendering RenderWidget is hidden.
121 bool was_hidden_;
122 // Set to true when the prerendering RenderWidget is shown, after having been
123 // hidden.
124 bool was_shown_;
125 // Expected final value of was_shown_. Defaults to true for
126 // FINAL_STATUS_USED, and false otherwise.
127 bool should_be_shown_;
128 // If true, |expected_final_status_| and other shutdown checks are skipped.
129 bool skip_final_checks_;
pasko07afa9f62016-10-27 15:01:15130
131 DISALLOW_COPY_AND_ASSIGN(TestPrerenderContents);
mattcary21521892016-09-08 07:25:59132};
133
134// A handle to a TestPrerenderContents whose lifetime is under the caller's
135// control. A PrerenderContents may be destroyed at any point. This allows
pasko07afa9f62016-10-27 15:01:15136// tracking the FinalStatus.
mattcary21521892016-09-08 07:25:59137class TestPrerender : public PrerenderContents::Observer,
138 public base::SupportsWeakPtr<TestPrerender> {
139 public:
140 TestPrerender();
141 ~TestPrerender() override;
142
143 TestPrerenderContents* contents() const { return contents_; }
144 int number_of_loads() const { return number_of_loads_; }
pasko07afa9f62016-10-27 15:01:15145 FinalStatus GetFinalStatus() const;
mattcary21521892016-09-08 07:25:59146
mattcary9b6654962016-10-20 10:57:20147 void WaitForCreate();
148 void WaitForStart();
149 void WaitForStop();
mattcary21521892016-09-08 07:25:59150
151 // Waits for |number_of_loads()| to be at least |expected_number_of_loads| OR
152 // for the prerender to stop running (just to avoid a timeout if the prerender
153 // dies). Note: this does not assert equality on the number of loads; the
154 // caller must do it instead.
155 void WaitForLoads(int expected_number_of_loads);
156
157 void OnPrerenderCreated(TestPrerenderContents* contents);
158
159 // PrerenderContents::Observer implementation:
160 void OnPrerenderStart(PrerenderContents* contents) override;
161
162 void OnPrerenderStopLoading(PrerenderContents* contents) override;
163
164 void OnPrerenderStop(PrerenderContents* contents) override;
165
166 private:
167 TestPrerenderContents* contents_;
pasko07afa9f62016-10-27 15:01:15168 FinalStatus final_status_;
mattcary21521892016-09-08 07:25:59169 int number_of_loads_;
170
171 int expected_number_of_loads_;
172 std::unique_ptr<base::RunLoop> load_waiter_;
173
mattcary9b6654962016-10-20 10:57:20174 bool started_;
175 bool stopped_;
176
mattcary21521892016-09-08 07:25:59177 base::RunLoop create_loop_;
178 base::RunLoop start_loop_;
179 base::RunLoop stop_loop_;
180
181 DISALLOW_COPY_AND_ASSIGN(TestPrerender);
182};
183
mattcaryfb7f2b62016-10-17 08:34:35184// Blocks until a TestPrerenderContents has been destroyed with the given final
185// status. Should be created with a TestPrerenderContents, and then
186// WaitForDestroy should be called and its return value checked.
187class DestructionWaiter {
188 public:
189 // Does not own the prerender_contents, which must outlive any call to
190 // WaitForDestroy().
191 DestructionWaiter(TestPrerenderContents* prerender_contents,
192 FinalStatus expected_final_status);
193
194 ~DestructionWaiter();
195
196 // Returns true if the TestPrerenderContents was destroyed with the correct
197 // final status, or false otherwise. Note this also may hang if the contents
198 // is never destroyed (which will presumably cause the test to time out).
199 bool WaitForDestroy();
200
201 private:
202 class DestructionMarker : public PrerenderContents::Observer {
203 public:
204 // Does not own the waiter which must outlive the TestPrerenderContents.
205 explicit DestructionMarker(DestructionWaiter* waiter);
206
207 ~DestructionMarker() override;
208
209 void OnPrerenderStop(PrerenderContents* contents) override;
210
211 private:
212 DestructionWaiter* waiter_;
pasko07afa9f62016-10-27 15:01:15213
214 DISALLOW_COPY_AND_ASSIGN(DestructionMarker);
mattcaryfb7f2b62016-10-17 08:34:35215 };
216
217 // To be called by a DestructionMarker.
218 void MarkDestruction(FinalStatus reason);
219
220 base::RunLoop wait_loop_;
221 FinalStatus expected_final_status_;
222 bool saw_correct_status_;
223 std::unique_ptr<DestructionMarker> marker_;
pasko07afa9f62016-10-27 15:01:15224
225 DISALLOW_COPY_AND_ASSIGN(DestructionWaiter);
mattcaryfb7f2b62016-10-17 08:34:35226};
227
mattcaryf564b5a82017-01-02 10:59:32228// Wait until a PrerenderManager has seen a first contentful paint.
229class FirstContentfulPaintManagerWaiter : public PrerenderManagerObserver {
230 public:
231 // Create and return a pointer to a |FirstContentfulPaintManagerWaiter|. The
232 // instance is owned by the |PrerenderManager|.
233 static FirstContentfulPaintManagerWaiter* Create(PrerenderManager* manager);
234
235 ~FirstContentfulPaintManagerWaiter() override;
236
237 void OnFirstContentfulPaint() override;
238
239 // Wait for a first contentful paint to be seen by our PrerenderManager.
240 void Wait();
241
242 private:
243 FirstContentfulPaintManagerWaiter();
244
245 std::unique_ptr<base::RunLoop> waiter_;
246 bool saw_fcp_;
247
248 DISALLOW_COPY_AND_ASSIGN(FirstContentfulPaintManagerWaiter);
249};
250
mattcaryfb7f2b62016-10-17 08:34:35251// PrerenderContentsFactory that uses TestPrerenderContents.
mattcary21521892016-09-08 07:25:59252class TestPrerenderContentsFactory : public PrerenderContents::Factory {
253 public:
254 TestPrerenderContentsFactory();
255
256 ~TestPrerenderContentsFactory() override;
257
258 std::unique_ptr<TestPrerender> ExpectPrerenderContents(
259 FinalStatus final_status);
260
Matthew Cary276256f2018-11-14 10:15:03261 void IgnorePrerenderContents();
262
mattcary21521892016-09-08 07:25:59263 PrerenderContents* CreatePrerenderContents(
264 PrerenderManager* prerender_manager,
265 Profile* profile,
266 const GURL& url,
267 const content::Referrer& referrer,
Ryan Sturmd154e1e2019-06-01 01:18:59268 const base::Optional<url::Origin>& initiator_origin,
mattcary21521892016-09-08 07:25:59269 Origin origin) override;
270
271 private:
272 struct ExpectedContents {
273 ExpectedContents();
274 ExpectedContents(const ExpectedContents& other);
275 ExpectedContents(FinalStatus final_status,
276 const base::WeakPtr<TestPrerender>& handle);
Matthew Cary276256f2018-11-14 10:15:03277 explicit ExpectedContents(bool ignore);
mattcary21521892016-09-08 07:25:59278 ~ExpectedContents();
279
Ryan Sturm74e5c532019-04-05 23:29:47280 FinalStatus final_status = FINAL_STATUS_UNKNOWN;
Matthew Cary276256f2018-11-14 10:15:03281 bool ignore = false;
282 base::WeakPtr<TestPrerender> handle = nullptr;
mattcary21521892016-09-08 07:25:59283 };
284
Brett Wilson275a1372017-09-01 20:27:54285 base::circular_deque<ExpectedContents> expected_contents_queue_;
pasko07afa9f62016-10-27 15:01:15286
287 DISALLOW_COPY_AND_ASSIGN(TestPrerenderContentsFactory);
mattcary21521892016-09-08 07:25:59288};
289
290class PrerenderInProcessBrowserTest : virtual public InProcessBrowserTest {
291 public:
292 PrerenderInProcessBrowserTest();
293
294 ~PrerenderInProcessBrowserTest() override;
295
296 void SetUpCommandLine(base::CommandLine* command_line) override;
Eric Seckler56964ea2018-09-07 11:08:55297 void CreatedBrowserMainParts(
298 content::BrowserMainParts* browser_main_parts) override;
mattcary21521892016-09-08 07:25:59299 void TearDownInProcessBrowserTestFixture() override;
300 void SetUpOnMainThread() override;
301 content::SessionStorageNamespace* GetSessionStorageNamespace() const;
302
mattcaryfb7f2b62016-10-17 08:34:35303 // Many of the file and server manipulation commands are fussy about paths
304 // being relative or absolute. This makes path absolute if it is not
305 // already. The path must not be empty.
306 std::string MakeAbsolute(const std::string& path);
307
mattcary21521892016-09-08 07:25:59308 bool UrlIsInPrerenderManager(const std::string& html_file) const;
309 bool UrlIsInPrerenderManager(const GURL& url) const;
310
311 // Convenience function to get the currently active WebContents in
312 // current_browser().
313 content::WebContents* GetActiveWebContents() const;
314
315 PrerenderManager* GetPrerenderManager() const;
316
317 TestPrerenderContents* GetPrerenderContentsFor(const GURL& url) const;
318
mattcary5b870b672016-10-17 12:58:02319 // Set up an HTTPS server.
mattcaryfb7f2b62016-10-17 08:34:35320 void UseHttpsSrcServer();
321
322 // Returns the currently active server. See |UseHttpsSrcServer|.
323 net::EmbeddedTestServer* src_server();
324
mattcary21521892016-09-08 07:25:59325 safe_browsing::TestSafeBrowsingServiceFactory* safe_browsing_factory() const {
326 return safe_browsing_factory_.get();
327 }
328
mattcaryfb7f2b62016-10-17 08:34:35329 test_utils::FakeSafeBrowsingDatabaseManager*
330 GetFakeSafeBrowsingDatabaseManager();
331
mattcary21521892016-09-08 07:25:59332 TestPrerenderContentsFactory* prerender_contents_factory() const {
333 return prerender_contents_factory_;
334 }
335
336 void set_autostart_test_server(bool value) { autostart_test_server_ = value; }
337
338 void set_browser(Browser* browser) { explicitly_set_browser_ = browser; }
339
340 Browser* current_browser() const {
341 return explicitly_set_browser_ ? explicitly_set_browser_ : browser();
342 }
343
mattcaryfb7f2b62016-10-17 08:34:35344 const base::HistogramTester& histogram_tester() { return histogram_tester_; }
345
346 // Returns a string for pattern-matching TaskManager tab entries.
347 base::string16 MatchTaskManagerTab(const char* page_title);
348
349 // Returns a string for pattern-matching TaskManager prerender entries.
350 base::string16 MatchTaskManagerPrerender(const char* page_title);
351
mattcaryf0abffc2017-04-14 10:44:37352 // Returns a GURL for an EmbeddedTestServer that will serves the file
353 // |url_file| with |replacement_text| replacing |replacement_variable|.
354 GURL GetURLWithReplacement(const std::string& url_file,
355 const std::string& replacement_variable,
356 const std::string& replacement_text);
357
mattcaryfb7f2b62016-10-17 08:34:35358 protected:
pasko07afa9f62016-10-27 15:01:15359 // For each FinalStatus in |expected_final_status_queue| creates a prerender
360 // that is going to verify the correctness of its FinalStatus upon
361 // destruction. Waits for creation of the first PrerenderContents.
mattcary5a8525ea2016-10-19 12:40:45362 std::vector<std::unique_ptr<TestPrerender>> NavigateWithPrerenders(
mattcaryfb7f2b62016-10-17 08:34:35363 const GURL& loader_url,
pasko07afa9f62016-10-27 15:01:15364 const std::vector<FinalStatus>& expected_final_status_queue);
365
366 // Creates the URL that instructs the test server to substitute the text
367 // |replacement_variable| in the contents of the file pointed to by
368 // |loader_path| with |url_to_prerender|. Also appends the |loader_query| to
369 // the URL.
370 GURL ServeLoaderURL(const std::string& loader_path,
371 const std::string& replacement_variable,
372 const GURL& url_to_prerender,
373 const std::string& loader_query);
mattcaryfb7f2b62016-10-17 08:34:35374
John Abd-El-Maleka18f97802017-11-27 15:54:14375 uint32_t GetRequestCount(const GURL& url);
376 void WaitForRequestCount(const GURL& url, uint32_t expected_count);
377
mattcary21521892016-09-08 07:25:59378 private:
John Abd-El-Maleka18f97802017-11-27 15:54:14379 void MonitorResourceRequest(const net::test_server::HttpRequest& request);
mattcary21521892016-09-08 07:25:59380 std::unique_ptr<ExternalProtocolHandler::Delegate>
381 external_protocol_handler_delegate_;
382 std::unique_ptr<safe_browsing::TestSafeBrowsingServiceFactory>
383 safe_browsing_factory_;
384 TestPrerenderContentsFactory* prerender_contents_factory_;
385 Browser* explicitly_set_browser_;
386 bool autostart_test_server_;
mattcaryfb7f2b62016-10-17 08:34:35387 base::HistogramTester histogram_tester_;
388 std::unique_ptr<net::EmbeddedTestServer> https_src_server_;
pasko07afa9f62016-10-27 15:01:15389
John Abd-El-Maleka18f97802017-11-27 15:54:14390 // The following are guarded by |lock_| as they're used on multiple threads.
391 std::map<GURL, uint32_t> requests_;
392 GURL waiting_url_;
393 uint32_t waiting_count_ = 0;
394 base::Closure waiting_closure_;
395 base::Lock lock_;
396
pasko07afa9f62016-10-27 15:01:15397 DISALLOW_COPY_AND_ASSIGN(PrerenderInProcessBrowserTest);
mattcary21521892016-09-08 07:25:59398};
399
mattcary6430db2f2017-03-20 18:16:08400// RAII class to save and restore the prerender mode.
401class RestorePrerenderMode {
402 public:
Egor Pasko6fed3822018-05-30 10:33:14403 RestorePrerenderMode() : prev_mode_(PrerenderManager::GetMode()) {}
mattcary6430db2f2017-03-20 18:16:08404
405 ~RestorePrerenderMode() {
406 PrerenderManager::SetMode(prev_mode_);
mattcary6430db2f2017-03-20 18:16:08407 }
408
409 private:
410 PrerenderManager::PrerenderManagerMode prev_mode_;
mattcary6430db2f2017-03-20 18:16:08411
412 DISALLOW_COPY_AND_ASSIGN(RestorePrerenderMode);
413};
414
mattcary21521892016-09-08 07:25:59415} // namespace test_utils
416
417} // namespace prerender
418
419#endif // CHROME_BROWSER_PRERENDER_PRERENDER_TEST_UTILS_H_