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 received_delegated_frame_(false) {}
112 ~TestBrowserPluginGuest() override
{}
114 void ResetTestData() {
115 last_surface_id_received_
= cc::SurfaceId();
116 last_frame_size_received_
= gfx::Size();
117 last_scale_factor_received_
= 0.f
;
118 received_delegated_frame_
= false;
121 void set_has_attached_since_surface_set(bool has_attached_since_surface_set
) {
122 BrowserPluginGuest::set_has_attached_since_surface_set_for_test(
123 has_attached_since_surface_set
);
126 void set_attached(bool attached
) {
127 BrowserPluginGuest::set_attached_for_test(attached
);
130 void SwapCompositorFrame(uint32_t output_surface_id
,
133 scoped_ptr
<cc::CompositorFrame
> frame
) override
{
134 received_delegated_frame_
= true;
135 last_frame_size_received_
=
136 frame
->delegated_frame_data
->render_pass_list
.back()
137 ->output_rect
.size();
138 last_scale_factor_received_
= frame
->metadata
.device_scale_factor
;
140 // Call base-class version so that we can test UpdateGuestSizeIfNecessary().
141 BrowserPluginGuest::SwapCompositorFrame(output_surface_id
, host_process_id
,
142 host_routing_id
, frame
.Pass());
145 void SetChildFrameSurface(const cc::SurfaceId
& surface_id
,
146 const gfx::Size
& frame_size
,
148 const cc::SurfaceSequence
& sequence
) override
{
149 last_surface_id_received_
= surface_id
;
150 last_frame_size_received_
= frame_size
;
151 last_scale_factor_received_
= scale_factor
;
154 cc::SurfaceId last_surface_id_received_
;
155 gfx::Size last_frame_size_received_
;
156 float last_scale_factor_received_
;
157 float update_scale_factor_received_
;
159 bool received_delegated_frame_
;
162 // TODO(wjmaclean): we should restructure RenderWidgetHostViewChildFrameTest to
163 // look more like this one, and then this one could be derived from it. Also,
164 // include CreateDelegatedFrame as part of the test class so we don't have to
166 class RenderWidgetHostViewGuestSurfaceTest
167 : public testing::Test
{
169 RenderWidgetHostViewGuestSurfaceTest()
170 : widget_host_(nullptr), view_(nullptr) {}
172 void SetUp() override
{
173 #if !defined(OS_ANDROID)
174 ImageTransportFactory::InitializeForUnitTests(
175 scoped_ptr
<ImageTransportFactory
>(
176 new NoTransportImageTransportFactory
));
178 browser_context_
.reset(new TestBrowserContext
);
179 MockRenderProcessHost
* process_host
=
180 new MockRenderProcessHost(browser_context_
.get());
182 TestWebContents::Create(browser_context_
.get(), nullptr));
183 // We don't own the BPG, the WebContents does.
184 browser_plugin_guest_
= new TestBrowserPluginGuest(
185 web_contents_
.get(), &browser_plugin_guest_delegate_
);
187 int32 routing_id
= process_host
->GetNextRoutingID();
188 int32 surface_id
= GpuSurfaceTracker::Get()->AddSurfaceForRenderer(
189 process_host
->GetID(), routing_id
);
190 widget_host_
= new RenderWidgetHostImpl(&delegate_
, process_host
,
191 routing_id
, surface_id
, false);
192 view_
= new RenderWidgetHostViewGuest(
193 widget_host_
, browser_plugin_guest_
,
194 (new TestRenderWidgetHostView(widget_host_
))->GetWeakPtr());
197 void TearDown() override
{
202 // It's important to make sure that the view finishes destructing before
203 // we hit the destructor for the TestBrowserThreadBundle, so run the message
205 base::RunLoop().RunUntilIdle();
206 #if !defined(OS_ANDROID)
207 ImageTransportFactory::Terminate();
211 cc::SurfaceId
surface_id() {
213 return static_cast<RenderWidgetHostViewChildFrame
*>(view_
)->surface_id_
;
217 TestBrowserThreadBundle thread_bundle_
;
218 scoped_ptr
<BrowserContext
> browser_context_
;
219 MockRenderWidgetHostDelegate delegate_
;
220 BrowserPluginGuestDelegate browser_plugin_guest_delegate_
;
221 scoped_ptr
<TestWebContents
> web_contents_
;
222 TestBrowserPluginGuest
* browser_plugin_guest_
;
224 // Tests should set these to NULL if they've already triggered their
226 RenderWidgetHostImpl
* widget_host_
;
227 RenderWidgetHostViewGuest
* view_
;
230 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewGuestSurfaceTest
);
234 scoped_ptr
<cc::CompositorFrame
> CreateDelegatedFrame(float scale_factor
,
236 const gfx::Rect
& damage
) {
237 scoped_ptr
<cc::CompositorFrame
> frame(new cc::CompositorFrame
);
238 frame
->metadata
.device_scale_factor
= scale_factor
;
239 frame
->delegated_frame_data
.reset(new cc::DelegatedFrameData
);
241 scoped_ptr
<cc::RenderPass
> pass
= cc::RenderPass::Create();
242 pass
->SetNew(cc::RenderPassId(1, 1), gfx::Rect(size
), damage
,
244 frame
->delegated_frame_data
->render_pass_list
.push_back(pass
.Pass());
247 } // anonymous namespace
249 TEST_F(RenderWidgetHostViewGuestSurfaceTest
, TestGuestSurface
) {
250 gfx::Size
view_size(100, 100);
251 gfx::Rect
view_rect(view_size
);
252 float scale_factor
= 1.f
;
254 ASSERT_TRUE(browser_plugin_guest_
);
256 view_
->SetSize(view_size
);
259 browser_plugin_guest_
->set_attached(true);
260 view_
->OnSwapCompositorFrame(
261 0, CreateDelegatedFrame(scale_factor
, view_size
, view_rect
));
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 if (UseSurfacesEnabled())
323 EXPECT_TRUE(surface_id().is_null());
326 } // namespace content