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

Side by Side Diff: services/view_manager/view_manager_service_apptest.cc

Issue 1531403003: Delete the ViewManager and WindowManager services. (Closed) Base URL: git@github.com:domokit/mojo.git@moz-3
Patch Set: rebase Created 4 years, 10 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 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.
4
5 #include "base/bind.h"
6 #include "base/message_loop/message_loop.h"
7 #include "base/run_loop.h"
8 #include "mojo/public/cpp/application/application_delegate.h"
9 #include "mojo/public/cpp/application/application_impl.h"
10 #include "mojo/public/cpp/application/application_test_base.h"
11 #include "mojo/services/view_manager/interfaces/view_manager.mojom.h"
12 #include "mojo/services/window_manager/interfaces/window_manager.mojom.h"
13 #include "mojo/services/window_manager/interfaces/window_manager_internal.mojom. h"
14 #include "services/view_manager/ids.h"
15 #include "services/view_manager/test_change_tracker.h"
16
17 using mojo::ApplicationConnection;
18 using mojo::ApplicationDelegate;
19 using mojo::Array;
20 using mojo::Callback;
21 using mojo::ConnectionSpecificId;
22 using mojo::ErrorCode;
23 using mojo::EventPtr;
24 using mojo::Id;
25 using mojo::InterfaceRequest;
26 using mojo::OrderDirection;
27 using mojo::RectPtr;
28 using mojo::ServiceProvider;
29 using mojo::ServiceProviderPtr;
30 using mojo::String;
31 using mojo::ViewDataPtr;
32 using mojo::ViewManagerClient;
33 using mojo::ViewManagerService;
34 using mojo::ViewportMetricsPtr;
35
36 namespace view_manager {
37
38 // Creates an id used for transport from the specified parameters.
39 Id BuildViewId(ConnectionSpecificId connection_id,
40 ConnectionSpecificId view_id) {
41 return (connection_id << 16) | view_id;
42 }
43
44 // Callback function from ViewManagerService functions. ------------------------
45
46 void BoolResultCallback(base::RunLoop* run_loop,
47 bool* result_cache,
48 bool result) {
49 *result_cache = result;
50 run_loop->Quit();
51 }
52
53 void ErrorCodeResultCallback(base::RunLoop* run_loop,
54 ErrorCode* result_cache,
55 ErrorCode result) {
56 *result_cache = result;
57 run_loop->Quit();
58 }
59
60 void ViewTreeResultCallback(base::RunLoop* run_loop,
61 std::vector<TestView>* views,
62 Array<ViewDataPtr> results) {
63 ViewDatasToTestViews(results, views);
64 run_loop->Quit();
65 }
66
67 // -----------------------------------------------------------------------------
68
69 // The following functions call through to the supplied ViewManagerService. They
70 // block until call completes and return the result.
71 bool CreateView(ViewManagerService* vm, Id view_id) {
72 ErrorCode result = ErrorCode::NONE;
73 base::RunLoop run_loop;
74 vm->CreateView(view_id,
75 base::Bind(&ErrorCodeResultCallback, &run_loop, &result));
76 run_loop.Run();
77 return result == ErrorCode::NONE;
78 }
79
80 bool EmbedUrl(ViewManagerService* vm, const String& url, Id root_id) {
81 bool result = false;
82 base::RunLoop run_loop;
83 {
84 vm->EmbedUrl(url, root_id, nullptr, nullptr,
85 base::Bind(&BoolResultCallback, &run_loop, &result));
86 }
87 run_loop.Run();
88 return result;
89 }
90
91 bool Embed(ViewManagerService* vm,
92 Id root_id,
93 mojo::ViewManagerClientPtr client) {
94 bool result = false;
95 base::RunLoop run_loop;
96 {
97 vm->Embed(root_id, client.Pass(),
98 base::Bind(&BoolResultCallback, &run_loop, &result));
99 }
100 run_loop.Run();
101 return result;
102 }
103
104 ErrorCode CreateViewWithErrorCode(ViewManagerService* vm, Id view_id) {
105 ErrorCode result = ErrorCode::NONE;
106 base::RunLoop run_loop;
107 vm->CreateView(view_id,
108 base::Bind(&ErrorCodeResultCallback, &run_loop, &result));
109 run_loop.Run();
110 return result;
111 }
112
113 bool AddView(ViewManagerService* vm, Id parent, Id child) {
114 bool result = false;
115 base::RunLoop run_loop;
116 vm->AddView(parent, child,
117 base::Bind(&BoolResultCallback, &run_loop, &result));
118 run_loop.Run();
119 return result;
120 }
121
122 bool RemoveViewFromParent(ViewManagerService* vm, Id view_id) {
123 bool result = false;
124 base::RunLoop run_loop;
125 vm->RemoveViewFromParent(view_id,
126 base::Bind(&BoolResultCallback, &run_loop, &result));
127 run_loop.Run();
128 return result;
129 }
130
131 bool ReorderView(ViewManagerService* vm,
132 Id view_id,
133 Id relative_view_id,
134 OrderDirection direction) {
135 bool result = false;
136 base::RunLoop run_loop;
137 vm->ReorderView(view_id, relative_view_id, direction,
138 base::Bind(&BoolResultCallback, &run_loop, &result));
139 run_loop.Run();
140 return result;
141 }
142
143 void GetViewTree(ViewManagerService* vm,
144 Id view_id,
145 std::vector<TestView>* views) {
146 base::RunLoop run_loop;
147 vm->GetViewTree(view_id,
148 base::Bind(&ViewTreeResultCallback, &run_loop, views));
149 run_loop.Run();
150 }
151
152 bool DeleteView(ViewManagerService* vm, Id view_id) {
153 base::RunLoop run_loop;
154 bool result = false;
155 vm->DeleteView(view_id, base::Bind(&BoolResultCallback, &run_loop, &result));
156 run_loop.Run();
157 return result;
158 }
159
160 bool SetViewBounds(ViewManagerService* vm,
161 Id view_id,
162 int x,
163 int y,
164 int w,
165 int h) {
166 base::RunLoop run_loop;
167 bool result = false;
168 RectPtr rect(mojo::Rect::New());
169 rect->x = x;
170 rect->y = y;
171 rect->width = w;
172 rect->height = h;
173 vm->SetViewBounds(view_id, rect.Pass(),
174 base::Bind(&BoolResultCallback, &run_loop, &result));
175 run_loop.Run();
176 return result;
177 }
178
179 bool SetViewVisibility(ViewManagerService* vm, Id view_id, bool visible) {
180 base::RunLoop run_loop;
181 bool result = false;
182 vm->SetViewVisibility(view_id, visible,
183 base::Bind(&BoolResultCallback, &run_loop, &result));
184 run_loop.Run();
185 return result;
186 }
187
188 bool SetViewProperty(ViewManagerService* vm,
189 Id view_id,
190 const std::string& name,
191 const std::vector<uint8_t>* data) {
192 base::RunLoop run_loop;
193 bool result = false;
194 Array<uint8_t> mojo_data;
195 if (data)
196 mojo_data = Array<uint8_t>::From(*data);
197 vm->SetViewProperty(view_id, name, mojo_data.Pass(),
198 base::Bind(&BoolResultCallback, &run_loop, &result));
199 run_loop.Run();
200 return result;
201 }
202
203 // Utility functions -----------------------------------------------------------
204
205 // Waits for all messages to be received by |vm|. This is done by attempting to
206 // create a bogus view. When we get the response we know all messages have been
207 // processed.
208 bool WaitForAllMessages(ViewManagerService* vm) {
209 ErrorCode result = ErrorCode::NONE;
210 base::RunLoop run_loop;
211 vm->CreateView(ViewIdToTransportId(InvalidViewId()),
212 base::Bind(&ErrorCodeResultCallback, &run_loop, &result));
213 run_loop.Run();
214 return result != ErrorCode::NONE;
215 }
216
217 bool HasClonedView(const std::vector<TestView>& views) {
218 for (size_t i = 0; i < views.size(); ++i)
219 if (views[i].view_id == ViewIdToTransportId(ClonedViewId()))
220 return true;
221 return false;
222 }
223
224 // -----------------------------------------------------------------------------
225
226 // A ViewManagerClient implementation that logs all changes to a tracker.
227 class ViewManagerClientImpl : public mojo::ViewManagerClient,
228 public TestChangeTracker::Delegate {
229 public:
230 ViewManagerClientImpl() : binding_(this) { tracker_.set_delegate(this); }
231
232 void Bind(mojo::InterfaceRequest<mojo::ViewManagerClient> request) {
233 binding_.Bind(request.Pass());
234 }
235
236 mojo::ViewManagerService* service() { return service_.get(); }
237 TestChangeTracker* tracker() { return &tracker_; }
238
239 // Runs a nested MessageLoop until |count| changes (calls to
240 // ViewManagerClient functions) have been received.
241 void WaitForChangeCount(size_t count) {
242 if (count == tracker_.changes()->size())
243 return;
244
245 ASSERT_TRUE(wait_state_.get() == nullptr);
246 wait_state_.reset(new WaitState);
247 wait_state_->change_count = count;
248 wait_state_->run_loop.Run();
249 wait_state_.reset();
250 }
251
252 // Runs a nested MessageLoop until OnEmbed() has been encountered.
253 void WaitForOnEmbed() {
254 if (service_)
255 return;
256 embed_run_loop_.reset(new base::RunLoop);
257 embed_run_loop_->Run();
258 embed_run_loop_.reset();
259 }
260
261 bool WaitForIncomingMethodCall() {
262 return binding_.WaitForIncomingMethodCall();
263 }
264
265 private:
266 // Used when running a nested MessageLoop.
267 struct WaitState {
268 WaitState() : change_count(0) {}
269
270 // Number of changes waiting for.
271 size_t change_count;
272 base::RunLoop run_loop;
273 };
274
275 // TestChangeTracker::Delegate:
276 void OnChangeAdded() override {
277 if (wait_state_.get() &&
278 wait_state_->change_count == tracker_.changes()->size()) {
279 wait_state_->run_loop.Quit();
280 }
281 }
282
283 // ViewManagerClient:
284 void OnEmbed(ConnectionSpecificId connection_id,
285 const String& creator_url,
286 ViewDataPtr root,
287 mojo::ViewManagerServicePtr view_manager_service,
288 InterfaceRequest<ServiceProvider> services,
289 ServiceProviderPtr exposed_services,
290 mojo::ScopedMessagePipeHandle window_manager_pipe) override {
291 service_ = view_manager_service.Pass();
292 tracker()->OnEmbed(connection_id, creator_url, root.Pass());
293 if (embed_run_loop_)
294 embed_run_loop_->Quit();
295 }
296 void OnEmbeddedAppDisconnected(Id view_id) override {
297 tracker()->OnEmbeddedAppDisconnected(view_id);
298 }
299 void OnViewBoundsChanged(Id view_id,
300 RectPtr old_bounds,
301 RectPtr new_bounds) override {
302 tracker()->OnViewBoundsChanged(view_id, old_bounds.Pass(),
303 new_bounds.Pass());
304 }
305 void OnViewViewportMetricsChanged(ViewportMetricsPtr old_metrics,
306 ViewportMetricsPtr new_metrics) override {
307 tracker()->OnViewViewportMetricsChanged(old_metrics.Pass(),
308 new_metrics.Pass());
309 }
310 void OnViewHierarchyChanged(Id view,
311 Id new_parent,
312 Id old_parent,
313 Array<ViewDataPtr> views) override {
314 tracker()->OnViewHierarchyChanged(view, new_parent, old_parent,
315 views.Pass());
316 }
317 void OnViewReordered(Id view_id,
318 Id relative_view_id,
319 OrderDirection direction) override {
320 tracker()->OnViewReordered(view_id, relative_view_id, direction);
321 }
322 void OnViewDeleted(Id view) override { tracker()->OnViewDeleted(view); }
323 void OnViewVisibilityChanged(uint32_t view, bool visible) override {
324 tracker()->OnViewVisibilityChanged(view, visible);
325 }
326 void OnViewDrawnStateChanged(uint32_t view, bool drawn) override {
327 tracker()->OnViewDrawnStateChanged(view, drawn);
328 }
329 void OnViewInputEvent(Id view_id,
330 EventPtr event,
331 const Callback<void()>& callback) override {
332 tracker()->OnViewInputEvent(view_id, event.Pass());
333 callback.Run();
334 }
335 void OnViewSharedPropertyChanged(uint32_t view,
336 const String& name,
337 Array<uint8_t> new_data) override {
338 tracker_.OnViewSharedPropertyChanged(view, name, new_data.Pass());
339 }
340 void OnPerformAction(uint32_t view,
341 const String& name,
342 const Callback<void(bool)>& callback) override {}
343
344 TestChangeTracker tracker_;
345
346 mojo::ViewManagerServicePtr service_;
347
348 // If non-null we're waiting for OnEmbed() using this RunLoop.
349 scoped_ptr<base::RunLoop> embed_run_loop_;
350
351 // If non-null we're waiting for a certain number of change notifications to
352 // be encountered.
353 scoped_ptr<WaitState> wait_state_;
354
355 mojo::Binding<ViewManagerClient> binding_;
356 DISALLOW_COPY_AND_ASSIGN(ViewManagerClientImpl);
357 };
358
359 // -----------------------------------------------------------------------------
360
361 // InterfaceFactory for vending ViewManagerClientImpls.
362 class ViewManagerClientFactory
363 : public mojo::InterfaceFactory<ViewManagerClient> {
364 public:
365 ViewManagerClientFactory() {}
366 ~ViewManagerClientFactory() override {}
367
368 // Runs a nested MessageLoop until a new instance has been created.
369 scoped_ptr<ViewManagerClientImpl> WaitForInstance() {
370 if (!client_impl_.get()) {
371 DCHECK(!run_loop_.get());
372 run_loop_.reset(new base::RunLoop);
373 run_loop_->Run();
374 run_loop_.reset();
375 }
376 return client_impl_.Pass();
377 }
378
379 private:
380 // InterfaceFactory<ViewManagerClient>:
381 void Create(ApplicationConnection* connection,
382 InterfaceRequest<ViewManagerClient> request) override {
383 client_impl_.reset(new ViewManagerClientImpl);
384 client_impl_->Bind(request.Pass());
385 if (run_loop_.get())
386 run_loop_->Quit();
387 }
388
389 scoped_ptr<ViewManagerClientImpl> client_impl_;
390 scoped_ptr<base::RunLoop> run_loop_;
391
392 DISALLOW_COPY_AND_ASSIGN(ViewManagerClientFactory);
393 };
394
395 class ViewManagerServiceAppTest
396 : public mojo::test::ApplicationTestBase,
397 public ApplicationDelegate,
398 public mojo::InterfaceFactory<mojo::WindowManagerInternal>,
399 public mojo::WindowManagerInternal {
400 public:
401 ViewManagerServiceAppTest() : wm_internal_binding_(this) {}
402 ~ViewManagerServiceAppTest() override {}
403
404 protected:
405 // Returns the changes from the various connections.
406 std::vector<Change>* changes1() { return vm_client1_.tracker()->changes(); }
407 std::vector<Change>* changes2() { return vm_client2_->tracker()->changes(); }
408 std::vector<Change>* changes3() { return vm_client3_->tracker()->changes(); }
409
410 // Various connections. |vm1()|, being the first connection, has special
411 // permissions (it's treated as the window manager).
412 ViewManagerService* vm1() { return vm1_.get(); }
413 ViewManagerService* vm2() { return vm_client2_->service(); }
414 ViewManagerService* vm3() { return vm_client3_->service(); }
415
416 void EstablishSecondConnectionWithRoot(Id root_id) {
417 ASSERT_TRUE(vm_client2_.get() == nullptr);
418 vm_client2_ = EstablishConnectionViaEmbed(vm1(), root_id);
419 ASSERT_TRUE(vm_client2_.get() != nullptr);
420 }
421
422 void EstablishSecondConnection(bool create_initial_view) {
423 if (create_initial_view)
424 ASSERT_TRUE(CreateView(vm1_.get(), BuildViewId(1, 1)));
425 ASSERT_NO_FATAL_FAILURE(
426 EstablishSecondConnectionWithRoot(BuildViewId(1, 1)));
427
428 if (create_initial_view)
429 EXPECT_EQ("[view=1,1 parent=null]", ChangeViewDescription(*changes2()));
430 }
431
432 void EstablishThirdConnection(ViewManagerService* owner, Id root_id) {
433 ASSERT_TRUE(vm_client3_.get() == nullptr);
434 vm_client3_ = EstablishConnectionViaEmbed(owner, root_id);
435 ASSERT_TRUE(vm_client3_.get() != nullptr);
436 }
437
438 // Establishes a new connection by way of Embed() on the specified
439 // ViewManagerService.
440 scoped_ptr<ViewManagerClientImpl> EstablishConnectionViaEmbed(
441 ViewManagerService* owner,
442 Id root_id) {
443 if (!EmbedUrl(owner, application_impl()->url(), root_id)) {
444 ADD_FAILURE() << "Embed() failed";
445 return nullptr;
446 }
447 scoped_ptr<ViewManagerClientImpl> client =
448 client_factory_.WaitForInstance();
449 if (!client.get()) {
450 ADD_FAILURE() << "WaitForInstance failed";
451 return nullptr;
452 }
453 client->WaitForOnEmbed();
454
455 const std::string expected_creator =
456 owner == vm1() ? "mojo:window_manager" : application_impl()->url();
457 EXPECT_EQ("OnEmbed creator=" + expected_creator,
458 SingleChangeToDescription(*client->tracker()->changes()));
459 return client;
460 }
461
462 // ApplicationTestBase:
463 ApplicationDelegate* GetApplicationDelegate() override { return this; }
464 void SetUp() override {
465 ApplicationTestBase::SetUp();
466 ApplicationConnection* vm_connection =
467 application_impl()->ConnectToApplication("mojo:view_manager");
468 vm_connection->AddService(this);
469 vm_connection->ConnectToService(&vm1_);
470 vm_connection->ConnectToService(&wm_internal_client_);
471 // Spin a run loop until the view manager service sends us the
472 // ViewManagerClient pipe to use for the "window manager" connection.
473 view_manager_setup_run_loop_.reset(new base::RunLoop);
474 view_manager_setup_run_loop_->Run();
475 view_manager_setup_run_loop_ = nullptr;
476 // Next we should get an embed call on the "window manager" client.
477 vm_client1_.WaitForIncomingMethodCall();
478 ASSERT_EQ(1u, changes1()->size());
479 EXPECT_EQ(CHANGE_TYPE_EMBED, (*changes1())[0].type);
480 // All these tests assume 1 for the client id. The only real assertion here
481 // is the client id is not zero, but adding this as rest of code here
482 // assumes 1.
483 ASSERT_EQ(1, (*changes1())[0].connection_id);
484 changes1()->clear();
485 }
486
487 // ApplicationDelegate implementation.
488 bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
489 connection->AddService(&client_factory_);
490 return true;
491 }
492
493 // mojo::InterfaceFactory<mojo::WindowManagerInternal> implementation.
494 void Create(
495 ApplicationConnection* connection,
496 mojo::InterfaceRequest<mojo::WindowManagerInternal> request) override {
497 DCHECK(!wm_internal_binding_.is_bound());
498 wm_internal_binding_.Bind(request.Pass());
499 }
500
501 // mojo::WindowManagerInternal implementation.
502 void CreateWindowManagerForViewManagerClient(
503 uint16_t connection_id,
504 mojo::ScopedMessagePipeHandle window_manager_pipe) override {}
505 void SetViewManagerClient(
506 mojo::ScopedMessagePipeHandle view_manager_client_request) override {
507 auto typed_request = mojo::MakeRequest<mojo::ViewManagerClient>(
508 view_manager_client_request.Pass());
509 vm_client1_.Bind(typed_request.Pass());
510 view_manager_setup_run_loop_->Quit();
511 }
512
513 mojo::Binding<mojo::WindowManagerInternal> wm_internal_binding_;
514 mojo::WindowManagerInternalClientPtr wm_internal_client_;
515 ViewManagerClientImpl vm_client1_;
516 scoped_ptr<ViewManagerClientImpl> vm_client2_;
517 scoped_ptr<ViewManagerClientImpl> vm_client3_;
518
519 private:
520 mojo::ViewManagerServicePtr vm1_;
521 ViewManagerClientFactory client_factory_;
522 scoped_ptr<base::RunLoop> view_manager_setup_run_loop_;
523
524 MOJO_DISALLOW_COPY_AND_ASSIGN(ViewManagerServiceAppTest);
525 };
526
527 // Verifies two clients/connections get different ids.
528 TEST_F(ViewManagerServiceAppTest, TwoClientsGetDifferentConnectionIds) {
529 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
530
531 // It isn't strictly necessary that the second connection gets 2, but these
532 // tests are written assuming that is the case. The key thing is the
533 // connection ids of |connection_| and |connection2_| differ.
534 ASSERT_EQ(1u, changes2()->size());
535 ASSERT_EQ(2, (*changes2())[0].connection_id);
536 }
537
538 // Verifies when Embed() is invoked any child views are removed.
539 TEST_F(ViewManagerServiceAppTest, ViewsRemovedWhenEmbedding) {
540 // Two views 1 and 2. 2 is parented to 1.
541 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 1)));
542 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 2)));
543 ASSERT_TRUE(AddView(vm1(), BuildViewId(1, 1), BuildViewId(1, 2)));
544
545 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false));
546 EXPECT_EQ("[view=1,1 parent=null]", ChangeViewDescription(*changes2()));
547
548 // Embed() removed view 2.
549 {
550 std::vector<TestView> views;
551 GetViewTree(vm1(), BuildViewId(1, 2), &views);
552 EXPECT_EQ("view=1,2 parent=null", SingleViewDescription(views));
553 }
554
555 // vm2 should not see view 2.
556 {
557 std::vector<TestView> views;
558 GetViewTree(vm2(), BuildViewId(1, 1), &views);
559 EXPECT_EQ("view=1,1 parent=null", SingleViewDescription(views));
560 }
561 {
562 std::vector<TestView> views;
563 GetViewTree(vm2(), BuildViewId(1, 2), &views);
564 EXPECT_TRUE(views.empty());
565 }
566
567 // Views 3 and 4 in connection 2.
568 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 3)));
569 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 4)));
570 ASSERT_TRUE(AddView(vm2(), BuildViewId(2, 3), BuildViewId(2, 4)));
571
572 // Connection 3 rooted at 2.
573 ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(vm2(), BuildViewId(2, 3)));
574
575 // View 4 should no longer have a parent.
576 {
577 std::vector<TestView> views;
578 GetViewTree(vm2(), BuildViewId(2, 3), &views);
579 EXPECT_EQ("view=2,3 parent=null", SingleViewDescription(views));
580
581 views.clear();
582 GetViewTree(vm2(), BuildViewId(2, 4), &views);
583 EXPECT_EQ("view=2,4 parent=null", SingleViewDescription(views));
584 }
585
586 // And view 4 should not be visible to connection 3.
587 {
588 std::vector<TestView> views;
589 GetViewTree(vm3(), BuildViewId(2, 3), &views);
590 EXPECT_EQ("view=2,3 parent=null", SingleViewDescription(views));
591 }
592 }
593
594 // Verifies once Embed() has been invoked the parent connection can't see any
595 // children.
596 TEST_F(ViewManagerServiceAppTest, CantAccessChildrenOfEmbeddedView) {
597 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
598
599 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 2)));
600 ASSERT_TRUE(AddView(vm2(), BuildViewId(1, 1), BuildViewId(2, 2)));
601
602 ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(vm2(), BuildViewId(2, 2)));
603
604 ASSERT_TRUE(CreateView(vm3(), BuildViewId(3, 3)));
605 ASSERT_TRUE(AddView(vm3(), BuildViewId(2, 2), BuildViewId(3, 3)));
606
607 // Even though 3 is a child of 2 connection 2 can't see 3 as it's from a
608 // different connection.
609 {
610 std::vector<TestView> views;
611 GetViewTree(vm2(), BuildViewId(2, 2), &views);
612 EXPECT_EQ("view=2,2 parent=1,1", SingleViewDescription(views));
613 }
614
615 // Connection 2 shouldn't be able to get view 3 at all.
616 {
617 std::vector<TestView> views;
618 GetViewTree(vm2(), BuildViewId(3, 3), &views);
619 EXPECT_TRUE(views.empty());
620 }
621
622 // Connection 1 should be able to see it all (its the root).
623 {
624 std::vector<TestView> views;
625 GetViewTree(vm1(), BuildViewId(1, 1), &views);
626 ASSERT_EQ(3u, views.size());
627 EXPECT_EQ("view=1,1 parent=null", views[0].ToString());
628 EXPECT_EQ("view=2,2 parent=1,1", views[1].ToString());
629 EXPECT_EQ("view=3,3 parent=2,2", views[2].ToString());
630 }
631 }
632
633 // Verifies once Embed() has been invoked the parent can't mutate the children.
634 TEST_F(ViewManagerServiceAppTest, CantModifyChildrenOfEmbeddedView) {
635 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
636
637 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 2)));
638 ASSERT_TRUE(AddView(vm2(), BuildViewId(1, 1), BuildViewId(2, 2)));
639
640 ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(vm2(), BuildViewId(2, 2)));
641
642 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 3)));
643 // Connection 2 shouldn't be able to add anything to the view anymore.
644 ASSERT_FALSE(AddView(vm2(), BuildViewId(2, 2), BuildViewId(2, 3)));
645
646 // Create view 3 in connection 3 and add it to view 3.
647 ASSERT_TRUE(CreateView(vm3(), BuildViewId(3, 3)));
648 ASSERT_TRUE(AddView(vm3(), BuildViewId(2, 2), BuildViewId(3, 3)));
649
650 // Connection 2 shouldn't be able to remove view 3.
651 ASSERT_FALSE(RemoveViewFromParent(vm2(), BuildViewId(3, 3)));
652 }
653
654 // Verifies client gets a valid id.
655 TEST_F(ViewManagerServiceAppTest, CreateView) {
656 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 1)));
657 EXPECT_TRUE(changes1()->empty());
658
659 // Can't create a view with the same id.
660 ASSERT_EQ(mojo::ErrorCode::VALUE_IN_USE,
661 CreateViewWithErrorCode(vm1(), BuildViewId(1, 1)));
662 EXPECT_TRUE(changes1()->empty());
663
664 // Can't create a view with a bogus connection id.
665 EXPECT_EQ(mojo::ErrorCode::ILLEGAL_ARGUMENT,
666 CreateViewWithErrorCode(vm1(), BuildViewId(2, 1)));
667 EXPECT_TRUE(changes1()->empty());
668 }
669
670 // Verifies AddView fails when view is already in position.
671 TEST_F(ViewManagerServiceAppTest, AddViewWithNoChange) {
672 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 2)));
673 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 3)));
674
675 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
676
677 // Make 3 a child of 2.
678 ASSERT_TRUE(AddView(vm1(), BuildViewId(1, 2), BuildViewId(1, 3)));
679
680 // Try again, this should fail.
681 EXPECT_FALSE(AddView(vm1(), BuildViewId(1, 2), BuildViewId(1, 3)));
682 }
683
684 // Verifies AddView fails when view is already in position.
685 TEST_F(ViewManagerServiceAppTest, AddAncestorFails) {
686 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 2)));
687 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 3)));
688
689 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
690
691 // Make 3 a child of 2.
692 ASSERT_TRUE(AddView(vm1(), BuildViewId(1, 2), BuildViewId(1, 3)));
693
694 // Try to make 2 a child of 3, this should fail since 2 is an ancestor of 3.
695 EXPECT_FALSE(AddView(vm1(), BuildViewId(1, 3), BuildViewId(1, 2)));
696 }
697
698 // Verifies adding to root sends right notifications.
699 TEST_F(ViewManagerServiceAppTest, AddToRoot) {
700 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 21)));
701 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 3)));
702
703 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
704 changes2()->clear();
705
706 // Make 3 a child of 21.
707 ASSERT_TRUE(AddView(vm1(), BuildViewId(1, 21), BuildViewId(1, 3)));
708
709 // Make 21 a child of 1.
710 ASSERT_TRUE(AddView(vm1(), BuildViewId(1, 1), BuildViewId(1, 21)));
711
712 // Connection 2 should not be told anything (because the view is from a
713 // different connection). Create a view to ensure we got a response from
714 // the server.
715 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 100)));
716 EXPECT_TRUE(changes2()->empty());
717 }
718
719 // Verifies HierarchyChanged is correctly sent for various adds/removes.
720 TEST_F(ViewManagerServiceAppTest, ViewHierarchyChangedViews) {
721 // 1,2->1,11.
722 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 2)));
723 ASSERT_TRUE(SetViewVisibility(vm1(), BuildViewId(1, 2), true));
724 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 11)));
725 ASSERT_TRUE(SetViewVisibility(vm1(), BuildViewId(1, 11), true));
726 ASSERT_TRUE(AddView(vm1(), BuildViewId(1, 2), BuildViewId(1, 11)));
727
728 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
729 ASSERT_TRUE(SetViewVisibility(vm1(), BuildViewId(1, 1), true));
730
731 ASSERT_TRUE(WaitForAllMessages(vm2()));
732 changes2()->clear();
733
734 // 1,1->1,2->1,11
735 {
736 // Client 2 should not get anything (1,2 is from another connection).
737 ASSERT_TRUE(AddView(vm1(), BuildViewId(1, 1), BuildViewId(1, 2)));
738 ASSERT_TRUE(WaitForAllMessages(vm2()));
739 EXPECT_TRUE(changes2()->empty());
740 }
741
742 // 0,1->1,1->1,2->1,11.
743 {
744 // Client 2 is now connected to the root, so it should have gotten a drawn
745 // notification.
746 ASSERT_TRUE(AddView(vm1(), BuildViewId(0, 1), BuildViewId(1, 1)));
747 vm_client2_->WaitForChangeCount(1u);
748 EXPECT_EQ("DrawnStateChanged view=1,1 drawn=true",
749 SingleChangeToDescription(*changes2()));
750 }
751
752 // 1,1->1,2->1,11.
753 {
754 // Client 2 is no longer connected to the root, should get drawn state
755 // changed.
756 changes2()->clear();
757 ASSERT_TRUE(RemoveViewFromParent(vm1(), BuildViewId(1, 1)));
758 vm_client2_->WaitForChangeCount(1);
759 EXPECT_EQ("DrawnStateChanged view=1,1 drawn=false",
760 SingleChangeToDescription(*changes2()));
761 }
762
763 // 1,1->1,2->1,11->1,111.
764 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 111)));
765 ASSERT_TRUE(SetViewVisibility(vm1(), BuildViewId(1, 111), true));
766 {
767 changes2()->clear();
768 ASSERT_TRUE(AddView(vm1(), BuildViewId(1, 11), BuildViewId(1, 111)));
769 ASSERT_TRUE(WaitForAllMessages(vm2()));
770 EXPECT_TRUE(changes2()->empty());
771 }
772
773 // 0,1->1,1->1,2->1,11->1,111
774 {
775 changes2()->clear();
776 ASSERT_TRUE(AddView(vm1(), BuildViewId(0, 1), BuildViewId(1, 1)));
777 vm_client2_->WaitForChangeCount(1);
778 EXPECT_EQ("DrawnStateChanged view=1,1 drawn=true",
779 SingleChangeToDescription(*changes2()));
780 }
781 }
782
783 TEST_F(ViewManagerServiceAppTest, ViewHierarchyChangedAddingKnownToUnknown) {
784 // Create the following structure: root -> 1 -> 11 and 2->21 (2 has no
785 // parent).
786 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
787
788 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 11)));
789 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 2)));
790 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 21)));
791
792 // Set up the hierarchy.
793 ASSERT_TRUE(AddView(vm1(), BuildViewId(0, 1), BuildViewId(1, 1)));
794 ASSERT_TRUE(AddView(vm2(), BuildViewId(1, 1), BuildViewId(2, 11)));
795 ASSERT_TRUE(AddView(vm2(), BuildViewId(2, 2), BuildViewId(2, 21)));
796
797 // Remove 11, should result in a hierarchy change for the root.
798 {
799 changes1()->clear();
800 ASSERT_TRUE(RemoveViewFromParent(vm2(), BuildViewId(2, 11)));
801
802 vm_client1_.WaitForChangeCount(1);
803 EXPECT_EQ("HierarchyChanged view=2,11 new_parent=null old_parent=1,1",
804 SingleChangeToDescription(*changes1()));
805 }
806
807 // Add 2 to 1.
808 {
809 changes1()->clear();
810 ASSERT_TRUE(AddView(vm2(), BuildViewId(1, 1), BuildViewId(2, 2)));
811
812 vm_client1_.WaitForChangeCount(1);
813 EXPECT_EQ("HierarchyChanged view=2,2 new_parent=1,1 old_parent=null",
814 SingleChangeToDescription(*changes1()));
815 EXPECT_EQ(
816 "[view=2,2 parent=1,1],"
817 "[view=2,21 parent=2,2]",
818 ChangeViewDescription(*changes1()));
819 }
820 }
821
822 TEST_F(ViewManagerServiceAppTest, ReorderView) {
823 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
824
825 Id view1_id = BuildViewId(2, 1);
826 Id view2_id = BuildViewId(2, 2);
827 Id view3_id = BuildViewId(2, 3);
828 Id view4_id = BuildViewId(1, 4); // Peer to 1,1
829 Id view5_id = BuildViewId(1, 5); // Peer to 1,1
830 Id view6_id = BuildViewId(2, 6); // Child of 1,2.
831 Id view7_id = BuildViewId(2, 7); // Unparented.
832 Id view8_id = BuildViewId(2, 8); // Unparented.
833 ASSERT_TRUE(CreateView(vm2(), view1_id));
834 ASSERT_TRUE(CreateView(vm2(), view2_id));
835 ASSERT_TRUE(CreateView(vm2(), view3_id));
836 ASSERT_TRUE(CreateView(vm1(), view4_id));
837 ASSERT_TRUE(CreateView(vm1(), view5_id));
838 ASSERT_TRUE(CreateView(vm2(), view6_id));
839 ASSERT_TRUE(CreateView(vm2(), view7_id));
840 ASSERT_TRUE(CreateView(vm2(), view8_id));
841 ASSERT_TRUE(AddView(vm2(), view1_id, view2_id));
842 ASSERT_TRUE(AddView(vm2(), view2_id, view6_id));
843 ASSERT_TRUE(AddView(vm2(), view1_id, view3_id));
844 ASSERT_TRUE(AddView(vm1(), ViewIdToTransportId(RootViewId()), view4_id));
845 ASSERT_TRUE(AddView(vm1(), ViewIdToTransportId(RootViewId()), view5_id));
846 ASSERT_TRUE(AddView(vm1(), ViewIdToTransportId(RootViewId()), view1_id));
847
848 {
849 changes1()->clear();
850 ASSERT_TRUE(ReorderView(vm2(), view2_id, view3_id, OrderDirection::ABOVE));
851
852 vm_client1_.WaitForChangeCount(1);
853 EXPECT_EQ("Reordered view=2,2 relative=2,3 direction=above",
854 SingleChangeToDescription(*changes1()));
855 }
856
857 {
858 changes1()->clear();
859 ASSERT_TRUE(ReorderView(vm2(), view2_id, view3_id, OrderDirection::BELOW));
860
861 vm_client1_.WaitForChangeCount(1);
862 EXPECT_EQ("Reordered view=2,2 relative=2,3 direction=below",
863 SingleChangeToDescription(*changes1()));
864 }
865
866 // view2 is already below view3.
867 EXPECT_FALSE(ReorderView(vm2(), view2_id, view3_id, OrderDirection::BELOW));
868
869 // view4 & 5 are unknown to connection2_.
870 EXPECT_FALSE(ReorderView(vm2(), view4_id, view5_id, OrderDirection::ABOVE));
871
872 // view6 & view3 have different parents.
873 EXPECT_FALSE(ReorderView(vm1(), view3_id, view6_id, OrderDirection::ABOVE));
874
875 // Non-existent view-ids
876 EXPECT_FALSE(ReorderView(vm1(), BuildViewId(1, 27), BuildViewId(1, 28),
877 OrderDirection::ABOVE));
878
879 // view7 & view8 are un-parented.
880 EXPECT_FALSE(ReorderView(vm1(), view7_id, view8_id, OrderDirection::ABOVE));
881 }
882
883 // Verifies DeleteView works.
884 TEST_F(ViewManagerServiceAppTest, DeleteView) {
885 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
886 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 2)));
887
888 // Make 2 a child of 1.
889 {
890 changes1()->clear();
891 ASSERT_TRUE(AddView(vm2(), BuildViewId(1, 1), BuildViewId(2, 2)));
892 vm_client1_.WaitForChangeCount(1);
893 EXPECT_EQ("HierarchyChanged view=2,2 new_parent=1,1 old_parent=null",
894 SingleChangeToDescription(*changes1()));
895 }
896
897 // Delete 2.
898 {
899 changes1()->clear();
900 changes2()->clear();
901 ASSERT_TRUE(DeleteView(vm2(), BuildViewId(2, 2)));
902 EXPECT_TRUE(changes2()->empty());
903
904 vm_client1_.WaitForChangeCount(1);
905 EXPECT_EQ("ViewDeleted view=2,2", SingleChangeToDescription(*changes1()));
906 }
907 }
908
909 // Verifies DeleteView isn't allowed from a separate connection.
910 TEST_F(ViewManagerServiceAppTest, DeleteViewFromAnotherConnectionDisallowed) {
911 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
912 EXPECT_FALSE(DeleteView(vm2(), BuildViewId(1, 1)));
913 }
914
915 // Verifies if a view was deleted and then reused that other clients are
916 // properly notified.
917 TEST_F(ViewManagerServiceAppTest, ReuseDeletedViewId) {
918 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
919 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 2)));
920
921 // Add 2 to 1.
922 {
923 changes1()->clear();
924 ASSERT_TRUE(AddView(vm2(), BuildViewId(1, 1), BuildViewId(2, 2)));
925
926 vm_client1_.WaitForChangeCount(1);
927 EXPECT_EQ("HierarchyChanged view=2,2 new_parent=1,1 old_parent=null",
928 SingleChangeToDescription(*changes1()));
929 EXPECT_EQ("[view=2,2 parent=1,1]", ChangeViewDescription(*changes1()));
930 }
931
932 // Delete 2.
933 {
934 changes1()->clear();
935 ASSERT_TRUE(DeleteView(vm2(), BuildViewId(2, 2)));
936
937 vm_client1_.WaitForChangeCount(1);
938 EXPECT_EQ("ViewDeleted view=2,2", SingleChangeToDescription(*changes1()));
939 }
940
941 // Create 2 again, and add it back to 1. Should get the same notification.
942 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 2)));
943 {
944 changes1()->clear();
945 ASSERT_TRUE(AddView(vm2(), BuildViewId(1, 1), BuildViewId(2, 2)));
946
947 vm_client1_.WaitForChangeCount(1);
948 EXPECT_EQ("HierarchyChanged view=2,2 new_parent=1,1 old_parent=null",
949 SingleChangeToDescription(*changes1()));
950 EXPECT_EQ("[view=2,2 parent=1,1]", ChangeViewDescription(*changes1()));
951 }
952 }
953
954 // Assertions for GetViewTree.
955 TEST_F(ViewManagerServiceAppTest, GetViewTree) {
956 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
957
958 // Create 11 in first connection and make it a child of 1.
959 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 11)));
960 ASSERT_TRUE(AddView(vm1(), BuildViewId(0, 1), BuildViewId(1, 1)));
961 ASSERT_TRUE(AddView(vm1(), BuildViewId(1, 1), BuildViewId(1, 11)));
962
963 // Create two views in second connection, 2 and 3, both children of 1.
964 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 2)));
965 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 3)));
966 ASSERT_TRUE(AddView(vm2(), BuildViewId(1, 1), BuildViewId(2, 2)));
967 ASSERT_TRUE(AddView(vm2(), BuildViewId(1, 1), BuildViewId(2, 3)));
968
969 // Verifies GetViewTree() on the root. The root connection sees all.
970 {
971 std::vector<TestView> views;
972 GetViewTree(vm1(), BuildViewId(0, 1), &views);
973 ASSERT_EQ(5u, views.size());
974 EXPECT_EQ("view=0,1 parent=null", views[0].ToString());
975 EXPECT_EQ("view=1,1 parent=0,1", views[1].ToString());
976 EXPECT_EQ("view=1,11 parent=1,1", views[2].ToString());
977 EXPECT_EQ("view=2,2 parent=1,1", views[3].ToString());
978 EXPECT_EQ("view=2,3 parent=1,1", views[4].ToString());
979 }
980
981 // Verifies GetViewTree() on the view 1,1 from vm2(). vm2() sees 1,1 as 1,1
982 // is vm2()'s root and vm2() sees all the views it created.
983 {
984 std::vector<TestView> views;
985 GetViewTree(vm2(), BuildViewId(1, 1), &views);
986 ASSERT_EQ(3u, views.size());
987 EXPECT_EQ("view=1,1 parent=null", views[0].ToString());
988 EXPECT_EQ("view=2,2 parent=1,1", views[1].ToString());
989 EXPECT_EQ("view=2,3 parent=1,1", views[2].ToString());
990 }
991
992 // Connection 2 shouldn't be able to get the root tree.
993 {
994 std::vector<TestView> views;
995 GetViewTree(vm2(), BuildViewId(0, 1), &views);
996 ASSERT_EQ(0u, views.size());
997 }
998 }
999
1000 TEST_F(ViewManagerServiceAppTest, SetViewBounds) {
1001 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 1)));
1002 ASSERT_TRUE(AddView(vm1(), BuildViewId(0, 1), BuildViewId(1, 1)));
1003
1004 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false));
1005
1006 changes2()->clear();
1007 ASSERT_TRUE(SetViewBounds(vm1(), BuildViewId(1, 1), 0, 0, 100, 100));
1008
1009 vm_client2_->WaitForChangeCount(1);
1010 EXPECT_EQ("BoundsChanged view=1,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100",
1011 SingleChangeToDescription(*changes2()));
1012
1013 // Should not be possible to change the bounds of a view created by another
1014 // connection.
1015 ASSERT_FALSE(SetViewBounds(vm2(), BuildViewId(1, 1), 0, 0, 0, 0));
1016 }
1017
1018 // Verify AddView fails when trying to manipulate views in other roots.
1019 TEST_F(ViewManagerServiceAppTest, CantMoveViewsFromOtherRoot) {
1020 // Create 1 and 2 in the first connection.
1021 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 1)));
1022 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 2)));
1023
1024 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false));
1025
1026 // Try to move 2 to be a child of 1 from connection 2. This should fail as 2
1027 // should not be able to access 1.
1028 ASSERT_FALSE(AddView(vm2(), BuildViewId(1, 1), BuildViewId(1, 2)));
1029
1030 // Try to reparent 1 to the root. A connection is not allowed to reparent its
1031 // roots.
1032 ASSERT_FALSE(AddView(vm2(), BuildViewId(0, 1), BuildViewId(1, 1)));
1033 }
1034
1035 // Verify RemoveViewFromParent fails for views that are descendants of the
1036 // roots.
1037 TEST_F(ViewManagerServiceAppTest, CantRemoveViewsInOtherRoots) {
1038 // Create 1 and 2 in the first connection and parent both to the root.
1039 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 1)));
1040 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 2)));
1041
1042 ASSERT_TRUE(AddView(vm1(), BuildViewId(0, 1), BuildViewId(1, 1)));
1043 ASSERT_TRUE(AddView(vm1(), BuildViewId(0, 1), BuildViewId(1, 2)));
1044
1045 // Establish the second connection and give it the root 1.
1046 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false));
1047
1048 // Connection 2 should not be able to remove view 2 or 1 from its parent.
1049 ASSERT_FALSE(RemoveViewFromParent(vm2(), BuildViewId(1, 2)));
1050 ASSERT_FALSE(RemoveViewFromParent(vm2(), BuildViewId(1, 1)));
1051
1052 // Create views 10 and 11 in 2.
1053 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 10)));
1054 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 11)));
1055
1056 // Parent 11 to 10.
1057 ASSERT_TRUE(AddView(vm2(), BuildViewId(2, 10), BuildViewId(2, 11)));
1058 // Remove 11 from 10.
1059 ASSERT_TRUE(RemoveViewFromParent(vm2(), BuildViewId(2, 11)));
1060
1061 // Verify nothing was actually removed.
1062 {
1063 std::vector<TestView> views;
1064 GetViewTree(vm1(), BuildViewId(0, 1), &views);
1065 ASSERT_EQ(3u, views.size());
1066 EXPECT_EQ("view=0,1 parent=null", views[0].ToString());
1067 EXPECT_EQ("view=1,1 parent=0,1", views[1].ToString());
1068 EXPECT_EQ("view=1,2 parent=0,1", views[2].ToString());
1069 }
1070 }
1071
1072 // Verify GetViewTree fails for views that are not descendants of the roots.
1073 TEST_F(ViewManagerServiceAppTest, CantGetViewTreeOfOtherRoots) {
1074 // Create 1 and 2 in the first connection and parent both to the root.
1075 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 1)));
1076 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 2)));
1077
1078 ASSERT_TRUE(AddView(vm1(), BuildViewId(0, 1), BuildViewId(1, 1)));
1079 ASSERT_TRUE(AddView(vm1(), BuildViewId(0, 1), BuildViewId(1, 2)));
1080
1081 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false));
1082
1083 std::vector<TestView> views;
1084
1085 // Should get nothing for the root.
1086 GetViewTree(vm2(), BuildViewId(0, 1), &views);
1087 ASSERT_TRUE(views.empty());
1088
1089 // Should get nothing for view 2.
1090 GetViewTree(vm2(), BuildViewId(1, 2), &views);
1091 ASSERT_TRUE(views.empty());
1092
1093 // Should get view 1 if asked for.
1094 GetViewTree(vm2(), BuildViewId(1, 1), &views);
1095 ASSERT_EQ(1u, views.size());
1096 EXPECT_EQ("view=1,1 parent=null", views[0].ToString());
1097 }
1098
1099 TEST_F(ViewManagerServiceAppTest, OnViewInputEvent) {
1100 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
1101 changes2()->clear();
1102
1103 // Dispatch an event to the view and verify it's received.
1104 {
1105 EventPtr event(mojo::Event::New());
1106 event->action = static_cast<mojo::EventType>(1);
1107 wm_internal_client_->DispatchInputEventToView(BuildViewId(1, 1),
1108 event.Pass());
1109 vm_client2_->WaitForChangeCount(1);
1110 EXPECT_EQ("InputEvent view=1,1 event_action=1",
1111 SingleChangeToDescription(*changes2()));
1112 }
1113 }
1114
1115 TEST_F(ViewManagerServiceAppTest, EmbedWithSameViewId) {
1116 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
1117 changes2()->clear();
1118
1119 ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(vm1(), BuildViewId(1, 1)));
1120
1121 // Connection2 should have been told the view was deleted.
1122 {
1123 vm_client2_->WaitForChangeCount(1);
1124 EXPECT_EQ("ViewDeleted view=1,1", SingleChangeToDescription(*changes2()));
1125 }
1126
1127 // Connection2 has no root. Verify it can't see view 1,1 anymore.
1128 {
1129 std::vector<TestView> views;
1130 GetViewTree(vm2(), BuildViewId(1, 1), &views);
1131 EXPECT_TRUE(views.empty());
1132 }
1133 }
1134
1135 TEST_F(ViewManagerServiceAppTest, EmbedWithSameViewId2) {
1136 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
1137 changes2()->clear();
1138
1139 ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(vm1(), BuildViewId(1, 1)));
1140
1141 // Connection2 should have been told the view was deleted.
1142 vm_client2_->WaitForChangeCount(1);
1143 changes2()->clear();
1144
1145 // Create a view in the third connection and parent it to the root.
1146 ASSERT_TRUE(CreateView(vm3(), BuildViewId(3, 1)));
1147 ASSERT_TRUE(AddView(vm3(), BuildViewId(1, 1), BuildViewId(3, 1)));
1148
1149 // Connection 1 should have been told about the add (it owns the view).
1150 {
1151 vm_client1_.WaitForChangeCount(1);
1152 EXPECT_EQ("HierarchyChanged view=3,1 new_parent=1,1 old_parent=null",
1153 SingleChangeToDescription(*changes1()));
1154 }
1155
1156 // Embed 1,1 again.
1157 {
1158 changes3()->clear();
1159
1160 // We should get a new connection for the new embedding.
1161 scoped_ptr<ViewManagerClientImpl> connection4(
1162 EstablishConnectionViaEmbed(vm1(), BuildViewId(1, 1)));
1163 ASSERT_TRUE(connection4.get());
1164 EXPECT_EQ("[view=1,1 parent=null]",
1165 ChangeViewDescription(*connection4->tracker()->changes()));
1166
1167 // And 3 should get a delete.
1168 vm_client3_->WaitForChangeCount(1);
1169 EXPECT_EQ("ViewDeleted view=1,1", SingleChangeToDescription(*changes3()));
1170 }
1171
1172 // vm3() has no root. Verify it can't see view 1,1 anymore.
1173 {
1174 std::vector<TestView> views;
1175 GetViewTree(vm3(), BuildViewId(1, 1), &views);
1176 EXPECT_TRUE(views.empty());
1177 }
1178
1179 // Verify 3,1 is no longer parented to 1,1. We have to do this from 1,1 as
1180 // vm3() can no longer see 1,1.
1181 {
1182 std::vector<TestView> views;
1183 GetViewTree(vm1(), BuildViewId(1, 1), &views);
1184 ASSERT_EQ(1u, views.size());
1185 EXPECT_EQ("view=1,1 parent=null", views[0].ToString());
1186 }
1187
1188 // Verify vm3() can still see the view it created 3,1.
1189 {
1190 std::vector<TestView> views;
1191 GetViewTree(vm3(), BuildViewId(3, 1), &views);
1192 ASSERT_EQ(1u, views.size());
1193 EXPECT_EQ("view=3,1 parent=null", views[0].ToString());
1194 }
1195 }
1196
1197 // Assertions for SetViewVisibility.
1198 TEST_F(ViewManagerServiceAppTest, SetViewVisibility) {
1199 // Create 1 and 2 in the first connection and parent both to the root.
1200 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 1)));
1201 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 2)));
1202
1203 ASSERT_TRUE(AddView(vm1(), BuildViewId(0, 1), BuildViewId(1, 1)));
1204 {
1205 std::vector<TestView> views;
1206 GetViewTree(vm1(), BuildViewId(0, 1), &views);
1207 ASSERT_EQ(2u, views.size());
1208 EXPECT_EQ("view=0,1 parent=null visible=true drawn=true",
1209 views[0].ToString2());
1210 EXPECT_EQ("view=1,1 parent=0,1 visible=false drawn=false",
1211 views[1].ToString2());
1212 }
1213
1214 // Show all the views.
1215 ASSERT_TRUE(SetViewVisibility(vm1(), BuildViewId(1, 1), true));
1216 ASSERT_TRUE(SetViewVisibility(vm1(), BuildViewId(1, 2), true));
1217 {
1218 std::vector<TestView> views;
1219 GetViewTree(vm1(), BuildViewId(0, 1), &views);
1220 ASSERT_EQ(2u, views.size());
1221 EXPECT_EQ("view=0,1 parent=null visible=true drawn=true",
1222 views[0].ToString2());
1223 EXPECT_EQ("view=1,1 parent=0,1 visible=true drawn=true",
1224 views[1].ToString2());
1225 }
1226
1227 // Hide 1.
1228 ASSERT_TRUE(SetViewVisibility(vm1(), BuildViewId(1, 1), false));
1229 {
1230 std::vector<TestView> views;
1231 GetViewTree(vm1(), BuildViewId(1, 1), &views);
1232 ASSERT_EQ(1u, views.size());
1233 EXPECT_EQ("view=1,1 parent=0,1 visible=false drawn=false",
1234 views[0].ToString2());
1235 }
1236
1237 // Attach 2 to 1.
1238 ASSERT_TRUE(AddView(vm1(), BuildViewId(1, 1), BuildViewId(1, 2)));
1239 {
1240 std::vector<TestView> views;
1241 GetViewTree(vm1(), BuildViewId(1, 1), &views);
1242 ASSERT_EQ(2u, views.size());
1243 EXPECT_EQ("view=1,1 parent=0,1 visible=false drawn=false",
1244 views[0].ToString2());
1245 EXPECT_EQ("view=1,2 parent=1,1 visible=true drawn=false",
1246 views[1].ToString2());
1247 }
1248
1249 // Show 1.
1250 ASSERT_TRUE(SetViewVisibility(vm1(), BuildViewId(1, 1), true));
1251 {
1252 std::vector<TestView> views;
1253 GetViewTree(vm1(), BuildViewId(1, 1), &views);
1254 ASSERT_EQ(2u, views.size());
1255 EXPECT_EQ("view=1,1 parent=0,1 visible=true drawn=true",
1256 views[0].ToString2());
1257 EXPECT_EQ("view=1,2 parent=1,1 visible=true drawn=true",
1258 views[1].ToString2());
1259 }
1260 }
1261
1262 // Assertions for SetViewVisibility sending notifications.
1263 TEST_F(ViewManagerServiceAppTest, SetViewVisibilityNotifications) {
1264 // Create 1,1 and 1,2. 1,2 is made a child of 1,1 and 1,1 a child of the root.
1265 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 1)));
1266 ASSERT_TRUE(SetViewVisibility(vm1(), BuildViewId(1, 1), true));
1267 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 2)));
1268 ASSERT_TRUE(SetViewVisibility(vm1(), BuildViewId(1, 2), true));
1269 ASSERT_TRUE(AddView(vm1(), BuildViewId(0, 1), BuildViewId(1, 1)));
1270 ASSERT_TRUE(AddView(vm1(), BuildViewId(1, 1), BuildViewId(1, 2)));
1271
1272 // Establish the second connection at 1,2.
1273 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnectionWithRoot(BuildViewId(1, 2)));
1274
1275 // Add 2,3 as a child of 1,2.
1276 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 3)));
1277 ASSERT_TRUE(SetViewVisibility(vm2(), BuildViewId(2, 3), true));
1278 ASSERT_TRUE(AddView(vm2(), BuildViewId(1, 2), BuildViewId(2, 3)));
1279 WaitForAllMessages(vm1());
1280
1281 changes2()->clear();
1282 // Hide 1,2 from connection 1. Connection 2 should see this.
1283 ASSERT_TRUE(SetViewVisibility(vm1(), BuildViewId(1, 2), false));
1284 {
1285 vm_client2_->WaitForChangeCount(1);
1286 EXPECT_EQ("VisibilityChanged view=1,2 visible=false",
1287 SingleChangeToDescription(*changes2()));
1288 }
1289
1290 changes1()->clear();
1291 // Show 1,2 from connection 2, connection 1 should be notified.
1292 ASSERT_TRUE(SetViewVisibility(vm2(), BuildViewId(1, 2), true));
1293 {
1294 vm_client1_.WaitForChangeCount(1);
1295 EXPECT_EQ("VisibilityChanged view=1,2 visible=true",
1296 SingleChangeToDescription(*changes1()));
1297 }
1298
1299 changes2()->clear();
1300 // Hide 1,1, connection 2 should be told the draw state changed.
1301 ASSERT_TRUE(SetViewVisibility(vm1(), BuildViewId(1, 1), false));
1302 {
1303 vm_client2_->WaitForChangeCount(1);
1304 EXPECT_EQ("DrawnStateChanged view=1,2 drawn=false",
1305 SingleChangeToDescription(*changes2()));
1306 }
1307
1308 changes2()->clear();
1309 // Show 1,1 from connection 1. Connection 2 should see this.
1310 ASSERT_TRUE(SetViewVisibility(vm1(), BuildViewId(1, 1), true));
1311 {
1312 vm_client2_->WaitForChangeCount(1);
1313 EXPECT_EQ("DrawnStateChanged view=1,2 drawn=true",
1314 SingleChangeToDescription(*changes2()));
1315 }
1316
1317 // Change visibility of 2,3, connection 1 should see this.
1318 changes1()->clear();
1319 ASSERT_TRUE(SetViewVisibility(vm2(), BuildViewId(2, 3), false));
1320 {
1321 vm_client1_.WaitForChangeCount(1);
1322 EXPECT_EQ("VisibilityChanged view=2,3 visible=false",
1323 SingleChangeToDescription(*changes1()));
1324 }
1325
1326 changes2()->clear();
1327 // Remove 1,1 from the root, connection 2 should see drawn state changed.
1328 ASSERT_TRUE(RemoveViewFromParent(vm1(), BuildViewId(1, 1)));
1329 {
1330 vm_client2_->WaitForChangeCount(1);
1331 EXPECT_EQ("DrawnStateChanged view=1,2 drawn=false",
1332 SingleChangeToDescription(*changes2()));
1333 }
1334
1335 changes2()->clear();
1336 // Add 1,1 back to the root, connection 2 should see drawn state changed.
1337 ASSERT_TRUE(AddView(vm1(), BuildViewId(0, 1), BuildViewId(1, 1)));
1338 {
1339 vm_client2_->WaitForChangeCount(1);
1340 EXPECT_EQ("DrawnStateChanged view=1,2 drawn=true",
1341 SingleChangeToDescription(*changes2()));
1342 }
1343 }
1344
1345 TEST_F(ViewManagerServiceAppTest, SetViewProperty) {
1346 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 1)));
1347
1348 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false));
1349 changes2()->clear();
1350
1351 ASSERT_TRUE(AddView(vm1(), BuildViewId(0, 1), BuildViewId(1, 1)));
1352 {
1353 std::vector<TestView> views;
1354 GetViewTree(vm1(), BuildViewId(0, 1), &views);
1355 ASSERT_EQ(2u, views.size());
1356 EXPECT_EQ(BuildViewId(0, 1), views[0].view_id);
1357 EXPECT_EQ(BuildViewId(1, 1), views[1].view_id);
1358 ASSERT_EQ(0u, views[1].properties.size());
1359 }
1360
1361 // Set properties on 1.
1362 changes2()->clear();
1363 std::vector<uint8_t> one(1, '1');
1364 ASSERT_TRUE(SetViewProperty(vm1(), BuildViewId(1, 1), "one", &one));
1365 {
1366 vm_client2_->WaitForChangeCount(1);
1367 EXPECT_EQ("PropertyChanged view=1,1 key=one value=1",
1368 SingleChangeToDescription(*changes2()));
1369 }
1370
1371 // Test that our properties exist in the view tree
1372 {
1373 std::vector<TestView> views;
1374 GetViewTree(vm1(), BuildViewId(1, 1), &views);
1375 ASSERT_EQ(1u, views.size());
1376 ASSERT_EQ(1u, views[0].properties.size());
1377 EXPECT_EQ(one, views[0].properties["one"]);
1378 }
1379
1380 changes2()->clear();
1381 // Set back to null.
1382 ASSERT_TRUE(SetViewProperty(vm1(), BuildViewId(1, 1), "one", NULL));
1383 {
1384 vm_client2_->WaitForChangeCount(1);
1385 EXPECT_EQ("PropertyChanged view=1,1 key=one value=NULL",
1386 SingleChangeToDescription(*changes2()));
1387 }
1388 }
1389
1390 TEST_F(ViewManagerServiceAppTest, OnEmbeddedAppDisconnected) {
1391 // Create connection 2 and 3.
1392 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
1393 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 2)));
1394 ASSERT_TRUE(AddView(vm2(), BuildViewId(1, 1), BuildViewId(2, 2)));
1395 changes2()->clear();
1396 ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(vm2(), BuildViewId(2, 2)));
1397
1398 // Close connection 3. Connection 2 (which had previously embedded 3) should
1399 // be notified of this.
1400 vm_client3_.reset();
1401 vm_client2_->WaitForChangeCount(1);
1402 EXPECT_EQ("OnEmbeddedAppDisconnected view=2,2",
1403 SingleChangeToDescription(*changes2()));
1404 }
1405
1406 // Verifies when the parent of an Embed() is destroyed the embedded app gets
1407 // a ViewDeleted (and doesn't trigger a DCHECK).
1408 TEST_F(ViewManagerServiceAppTest, OnParentOfEmbedDisconnects) {
1409 // Create connection 2 and 3.
1410 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
1411 ASSERT_TRUE(AddView(vm1(), BuildViewId(0, 1), BuildViewId(1, 1)));
1412 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 2)));
1413 ASSERT_TRUE(AddView(vm2(), BuildViewId(1, 1), BuildViewId(2, 2)));
1414 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 3)));
1415 ASSERT_TRUE(AddView(vm2(), BuildViewId(2, 2), BuildViewId(2, 3)));
1416 changes2()->clear();
1417 ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(vm2(), BuildViewId(2, 3)));
1418 changes3()->clear();
1419
1420 // Close connection 2. Connection 3 should get a delete (for its root).
1421 vm_client2_.reset();
1422 vm_client3_->WaitForChangeCount(1);
1423 EXPECT_EQ("ViewDeleted view=2,3", SingleChangeToDescription(*changes3()));
1424 }
1425
1426 // Verifies ViewManagerServiceImpl doesn't incorrectly erase from its internal
1427 // map when a view from another connection with the same view_id is removed.
1428 TEST_F(ViewManagerServiceAppTest, DontCleanMapOnDestroy) {
1429 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
1430 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 1)));
1431 changes1()->clear();
1432 vm_client2_.reset();
1433 vm_client1_.WaitForChangeCount(1);
1434 EXPECT_EQ("OnEmbeddedAppDisconnected view=1,1",
1435 SingleChangeToDescription(*changes1()));
1436 std::vector<TestView> views;
1437 GetViewTree(vm1(), BuildViewId(1, 1), &views);
1438 EXPECT_FALSE(views.empty());
1439 }
1440
1441 TEST_F(ViewManagerServiceAppTest, CloneAndAnimate) {
1442 // Create connection 2 and 3.
1443 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true));
1444 ASSERT_TRUE(AddView(vm1(), BuildViewId(0, 1), BuildViewId(1, 1)));
1445 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 2)));
1446 ASSERT_TRUE(CreateView(vm2(), BuildViewId(2, 3)));
1447 ASSERT_TRUE(AddView(vm2(), BuildViewId(1, 1), BuildViewId(2, 2)));
1448 ASSERT_TRUE(AddView(vm2(), BuildViewId(2, 2), BuildViewId(2, 3)));
1449 changes2()->clear();
1450
1451 ASSERT_TRUE(WaitForAllMessages(vm1()));
1452 changes1()->clear();
1453
1454 wm_internal_client_->CloneAndAnimate(BuildViewId(2, 3));
1455 ASSERT_TRUE(WaitForAllMessages(vm1()));
1456
1457 ASSERT_TRUE(WaitForAllMessages(vm1()));
1458 ASSERT_TRUE(WaitForAllMessages(vm2()));
1459
1460 // No messages should have been received.
1461 EXPECT_TRUE(changes1()->empty());
1462 EXPECT_TRUE(changes2()->empty());
1463
1464 // No one should be able to see the cloned tree.
1465 std::vector<TestView> views;
1466 GetViewTree(vm1(), BuildViewId(1, 1), &views);
1467 EXPECT_FALSE(HasClonedView(views));
1468 views.clear();
1469
1470 GetViewTree(vm2(), BuildViewId(1, 1), &views);
1471 EXPECT_FALSE(HasClonedView(views));
1472 }
1473
1474 // Verifies Embed() works when supplying a ViewManagerClient.
1475 TEST_F(ViewManagerServiceAppTest, EmbedSupplyingViewManagerClient) {
1476 ASSERT_TRUE(CreateView(vm1(), BuildViewId(1, 1)));
1477
1478 ViewManagerClientImpl client2;
1479 mojo::ViewManagerClientPtr client2_ptr;
1480 mojo::Binding<ViewManagerClient> client2_binding(&client2, &client2_ptr);
1481 ASSERT_TRUE(Embed(vm1(), BuildViewId(1, 1), client2_ptr.Pass()));
1482 client2.WaitForOnEmbed();
1483 EXPECT_EQ("OnEmbed creator=mojo:window_manager",
1484 SingleChangeToDescription(*client2.tracker()->changes()));
1485 }
1486
1487 // TODO(sky): need to better track changes to initial connection. For example,
1488 // that SetBounsdViews/AddView and the like don't result in messages to the
1489 // originating connection.
1490
1491 // TODO(sky): make sure coverage of what was
1492 // ViewManagerTest.SecondEmbedRoot_InitService and
1493 // ViewManagerTest.MultipleEmbedRootsBeforeWTHReady gets added to window manager
1494 // tests.
1495
1496 } // namespace view_manager
OLDNEW
« no previous file with comments | « services/view_manager/view_manager_root_connection.cc ('k') | services/view_manager/view_manager_service_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698