blob: 3183d43456c9ad9f6bfe5a22c4f745370aa1d493 [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>
9
mattcary21521892016-09-08 07:25:5910#include "base/memory/weak_ptr.h"
11#include "base/run_loop.h"
mattcaryfb7f2b62016-10-17 08:34:3512#include "base/test/histogram_tester.h"
mattcary21521892016-09-08 07:25:5913#include "chrome/browser/external_protocol/external_protocol_handler.h"
14#include "chrome/browser/prerender/prerender_contents.h"
mattcaryfb7f2b62016-10-17 08:34:3515#include "chrome/browser/prerender/prerender_manager.h"
mattcary21521892016-09-08 07:25:5916#include "chrome/browser/safe_browsing/test_safe_browsing_service.h"
17#include "chrome/test/base/in_process_browser_test.h"
18#include "components/safe_browsing_db/test_database_manager.h"
19#include "content/public/browser/browser_thread.h"
20#include "net/test/url_request/url_request_mock_http_job.h"
21#include "net/url_request/url_request_interceptor.h"
22#include "url/gurl.h"
23
24namespace base {
25class FilePath;
26} // namespace base
27
28namespace net {
29class URLRequest;
30class NetworkDelegate;
31} // namespace net
32
33namespace prerender {
34
35namespace test_utils {
36
37// Dummy counter class to live on the UI thread for counting requests.
38class RequestCounter : public base::SupportsWeakPtr<RequestCounter> {
39 public:
40 RequestCounter();
41
42 ~RequestCounter();
43
44 int count() const { return count_; }
45
46 void RequestStarted();
47 void WaitForCount(int expected_count);
48
49 private:
50 int count_;
51 int expected_count_;
52 std::unique_ptr<base::RunLoop> loop_;
53};
54
55// A SafeBrowsingDatabaseManager implementation that returns a fixed result for
56// a given URL.
57class FakeSafeBrowsingDatabaseManager
58 : public safe_browsing::TestSafeBrowsingDatabaseManager {
59 public:
60 FakeSafeBrowsingDatabaseManager();
61
62 // Called on the IO thread to check if the given url is safe or not. If we
63 // can synchronously determine that the url is safe, CheckUrl returns true.
64 // Otherwise it returns false, and "client" is called asynchronously with the
65 // result when it is ready.
66 // Returns true, indicating a SAFE result, unless the URL is the fixed URL
67 // specified by the user, and the user-specified result is not SAFE
68 // (in which that result will be communicated back via a call into the
69 // client, and false will be returned).
70 // Overrides SafeBrowsingDatabaseManager::CheckBrowseUrl.
71 bool CheckBrowseUrl(const GURL& gurl, Client* client) override;
72
73 void SetThreatTypeForUrl(const GURL& url,
74 safe_browsing::SBThreatType threat_type) {
75 bad_urls_[url.spec()] = threat_type;
76 }
77
78 // These are called when checking URLs, so we implement them.
79 bool IsSupported() const override;
80 bool ChecksAreAlwaysAsync() const override;
81 bool CanCheckResourceType(
82 content::ResourceType /* resource_type */) const override;
83
84 bool CheckExtensionIDs(const std::set<std::string>& extension_ids,
85 Client* client) override;
86
87 private:
88 ~FakeSafeBrowsingDatabaseManager() override;
89
90 void OnCheckBrowseURLDone(const GURL& gurl, Client* client);
91
92 std::unordered_map<std::string, safe_browsing::SBThreatType> bad_urls_;
93 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingDatabaseManager);
94};
95
96// PrerenderContents that stops the UI message loop on DidStopLoading().
97class TestPrerenderContents : public PrerenderContents {
98 public:
99 TestPrerenderContents(PrerenderManager* prerender_manager,
100 Profile* profile,
101 const GURL& url,
102 const content::Referrer& referrer,
103 Origin origin,
104 FinalStatus expected_final_status);
105
106 ~TestPrerenderContents() override;
107
108 void RenderProcessGone(base::TerminationStatus status) override;
109 bool CheckURL(const GURL& url) override;
110
111 // For tests that open the prerender in a new background tab, the RenderView
112 // will not have been made visible when the PrerenderContents is destroyed
113 // even though it is used.
114 void set_should_be_shown(bool value) { should_be_shown_ = value; }
115
116 // For tests which do not know whether the prerender will be used.
117 void set_skip_final_checks(bool value) { skip_final_checks_ = value; }
118
119 FinalStatus expected_final_status() const { return expected_final_status_; }
120
121 private:
122 void OnRenderViewHostCreated(
123 content::RenderViewHost* new_render_view_host) override;
124 void Observe(int type,
125 const content::NotificationSource& source,
126 const content::NotificationDetails& details) override;
127
128 FinalStatus expected_final_status_;
129
130 // The RenderViewHost created for the prerender, if any.
131 content::RenderViewHost* new_render_view_host_;
132 // Set to true when the prerendering RenderWidget is hidden.
133 bool was_hidden_;
134 // Set to true when the prerendering RenderWidget is shown, after having been
135 // hidden.
136 bool was_shown_;
137 // Expected final value of was_shown_. Defaults to true for
138 // FINAL_STATUS_USED, and false otherwise.
139 bool should_be_shown_;
140 // If true, |expected_final_status_| and other shutdown checks are skipped.
141 bool skip_final_checks_;
142};
143
144// A handle to a TestPrerenderContents whose lifetime is under the caller's
145// control. A PrerenderContents may be destroyed at any point. This allows
146// tracking the final status, etc.
147class TestPrerender : public PrerenderContents::Observer,
148 public base::SupportsWeakPtr<TestPrerender> {
149 public:
150 TestPrerender();
151 ~TestPrerender() override;
152
153 TestPrerenderContents* contents() const { return contents_; }
154 int number_of_loads() const { return number_of_loads_; }
155
156 void WaitForCreate() { create_loop_.Run(); }
157 void WaitForStart() { start_loop_.Run(); }
158 void WaitForStop() { stop_loop_.Run(); }
159
160 // Waits for |number_of_loads()| to be at least |expected_number_of_loads| OR
161 // for the prerender to stop running (just to avoid a timeout if the prerender
162 // dies). Note: this does not assert equality on the number of loads; the
163 // caller must do it instead.
164 void WaitForLoads(int expected_number_of_loads);
165
166 void OnPrerenderCreated(TestPrerenderContents* contents);
167
168 // PrerenderContents::Observer implementation:
169 void OnPrerenderStart(PrerenderContents* contents) override;
170
171 void OnPrerenderStopLoading(PrerenderContents* contents) override;
172
173 void OnPrerenderStop(PrerenderContents* contents) override;
174
175 private:
176 TestPrerenderContents* contents_;
177 int number_of_loads_;
178
179 int expected_number_of_loads_;
180 std::unique_ptr<base::RunLoop> load_waiter_;
181
182 base::RunLoop create_loop_;
183 base::RunLoop start_loop_;
184 base::RunLoop stop_loop_;
185
186 DISALLOW_COPY_AND_ASSIGN(TestPrerender);
187};
188
mattcaryfb7f2b62016-10-17 08:34:35189// Blocks until a TestPrerenderContents has been destroyed with the given final
190// status. Should be created with a TestPrerenderContents, and then
191// WaitForDestroy should be called and its return value checked.
192class DestructionWaiter {
193 public:
194 // Does not own the prerender_contents, which must outlive any call to
195 // WaitForDestroy().
196 DestructionWaiter(TestPrerenderContents* prerender_contents,
197 FinalStatus expected_final_status);
198
199 ~DestructionWaiter();
200
201 // Returns true if the TestPrerenderContents was destroyed with the correct
202 // final status, or false otherwise. Note this also may hang if the contents
203 // is never destroyed (which will presumably cause the test to time out).
204 bool WaitForDestroy();
205
206 private:
207 class DestructionMarker : public PrerenderContents::Observer {
208 public:
209 // Does not own the waiter which must outlive the TestPrerenderContents.
210 explicit DestructionMarker(DestructionWaiter* waiter);
211
212 ~DestructionMarker() override;
213
214 void OnPrerenderStop(PrerenderContents* contents) override;
215
216 private:
217 DestructionWaiter* waiter_;
218 };
219
220 // To be called by a DestructionMarker.
221 void MarkDestruction(FinalStatus reason);
222
223 base::RunLoop wait_loop_;
224 FinalStatus expected_final_status_;
225 bool saw_correct_status_;
226 std::unique_ptr<DestructionMarker> marker_;
227};
228
229// PrerenderContentsFactory that uses TestPrerenderContents.
mattcary21521892016-09-08 07:25:59230class TestPrerenderContentsFactory : public PrerenderContents::Factory {
231 public:
232 TestPrerenderContentsFactory();
233
234 ~TestPrerenderContentsFactory() override;
235
236 std::unique_ptr<TestPrerender> ExpectPrerenderContents(
237 FinalStatus final_status);
238
239 PrerenderContents* CreatePrerenderContents(
240 PrerenderManager* prerender_manager,
241 Profile* profile,
242 const GURL& url,
243 const content::Referrer& referrer,
244 Origin origin) override;
245
246 private:
247 struct ExpectedContents {
248 ExpectedContents();
249 ExpectedContents(const ExpectedContents& other);
250 ExpectedContents(FinalStatus final_status,
251 const base::WeakPtr<TestPrerender>& handle);
252 ~ExpectedContents();
253
254 FinalStatus final_status;
255 base::WeakPtr<TestPrerender> handle;
256 };
257
258 std::deque<ExpectedContents> expected_contents_queue_;
259};
260
261class PrerenderInProcessBrowserTest : virtual public InProcessBrowserTest {
262 public:
263 PrerenderInProcessBrowserTest();
264
265 ~PrerenderInProcessBrowserTest() override;
266
267 void SetUpCommandLine(base::CommandLine* command_line) override;
268 void SetUpInProcessBrowserTestFixture() override;
269 void TearDownInProcessBrowserTestFixture() override;
270 void SetUpOnMainThread() override;
271 content::SessionStorageNamespace* GetSessionStorageNamespace() const;
272
mattcaryfb7f2b62016-10-17 08:34:35273 // Many of the file and server manipulation commands are fussy about paths
274 // being relative or absolute. This makes path absolute if it is not
275 // already. The path must not be empty.
276 std::string MakeAbsolute(const std::string& path);
277
mattcary21521892016-09-08 07:25:59278 bool UrlIsInPrerenderManager(const std::string& html_file) const;
279 bool UrlIsInPrerenderManager(const GURL& url) const;
280
281 // Convenience function to get the currently active WebContents in
282 // current_browser().
283 content::WebContents* GetActiveWebContents() const;
284
285 PrerenderManager* GetPrerenderManager() const;
286
287 TestPrerenderContents* GetPrerenderContentsFor(const GURL& url) const;
288
289 std::unique_ptr<TestPrerender> PrerenderTestURL(
290 const std::string& html_file,
291 FinalStatus expected_final_status,
292 int expected_number_of_loads);
293
mattcary21521892016-09-08 07:25:59294 std::unique_ptr<TestPrerender> PrerenderTestURL(
295 const GURL& url,
296 FinalStatus expected_final_status,
297 int expected_number_of_loads);
298
mattcaryfb7f2b62016-10-17 08:34:35299 ScopedVector<TestPrerender> PrerenderTestURL(
300 const std::string& html_file,
301 const std::vector<FinalStatus>& expected_final_status_queue,
302 int expected_number_of_loads);
303
304 void UseHttpsSrcServer();
305
306 // Returns the currently active server. See |UseHttpsSrcServer|.
307 net::EmbeddedTestServer* src_server();
308
mattcary21521892016-09-08 07:25:59309 safe_browsing::TestSafeBrowsingServiceFactory* safe_browsing_factory() const {
310 return safe_browsing_factory_.get();
311 }
312
mattcaryfb7f2b62016-10-17 08:34:35313 test_utils::FakeSafeBrowsingDatabaseManager*
314 GetFakeSafeBrowsingDatabaseManager();
315
mattcary21521892016-09-08 07:25:59316 TestPrerenderContentsFactory* prerender_contents_factory() const {
317 return prerender_contents_factory_;
318 }
319
320 void set_autostart_test_server(bool value) { autostart_test_server_ = value; }
321
322 void set_browser(Browser* browser) { explicitly_set_browser_ = browser; }
323
324 Browser* current_browser() const {
325 return explicitly_set_browser_ ? explicitly_set_browser_ : browser();
326 }
327
mattcaryfb7f2b62016-10-17 08:34:35328 const base::HistogramTester& histogram_tester() { return histogram_tester_; }
329
330 // Returns a string for pattern-matching TaskManager tab entries.
331 base::string16 MatchTaskManagerTab(const char* page_title);
332
333 // Returns a string for pattern-matching TaskManager prerender entries.
334 base::string16 MatchTaskManagerPrerender(const char* page_title);
335
336 protected:
337 // To be called from PrerenderTestUrlImpl. Sets up the appropraite prerenders,
338 // checking for the expected final status, navigates to the loader url, and
339 // waits for the load.
340 ScopedVector<TestPrerender> NavigateWithPrerenders(
341 const GURL& loader_url,
342 const std::vector<FinalStatus>& expected_final_status_queue,
343 int expected_number_of_loads);
344
mattcary21521892016-09-08 07:25:59345 private:
346 // Implement load of a url for a prerender test. prerender_url should be
347 // loaded, and we should expect to see one prerenderer created, and exit, for
348 // each entry in expected_final_status_queue, and seeing
349 // expected_number_of_loads. Specific tests can provide additional
350 // verification. Note this should be called by one of the convenience wrappers
351 // defined above.
352 virtual ScopedVector<TestPrerender> PrerenderTestURLImpl(
353 const GURL& prerender_url,
354 const std::vector<FinalStatus>& expected_final_status_queue,
355 int expected_number_of_loads) = 0;
356
357 std::unique_ptr<ExternalProtocolHandler::Delegate>
358 external_protocol_handler_delegate_;
359 std::unique_ptr<safe_browsing::TestSafeBrowsingServiceFactory>
360 safe_browsing_factory_;
361 TestPrerenderContentsFactory* prerender_contents_factory_;
362 Browser* explicitly_set_browser_;
363 bool autostart_test_server_;
mattcaryfb7f2b62016-10-17 08:34:35364 base::HistogramTester histogram_tester_;
365 std::unique_ptr<net::EmbeddedTestServer> https_src_server_;
mattcary21521892016-09-08 07:25:59366};
367
368// Makes |url| respond to requests with the contents of |file|, counting the
369// number that start in |counter|.
370void CreateCountingInterceptorOnIO(
371 const GURL& url,
372 const base::FilePath& file,
373 const base::WeakPtr<RequestCounter>& counter);
374
375// Makes |url| respond to requests with the contents of |file|.
376void CreateMockInterceptorOnIO(const GURL& url, const base::FilePath& file);
377
378} // namespace test_utils
379
380} // namespace prerender
381
382#endif // CHROME_BROWSER_PRERENDER_PRERENDER_TEST_UTILS_H_