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 #ifndef CONTENT_PUBLIC_TEST_TEST_RENDERER_HOST_H_
6 #define CONTENT_PUBLIC_TEST_TEST_RENDERER_HOST_H_
7 
8 #include <stdint.h>
9 
10 #include <memory>
11 #include <string>
12 #include <utility>
13 #include <vector>
14 
15 #include "base/macros.h"
16 #include "base/optional.h"
17 #include "base/test/task_environment.h"
18 #include "build/build_config.h"
19 #include "content/public/browser/render_frame_host.h"
20 #include "content/public/browser/render_view_host.h"
21 #include "content/public/test/browser_task_environment.h"
22 #include "content/public/test/browser_test_utils.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h"
25 #include "third_party/blink/public/common/input/web_input_event.h"
26 #include "ui/base/page_transition_types.h"
27 
28 #if defined(USE_AURA)
29 #include "ui/aura/test/aura_test_helper.h"
30 #endif
31 
32 namespace aura {
33 namespace test {
34 class AuraTestHelper;
35 }
36 }  // namespace aura
37 
38 namespace blink {
39 namespace web_pref {
40 struct WebPreferences;
41 }
42 }  // namespace blink
43 
44 namespace display {
45 class Screen;
46 }
47 
48 namespace net {
49 namespace test {
50 class MockNetworkChangeNotifier;
51 }
52 }  // namespace net
53 
54 namespace ui {
55 class ScopedOleInitializer;
56 }
57 
58 namespace content {
59 
60 class BrowserContext;
61 class ContentBrowserConsistencyChecker;
62 class MockRenderProcessHost;
63 class MockRenderProcessHostFactory;
64 class NavigationController;
65 class RenderProcessHostFactory;
66 class TestRenderFrameHostFactory;
67 class TestRenderViewHostFactory;
68 class TestRenderWidgetHostFactory;
69 class TestNavigationURLLoaderFactory;
70 class WebContents;
71 
72 // An interface and utility for driving tests of RenderFrameHost.
73 class RenderFrameHostTester {
74  public:
75   enum class HeavyAdIssueType {
76     kNetworkTotal,
77     kCpuTotal,
78     kCpuPeak,
79     kAll,
80   };
81 
82   // Retrieves the RenderFrameHostTester that drives the specified
83   // RenderFrameHost. The RenderFrameHost must have been created while
84   // RenderFrameHost testing was enabled; use a
85   // RenderViewHostTestEnabler instance (see below) to do this.
86   static RenderFrameHostTester* For(RenderFrameHost* host);
87 
88   // Calls the RenderFrameHost's private OnMessageReceived function with the
89   // given message.
90   static bool TestOnMessageReceived(RenderFrameHost* rfh,
91                                     const IPC::Message& msg);
92 
93   // Commit the load pending in the given |controller| if any.
94   // TODO(ahemery): This should take a WebContents directly.
95   static void CommitPendingLoad(NavigationController* controller);
96 
~RenderFrameHostTester()97   virtual ~RenderFrameHostTester() {}
98 
99   // Simulates initialization of the RenderFrame object in the renderer process
100   // and ensures internal state of RenderFrameHost is ready for simulating
101   // RenderFrame originated IPCs.
102   virtual void InitializeRenderFrameIfNeeded() = 0;
103 
104   // Gives tests access to RenderFrameHostImpl::OnCreateChild. The returned
105   // RenderFrameHost is owned by the parent RenderFrameHost.
106   virtual RenderFrameHost* AppendChild(const std::string& frame_name) = 0;
107 
108   // Same as AppendChild above, but simulates a custom allow attribute being
109   // used as the container policy.
110   virtual RenderFrameHost* AppendChildWithPolicy(
111       const std::string& frame_name,
112       const blink::ParsedFeaturePolicy& allow) = 0;
113 
114   // Gives tests access to RenderFrameHostImpl::OnDetach. Destroys |this|.
115   virtual void Detach() = 0;
116 
117   // Calls ProcessBeforeUnloadCompleted on this RenderFrameHost with the given
118   // parameter.
119   virtual void SimulateBeforeUnloadCompleted(bool proceed) = 0;
120 
121   // Simulates the FrameHostMsg_Unload_ACK that fires if you commit a cross-site
122   // navigation without making any network requests.
123   virtual void SimulateUnloadACK() = 0;
124 
125   // Set the feature policy header for the RenderFrameHost for test. Currently
126   // this is limited to setting an allowlist for a single feature. This function
127   // can be generalized as needed. Setting a header policy should only be done
128   // once per navigation of the RFH.
129   virtual void SimulateFeaturePolicyHeader(
130       blink::mojom::FeaturePolicyFeature feature,
131       const std::vector<url::Origin>& allowlist) = 0;
132 
133   // Simulates the frame receiving a user activation.
134   virtual void SimulateUserActivation() = 0;
135 
136   // Gets all the console messages requested via
137   // RenderFrameHost::AddMessageToConsole in this frame.
138   virtual const std::vector<std::string>& GetConsoleMessages() = 0;
139 
140   // Get a count of the total number of heavy ad issues reported.
141   virtual int GetHeavyAdIssueCount(HeavyAdIssueType type) = 0;
142 };
143 
144 // An interface and utility for driving tests of RenderViewHost.
145 class RenderViewHostTester {
146  public:
147   // Retrieves the RenderViewHostTester that drives the specified
148   // RenderViewHost.  The RenderViewHost must have been created while
149   // RenderViewHost testing was enabled; use a
150   // RenderViewHostTestEnabler instance (see below) to do this.
151   static RenderViewHostTester* For(RenderViewHost* host);
152 
153   static void SimulateFirstPaint(RenderViewHost* rvh);
154 
155   static std::unique_ptr<content::InputMsgWatcher> CreateInputWatcher(
156       RenderViewHost* rvh,
157       blink::WebInputEvent::Type type);
158 
159   static void SendTouchEvent(RenderViewHost* rvh,
160                              blink::SyntheticWebTouchEvent* touch_event);
161 
~RenderViewHostTester()162   virtual ~RenderViewHostTester() {}
163 
164   // Gives tests access to RenderViewHostImpl::CreateRenderView.
165   virtual bool CreateTestRenderView(
166       const base::Optional<base::UnguessableToken>& opener_frame_route_id,
167       int proxy_routing_id,
168       bool created_with_opener) = 0;
169 
170   // Makes the WasHidden/WasShown calls to the RenderWidget that
171   // tell it it has been hidden or restored from having been hidden.
172   virtual void SimulateWasHidden() = 0;
173   virtual void SimulateWasShown() = 0;
174 
175   // Promote ComputeWebPreferences to public.
176   virtual blink::web_pref::WebPreferences TestComputeWebPreferences() = 0;
177 };
178 
179 // You can instantiate only one class like this at a time.  During its
180 // lifetime, RenderViewHost and RenderFrameHost objects created may be used via
181 // RenderViewHostTester and RenderFrameHostTester respectively.
182 class RenderViewHostTestEnabler {
183  public:
184   RenderViewHostTestEnabler();
185   ~RenderViewHostTestEnabler();
186 
187  private:
188   DISALLOW_COPY_AND_ASSIGN(RenderViewHostTestEnabler);
189   friend class RenderViewHostTestHarness;
190 
191 #if defined(OS_ANDROID)
192   std::unique_ptr<display::Screen> screen_;
193 #endif
194   std::unique_ptr<base::test::SingleThreadTaskEnvironment> task_environment_;
195   std::unique_ptr<MockRenderProcessHostFactory> rph_factory_;
196   std::unique_ptr<TestRenderViewHostFactory> rvh_factory_;
197   std::unique_ptr<TestRenderFrameHostFactory> rfh_factory_;
198   std::unique_ptr<TestRenderWidgetHostFactory> rwhi_factory_;
199   std::unique_ptr<TestNavigationURLLoaderFactory> loader_factory_;
200 };
201 
202 // RenderViewHostTestHarness ---------------------------------------------------
203 class RenderViewHostTestHarness : public testing::Test {
204  public:
205   // Constructs a RenderViewHostTestHarness which uses |traits| to initialize
206   // its BrowserTaskEnvironment.
207   template <typename... TaskEnvironmentTraits>
RenderViewHostTestHarness(TaskEnvironmentTraits &&...traits)208   explicit RenderViewHostTestHarness(TaskEnvironmentTraits&&... traits)
209       : RenderViewHostTestHarness(std::make_unique<BrowserTaskEnvironment>(
210             std::forward<TaskEnvironmentTraits>(traits)...)) {}
211 
212   ~RenderViewHostTestHarness() override;
213 
214   NavigationController& controller();
215 
216   // The contents under test.
217   WebContents* web_contents();
218 
219   // RVH/RFH getters are shorthand for oft-used bits of web_contents().
220 
221   // rvh() is equivalent to either of:
222   //   web_contents()->GetMainFrame()->GetRenderViewHost()
223   //   web_contents()->GetRenderViewHost()
224   RenderViewHost* rvh();
225 
226   // pending_rvh() is equivalent to:
227   //   WebContentsTester::For(web_contents())->GetPendingRenderViewHost()
228   RenderViewHost* pending_rvh();
229 
230   // active_rvh() is equivalent to pending_rvh() ? pending_rvh() : rvh()
231   RenderViewHost* active_rvh();
232 
233   // main_rfh() is equivalent to web_contents()->GetMainFrame()
234   RenderFrameHost* main_rfh();
235 
236   // pending_main_rfh() is equivalent to:
237   //   WebContentsTester::For(web_contents())->GetPendingMainFrame()
238   RenderFrameHost* pending_main_rfh();
239 
240   BrowserContext* browser_context();
241   MockRenderProcessHost* process();
242 
243   // Frees the current WebContents for tests that want to test destruction.
244   void DeleteContents();
245 
246   // Sets the current WebContents for tests that want to alter it. Takes
247   // ownership of the WebContents passed.
248   void SetContents(std::unique_ptr<WebContents> contents);
249 
250   // Creates a new test-enabled WebContents. Ownership passes to the
251   // caller.
252   std::unique_ptr<WebContents> CreateTestWebContents();
253 
254   // Cover for |contents()->NavigateAndCommit(url)|. See
255   // WebContentsTester::NavigateAndCommit for details.
256   // Optional parameter transition allows transition type to be controlled for
257   // greater flexibility for tests.
258   void NavigateAndCommit(
259       const GURL& url,
260       ui::PageTransition transition = ui::PAGE_TRANSITION_LINK);
261 
262   // Sets the focused frame to the main frame of the WebContents for tests that
263   // rely on the focused frame not being null.
264   void FocusWebContentsOnMainFrame();
265 
266  protected:
267   // testing::Test
268   void SetUp() override;
269   void TearDown() override;
270 
271   // Derived classes should override this method to use a custom BrowserContext.
272   // It is invoked by SetUp after threads were started.
273   // RenderViewHostTestHarness will take ownership of the returned
274   // BrowserContext.
275   virtual std::unique_ptr<BrowserContext> CreateBrowserContext();
276 
277   // Derived classes can override this method to have the test harness use a
278   // different BrowserContext than the one owned by this class. This is most
279   // useful for off-the-record contexts, which are usually owned by the original
280   // context.
281   virtual BrowserContext* GetBrowserContext();
282 
task_environment()283   BrowserTaskEnvironment* task_environment() { return task_environment_.get(); }
284 
285 #if defined(USE_AURA)
root_window()286   aura::Window* root_window() { return aura_test_helper_->GetContext(); }
287 #endif
288 
289   // Replaces the RPH being used.
290   void SetRenderProcessHostFactory(RenderProcessHostFactory* factory);
291 
292  private:
293   // The template constructor has to be in the header but it delegates to this
294   // constructor to initialize all other members out-of-line.
295   explicit RenderViewHostTestHarness(
296       std::unique_ptr<BrowserTaskEnvironment> task_environment);
297 
298   std::unique_ptr<BrowserTaskEnvironment> task_environment_;
299 
300   std::unique_ptr<ContentBrowserConsistencyChecker> consistency_checker_;
301 
302   // TODO(crbug.com/1011275): This is a temporary work around to fix flakiness
303   // on tests. The default behavior of the network stack is to allocate a
304   // leaking SystemDnsConfigChangeNotifier. This holds on to a set of
305   // FilePathWatchers on Posix and ObjectWatchers on Windows that outlive
306   // the message queues of the task_environment_ and may post messages after
307   // their death.
308   std::unique_ptr<net::test::MockNetworkChangeNotifier>
309       network_change_notifier_;
310 
311   std::unique_ptr<BrowserContext> browser_context_;
312 
313   // This must be placed before |contents_| such that it will be destructed
314   // after it. See https://crbug.com/770451
315   std::unique_ptr<RenderViewHostTestEnabler> rvh_test_enabler_;
316 
317   std::unique_ptr<WebContents> contents_;
318 #if defined(OS_WIN)
319   std::unique_ptr<ui::ScopedOleInitializer> ole_initializer_;
320 #endif
321 #if defined(USE_AURA)
322   std::unique_ptr<aura::test::AuraTestHelper> aura_test_helper_;
323 #endif
324   RenderProcessHostFactory* factory_ = nullptr;
325 
326   DISALLOW_COPY_AND_ASSIGN(RenderViewHostTestHarness);
327 };
328 
329 }  // namespace content
330 
331 #endif  // CONTENT_PUBLIC_TEST_TEST_RENDERER_HOST_H_
332