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

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

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

Powered by Google App Engine
This is Rietveld 408576698