forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontent_browser_test_utils_internal.h
344 lines (265 loc) · 11.8 KB
/
content_browser_test_utils_internal.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_TEST_CONTENT_BROWSER_TEST_UTILS_INTERNAL_H_
#define CONTENT_TEST_CONTENT_BROWSER_TEST_UTILS_INTERNAL_H_
// A collection of functions designed for use with content_shell based browser
// tests internal to the content/ module.
// Note: If a function here also works with browser_tests, it should be in
// the content public API.
#include <memory>
#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
#include "build/build_config.h"
#include "content/browser/bad_message.h"
#include "content/common/frame_messages.h"
#include "content/public/browser/javascript_dialog_manager.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
#include "url/gurl.h"
namespace content {
class FrameTreeNode;
class RenderFrameHost;
class Shell;
class SiteInstance;
class ToRenderFrameHost;
// Navigates the frame represented by |node| to |url|, blocking until the
// navigation finishes.
void NavigateFrameToURL(FrameTreeNode* node, const GURL& url);
// Sets the DialogManager to proceed by default or not when showing a
// BeforeUnload dialog, and if it proceeds, what value to return.
void SetShouldProceedOnBeforeUnload(Shell* shell, bool proceed, bool success);
// Extends the ToRenderFrameHost mechanism to FrameTreeNodes.
RenderFrameHost* ConvertToRenderFrameHost(FrameTreeNode* frame_tree_node);
// Helper function to navigate a window to a |url|, using a browser-initiated
// navigation that will stay in the same BrowsingInstance. Most
// browser-initiated navigations swap BrowsingInstances, but some tests need a
// navigation to swap processes for cross-site URLs (even outside of
// --site-per-process) while staying in the same BrowsingInstance.
WARN_UNUSED_RESULT bool NavigateToURLInSameBrowsingInstance(Shell* window,
const GURL& url);
// Creates compact textual representations of the state of the frame tree that
// is appropriate for use in assertions.
//
// The diagrams show frame tree structure, the SiteInstance of current frames,
// presence of pending frames, and the SiteInstances of any and all proxies.
// They look like this:
//
// Site A (D pending) -- proxies for B C
// |--Site B --------- proxies for A C
// +--Site C --------- proxies for B A
// |--Site A ---- proxies for B
// +--Site A ---- proxies for B
// +--Site A -- proxies for B
// Where A = http://127.0.0.1/
// B = http://foo.com/ (no process)
// C = http://bar.com/
// D = http://next.com/
//
// SiteInstances are assigned single-letter names (A, B, C) which are remembered
// across invocations of the pretty-printer.
class FrameTreeVisualizer {
public:
FrameTreeVisualizer();
~FrameTreeVisualizer();
// Formats and returns a diagram for the provided FrameTreeNode.
std::string DepictFrameTree(FrameTreeNode* root);
private:
// Assign or retrive the abbreviated short name (A, B, C) for a site instance.
std::string GetName(SiteInstance* site_instance);
// Elements are site instance ids. The index of the SiteInstance in the vector
// determines the abbreviated name (0->A, 1->B) for that SiteInstance.
std::vector<int> seen_site_instance_ids_;
DISALLOW_COPY_AND_ASSIGN(FrameTreeVisualizer);
};
// Uses window.open to open a popup from the frame |opener| with the specified
// |url| and |name|. Waits for the navigation to |url| to finish and then
// returns the new popup's Shell. Note that since this navigation to |url| is
// renderer-initiated, it won't cause a process swap unless used in
// --site-per-process mode.
Shell* OpenPopup(const ToRenderFrameHost& opener,
const GURL& url,
const std::string& name);
// Helper for mocking choosing a file via a file dialog.
class FileChooserDelegate : public WebContentsDelegate {
public:
// Constructs a WebContentsDelegate that mocks a file dialog.
// The mocked file dialog will always reply that the user selected |file|.
// |callback| is invoked when RunFileChooser() is called.
FileChooserDelegate(const base::FilePath& file, base::OnceClosure callback);
~FileChooserDelegate() override;
// Implementation of WebContentsDelegate::RunFileChooser.
void RunFileChooser(RenderFrameHost* render_frame_host,
std::unique_ptr<content::FileSelectListener> listener,
const blink::mojom::FileChooserParams& params) override;
// The params passed to RunFileChooser.
const blink::mojom::FileChooserParams& params() const { return *params_; }
private:
base::FilePath file_;
base::OnceClosure callback_;
blink::mojom::FileChooserParamsPtr params_;
};
// This class is a TestNavigationManager that only monitors notifications within
// the given frame tree node.
class FrameTestNavigationManager : public TestNavigationManager {
public:
FrameTestNavigationManager(int frame_tree_node_id,
WebContents* web_contents,
const GURL& url);
private:
// TestNavigationManager:
bool ShouldMonitorNavigation(NavigationHandle* handle) override;
// Notifications are filtered so only this frame is monitored.
int filtering_frame_tree_node_id_;
DISALLOW_COPY_AND_ASSIGN(FrameTestNavigationManager);
};
// An observer that can wait for a specific URL to be committed in a specific
// frame.
// Note: it does not track the start of a navigation, unlike other observers.
class UrlCommitObserver : WebContentsObserver {
public:
explicit UrlCommitObserver(FrameTreeNode* frame_tree_node, const GURL& url);
~UrlCommitObserver() override;
void Wait();
private:
void DidFinishNavigation(NavigationHandle* navigation_handle) override;
// The id of the FrameTreeNode in which navigations are peformed.
int frame_tree_node_id_;
// The URL this observer is expecting to be committed.
GURL url_;
// The RunLoop used to spin the message loop.
base::RunLoop run_loop_;
DISALLOW_COPY_AND_ASSIGN(UrlCommitObserver);
};
// Waits for a kill of the given RenderProcessHost and returns the
// BadMessageReason that caused a //content-triggerred kill.
//
// Example usage:
// RenderProcessHostKillWaiter kill_waiter(render_process_host);
// ... test code that triggers a renderer kill ...
// EXPECT_EQ(bad_message::RFH_INVALID_ORIGIN_ON_COMMIT, kill_waiter.Wait());
//
// Tests that don't expect kills (e.g. tests where a renderer process exits
// normally, like RenderFrameHostManagerTest.ProcessExitWithSwappedOutViews)
// should use RenderProcessHostWatcher instead of RenderProcessHostKillWaiter.
class RenderProcessHostKillWaiter {
public:
explicit RenderProcessHostKillWaiter(RenderProcessHost* render_process_host);
// Waits until the renderer process exits. Returns the bad message that made
// //content kill the renderer. |base::nullopt| is returned if the renderer
// was killed outside of //content or exited normally.
base::Optional<bad_message::BadMessageReason> Wait() WARN_UNUSED_RESULT;
private:
RenderProcessHostWatcher exit_watcher_;
base::HistogramTester histogram_tester_;
DISALLOW_COPY_AND_ASSIGN(RenderProcessHostKillWaiter);
};
class ShowWidgetMessageFilter : public content::BrowserMessageFilter {
public:
ShowWidgetMessageFilter();
bool OnMessageReceived(const IPC::Message& message) override;
gfx::Rect last_initial_rect() const { return initial_rect_; }
int last_routing_id() const { return routing_id_; }
void Wait();
void Reset();
private:
~ShowWidgetMessageFilter() override;
void OnShowWidget(int route_id, const gfx::Rect& initial_rect);
#if defined(OS_MACOSX) || defined(OS_ANDROID)
void OnShowPopup(const FrameHostMsg_ShowPopup_Params& params);
#endif
void OnShowWidgetOnUI(int route_id, const gfx::Rect& initial_rect);
scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
gfx::Rect initial_rect_;
int routing_id_ = MSG_ROUTING_NONE;
DISALLOW_COPY_AND_ASSIGN(ShowWidgetMessageFilter);
};
// A BrowserMessageFilter that drops a blacklisted message.
class DropMessageFilter : public BrowserMessageFilter {
public:
DropMessageFilter(uint32_t message_class, uint32_t drop_message_id);
protected:
~DropMessageFilter() override;
private:
// BrowserMessageFilter:
bool OnMessageReceived(const IPC::Message& message) override;
const uint32_t drop_message_id_;
DISALLOW_COPY_AND_ASSIGN(DropMessageFilter);
};
// A BrowserMessageFilter that observes a message without handling it, and
// reports when it was seen.
class ObserveMessageFilter : public BrowserMessageFilter {
public:
ObserveMessageFilter(uint32_t message_class, uint32_t watch_message_id);
bool has_received_message() { return received_; }
// Spins a RunLoop until the message is observed.
void Wait();
protected:
~ObserveMessageFilter() override;
// BrowserMessageFilter:
bool OnMessageReceived(const IPC::Message& message) override;
private:
void QuitWait();
const uint32_t watch_message_id_;
bool received_ = false;
base::OnceClosure quit_closure_;
DISALLOW_COPY_AND_ASSIGN(ObserveMessageFilter);
};
// This observer waits until WebContentsObserver::OnRendererUnresponsive
// notification.
class UnresponsiveRendererObserver : public WebContentsObserver {
public:
explicit UnresponsiveRendererObserver(WebContents* web_contents);
~UnresponsiveRendererObserver() override;
RenderProcessHost* Wait(base::TimeDelta timeout = base::TimeDelta::Max());
private:
// WebContentsObserver:
void OnRendererUnresponsive(RenderProcessHost* render_process_host) override;
RenderProcessHost* captured_render_process_host_ = nullptr;
base::RunLoop run_loop_;
DISALLOW_COPY_AND_ASSIGN(UnresponsiveRendererObserver);
};
// Helper class that overrides the JavaScriptDialogManager of a WebContents
// to endlessly block on beforeunload.
class BeforeUnloadBlockingDelegate : public JavaScriptDialogManager,
public WebContentsDelegate {
public:
explicit BeforeUnloadBlockingDelegate(WebContentsImpl* web_contents);
~BeforeUnloadBlockingDelegate() override;
void Wait();
// WebContentsDelegate
JavaScriptDialogManager* GetJavaScriptDialogManager(
WebContents* source) override;
// JavaScriptDialogManager
void RunJavaScriptDialog(WebContents* web_contents,
RenderFrameHost* render_frame_host,
JavaScriptDialogType dialog_type,
const base::string16& message_text,
const base::string16& default_prompt_text,
DialogClosedCallback callback,
bool* did_suppress_message) override;
void RunBeforeUnloadDialog(WebContents* web_contents,
RenderFrameHost* render_frame_host,
bool is_reload,
DialogClosedCallback callback) override;
bool HandleJavaScriptDialog(WebContents* web_contents,
bool accept,
const base::string16* prompt_override) override;
void CancelDialogs(WebContents* web_contents, bool reset_state) override {}
private:
WebContentsImpl* web_contents_;
DialogClosedCallback callback_;
std::unique_ptr<base::RunLoop> run_loop_ = std::make_unique<base::RunLoop>();
DISALLOW_COPY_AND_ASSIGN(BeforeUnloadBlockingDelegate);
};
} // namespace content
#endif // CONTENT_TEST_CONTENT_BROWSER_TEST_UTILS_INTERNAL_H_