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 // RenderWidgetHostDelegate:
37 void Cut() override
{}
38 void Copy() override
{}
39 void Paste() override
{}
40 void SelectAll() override
{}
43 class RenderWidgetHostViewGuestTest
: public testing::Test
{
45 RenderWidgetHostViewGuestTest() {}
47 void SetUp() override
{
48 #if !defined(OS_ANDROID)
49 ImageTransportFactory::InitializeForUnitTests(
50 scoped_ptr
<ImageTransportFactory
>(
51 new NoTransportImageTransportFactory
));
53 browser_context_
.reset(new TestBrowserContext
);
54 MockRenderProcessHost
* process_host
=
55 new MockRenderProcessHost(browser_context_
.get());
56 widget_host_
= new RenderWidgetHostImpl(
57 &delegate_
, process_host
, MSG_ROUTING_NONE
, false);
58 view_
= new RenderWidgetHostViewGuest(
60 (new TestRenderWidgetHostView(widget_host_
))->GetWeakPtr());
63 void TearDown() override
{
68 browser_context_
.reset();
70 message_loop_
.DeleteSoon(FROM_HERE
, browser_context_
.release());
71 message_loop_
.RunUntilIdle();
72 #if !defined(OS_ANDROID)
73 ImageTransportFactory::Terminate();
78 base::MessageLoopForUI message_loop_
;
79 scoped_ptr
<BrowserContext
> browser_context_
;
80 MockRenderWidgetHostDelegate delegate_
;
82 // Tests should set these to NULL if they've already triggered their
84 RenderWidgetHostImpl
* widget_host_
;
85 RenderWidgetHostViewGuest
* view_
;
88 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewGuestTest
);
93 TEST_F(RenderWidgetHostViewGuestTest
, VisibilityTest
) {
95 ASSERT_TRUE(view_
->IsShowing());
98 ASSERT_FALSE(view_
->IsShowing());
101 class TestBrowserPluginGuest
: public BrowserPluginGuest
{
103 TestBrowserPluginGuest(WebContentsImpl
* web_contents
,
104 BrowserPluginGuestDelegate
* delegate
):
105 BrowserPluginGuest(web_contents
->HasOpener(), web_contents
, delegate
),
106 last_scale_factor_received_(0.f
),
107 update_scale_factor_received_(0.f
),
108 received_delegated_frame_(false) {}
109 ~TestBrowserPluginGuest() override
{}
111 void ResetTestData() {
112 update_frame_size_received_
= gfx::Size();
113 update_scale_factor_received_
= 0.f
;
114 last_surface_id_received_
= cc::SurfaceId();
115 last_frame_size_received_
= gfx::Size();
116 last_scale_factor_received_
= 0.f
;
117 received_delegated_frame_
= false;
120 void set_has_attached_since_surface_set(bool has_attached_since_surface_set
) {
121 BrowserPluginGuest::set_has_attached_since_surface_set_for_test(
122 has_attached_since_surface_set
);
125 void set_attached(bool attached
) {
126 BrowserPluginGuest::set_attached_for_test(attached
);
129 void UpdateGuestSizeIfNecessary(const gfx::Size
& frame_size
,
130 float scale_factor
) override
{
131 update_frame_size_received_
= frame_size
;
132 update_scale_factor_received_
= scale_factor
;
135 void SwapCompositorFrame(uint32_t output_surface_id
,
138 scoped_ptr
<cc::CompositorFrame
> frame
) override
{
139 received_delegated_frame_
= true;
140 last_frame_size_received_
=
141 frame
->delegated_frame_data
->render_pass_list
.back()
142 ->output_rect
.size();
143 last_scale_factor_received_
= frame
->metadata
.device_scale_factor
;
145 // Call base-class version so that we can test UpdateGuestSizeIfNecessary().
146 BrowserPluginGuest::SwapCompositorFrame(output_surface_id
, host_process_id
,
147 host_routing_id
, frame
.Pass());
150 void SetChildFrameSurface(const cc::SurfaceId
& surface_id
,
151 const gfx::Size
& frame_size
,
153 const cc::SurfaceSequence
& sequence
) override
{
154 last_surface_id_received_
= surface_id
;
155 last_frame_size_received_
= frame_size
;
156 last_scale_factor_received_
= scale_factor
;
159 cc::SurfaceId last_surface_id_received_
;
160 gfx::Size last_frame_size_received_
;
161 gfx::Size update_frame_size_received_
;
162 float last_scale_factor_received_
;
163 float update_scale_factor_received_
;
165 bool received_delegated_frame_
;
168 // TODO(wjmaclean): we should restructure RenderWidgetHostViewChildFrameTest to
169 // look more like this one, and then this one could be derived from it. Also,
170 // include CreateDelegatedFrame as part of the test class so we don't have to
172 class RenderWidgetHostViewGuestSurfaceTest
173 : public testing::Test
{
175 RenderWidgetHostViewGuestSurfaceTest()
176 : widget_host_(nullptr), view_(nullptr) {}
178 void SetUp() override
{
179 #if !defined(OS_ANDROID)
180 ImageTransportFactory::InitializeForUnitTests(
181 scoped_ptr
<ImageTransportFactory
>(
182 new NoTransportImageTransportFactory
));
184 browser_context_
.reset(new TestBrowserContext
);
185 MockRenderProcessHost
* process_host
=
186 new MockRenderProcessHost(browser_context_
.get());
188 TestWebContents::Create(browser_context_
.get(), nullptr));
189 // We don't own the BPG, the WebContents does.
190 browser_plugin_guest_
= new TestBrowserPluginGuest(
191 web_contents_
.get(), &browser_plugin_guest_delegate_
);
193 widget_host_
= new RenderWidgetHostImpl(&delegate_
, process_host
,
194 MSG_ROUTING_NONE
, false);
195 view_
= new RenderWidgetHostViewGuest(
196 widget_host_
, browser_plugin_guest_
,
197 (new TestRenderWidgetHostView(widget_host_
))->GetWeakPtr());
200 void TearDown() override
{
205 // It's important to make sure that the view finishes destructing before
206 // we hit the destructor for the TestBrowserThreadBundle, so run the message
208 base::RunLoop().RunUntilIdle();
209 #if !defined(OS_ANDROID)
210 ImageTransportFactory::Terminate();
214 cc::SurfaceId
surface_id() {
216 return static_cast<RenderWidgetHostViewChildFrame
*>(view_
)->surface_id_
;
220 TestBrowserThreadBundle thread_bundle_
;
221 scoped_ptr
<BrowserContext
> browser_context_
;
222 MockRenderWidgetHostDelegate delegate_
;
223 BrowserPluginGuestDelegate browser_plugin_guest_delegate_
;
224 scoped_ptr
<TestWebContents
> web_contents_
;
225 TestBrowserPluginGuest
* browser_plugin_guest_
;
227 // Tests should set these to NULL if they've already triggered their
229 RenderWidgetHostImpl
* widget_host_
;
230 RenderWidgetHostViewGuest
* view_
;
233 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewGuestSurfaceTest
);
237 scoped_ptr
<cc::CompositorFrame
> CreateDelegatedFrame(float scale_factor
,
239 const gfx::Rect
& damage
) {
240 scoped_ptr
<cc::CompositorFrame
> frame(new cc::CompositorFrame
);
241 frame
->metadata
.device_scale_factor
= scale_factor
;
242 frame
->delegated_frame_data
.reset(new cc::DelegatedFrameData
);
244 scoped_ptr
<cc::RenderPass
> pass
= cc::RenderPass::Create();
245 pass
->SetNew(cc::RenderPassId(1, 1), gfx::Rect(size
), damage
,
247 frame
->delegated_frame_data
->render_pass_list
.push_back(pass
.Pass());
250 } // anonymous namespace
252 TEST_F(RenderWidgetHostViewGuestSurfaceTest
, TestGuestSurface
) {
253 gfx::Size
view_size(100, 100);
254 gfx::Rect
view_rect(view_size
);
255 float scale_factor
= 1.f
;
257 ASSERT_TRUE(browser_plugin_guest_
);
259 view_
->SetSize(view_size
);
262 browser_plugin_guest_
->set_attached(true);
263 view_
->OnSwapCompositorFrame(
264 0, CreateDelegatedFrame(scale_factor
, view_size
, view_rect
));
266 EXPECT_EQ(view_size
, browser_plugin_guest_
->update_frame_size_received_
);
267 EXPECT_EQ(scale_factor
,
268 browser_plugin_guest_
->update_scale_factor_received_
);
270 if (UseSurfacesEnabled()) {
271 cc::SurfaceId id
= surface_id();
273 #if !defined(OS_ANDROID)
274 ImageTransportFactory
* factory
= ImageTransportFactory::GetInstance();
275 cc::SurfaceManager
* manager
= factory
->GetSurfaceManager();
276 cc::Surface
* surface
= manager
->GetSurfaceForId(id
);
277 EXPECT_TRUE(surface
);
278 // There should be a SurfaceSequence created by the RWHVGuest.
279 EXPECT_EQ(1u, surface
->GetDestructionDependencyCount());
281 // Surface ID should have been passed to BrowserPluginGuest to
282 // be sent to the embedding renderer.
283 EXPECT_EQ(id
, browser_plugin_guest_
->last_surface_id_received_
);
284 EXPECT_EQ(view_size
, browser_plugin_guest_
->last_frame_size_received_
);
285 EXPECT_EQ(scale_factor
,
286 browser_plugin_guest_
->last_scale_factor_received_
);
289 EXPECT_TRUE(browser_plugin_guest_
->received_delegated_frame_
);
290 EXPECT_EQ(view_size
, browser_plugin_guest_
->last_frame_size_received_
);
291 EXPECT_EQ(scale_factor
, browser_plugin_guest_
->last_scale_factor_received_
);
294 browser_plugin_guest_
->ResetTestData();
295 browser_plugin_guest_
->set_has_attached_since_surface_set(true);
297 view_
->OnSwapCompositorFrame(
298 0, CreateDelegatedFrame(scale_factor
, view_size
, view_rect
));
300 if (UseSurfacesEnabled()) {
301 cc::SurfaceId id
= surface_id();
303 #if !defined(OS_ANDROID)
304 ImageTransportFactory
* factory
= ImageTransportFactory::GetInstance();
305 cc::SurfaceManager
* manager
= factory
->GetSurfaceManager();
306 cc::Surface
* surface
= manager
->GetSurfaceForId(id
);
307 EXPECT_TRUE(surface
);
308 // There should be a SurfaceSequence created by the RWHVGuest.
309 EXPECT_EQ(1u, surface
->GetDestructionDependencyCount());
311 // Surface ID should have been passed to BrowserPluginGuest to
312 // be sent to the embedding renderer.
313 EXPECT_EQ(id
, browser_plugin_guest_
->last_surface_id_received_
);
314 EXPECT_EQ(view_size
, browser_plugin_guest_
->last_frame_size_received_
);
315 EXPECT_EQ(scale_factor
,
316 browser_plugin_guest_
->last_scale_factor_received_
);
319 EXPECT_TRUE(browser_plugin_guest_
->received_delegated_frame_
);
320 EXPECT_EQ(view_size
, browser_plugin_guest_
->last_frame_size_received_
);
321 EXPECT_EQ(scale_factor
, browser_plugin_guest_
->last_scale_factor_received_
);
324 browser_plugin_guest_
->set_attached(false);
325 browser_plugin_guest_
->ResetTestData();
327 view_
->OnSwapCompositorFrame(
328 0, CreateDelegatedFrame(scale_factor
, view_size
, view_rect
));
329 EXPECT_EQ(gfx::Size(), browser_plugin_guest_
->update_frame_size_received_
);
330 EXPECT_EQ(0.f
, browser_plugin_guest_
->update_scale_factor_received_
);
331 if (UseSurfacesEnabled())
332 EXPECT_TRUE(surface_id().is_null());
335 } // namespace content