Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(598)

Side by Side Diff: content/browser/renderer_host/offscreen_canvas_provider_impl_unittest.cc

Issue 2810703004: Add observers to FrameSinkManagerHost. (Closed)
Patch Set: Make more better. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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 #include "content/browser/renderer_host/offscreen_canvas_provider_impl.h"
6
7 #include "base/memory/ptr_util.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "cc/ipc/mojo_compositor_frame_sink.mojom.h"
11 #include "content/browser/compositor/test/no_transport_image_transport_factory.h "
12 #include "content/browser/renderer_host/offscreen_canvas_surface_impl.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/WebKit/public/platform/modules/offscreencanvas/offscreen_c anvas_surface.mojom.h"
16
17 #if !defined(OS_ANDROID)
18 #include "content/browser/compositor/image_transport_factory.h"
19 #endif
20
21 using testing::ElementsAre;
22 using testing::IsEmpty;
23
24 namespace content {
25 namespace {
26
27 constexpr uint32_t kRendererClientId = 3;
28 constexpr cc::FrameSinkId kParentFrameSink(kRendererClientId, 1);
29 constexpr cc::FrameSinkId kFrameSinkA(kRendererClientId, 3);
30 constexpr cc::FrameSinkId kFrameSinkB(kRendererClientId, 4);
31
32 class StubOffscreenCanvasSurfaceClient
33 : public blink::mojom::OffscreenCanvasSurfaceClient {
34 public:
35 StubOffscreenCanvasSurfaceClient() : binding_(this) {}
36 ~StubOffscreenCanvasSurfaceClient() override {}
37
38 blink::mojom::OffscreenCanvasSurfaceClientPtr GetInterfacePtr() {
39 return binding_.CreateInterfacePtrAndBind();
40 }
41
42 const cc::SurfaceInfo& GetLastSurfaceInfo() const { return surface_info_; }
43
44 // blink::mojom::OffscreenCanvasSurfaceClient:
45 void OnSurfaceCreated(const cc::SurfaceInfo& surface_info) override {
46 surface_info_ = surface_info;
47 }
48
49 private:
50 mojo::Binding<blink::mojom::OffscreenCanvasSurfaceClient> binding_;
51
52 cc::SurfaceInfo surface_info_;
53
54 DISALLOW_COPY_AND_ASSIGN(StubOffscreenCanvasSurfaceClient);
55 };
56
57 class StubClientCompositorFrameSink
58 : public cc::mojom::MojoCompositorFrameSinkClient {
59 public:
60 StubClientCompositorFrameSink() : binding_(this) {}
61 ~StubClientCompositorFrameSink() override {}
62
63 cc::mojom::MojoCompositorFrameSinkClientPtr GetInterfacePtr() {
64 return binding_.CreateInterfacePtrAndBind();
65 }
66
67 // cc::mojom::MojoCompositorFrameSinkClient:
68 void DidReceiveCompositorFrameAck(
69 const cc::ReturnedResourceArray& resources) override {}
70 void OnBeginFrame(const cc::BeginFrameArgs& begin_frame_args) override {}
71 void ReclaimResources(const cc::ReturnedResourceArray& resources) override {}
72
73 private:
74 mojo::Binding<cc::mojom::MojoCompositorFrameSinkClient> binding_;
75
76 DISALLOW_COPY_AND_ASSIGN(StubClientCompositorFrameSink);
77 };
78
79 // Create a CompositorFrame suitable to send over IPC.
80 cc::CompositorFrame MakeCompositorFrame() {
81 cc::CompositorFrame frame;
82 frame.metadata.begin_frame_ack.source_id =
83 cc::BeginFrameArgs::kManualSourceId;
84 frame.metadata.begin_frame_ack.sequence_number =
85 cc::BeginFrameArgs::kStartingFrameNumber;
86 frame.metadata.device_scale_factor = 1.0f;
87
88 auto render_pass = cc::RenderPass::Create();
89 render_pass->id = 1;
90 render_pass->output_rect = gfx::Rect(100, 100);
91
92 frame.render_pass_list.push_back(std::move(render_pass));
93 return frame;
94 }
95
96 void RunUntilIdle() {
97 base::RunLoop().RunUntilIdle();
98 }
99
100 } // namespace
101
102 class OffscreenCanvasProviderImplTest : public testing::Test {
103 public:
104 OffscreenCanvasProviderImpl* provider() { return provider_.get(); }
105
106 OffscreenCanvasSurfaceImpl* GetOffscreenCanvasSurface(
107 const cc::FrameSinkId& frame_sink_id) {
108 auto iter = provider_->surfaces_.find(frame_sink_id);
109 if (iter == provider_->surfaces_.end())
110 return nullptr;
111 return iter->second.get();
112 }
113
114 std::vector<cc::FrameSinkId> ActiveSurfaces() {
115 std::vector<cc::FrameSinkId> frame_sink_ids;
116 for (auto& map_entry : provider_->surfaces_) {
117 frame_sink_ids.push_back(map_entry.second->frame_sink_id());
118 }
119 std::sort(frame_sink_ids.begin(), frame_sink_ids.end());
120 return frame_sink_ids;
121 }
122
123 void DeleteOffscreenCanvasProviderImpl() { provider_.reset(); }
124
125 protected:
126 void SetUp() override {
127 #if !defined(OS_ANDROID)
128 ImageTransportFactory::InitializeForUnitTests(
129 std::unique_ptr<ImageTransportFactory>(
130 new NoTransportImageTransportFactory));
131 ImageTransportFactory::GetInstance()
132 ->GetFrameSinkManagerHost()
133 ->ConnectToFrameSinkManager();
134 #endif
135 provider_ =
136 base::MakeUnique<OffscreenCanvasProviderImpl>(kRendererClientId);
137 }
138 void TearDown() override {
139 provider_.reset();
140 #if !defined(OS_ANDROID)
141 ImageTransportFactory::Terminate();
142 #endif
143 }
144
145 private:
146 base::MessageLoop message_loop_;
147 std::unique_ptr<OffscreenCanvasProviderImpl> provider_;
148 };
149
150 // Mimics the workflow of OffscreenCanvas.commit() on renderer process.
151 TEST_F(OffscreenCanvasProviderImplTest,
152 SingleHTMLCanvasElementTransferToOffscreen) {
153 // Mimic connection from the renderer main thread.
154 StubOffscreenCanvasSurfaceClient surface_client;
155 blink::mojom::OffscreenCanvasSurfacePtr surface;
156 provider()->CreateOffscreenCanvasSurface(kParentFrameSink, kFrameSinkA,
157 surface_client.GetInterfacePtr(),
158 mojo::MakeRequest(&surface));
159
160 OffscreenCanvasSurfaceImpl* surface_impl =
161 GetOffscreenCanvasSurface(kFrameSinkA);
162
163 // There should be a single OffscreenCanvasSurfaceImpl and it should have the
164 // provided FrameSinkId and parent FrameSinkId.
165 EXPECT_EQ(kFrameSinkA, surface_impl->frame_sink_id());
166 EXPECT_EQ(kParentFrameSink, surface_impl->parent_frame_sink_id());
167 EXPECT_THAT(ActiveSurfaces(), ElementsAre(kFrameSinkA));
168
169 // Mimic connection from the renderer main or worker thread.
170 cc::mojom::MojoCompositorFrameSinkPtr compositor_frame_sink;
171 StubClientCompositorFrameSink compositor_frame_sink_client;
172 provider()->CreateCompositorFrameSink(
173 kFrameSinkA, compositor_frame_sink_client.GetInterfacePtr(),
174 mojo::MakeRequest(&compositor_frame_sink));
175
176 // Submit a CompositorFrame with |local_id|.
177 const cc::LocalSurfaceId local_id(1, base::UnguessableToken::Create());
178 compositor_frame_sink->SubmitCompositorFrame(local_id, MakeCompositorFrame());
179
180 RunUntilIdle();
181
182 // OffscreenCanvasSurfaceImpl should have LocalSurfaceId that was submitted
183 // with the CompositorFrame.
184 EXPECT_EQ(local_id, surface_impl->local_surface_id());
185
186 // OffscreenCanvasSurfaceClient should get the new SurfaceId.
187 const auto& surface_info = surface_client.GetLastSurfaceInfo();
188 EXPECT_EQ(kFrameSinkA, surface_info.id().frame_sink_id());
189 EXPECT_EQ(local_id, surface_info.id().local_surface_id());
190
191 provider()->DestroyOffscreenCanvasSurface(kFrameSinkA);
192
193 EXPECT_THAT(ActiveSurfaces(), IsEmpty());
194 }
195
196 TEST_F(OffscreenCanvasProviderImplTest, ClientClosesConnection) {
197 StubOffscreenCanvasSurfaceClient surface_client;
198 blink::mojom::OffscreenCanvasSurfacePtr surface;
199 provider()->CreateOffscreenCanvasSurface(kParentFrameSink, kFrameSinkA,
200 surface_client.GetInterfacePtr(),
201 mojo::MakeRequest(&surface));
202
203 base::RunLoop().RunUntilIdle();
204
205 EXPECT_THAT(ActiveSurfaces(), ElementsAre(kFrameSinkA));
206
207 // Mimic closing the connection from the renderer.
208 surface.reset();
209
210 RunUntilIdle();
211
212 // The renderer closing the connection should destroy the
213 // OffscreenCanvasSurfaceImpl.
214 EXPECT_THAT(ActiveSurfaces(), IsEmpty());
215 }
216
217 // Check that destroying OffscreenCanvasProviderImpl closes all connections.
218 TEST_F(OffscreenCanvasProviderImplTest, OffscreenCanvasNotDestroyed) {
219 StubOffscreenCanvasSurfaceClient surface_client;
220 blink::mojom::OffscreenCanvasSurfacePtr surface;
221 provider()->CreateOffscreenCanvasSurface(kParentFrameSink, kFrameSinkA,
222 surface_client.GetInterfacePtr(),
223 mojo::MakeRequest(&surface));
224
225 bool encountered_error = false;
226 surface.set_connection_error_handler(
227 base::Bind([](bool* encountered_error) { *encountered_error = true; },
228 &encountered_error));
229
230 RunUntilIdle();
231
232 // There should be OffscreenCanvasSurfaceImpl and |surface| be connected.
233 EXPECT_THAT(ActiveSurfaces(), ElementsAre(kFrameSinkA));
234 EXPECT_TRUE(surface.is_bound());
235 EXPECT_FALSE(encountered_error);
236
237 // Delete OffscreenCanvasProviderImpl before all clients are disconnected.
238 DeleteOffscreenCanvasProviderImpl();
239
240 RunUntilIdle();
241
242 // This should destroy the OffscreenCanvasSurfaceImpl and close the connection
243 // to |surface|.
244 EXPECT_TRUE(encountered_error);
245 }
246
247 // This test tries to create an OffscreenCanvasSurfaceImpl with a client id that
248 // doesn't match the renderer. This should fail.
249 TEST_F(OffscreenCanvasProviderImplTest, InvalidClientId) {
250 const cc::FrameSinkId invalid_frame_sink_id(4, 3);
251 EXPECT_NE(kRendererClientId, invalid_frame_sink_id.client_id());
252
253 StubOffscreenCanvasSurfaceClient surface_client;
254 blink::mojom::OffscreenCanvasSurfacePtr surface;
255 provider()->CreateOffscreenCanvasSurface(
256 kParentFrameSink, invalid_frame_sink_id, surface_client.GetInterfacePtr(),
257 mojo::MakeRequest(&surface));
258
259 RunUntilIdle();
260
261 // No OffscreenCanvasSurfaceImpl should have been created.
262 EXPECT_THAT(ActiveSurfaces(), IsEmpty());
263 }
264
265 // Mimic renderer making two offscreen canvases.
266 TEST_F(OffscreenCanvasProviderImplTest,
267 MultiHTMLCanvasElementTransferToOffscreen) {
268 StubOffscreenCanvasSurfaceClient surface_client_a;
269 blink::mojom::OffscreenCanvasSurfacePtr surface_a;
270 provider()->CreateOffscreenCanvasSurface(kParentFrameSink, kFrameSinkA,
271 surface_client_a.GetInterfacePtr(),
272 mojo::MakeRequest(&surface_a));
273
274 StubOffscreenCanvasSurfaceClient surface_client_b;
275 blink::mojom::OffscreenCanvasSurfacePtr surface_b;
276 provider()->CreateOffscreenCanvasSurface(kParentFrameSink, kFrameSinkB,
277 surface_client_b.GetInterfacePtr(),
278 mojo::MakeRequest(&surface_b));
279
280 RunUntilIdle();
281
282 // There should be two OffscreenCanvasSurfaceImpls created.
283 EXPECT_THAT(ActiveSurfaces(), ElementsAre(kFrameSinkA, kFrameSinkB));
284
285 // Mimic closing first connection from the renderer.
286 surface_a.reset();
287 RunUntilIdle();
288
289 EXPECT_THAT(ActiveSurfaces(), ElementsAre(kFrameSinkB));
290
291 // Mimic closing second connection from the renderer.
292 surface_b.reset();
293 RunUntilIdle();
294
295 EXPECT_THAT(ActiveSurfaces(), IsEmpty());
296 }
297
298 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698