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 "content/public/test/test_renderer_host.h"
6
7 #include <utility>
8
9 #include "base/run_loop.h"
10 #include "base/task/current_thread.h"
11 #include "base/test/task_environment.h"
12 #include "base/threading/thread_task_runner_handle.h"
13 #include "build/build_config.h"
14 #include "content/browser/compositor/test/test_image_transport_factory.h"
15 #include "content/browser/gpu/gpu_data_manager_impl.h"
16 #include "content/browser/renderer_host/frame_tree_node.h"
17 #include "content/browser/renderer_host/navigation_entry_impl.h"
18 #include "content/browser/renderer_host/navigation_request.h"
19 #include "content/browser/renderer_host/render_view_host_factory.h"
20 #include "content/browser/renderer_host/render_widget_host_impl.h"
21 #include "content/browser/renderer_host/render_widget_host_input_event_router.h"
22 #include "content/browser/site_instance_impl.h"
23 #include "content/public/browser/browser_task_traits.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/render_widget_host_iterator.h"
26 #include "content/public/browser/web_contents.h"
27 #include "content/public/common/navigation_policy.h"
28 #include "content/public/test/browser_test_utils.h"
29 #include "content/public/test/mock_render_process_host.h"
30 #include "content/public/test/navigation_simulator.h"
31 #include "content/public/test/test_browser_context.h"
32 #include "content/test/content_browser_consistency_checker.h"
33 #include "content/test/test_navigation_url_loader_factory.h"
34 #include "content/test/test_render_frame_host.h"
35 #include "content/test/test_render_frame_host_factory.h"
36 #include "content/test/test_render_view_host.h"
37 #include "content/test/test_render_view_host_factory.h"
38 #include "content/test/test_render_widget_host_factory.h"
39 #include "content/test/test_web_contents.h"
40 #include "net/base/mock_network_change_notifier.h"
41 #include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h"
42 #include "third_party/blink/public/common/input/web_input_event.h"
43
44 #if defined(OS_ANDROID)
45 #include "ui/android/dummy_screen_android.h"
46 #include "ui/display/screen.h"
47 #endif
48
49 #if defined(OS_WIN)
50 #include "ui/base/win/scoped_ole_initializer.h"
51 #endif
52
53 #if defined(USE_AURA)
54 #include "ui/aura/test/aura_test_helper.h"
55 #endif
56
57 #if defined(OS_MAC)
58 #include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
59 #endif
60
61 namespace content {
62
63 // RenderFrameHostTester ------------------------------------------------------
64
65 // static
For(RenderFrameHost * host)66 RenderFrameHostTester* RenderFrameHostTester::For(RenderFrameHost* host) {
67 return static_cast<TestRenderFrameHost*>(host);
68 }
69
70 // static
TestOnMessageReceived(RenderFrameHost * rfh,const IPC::Message & msg)71 bool RenderFrameHostTester::TestOnMessageReceived(RenderFrameHost* rfh,
72 const IPC::Message& msg) {
73 return static_cast<RenderFrameHostImpl*>(rfh)->OnMessageReceived(msg);
74 }
75
76 // static
CommitPendingLoad(NavigationController * controller)77 void RenderFrameHostTester::CommitPendingLoad(
78 NavigationController* controller) {
79 // This function is currently used by BrowserWithTestWindowTest. It would be
80 // ideal to instead make the users of that class create TestWebContents
81 // (rather than WebContentsImpl directly). It is not trivial to make
82 // that change, so for now we have this extra function for
83 // non-TestWebContents.
84 auto navigation =
85 NavigationSimulator::CreateFromPending(controller->GetWebContents());
86 navigation->Commit();
87 }
88
89 // RenderViewHostTester -------------------------------------------------------
90
91 // static
For(RenderViewHost * host)92 RenderViewHostTester* RenderViewHostTester::For(RenderViewHost* host) {
93 return static_cast<TestRenderViewHost*>(host);
94 }
95
96 // static
SimulateFirstPaint(RenderViewHost * rvh)97 void RenderViewHostTester::SimulateFirstPaint(RenderViewHost* rvh) {
98 static_cast<RenderViewHostImpl*>(rvh)
99 ->GetWidget()
100 ->DidFirstVisuallyNonEmptyPaint();
101 }
102
103 // static
104 std::unique_ptr<content::InputMsgWatcher>
CreateInputWatcher(RenderViewHost * rvh,blink::WebInputEvent::Type type)105 RenderViewHostTester::CreateInputWatcher(RenderViewHost* rvh,
106 blink::WebInputEvent::Type type) {
107 RenderWidgetHostImpl* host_impl =
108 RenderWidgetHostImpl::From(rvh->GetWidget());
109 return std::make_unique<content::InputMsgWatcher>(host_impl, type);
110 }
111
112 // static
SendTouchEvent(RenderViewHost * rvh,blink::SyntheticWebTouchEvent * touch_event)113 void RenderViewHostTester::SendTouchEvent(
114 RenderViewHost* rvh,
115 blink::SyntheticWebTouchEvent* touch_event) {
116 RenderWidgetHostImpl* host_impl =
117 RenderWidgetHostImpl::From(rvh->GetWidget());
118 auto* input_event_router = host_impl->delegate()->GetInputEventRouter();
119 input_event_router->RouteTouchEvent(host_impl->GetView(), touch_event,
120 ui::LatencyInfo());
121 }
122
123 // RenderViewHostTestEnabler --------------------------------------------------
124
RenderViewHostTestEnabler()125 RenderViewHostTestEnabler::RenderViewHostTestEnabler()
126 : rph_factory_(new MockRenderProcessHostFactory()),
127 rvh_factory_(new TestRenderViewHostFactory(rph_factory_.get())),
128 rfh_factory_(new TestRenderFrameHostFactory()),
129 rwhi_factory_(new TestRenderWidgetHostFactory()),
130 loader_factory_(new TestNavigationURLLoaderFactory()) {
131 // A TaskEnvironment is needed on the main thread for Mojo bindings to
132 // graphics services. Some tests have their own, so this only creates one
133 // (single-threaded) when none exists. This means tests must ensure any
134 // TaskEnvironment they make is created before the RenderViewHostTestEnabler.
135 if (!base::CurrentThread::Get()) {
136 task_environment_ =
137 std::make_unique<base::test::SingleThreadTaskEnvironment>();
138 }
139 #if !defined(OS_ANDROID)
140 ImageTransportFactory::SetFactory(
141 std::make_unique<TestImageTransportFactory>());
142 #else
143 if (!screen_)
144 screen_.reset(ui::CreateDummyScreenAndroid());
145 display::Screen::SetScreenInstance(screen_.get());
146 #endif
147 #if defined(OS_MAC)
148 if (base::ThreadTaskRunnerHandle::IsSet())
149 ui::WindowResizeHelperMac::Get()->Init(base::ThreadTaskRunnerHandle::Get());
150 #endif // OS_MAC
151 }
152
~RenderViewHostTestEnabler()153 RenderViewHostTestEnabler::~RenderViewHostTestEnabler() {
154 #if defined(OS_MAC)
155 ui::WindowResizeHelperMac::Get()->ShutdownForTests();
156 #endif // OS_MAC
157 #if !defined(OS_ANDROID)
158 // RenderWidgetHostView holds on to a reference to SurfaceManager, so it
159 // must be shut down before the ImageTransportFactory.
160 ImageTransportFactory::Terminate();
161 #else
162 display::Screen::SetScreenInstance(nullptr);
163 #endif
164 }
165
166
167 // RenderViewHostTestHarness --------------------------------------------------
168
~RenderViewHostTestHarness()169 RenderViewHostTestHarness::~RenderViewHostTestHarness() {
170 }
171
controller()172 NavigationController& RenderViewHostTestHarness::controller() {
173 return web_contents()->GetController();
174 }
175
web_contents()176 WebContents* RenderViewHostTestHarness::web_contents() {
177 return contents_.get();
178 }
179
rvh()180 RenderViewHost* RenderViewHostTestHarness::rvh() {
181 RenderViewHost* result = web_contents()->GetMainFrame()->GetRenderViewHost();
182 CHECK_EQ(result, web_contents()->GetMainFrame()->GetRenderViewHost());
183 return result;
184 }
185
pending_rvh()186 RenderViewHost* RenderViewHostTestHarness::pending_rvh() {
187 return pending_main_rfh() ? pending_main_rfh()->GetRenderViewHost() : nullptr;
188 }
189
active_rvh()190 RenderViewHost* RenderViewHostTestHarness::active_rvh() {
191 return pending_rvh() ? pending_rvh() : rvh();
192 }
193
main_rfh()194 RenderFrameHost* RenderViewHostTestHarness::main_rfh() {
195 return web_contents()->GetMainFrame();
196 }
197
pending_main_rfh()198 RenderFrameHost* RenderViewHostTestHarness::pending_main_rfh() {
199 return static_cast<TestWebContents*>(web_contents())->GetPendingMainFrame();
200 }
201
browser_context()202 BrowserContext* RenderViewHostTestHarness::browser_context() {
203 return GetBrowserContext();
204 }
205
process()206 MockRenderProcessHost* RenderViewHostTestHarness::process() {
207 return static_cast<MockRenderProcessHost*>(active_rvh()->GetProcess());
208 }
209
DeleteContents()210 void RenderViewHostTestHarness::DeleteContents() {
211 contents_.reset();
212 }
213
SetContents(std::unique_ptr<WebContents> contents)214 void RenderViewHostTestHarness::SetContents(
215 std::unique_ptr<WebContents> contents) {
216 contents_ = std::move(contents);
217 }
218
219 std::unique_ptr<WebContents>
CreateTestWebContents()220 RenderViewHostTestHarness::CreateTestWebContents() {
221 // Make sure we ran SetUp() already.
222 #if defined(OS_WIN)
223 DCHECK(ole_initializer_);
224 #endif
225 #if defined(USE_AURA)
226 DCHECK(aura_test_helper_);
227 #endif
228
229 scoped_refptr<SiteInstance> instance =
230 SiteInstance::Create(GetBrowserContext());
231 instance->GetProcess()->Init();
232
233 return TestWebContents::Create(GetBrowserContext(), std::move(instance));
234 }
FocusWebContentsOnMainFrame()235 void RenderViewHostTestHarness::FocusWebContentsOnMainFrame() {
236 TestWebContents* contents = static_cast<TestWebContents*>(web_contents());
237 auto* root = contents->GetFrameTree()->root();
238 contents->GetFrameTree()->SetFocusedFrame(
239 root, root->current_frame_host()->GetSiteInstance());
240 }
241
NavigateAndCommit(const GURL & url,ui::PageTransition transition)242 void RenderViewHostTestHarness::NavigateAndCommit(
243 const GURL& url,
244 ui::PageTransition transition) {
245 static_cast<TestWebContents*>(web_contents())
246 ->NavigateAndCommit(url, transition);
247 }
248
SetUp()249 void RenderViewHostTestHarness::SetUp() {
250 rvh_test_enabler_ = std::make_unique<RenderViewHostTestEnabler>();
251 if (factory_)
252 rvh_test_enabler_->rvh_factory_->set_render_process_host_factory(factory_);
253
254 #if defined(OS_WIN)
255 ole_initializer_ = std::make_unique<ui::ScopedOleInitializer>();
256 #endif
257 #if defined(USE_AURA)
258 aura_test_helper_ = std::make_unique<aura::test::AuraTestHelper>(
259 ImageTransportFactory::GetInstance()->GetContextFactory());
260 aura_test_helper_->SetUp();
261 #endif
262
263 consistency_checker_ = std::make_unique<ContentBrowserConsistencyChecker>();
264
265 #if !defined(OS_ANDROID)
266 network_change_notifier_ = net::test::MockNetworkChangeNotifier::Create();
267 #endif
268
269 DCHECK(!browser_context_);
270 browser_context_ = CreateBrowserContext();
271
272 SetContents(CreateTestWebContents());
273
274 // Create GpuDataManagerImpl here so it always runs on the main thread.
275 GpuDataManagerImpl::GetInstance();
276 }
277
TearDown()278 void RenderViewHostTestHarness::TearDown() {
279 DeleteContents();
280 #if defined(USE_AURA)
281 aura_test_helper_->TearDown();
282 #endif
283 // Make sure that we flush any messages related to WebContentsImpl destruction
284 // before we destroy the browser context.
285 base::RunLoop().RunUntilIdle();
286
287 #if defined(OS_WIN)
288 ole_initializer_.reset();
289 #endif
290
291 // Delete any RenderProcessHosts before the BrowserContext goes away.
292 if (rvh_test_enabler_->rph_factory_) {
293 auto render_widget_hosts = RenderWidgetHost::GetRenderWidgetHosts();
294 ASSERT_EQ(nullptr, render_widget_hosts->GetNextHost()) <<
295 "Test is leaking at least one RenderWidgetHost.";
296 rvh_test_enabler_->rph_factory_.reset();
297 }
298
299 rvh_test_enabler_.reset();
300
301 // Release the browser context by posting itself on the end of the task
302 // queue. This is preferable to immediate deletion because it will behave
303 // properly if the |rph_factory_| reset above enqueued any tasks which
304 // depend on |browser_context_|.
305 content::GetUIThreadTaskRunner({})->DeleteSoon(FROM_HERE,
306 browser_context_.release());
307
308 // Although this isn't required by many, some subclasses members require that
309 // the task environment is gone by the time that they are destroyed (akin to
310 // browser shutdown).
311 task_environment_.reset();
312 }
313
314 std::unique_ptr<BrowserContext>
CreateBrowserContext()315 RenderViewHostTestHarness::CreateBrowserContext() {
316 return std::make_unique<TestBrowserContext>();
317 }
318
GetBrowserContext()319 BrowserContext* RenderViewHostTestHarness::GetBrowserContext() {
320 return browser_context_.get();
321 }
322
SetRenderProcessHostFactory(RenderProcessHostFactory * factory)323 void RenderViewHostTestHarness::SetRenderProcessHostFactory(
324 RenderProcessHostFactory* factory) {
325 if (rvh_test_enabler_)
326 rvh_test_enabler_->rvh_factory_->set_render_process_host_factory(factory);
327 else
328 factory_ = factory;
329 }
330
RenderViewHostTestHarness(std::unique_ptr<BrowserTaskEnvironment> task_environment)331 RenderViewHostTestHarness::RenderViewHostTestHarness(
332 std::unique_ptr<BrowserTaskEnvironment> task_environment)
333 : task_environment_(std::move(task_environment)) {}
334
335 } // namespace content
336