1 // Copyright 2014 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.
5 #include "content/browser/frame_host/render_widget_host_view_guest.h"
7 #include "base/basictypes.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "cc/surfaces/surface.h"
11 #include "cc/surfaces/surface_factory.h"
12 #include "cc/surfaces/surface_manager.h"
13 #include "cc/surfaces/surface_sequence.h"
14 #include "content/browser/browser_plugin/browser_plugin_guest.h"
15 #include "content/browser/compositor/test/no_transport_image_transport_factory.h"
16 #include "content/browser/gpu/compositor_util.h"
17 #include "content/browser/gpu/gpu_surface_tracker.h"
18 #include "content/browser/renderer_host/render_widget_host_delegate.h"
19 #include "content/browser/renderer_host/render_widget_host_impl.h"
20 #include "content/common/view_messages.h"
21 #include "content/public/browser/browser_plugin_guest_delegate.h"
22 #include "content/public/browser/render_widget_host_view.h"
23 #include "content/public/test/mock_render_process_host.h"
24 #include "content/public/test/test_browser_context.h"
25 #include "content/test/test_render_view_host.h"
26 #include "content/test/test_web_contents.h"
27 #include "testing/gtest/include/gtest/gtest.h"
31 class MockRenderWidgetHostDelegate
: public RenderWidgetHostDelegate
{
33 MockRenderWidgetHostDelegate() {}
34 ~MockRenderWidgetHostDelegate() override
{}
37 // RenderWidgetHostDelegate:
38 void Cut() override
{}
39 void Copy() override
{}
40 void Paste() override
{}
41 void SelectAll() override
{}
44 class RenderWidgetHostViewGuestTest
: public testing::Test
{
46 RenderWidgetHostViewGuestTest() {}
48 void SetUp() override
{
49 #if !defined(OS_ANDROID)
50 ImageTransportFactory::InitializeForUnitTests(
51 scoped_ptr
<ImageTransportFactory
>(
52 new NoTransportImageTransportFactory
));
54 browser_context_
.reset(new TestBrowserContext
);
55 MockRenderProcessHost
* process_host
=
56 new MockRenderProcessHost(browser_context_
.get());
57 int32 routing_id
= process_host
->GetNextRoutingID();
58 int32 surface_id
= GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
59 process_host
->GetID(), routing_id
);
60 widget_host_
= new RenderWidgetHostImpl(&delegate_
, process_host
,
61 routing_id
, surface_id
, false);
62 view_
= new RenderWidgetHostViewGuest(
64 (new TestRenderWidgetHostView(widget_host_
))->GetWeakPtr());
67 void TearDown() override
{
72 browser_context_
.reset();
74 message_loop_
.DeleteSoon(FROM_HERE
, browser_context_
.release());
75 message_loop_
.RunUntilIdle();
76 #if !defined(OS_ANDROID)
77 ImageTransportFactory::Terminate();
82 base::MessageLoopForUI message_loop_
;
83 scoped_ptr
<BrowserContext
> browser_context_
;
84 MockRenderWidgetHostDelegate delegate_
;
86 // Tests should set these to NULL if they've already triggered their
88 RenderWidgetHostImpl
* widget_host_
;
89 RenderWidgetHostViewGuest
* view_
;
92 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewGuestTest
);
97 TEST_F(RenderWidgetHostViewGuestTest
, VisibilityTest
) {
99 ASSERT_TRUE(view_
->IsShowing());
102 ASSERT_FALSE(view_
->IsShowing());
105 class TestBrowserPluginGuest
: public BrowserPluginGuest
{
107 TestBrowserPluginGuest(WebContentsImpl
* web_contents
,
108 BrowserPluginGuestDelegate
* delegate
):
109 BrowserPluginGuest(web_contents
->HasOpener(), web_contents
, delegate
),
110 last_scale_factor_received_(0.f
),
111 update_scale_factor_received_(0.f
),
112 received_delegated_frame_(false) {}
113 ~TestBrowserPluginGuest() override
{}
115 void ResetTestData() {
116 update_frame_size_received_
= gfx::Size();
117 update_scale_factor_received_
= 0.f
;
118 last_surface_id_received_
= cc::SurfaceId();
119 last_frame_size_received_
= gfx::Size();
120 last_scale_factor_received_
= 0.f
;
121 received_delegated_frame_
= false;
124 void set_has_attached_since_surface_set(bool has_attached_since_surface_set
) {
125 BrowserPluginGuest::set_has_attached_since_surface_set_for_test(
126 has_attached_since_surface_set
);
129 void set_attached(bool attached
) {
130 BrowserPluginGuest::set_attached_for_test(attached
);
133 void UpdateGuestSizeIfNecessary(const gfx::Size
& frame_size
,
134 float scale_factor
) override
{
135 update_frame_size_received_
= frame_size
;
136 update_scale_factor_received_
= scale_factor
;
139 void SwapCompositorFrame(uint32_t output_surface_id
,
142 scoped_ptr
<cc::CompositorFrame
> frame
) override
{
143 received_delegated_frame_
= true;
144 last_frame_size_received_
=
145 frame
->delegated_frame_data
->render_pass_list
.back()
146 ->output_rect
.size();
147 last_scale_factor_received_
= frame
->metadata
.device_scale_factor
;
149 // Call base-class version so that we can test UpdateGuestSizeIfNecessary().
150 BrowserPluginGuest::SwapCompositorFrame(output_surface_id
, host_process_id
,
151 host_routing_id
, frame
.Pass());
154 void SetChildFrameSurface(const cc::SurfaceId
& surface_id
,
155 const gfx::Size
& frame_size
,
157 const cc::SurfaceSequence
& sequence
) override
{
158 last_surface_id_received_
= surface_id
;
159 last_frame_size_received_
= frame_size
;
160 last_scale_factor_received_
= scale_factor
;
163 cc::SurfaceId last_surface_id_received_
;
164 gfx::Size last_frame_size_received_
;
165 gfx::Size update_frame_size_received_
;
166 float last_scale_factor_received_
;
167 float update_scale_factor_received_
;
169 bool received_delegated_frame_
;
172 // TODO(wjmaclean): we should restructure RenderWidgetHostViewChildFrameTest to
173 // look more like this one, and then this one could be derived from it. Also,
174 // include CreateDelegatedFrame as part of the test class so we don't have to
176 class RenderWidgetHostViewGuestSurfaceTest
177 : public testing::Test
{
179 RenderWidgetHostViewGuestSurfaceTest()
180 : widget_host_(nullptr), view_(nullptr) {}
182 void SetUp() override
{
183 #if !defined(OS_ANDROID)
184 ImageTransportFactory::InitializeForUnitTests(
185 scoped_ptr
<ImageTransportFactory
>(
186 new NoTransportImageTransportFactory
));
188 browser_context_
.reset(new TestBrowserContext
);
189 MockRenderProcessHost
* process_host
=
190 new MockRenderProcessHost(browser_context_
.get());
192 TestWebContents::Create(browser_context_
.get(), nullptr));
193 // We don't own the BPG, the WebContents does.
194 browser_plugin_guest_
= new TestBrowserPluginGuest(
195 web_contents_
.get(), &browser_plugin_guest_delegate_
);
197 int32 routing_id
= process_host
->GetNextRoutingID();
198 int32 surface_id
= GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
199 process_host
->GetID(), routing_id
);
200 widget_host_
= new RenderWidgetHostImpl(&delegate_
, process_host
,
201 routing_id
, surface_id
, false);
202 view_
= new RenderWidgetHostViewGuest(
203 widget_host_
, browser_plugin_guest_
,
204 (new TestRenderWidgetHostView(widget_host_
))->GetWeakPtr());
207 void TearDown() override
{
212 // It's important to make sure that the view finishes destructing before
213 // we hit the destructor for the TestBrowserThreadBundle, so run the message
215 base::RunLoop().RunUntilIdle();
216 #if !defined(OS_ANDROID)
217 ImageTransportFactory::Terminate();
221 cc::SurfaceId
surface_id() {
223 return static_cast<RenderWidgetHostViewChildFrame
*>(view_
)->surface_id_
;
227 TestBrowserThreadBundle thread_bundle_
;
228 scoped_ptr
<BrowserContext
> browser_context_
;
229 MockRenderWidgetHostDelegate delegate_
;
230 BrowserPluginGuestDelegate browser_plugin_guest_delegate_
;
231 scoped_ptr
<TestWebContents
> web_contents_
;
232 TestBrowserPluginGuest
* browser_plugin_guest_
;
234 // Tests should set these to NULL if they've already triggered their
236 RenderWidgetHostImpl
* widget_host_
;
237 RenderWidgetHostViewGuest
* view_
;
240 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewGuestSurfaceTest
);
244 scoped_ptr
<cc::CompositorFrame
> CreateDelegatedFrame(float scale_factor
,
246 const gfx::Rect
& damage
) {
247 scoped_ptr
<cc::CompositorFrame
> frame(new cc::CompositorFrame
);
248 frame
->metadata
.device_scale_factor
= scale_factor
;
249 frame
->delegated_frame_data
.reset(new cc::DelegatedFrameData
);
251 scoped_ptr
<cc::RenderPass
> pass
= cc::RenderPass::Create();
252 pass
->SetNew(cc::RenderPassId(1, 1), gfx::Rect(size
), damage
,
254 frame
->delegated_frame_data
->render_pass_list
.push_back(pass
.Pass());
257 } // anonymous namespace
259 TEST_F(RenderWidgetHostViewGuestSurfaceTest
, TestGuestSurface
) {
260 gfx::Size
view_size(100, 100);
261 gfx::Rect
view_rect(view_size
);
262 float scale_factor
= 1.f
;
264 ASSERT_TRUE(browser_plugin_guest_
);
266 view_
->SetSize(view_size
);
269 browser_plugin_guest_
->set_attached(true);
270 view_
->OnSwapCompositorFrame(
271 0, CreateDelegatedFrame(scale_factor
, view_size
, view_rect
));
273 EXPECT_EQ(view_size
, browser_plugin_guest_
->update_frame_size_received_
);
274 EXPECT_EQ(scale_factor
,
275 browser_plugin_guest_
->update_scale_factor_received_
);
277 if (UseSurfacesEnabled()) {
278 cc::SurfaceId id
= surface_id();
280 #if !defined(OS_ANDROID)
281 ImageTransportFactory
* factory
= ImageTransportFactory::GetInstance();
282 cc::SurfaceManager
* manager
= factory
->GetSurfaceManager();
283 cc::Surface
* surface
= manager
->GetSurfaceForId(id
);
284 EXPECT_TRUE(surface
);
285 // There should be a SurfaceSequence created by the RWHVGuest.
286 EXPECT_EQ(1u, surface
->GetDestructionDependencyCount());
288 // Surface ID should have been passed to BrowserPluginGuest to
289 // be sent to the embedding renderer.
290 EXPECT_EQ(id
, browser_plugin_guest_
->last_surface_id_received_
);
291 EXPECT_EQ(view_size
, browser_plugin_guest_
->last_frame_size_received_
);
292 EXPECT_EQ(scale_factor
,
293 browser_plugin_guest_
->last_scale_factor_received_
);
296 EXPECT_TRUE(browser_plugin_guest_
->received_delegated_frame_
);
297 EXPECT_EQ(view_size
, browser_plugin_guest_
->last_frame_size_received_
);
298 EXPECT_EQ(scale_factor
, browser_plugin_guest_
->last_scale_factor_received_
);
301 browser_plugin_guest_
->ResetTestData();
302 browser_plugin_guest_
->set_has_attached_since_surface_set(true);
304 view_
->OnSwapCompositorFrame(
305 0, CreateDelegatedFrame(scale_factor
, view_size
, view_rect
));
307 if (UseSurfacesEnabled()) {
308 cc::SurfaceId id
= surface_id();
310 #if !defined(OS_ANDROID)
311 ImageTransportFactory
* factory
= ImageTransportFactory::GetInstance();
312 cc::SurfaceManager
* manager
= factory
->GetSurfaceManager();
313 cc::Surface
* surface
= manager
->GetSurfaceForId(id
);
314 EXPECT_TRUE(surface
);
315 // There should be a SurfaceSequence created by the RWHVGuest.
316 EXPECT_EQ(1u, surface
->GetDestructionDependencyCount());
318 // Surface ID should have been passed to BrowserPluginGuest to
319 // be sent to the embedding renderer.
320 EXPECT_EQ(id
, browser_plugin_guest_
->last_surface_id_received_
);
321 EXPECT_EQ(view_size
, browser_plugin_guest_
->last_frame_size_received_
);
322 EXPECT_EQ(scale_factor
,
323 browser_plugin_guest_
->last_scale_factor_received_
);
326 EXPECT_TRUE(browser_plugin_guest_
->received_delegated_frame_
);
327 EXPECT_EQ(view_size
, browser_plugin_guest_
->last_frame_size_received_
);
328 EXPECT_EQ(scale_factor
, browser_plugin_guest_
->last_scale_factor_received_
);
331 browser_plugin_guest_
->set_attached(false);
332 browser_plugin_guest_
->ResetTestData();
334 view_
->OnSwapCompositorFrame(
335 0, CreateDelegatedFrame(scale_factor
, view_size
, view_rect
));
336 EXPECT_EQ(gfx::Size(), browser_plugin_guest_
->update_frame_size_received_
);
337 EXPECT_EQ(0.f
, browser_plugin_guest_
->update_scale_factor_received_
);
338 if (UseSurfacesEnabled())
339 EXPECT_TRUE(surface_id().is_null());
342 } // namespace content