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/renderer_host/render_widget_host_delegate.h"
18 #include "content/browser/renderer_host/render_widget_host_impl.h"
19 #include "content/common/view_messages.h"
20 #include "content/public/browser/browser_plugin_guest_delegate.h"
21 #include "content/public/browser/render_widget_host_view.h"
22 #include "content/public/test/mock_render_process_host.h"
23 #include "content/public/test/test_browser_context.h"
24 #include "content/test/test_render_view_host.h"
25 #include "content/test/test_web_contents.h"
26 #include "testing/gtest/include/gtest/gtest.h"
30 class MockRenderWidgetHostDelegate
: public RenderWidgetHostDelegate
{
32 MockRenderWidgetHostDelegate() {}
33 ~MockRenderWidgetHostDelegate() override
{}
36 class RenderWidgetHostViewGuestTest
: public testing::Test
{
38 RenderWidgetHostViewGuestTest() {}
40 void SetUp() override
{
41 #if !defined(OS_ANDROID)
42 ImageTransportFactory::InitializeForUnitTests(
43 scoped_ptr
<ImageTransportFactory
>(
44 new NoTransportImageTransportFactory
));
46 browser_context_
.reset(new TestBrowserContext
);
47 MockRenderProcessHost
* process_host
=
48 new MockRenderProcessHost(browser_context_
.get());
49 widget_host_
= new RenderWidgetHostImpl(
50 &delegate_
, process_host
, MSG_ROUTING_NONE
, false);
51 view_
= new RenderWidgetHostViewGuest(
53 (new TestRenderWidgetHostView(widget_host_
))->GetWeakPtr());
56 void TearDown() override
{
61 browser_context_
.reset();
63 message_loop_
.DeleteSoon(FROM_HERE
, browser_context_
.release());
64 message_loop_
.RunUntilIdle();
65 #if !defined(OS_ANDROID)
66 ImageTransportFactory::Terminate();
71 base::MessageLoopForUI message_loop_
;
72 scoped_ptr
<BrowserContext
> browser_context_
;
73 MockRenderWidgetHostDelegate delegate_
;
75 // Tests should set these to NULL if they've already triggered their
77 RenderWidgetHostImpl
* widget_host_
;
78 RenderWidgetHostViewGuest
* view_
;
81 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewGuestTest
);
86 TEST_F(RenderWidgetHostViewGuestTest
, VisibilityTest
) {
88 ASSERT_TRUE(view_
->IsShowing());
91 ASSERT_FALSE(view_
->IsShowing());
94 class TestBrowserPluginGuest
: public BrowserPluginGuest
{
96 TestBrowserPluginGuest(WebContentsImpl
* web_contents
,
97 BrowserPluginGuestDelegate
* delegate
):
98 BrowserPluginGuest(web_contents
->HasOpener(), web_contents
, delegate
),
99 last_scale_factor_received_(0.f
),
100 update_scale_factor_received_(0.f
),
101 received_delegated_frame_(false) {}
102 ~TestBrowserPluginGuest() override
{}
104 void ResetTestData() {
105 update_frame_size_received_
= gfx::Size();
106 update_scale_factor_received_
= 0.f
;
107 last_surface_id_received_
= cc::SurfaceId();
108 last_frame_size_received_
= gfx::Size();
109 last_scale_factor_received_
= 0.f
;
110 received_delegated_frame_
= false;
113 void set_has_attached_since_surface_set(bool has_attached_since_surface_set
) {
114 BrowserPluginGuest::set_has_attached_since_surface_set_for_test(
115 has_attached_since_surface_set
);
118 void set_attached(bool attached
) {
119 BrowserPluginGuest::set_attached_for_test(attached
);
122 void UpdateGuestSizeIfNecessary(const gfx::Size
& frame_size
,
123 float scale_factor
) override
{
124 update_frame_size_received_
= frame_size
;
125 update_scale_factor_received_
= scale_factor
;
128 void SwapCompositorFrame(uint32_t output_surface_id
,
131 scoped_ptr
<cc::CompositorFrame
> frame
) override
{
132 received_delegated_frame_
= true;
133 last_frame_size_received_
=
134 frame
->delegated_frame_data
->render_pass_list
.back()
135 ->output_rect
.size();
136 last_scale_factor_received_
= frame
->metadata
.device_scale_factor
;
138 // Call base-class version so that we can test UpdateGuestSizeIfNecessary().
139 BrowserPluginGuest::SwapCompositorFrame(output_surface_id
, host_process_id
,
140 host_routing_id
, frame
.Pass());
143 void SetChildFrameSurface(const cc::SurfaceId
& surface_id
,
144 const gfx::Size
& frame_size
,
146 const cc::SurfaceSequence
& sequence
) override
{
147 last_surface_id_received_
= surface_id
;
148 last_frame_size_received_
= frame_size
;
149 last_scale_factor_received_
= scale_factor
;
152 cc::SurfaceId last_surface_id_received_
;
153 gfx::Size last_frame_size_received_
;
154 gfx::Size update_frame_size_received_
;
155 float last_scale_factor_received_
;
156 float update_scale_factor_received_
;
158 bool received_delegated_frame_
;
161 // TODO(wjmaclean): we should restructure RenderWidgetHostViewChildFrameTest to
162 // look more like this one, and then this one could be derived from it. Also,
163 // include CreateDelegatedFrame as part of the test class so we don't have to
165 class RenderWidgetHostViewGuestSurfaceTest
166 : public testing::Test
{
168 RenderWidgetHostViewGuestSurfaceTest()
169 : widget_host_(nullptr), view_(nullptr) {}
171 void SetUp() override
{
172 #if !defined(OS_ANDROID)
173 ImageTransportFactory::InitializeForUnitTests(
174 scoped_ptr
<ImageTransportFactory
>(
175 new NoTransportImageTransportFactory
));
177 browser_context_
.reset(new TestBrowserContext
);
178 MockRenderProcessHost
* process_host
=
179 new MockRenderProcessHost(browser_context_
.get());
181 TestWebContents::Create(browser_context_
.get(), nullptr));
182 // We don't own the BPG, the WebContents does.
183 browser_plugin_guest_
= new TestBrowserPluginGuest(
184 web_contents_
.get(), &browser_plugin_guest_delegate_
);
186 widget_host_
= new RenderWidgetHostImpl(&delegate_
, process_host
,
187 MSG_ROUTING_NONE
, false);
188 view_
= new RenderWidgetHostViewGuest(
189 widget_host_
, browser_plugin_guest_
,
190 (new TestRenderWidgetHostView(widget_host_
))->GetWeakPtr());
193 void TearDown() override
{
198 // It's important to make sure that the view finishes destructing before
199 // we hit the destructor for the TestBrowserThreadBundle, so run the message
201 base::RunLoop().RunUntilIdle();
202 #if !defined(OS_ANDROID)
203 ImageTransportFactory::Terminate();
207 cc::SurfaceId
surface_id() {
209 return static_cast<RenderWidgetHostViewChildFrame
*>(view_
)->surface_id_
;
213 TestBrowserThreadBundle thread_bundle_
;
214 scoped_ptr
<BrowserContext
> browser_context_
;
215 MockRenderWidgetHostDelegate delegate_
;
216 BrowserPluginGuestDelegate browser_plugin_guest_delegate_
;
217 scoped_ptr
<TestWebContents
> web_contents_
;
218 TestBrowserPluginGuest
* browser_plugin_guest_
;
220 // Tests should set these to NULL if they've already triggered their
222 RenderWidgetHostImpl
* widget_host_
;
223 RenderWidgetHostViewGuest
* view_
;
226 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewGuestSurfaceTest
);
230 scoped_ptr
<cc::CompositorFrame
> CreateDelegatedFrame(float scale_factor
,
232 const gfx::Rect
& damage
) {
233 scoped_ptr
<cc::CompositorFrame
> frame(new cc::CompositorFrame
);
234 frame
->metadata
.device_scale_factor
= scale_factor
;
235 frame
->delegated_frame_data
.reset(new cc::DelegatedFrameData
);
237 scoped_ptr
<cc::RenderPass
> pass
= cc::RenderPass::Create();
238 pass
->SetNew(cc::RenderPassId(1, 1), gfx::Rect(size
), damage
,
240 frame
->delegated_frame_data
->render_pass_list
.push_back(pass
.Pass());
243 } // anonymous namespace
245 TEST_F(RenderWidgetHostViewGuestSurfaceTest
, TestGuestSurface
) {
246 gfx::Size
view_size(100, 100);
247 gfx::Rect
view_rect(view_size
);
248 float scale_factor
= 1.f
;
250 ASSERT_TRUE(browser_plugin_guest_
);
252 view_
->SetSize(view_size
);
255 browser_plugin_guest_
->set_attached(true);
256 view_
->OnSwapCompositorFrame(
257 0, CreateDelegatedFrame(scale_factor
, view_size
, view_rect
));
259 EXPECT_EQ(view_size
, browser_plugin_guest_
->update_frame_size_received_
);
260 EXPECT_EQ(scale_factor
,
261 browser_plugin_guest_
->update_scale_factor_received_
);
263 if (UseSurfacesEnabled()) {
264 cc::SurfaceId id
= surface_id();
266 #if !defined(OS_ANDROID)
267 ImageTransportFactory
* factory
= ImageTransportFactory::GetInstance();
268 cc::SurfaceManager
* manager
= factory
->GetSurfaceManager();
269 cc::Surface
* surface
= manager
->GetSurfaceForId(id
);
270 EXPECT_TRUE(surface
);
271 // There should be a SurfaceSequence created by the RWHVGuest.
272 EXPECT_EQ(1u, surface
->GetDestructionDependencyCount());
274 // Surface ID should have been passed to BrowserPluginGuest to
275 // be sent to the embedding renderer.
276 EXPECT_EQ(id
, browser_plugin_guest_
->last_surface_id_received_
);
277 EXPECT_EQ(view_size
, browser_plugin_guest_
->last_frame_size_received_
);
278 EXPECT_EQ(scale_factor
,
279 browser_plugin_guest_
->last_scale_factor_received_
);
282 EXPECT_TRUE(browser_plugin_guest_
->received_delegated_frame_
);
283 EXPECT_EQ(view_size
, browser_plugin_guest_
->last_frame_size_received_
);
284 EXPECT_EQ(scale_factor
, browser_plugin_guest_
->last_scale_factor_received_
);
287 browser_plugin_guest_
->ResetTestData();
288 browser_plugin_guest_
->set_has_attached_since_surface_set(true);
290 view_
->OnSwapCompositorFrame(
291 0, CreateDelegatedFrame(scale_factor
, view_size
, view_rect
));
293 if (UseSurfacesEnabled()) {
294 cc::SurfaceId id
= surface_id();
296 #if !defined(OS_ANDROID)
297 ImageTransportFactory
* factory
= ImageTransportFactory::GetInstance();
298 cc::SurfaceManager
* manager
= factory
->GetSurfaceManager();
299 cc::Surface
* surface
= manager
->GetSurfaceForId(id
);
300 EXPECT_TRUE(surface
);
301 // There should be a SurfaceSequence created by the RWHVGuest.
302 EXPECT_EQ(1u, surface
->GetDestructionDependencyCount());
304 // Surface ID should have been passed to BrowserPluginGuest to
305 // be sent to the embedding renderer.
306 EXPECT_EQ(id
, browser_plugin_guest_
->last_surface_id_received_
);
307 EXPECT_EQ(view_size
, browser_plugin_guest_
->last_frame_size_received_
);
308 EXPECT_EQ(scale_factor
,
309 browser_plugin_guest_
->last_scale_factor_received_
);
312 EXPECT_TRUE(browser_plugin_guest_
->received_delegated_frame_
);
313 EXPECT_EQ(view_size
, browser_plugin_guest_
->last_frame_size_received_
);
314 EXPECT_EQ(scale_factor
, browser_plugin_guest_
->last_scale_factor_received_
);
317 browser_plugin_guest_
->set_attached(false);
318 browser_plugin_guest_
->ResetTestData();
320 view_
->OnSwapCompositorFrame(
321 0, CreateDelegatedFrame(scale_factor
, view_size
, view_rect
));
322 EXPECT_EQ(gfx::Size(), browser_plugin_guest_
->update_frame_size_received_
);
323 EXPECT_EQ(0.f
, browser_plugin_guest_
->update_scale_factor_received_
);
324 if (UseSurfacesEnabled())
325 EXPECT_TRUE(surface_id().is_null());
328 } // namespace content