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_TEST_TEST_RENDER_VIEW_HOST_H_
6 #define CONTENT_TEST_TEST_RENDER_VIEW_HOST_H_
7 
8 #include <stdint.h>
9 
10 #include <string>
11 #include <vector>
12 
13 #include "base/gtest_prod_util.h"
14 #include "base/macros.h"
15 #include "build/build_config.h"
16 #include "components/viz/common/surfaces/frame_sink_id.h"
17 #include "components/viz/host/host_frame_sink_client.h"
18 #include "content/browser/renderer_host/render_view_host_impl.h"
19 #include "content/browser/renderer_host/render_widget_host_view_base.h"
20 #include "content/public/test/mock_render_process_host.h"
21 #include "content/public/test/test_renderer_host.h"
22 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
23 #include "ui/base/ime/dummy_text_input_client.h"
24 #include "ui/base/layout.h"
25 #include "ui/base/page_transition_types.h"
26 #include "ui/gfx/geometry/vector2d_f.h"
27 
28 #if defined(USE_AURA)
29 #include "ui/aura/window.h"
30 #endif
31 
32 // This file provides a testing framework for mocking out the RenderProcessHost
33 // layer. It allows you to test RenderViewHost, WebContentsImpl,
34 // NavigationController, and other layers above that without running an actual
35 // renderer process.
36 //
37 // To use, derive your test base class from RenderViewHostImplTestHarness.
38 
39 struct FrameHostMsg_DidCommitProvisionalLoad_Params;
40 
41 namespace gfx {
42 class Rect;
43 }
44 
45 namespace content {
46 
47 class SiteInstance;
48 class TestRenderFrameHost;
49 class TestWebContents;
50 
51 // Utility function to initialize FrameHostMsg_DidCommitProvisionalLoad_Params
52 // with given parameters.
53 void InitNavigateParams(FrameHostMsg_DidCommitProvisionalLoad_Params* params,
54                         int nav_entry_id,
55                         bool did_create_new_entry,
56                         const GURL& url,
57                         ui::PageTransition transition_type);
58 
59 // TestRenderWidgetHostView ----------------------------------------------------
60 
61 // Subclass the RenderViewHost's view so that we can call Show(), etc.,
62 // without having side-effects.
63 class TestRenderWidgetHostView : public RenderWidgetHostViewBase,
64                                  public viz::HostFrameSinkClient {
65  public:
66   explicit TestRenderWidgetHostView(RenderWidgetHost* rwh);
67   ~TestRenderWidgetHostView() override;
68 
69   // RenderWidgetHostView:
InitAsChild(gfx::NativeView parent_view)70   void InitAsChild(gfx::NativeView parent_view) override {}
SetSize(const gfx::Size & size)71   void SetSize(const gfx::Size& size) override {}
SetBounds(const gfx::Rect & rect)72   void SetBounds(const gfx::Rect& rect) override {}
73   gfx::NativeView GetNativeView() override;
74   gfx::NativeViewAccessible GetNativeViewAccessible() override;
75   ui::TextInputClient* GetTextInputClient() override;
76   bool HasFocus() override;
77   void Show() override;
78   void Hide() override;
79   bool IsShowing() override;
80   void WasUnOccluded() override;
81   void WasOccluded() override;
82   gfx::Rect GetViewBounds() override;
83 #if defined(OS_MAC)
84   void SetActive(bool active) override;
ShowDefinitionForSelection()85   void ShowDefinitionForSelection() override {}
86   void SpeakSelection() override;
87   void SetWindowFrameInScreen(const gfx::Rect& rect) override;
88 #endif  // defined(OS_MAC)
89 
90   // Advances the fallback surface to the first surface after navigation. This
91   // ensures that stale surfaces are not presented to the user for an indefinite
92   // period of time.
ResetFallbackToFirstNavigationSurface()93   void ResetFallbackToFirstNavigationSurface() override {}
94 
95   void TakeFallbackContentFrom(RenderWidgetHostView* view) override;
96   void EnsureSurfaceSynchronizedForWebTest() override;
97 
98   // RenderWidgetHostViewBase:
99   uint32_t GetCaptureSequenceNumber() const override;
InitAsPopup(RenderWidgetHostView * parent_host_view,const gfx::Rect & bounds)100   void InitAsPopup(RenderWidgetHostView* parent_host_view,
101                    const gfx::Rect& bounds) override {}
InitAsFullscreen(RenderWidgetHostView * reference_host_view)102   void InitAsFullscreen(RenderWidgetHostView* reference_host_view) override {}
Focus()103   void Focus() override {}
SetIsLoading(bool is_loading)104   void SetIsLoading(bool is_loading) override {}
105   void UpdateCursor(const WebCursor& cursor) override;
106   void RenderProcessGone() override;
107   void Destroy() override;
SetTooltipText(const base::string16 & tooltip_text)108   void SetTooltipText(const base::string16& tooltip_text) override {}
109   gfx::Rect GetBoundsInRootWindow() override;
110   blink::mojom::PointerLockResult LockMouse(bool) override;
111   blink::mojom::PointerLockResult ChangeMouseLock(bool) override;
112   void UnlockMouse() override;
113   const viz::FrameSinkId& GetFrameSinkId() const override;
114   const viz::LocalSurfaceId& GetLocalSurfaceId() const override;
115   viz::SurfaceId GetCurrentSurfaceId() const override;
116   std::unique_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget()
117       override;
118 
is_showing()119   bool is_showing() const { return is_showing_; }
is_occluded()120   bool is_occluded() const { return is_occluded_; }
121 
122   // viz::HostFrameSinkClient implementation.
123   void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
124   void OnFrameTokenChanged(uint32_t frame_token) override;
125 
last_cursor()126   const WebCursor& last_cursor() const { return last_cursor_; }
127 
128  protected:
129   // RenderWidgetHostViewBase:
130   void UpdateBackgroundColor() override;
131   base::Optional<DisplayFeature> GetDisplayFeature() override;
132   void SetDisplayFeatureForTesting(
133       const DisplayFeature* display_feature) override;
134 
135   viz::FrameSinkId frame_sink_id_;
136 
137  private:
138   bool is_showing_;
139   bool is_occluded_;
140   ui::DummyTextInputClient text_input_client_;
141   WebCursor last_cursor_;
142 
143   // Latest capture sequence number which is incremented when the caller
144   // requests surfaces be synchronized via
145   // EnsureSurfaceSynchronizedForWebTest().
146   uint32_t latest_capture_sequence_number_ = 0u;
147 
148 #if defined(USE_AURA)
149   std::unique_ptr<aura::Window> window_;
150 #endif
151 
152   base::Optional<DisplayFeature> display_feature_;
153 };
154 
155 // TestRenderViewHost ----------------------------------------------------------
156 
157 // TODO(brettw) this should use a TestWebContents which should be generalized
158 // from the WebContentsImpl test. We will probably also need that class' version
159 // of CreateRenderViewForRenderManager when more complicated tests start using
160 // this.
161 //
162 // Note that users outside of content must use this class by getting
163 // the separate RenderViewHostTester interface via
164 // RenderViewHostTester::For(rvh) on the RenderViewHost they want to
165 // drive tests on.
166 //
167 // Users within content may directly static_cast from a
168 // RenderViewHost* to a TestRenderViewHost*.
169 //
170 // The reasons we do it this way rather than extending the parallel
171 // inheritance hierarchy we have for RenderWidgetHost/RenderViewHost
172 // vs. RenderWidgetHostImpl/RenderViewHostImpl are:
173 //
174 // a) Extending the parallel class hierarchy further would require
175 // more classes to use virtual inheritance.  This is a complexity that
176 // is better to avoid, especially when it would be introduced in the
177 // production code solely to facilitate testing code.
178 //
179 // b) While users outside of content only need to drive tests on a
180 // RenderViewHost, content needs a test version of the full
181 // RenderViewHostImpl so that it can test all methods on that concrete
182 // class (e.g. overriding a method such as
183 // RenderViewHostImpl::CreateRenderView).  This would have complicated
184 // the dual class hierarchy even further.
185 //
186 // The reason we do it this way instead of using composition is
187 // similar to (b) above, essentially it gets very tricky.  By using
188 // the split interface we avoid complexity within content and maintain
189 // reasonable utility for embedders.
190 class TestRenderViewHost
191     : public RenderViewHostImpl,
192       public RenderViewHostTester {
193  public:
194   TestRenderViewHost(SiteInstance* instance,
195                      std::unique_ptr<RenderWidgetHostImpl> widget,
196                      RenderViewHostDelegate* delegate,
197                      int32_t routing_id,
198                      int32_t main_frame_routing_id,
199                      bool swapped_out);
200   // RenderViewHostTester implementation.  Note that CreateRenderView
201   // is not specified since it is synonymous with the one from
202   // RenderViewHostImpl, see below.
203   void SimulateWasHidden() override;
204   void SimulateWasShown() override;
205   blink::web_pref::WebPreferences TestComputeWebPreferences() override;
206 
207   void TestOnUpdateStateWithFile(const base::FilePath& file_path);
208 
209   void TestStartDragging(const DropData& drop_data, SkBitmap bitmap = {});
210 
211   // If set, *delete_counter is incremented when this object destructs.
set_delete_counter(int * delete_counter)212   void set_delete_counter(int* delete_counter) {
213     delete_counter_ = delete_counter;
214   }
215 
216   // The opener frame route id passed to CreateRenderView().
opener_frame_token()217   const base::Optional<base::UnguessableToken>& opener_frame_token() const {
218     return opener_frame_token_;
219   }
220 
221   // RenderWidgetHost overrides (same value, but in the Mock* type)
222   MockRenderProcessHost* GetProcess() override;
223 
224   bool CreateTestRenderView(
225       const base::Optional<base::UnguessableToken>& opener_frame_token,
226       int proxy_route_id,
227       bool window_was_created_with_opener) override;
228 
229   // RenderViewHost:
230   bool CreateRenderView(
231       const base::Optional<base::UnguessableToken>& opener_frame_token,
232       int proxy_route_id,
233       bool window_was_created_with_opener) override;
234 
235   // RenderViewHostImpl:
236   bool IsTestRenderViewHost() const override;
237 
238  private:
239   FRIEND_TEST_ALL_PREFIXES(RenderViewHostTest, FilterNavigate);
240 
241   ~TestRenderViewHost() override;
242 
243   void SendNavigateWithTransitionAndResponseCode(const GURL& url,
244                                                  ui::PageTransition transition,
245                                                  int response_code);
246 
247   // Calls OnNavigate on the RenderViewHost with the given information.
248   // Sets the rest of the parameters in the message to the "typical" values.
249   // This is a helper function for simulating the most common types of loads.
250   void SendNavigateWithParameters(
251       const GURL& url,
252       ui::PageTransition transition,
253       const GURL& original_request_url,
254       int response_code,
255       const base::FilePath* file_path_for_history_item);
256 
257   // See set_delete_counter() above. May be NULL.
258   int* delete_counter_;
259 
260   // See opener_frame_route_id() above.
261   base::Optional<base::UnguessableToken> opener_frame_token_;
262 
263   DISALLOW_COPY_AND_ASSIGN(TestRenderViewHost);
264 };
265 
266 // Adds methods to get straight at the impl classes.
267 class RenderViewHostImplTestHarness : public RenderViewHostTestHarness {
268  public:
269   RenderViewHostImplTestHarness();
270   ~RenderViewHostImplTestHarness() override;
271 
272   // contents() is equivalent to static_cast<TestWebContents*>(web_contents())
273   TestWebContents* contents();
274 
275   // RVH/RFH getters are shorthand for oft-used bits of web_contents().
276 
277   // test_rvh() is equivalent to any of the following:
278   //   contents()->GetMainFrame()->GetRenderViewHost()
279   //   contents()->GetRenderViewHost()
280   //   static_cast<TestRenderViewHost*>(rvh())
281   //
282   // Since most functionality will eventually shift from RVH to RFH, you may
283   // prefer to use the GetMainFrame() method in tests.
284   TestRenderViewHost* test_rvh();
285 
286   // pending_test_rvh() is equivalent to all of the following:
287   //   contents()->GetPendingMainFrame()->GetRenderViewHost() [if frame exists]
288   //   contents()->GetPendingRenderViewHost()
289   //   static_cast<TestRenderViewHost*>(pending_rvh())
290   //
291   // Since most functionality will eventually shift from RVH to RFH, you may
292   // prefer to use the GetPendingMainFrame() method in tests.
293   TestRenderViewHost* pending_test_rvh();
294 
295   // active_test_rvh() is equivalent to:
296   //   contents()->GetPendingRenderViewHost() ?
297   //        contents()->GetPendingRenderViewHost() :
298   //        contents()->GetRenderViewHost();
299   TestRenderViewHost* active_test_rvh();
300 
301   // main_test_rfh() is equivalent to contents()->GetMainFrame()
302   // TODO(nick): Replace all uses with contents()->GetMainFrame()
303   TestRenderFrameHost* main_test_rfh();
304 
305  private:
306   typedef std::unique_ptr<ui::test::ScopedSetSupportedScaleFactors>
307       ScopedSetSupportedScaleFactors;
308   ScopedSetSupportedScaleFactors scoped_set_supported_scale_factors_;
309   DISALLOW_COPY_AND_ASSIGN(RenderViewHostImplTestHarness);
310 };
311 
312 }  // namespace content
313 
314 #endif  // CONTENT_TEST_TEST_RENDER_VIEW_HOST_H_
315