blob: e1f19b11de7e9fab2c15ef98e8d9ae75af70e4e6 [file] [log] [blame]
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +01001// 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 "mojo/services/public/cpp/view_manager/view_manager.h"
6
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +01007#include "base/auto_reset.h"
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +01008#include "base/bind.h"
9#include "base/logging.h"
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010010#include "mojo/public/cpp/application/application.h"
11#include "mojo/service_manager/service_manager.h"
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010012#include "mojo/services/public/cpp/view_manager/lib/node_private.h"
13#include "mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.h"
14#include "mojo/services/public/cpp/view_manager/node_observer.h"
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +010015#include "mojo/services/public/cpp/view_manager/util.h"
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010016#include "mojo/services/public/cpp/view_manager/view.h"
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010017#include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010018#include "mojo/services/public/cpp/view_manager/view_observer.h"
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +010019#include "mojo/shell/shell_test_helper.h"
20#include "testing/gtest/include/gtest/gtest.h"
21
22namespace mojo {
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +010023namespace view_manager {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010024namespace {
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +010025
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010026const char kWindowManagerURL[] = "mojo:window_manager";
27const char kEmbeddedApp1URL[] = "mojo:embedded_app_1";
28
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +010029base::RunLoop* current_run_loop = NULL;
30
31void DoRunLoop() {
32 base::RunLoop run_loop;
33 current_run_loop = &run_loop;
34 current_run_loop->Run();
35 current_run_loop = NULL;
36}
37
38void QuitRunLoop() {
39 current_run_loop->Quit();
40}
41
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010042void WaitForAllChangesToBeAcked(ViewManagerClientImpl* client) {
43 client->set_changes_acked_callback(base::Bind(&QuitRunLoop));
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010044 DoRunLoop();
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010045 client->ClearChangesAckedCallback();
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010046}
47
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010048class ConnectServiceLoader : public ServiceLoader,
49 public ViewManagerDelegate {
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010050 public:
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010051 typedef base::Callback<void(ViewManager*, Node*)> LoadedCallback;
52
53 explicit ConnectServiceLoader(const LoadedCallback& callback)
54 : callback_(callback) {
55 }
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010056 virtual ~ConnectServiceLoader() {}
57
58 private:
59 // Overridden from ServiceLoader:
60 virtual void LoadService(ServiceManager* manager,
61 const GURL& url,
62 ScopedMessagePipeHandle shell_handle) OVERRIDE {
63 scoped_ptr<Application> app(new Application(shell_handle.Pass()));
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010064 ViewManager::Create(app.get(), this);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010065 apps_.push_back(app.release());
66 }
67 virtual void OnServiceError(ServiceManager* manager,
68 const GURL& url) OVERRIDE {
69 }
70
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010071 // Overridden from ViewManagerDelegate:
72 virtual void OnRootAdded(ViewManager* view_manager,
73 Node* root) OVERRIDE {
74 callback_.Run(view_manager, root);
75 }
76
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010077 ScopedVector<Application> apps_;
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010078 LoadedCallback callback_;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010079
80 DISALLOW_COPY_AND_ASSIGN(ConnectServiceLoader);
81};
82
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010083class ActiveViewChangedObserver : public NodeObserver {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010084 public:
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010085 explicit ActiveViewChangedObserver(Node* node)
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010086 : node_(node) {}
87 virtual ~ActiveViewChangedObserver() {}
88
89 private:
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010090 // Overridden from NodeObserver:
91 virtual void OnNodeActiveViewChange(Node* node,
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010092 View* old_view,
93 View* new_view,
94 DispositionChangePhase phase) OVERRIDE {
95 DCHECK_EQ(node, node_);
96 QuitRunLoop();
97 }
98
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010099 Node* node_;
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100100
101 DISALLOW_COPY_AND_ASSIGN(ActiveViewChangedObserver);
102};
103
104// Waits until the active view id of the supplied node changes.
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100105void WaitForActiveViewToChange(Node* node) {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100106 ActiveViewChangedObserver observer(node);
107 node->AddObserver(&observer);
108 DoRunLoop();
109 node->RemoveObserver(&observer);
110}
111
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100112class BoundsChangeObserver : public NodeObserver {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100113 public:
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100114 explicit BoundsChangeObserver(Node* node) : node_(node) {}
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100115 virtual ~BoundsChangeObserver() {}
116
117 private:
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100118 // Overridden from NodeObserver:
119 virtual void OnNodeBoundsChange(Node* node,
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100120 const gfx::Rect& old_bounds,
121 const gfx::Rect& new_bounds,
122 DispositionChangePhase phase) OVERRIDE {
123 DCHECK_EQ(node, node_);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100124 if (phase != NodeObserver::DISPOSITION_CHANGED)
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100125 return;
126 QuitRunLoop();
127 }
128
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100129 Node* node_;
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100130
131 DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver);
132};
133
134// Wait until the bounds of the supplied node change.
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100135void WaitForBoundsToChange(Node* node) {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100136 BoundsChangeObserver observer(node);
137 node->AddObserver(&observer);
138 DoRunLoop();
139 node->RemoveObserver(&observer);
140}
141
142// Spins a runloop until the tree beginning at |root| has |tree_size| nodes
143// (including |root|).
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100144class TreeSizeMatchesObserver : public NodeObserver {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100145 public:
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100146 TreeSizeMatchesObserver(Node* tree, size_t tree_size)
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100147 : tree_(tree),
148 tree_size_(tree_size) {}
149 virtual ~TreeSizeMatchesObserver() {}
150
151 bool IsTreeCorrectSize() {
152 return CountNodes(tree_) == tree_size_;
153 }
154
155 private:
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100156 // Overridden from NodeObserver:
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100157 virtual void OnTreeChange(const TreeChangeParams& params) OVERRIDE {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100158 if (IsTreeCorrectSize())
159 QuitRunLoop();
160 }
161
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100162 size_t CountNodes(const Node* node) const {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100163 size_t count = 1;
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100164 Node::Children::const_iterator it = node->children().begin();
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100165 for (; it != node->children().end(); ++it)
166 count += CountNodes(*it);
167 return count;
168 }
169
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100170 Node* tree_;
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100171 size_t tree_size_;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100172
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100173 DISALLOW_COPY_AND_ASSIGN(TreeSizeMatchesObserver);
174};
175
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100176void WaitForTreeSizeToMatch(Node* node, size_t tree_size) {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100177 TreeSizeMatchesObserver observer(node, tree_size);
178 if (observer.IsTreeCorrectSize())
179 return;
180 node->AddObserver(&observer);
181 DoRunLoop();
182 node->RemoveObserver(&observer);
183}
184
185
186// Utility class that waits for the destruction of some number of nodes and
187// views.
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100188class DestructionObserver : public NodeObserver, public ViewObserver {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100189 public:
190 // |nodes| or |views| can be NULL.
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100191 DestructionObserver(std::set<Id>* nodes, std::set<Id>* views)
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100192 : nodes_(nodes),
193 views_(views) {}
194
195 private:
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100196 // Overridden from NodeObserver:
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100197 virtual void OnNodeDestroy(
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100198 Node* node,
199 NodeObserver::DispositionChangePhase phase) OVERRIDE {
200 if (phase != NodeObserver::DISPOSITION_CHANGED)
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100201 return;
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100202 std::set<Id>::iterator it = nodes_->find(node->id());
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100203 if (it != nodes_->end())
204 nodes_->erase(it);
205 if (CanQuit())
206 QuitRunLoop();
207 }
208
209 // Overridden from ViewObserver:
210 virtual void OnViewDestroy(
211 View* view,
212 ViewObserver::DispositionChangePhase phase) OVERRIDE {
213 if (phase != ViewObserver::DISPOSITION_CHANGED)
214 return;
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100215 std::set<Id>::iterator it = views_->find(view->id());
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100216 if (it != views_->end())
217 views_->erase(it);
218 if (CanQuit())
219 QuitRunLoop();
220 }
221
222 bool CanQuit() {
223 return (!nodes_ || nodes_->empty()) && (!views_ || views_->empty());
224 }
225
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100226 std::set<Id>* nodes_;
227 std::set<Id>* views_;
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100228
229 DISALLOW_COPY_AND_ASSIGN(DestructionObserver);
230};
231
232void WaitForDestruction(ViewManager* view_manager,
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100233 std::set<Id>* nodes,
234 std::set<Id>* views) {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100235 DestructionObserver observer(nodes, views);
236 DCHECK(nodes || views);
237 if (nodes) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100238 for (std::set<Id>::const_iterator it = nodes->begin();
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100239 it != nodes->end(); ++it) {
240 view_manager->GetNodeById(*it)->AddObserver(&observer);
241 }
242 }
243 if (views) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100244 for (std::set<Id>::const_iterator it = views->begin();
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100245 it != views->end(); ++it) {
246 view_manager->GetViewById(*it)->AddObserver(&observer);
247 }
248 }
249 DoRunLoop();
250}
251
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100252class OrderChangeObserver : public NodeObserver {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100253 public:
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100254 OrderChangeObserver(Node* node) : node_(node) {
255 node_->AddObserver(this);
256 }
257 virtual ~OrderChangeObserver() {
258 node_->RemoveObserver(this);
259 }
260
261 private:
262 // Overridden from NodeObserver:
263 virtual void OnNodeReordered(Node* node,
264 Node* relative_node,
265 OrderDirection direction,
266 DispositionChangePhase phase) OVERRIDE {
267 if (phase != NodeObserver::DISPOSITION_CHANGED)
268 return;
269
270 DCHECK_EQ(node, node_);
271 QuitRunLoop();
272 }
273
274 Node* node_;
275
276 DISALLOW_COPY_AND_ASSIGN(OrderChangeObserver);
277};
278
279void WaitForOrderChange(ViewManager* view_manager, Node* node) {
280 OrderChangeObserver observer(node);
281 DoRunLoop();
282}
283
284// Tracks a node's destruction. Query is_valid() for current state.
285class NodeTracker : public NodeObserver {
286 public:
287 explicit NodeTracker(Node* node) : node_(node) {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100288 node_->AddObserver(this);
289 }
290 virtual ~NodeTracker() {
291 if (node_)
292 node_->RemoveObserver(this);
293 }
294
295 bool is_valid() const { return !!node_; }
296
297 private:
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100298 // Overridden from NodeObserver:
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100299 virtual void OnNodeDestroy(
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100300 Node* node,
301 NodeObserver::DispositionChangePhase phase) OVERRIDE {
302 if (phase != NodeObserver::DISPOSITION_CHANGED)
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100303 return;
304 DCHECK_EQ(node, node_);
305 node_ = NULL;
306 }
307
308 int id_;
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100309 Node* node_;
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100310
311 DISALLOW_COPY_AND_ASSIGN(NodeTracker);
312};
313
314} // namespace
315
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100316// ViewManager -----------------------------------------------------------------
317
Torne (Richard Coles)0de60732014-05-15 12:16:31 +0100318// These tests model synchronization of two peer connections to the view manager
319// service, that are given access to some root node.
320
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100321class ViewManagerTest : public testing::Test {
322 public:
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100323 ViewManagerTest()
324 : connect_loop_(NULL),
325 loaded_view_manager_(NULL),
326 window_manager_(NULL),
327 commit_count_(0) {}
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100328
329 protected:
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100330 ViewManager* window_manager() { return window_manager_; }
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100331
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100332 Node* CreateNodeInParent(Node* parent) {
333 ViewManager* parent_manager = NodePrivate(parent).view_manager();
334 Node* node = Node::Create(parent_manager);
Torne (Richard Coles)0de60732014-05-15 12:16:31 +0100335 parent->AddChild(node);
336 return node;
337 }
338
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100339 // Embeds another version of the test app @ node.
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100340 ViewManager* Embed(ViewManager* view_manager, Node* node) {
341 DCHECK_EQ(view_manager, NodePrivate(node).view_manager());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100342 node->Embed(kEmbeddedApp1URL);
343 RunRunLoop();
344 return GetLoadedViewManager();
345 }
346
347 // TODO(beng): remove these methods once all the tests are migrated.
348 void DestroyViewManager1() {}
349 ViewManager* view_manager_1() { return NULL; }
350 ViewManager* view_manager_2() { return NULL; }
351
352 ViewManager* GetLoadedViewManager() {
353 ViewManager* view_manager = loaded_view_manager_;
354 loaded_view_manager_ = NULL;
355 return view_manager;
356 }
357
358 void UnloadApplication(const GURL& url) {
359 test_helper_.SetLoaderForURL(scoped_ptr<ServiceLoader>(), url);
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100360 }
361
362 private:
363 // Overridden from testing::Test:
364 virtual void SetUp() OVERRIDE {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100365 ConnectServiceLoader::LoadedCallback ready_callback =
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100366 base::Bind(&ViewManagerTest::OnViewManagerLoaded,
367 base::Unretained(this));
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100368 test_helper_.Init();
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100369 test_helper_.SetLoaderForURL(
370 scoped_ptr<ServiceLoader>(new ConnectServiceLoader(ready_callback)),
371 GURL(kWindowManagerURL));
372 test_helper_.SetLoaderForURL(
373 scoped_ptr<ServiceLoader>(new ConnectServiceLoader(ready_callback)),
374 GURL(kEmbeddedApp1URL));
375
376 ConnectToService(test_helper_.service_provider(),
377 "mojo:mojo_view_manager",
378 &view_manager_init_);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100379 ASSERT_TRUE(EmbedRoot(view_manager_init_.get(), kWindowManagerURL));
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100380 }
381
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100382 void EmbedRootCallback(bool* result_cache, bool result) {
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100383 *result_cache = result;
384 }
385
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100386 bool EmbedRoot(ViewManagerInitService* view_manager_init,
387 const std::string& url) {
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100388 bool result = false;
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100389 view_manager_init->EmbedRoot(
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100390 url,
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100391 base::Bind(&ViewManagerTest::EmbedRootCallback, base::Unretained(this),
392 &result));
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100393 RunRunLoop();
394 window_manager_ = GetLoadedViewManager();
395 return result;
396 }
397
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100398 void OnViewManagerLoaded(ViewManager* view_manager, Node* root) {
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100399 loaded_view_manager_ = view_manager;
400 connect_loop_->Quit();
401 }
402
403 void RunRunLoop() {
404 base::RunLoop run_loop;
405 connect_loop_ = &run_loop;
406 connect_loop_->Run();
407 connect_loop_ = NULL;
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100408 }
409
410 base::MessageLoop loop_;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100411 base::RunLoop* connect_loop_;
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100412 shell::ShellTestHelper test_helper_;
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100413 ViewManagerInitServicePtr view_manager_init_;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100414 // Used to receive the most recent view manager loaded by an embed action.
415 ViewManager* loaded_view_manager_;
416 // The View Manager connection held by the window manager (app running at the
417 // root node).
418 ViewManager* window_manager_;
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100419 int commit_count_;
420
421 DISALLOW_COPY_AND_ASSIGN(ViewManagerTest);
422};
423
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100424TEST_F(ViewManagerTest, SetUp) {}
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100425
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100426TEST_F(ViewManagerTest, Embed) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100427 Node* node = Node::Create(window_manager());
428 window_manager()->GetRoots().front()->AddChild(node);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100429 ViewManager* embedded = Embed(window_manager(), node);
430 EXPECT_TRUE(NULL != embedded);
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100431
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100432 Node* node_in_embedded = embedded->GetRoots().front();
433 EXPECT_EQ(node->parent(), window_manager()->GetRoots().front());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100434 EXPECT_EQ(NULL, node_in_embedded->parent());
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100435}
436
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100437// When Window Manager embeds A @ N, then creates N2 and parents to N, N becomes
438// visible to A.
439// TODO(beng): verify whether or not this is a policy we like.
440TEST_F(ViewManagerTest, HierarchyChanged_NodeAdded) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100441 Node* node = Node::Create(window_manager());
442 window_manager()->GetRoots().front()->AddChild(node);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100443 ViewManager* embedded = Embed(window_manager(), node);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100444 Node* nested = Node::Create(window_manager());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100445 node->AddChild(nested);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100446 WaitForTreeSizeToMatch(embedded->GetRoots().front(), 2);
447 EXPECT_EQ(embedded->GetRoots().front()->children().front()->id(),
448 nested->id());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100449}
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100450
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100451// Window manager has two nodes, N1 & N2. Embeds A at N1. Creates node N21,
452// a child of N2. Reparents N2 to N1. N1 should become visible to A.
453// TODO(beng): verify whether or not this is a policy we like.
454TEST_F(ViewManagerTest, HierarchyChanged_NodeMoved) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100455 Node* node1 = Node::Create(window_manager());
456 window_manager()->GetRoots().front()->AddChild(node1);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100457 ViewManager* embedded = Embed(window_manager(), node1);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100458 WaitForTreeSizeToMatch(embedded->GetRoots().front(), 1);
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100459
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100460 Node* node2 = Node::Create(window_manager());
461 window_manager()->GetRoots().front()->AddChild(node2);
462 WaitForTreeSizeToMatch(embedded->GetRoots().front(), 1);
463 EXPECT_TRUE(embedded->GetRoots().front()->children().empty());
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100464
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100465 Node* node21 = Node::Create(window_manager());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100466 node2->AddChild(node21);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100467 WaitForTreeSizeToMatch(embedded->GetRoots().front(), 1);
468 EXPECT_TRUE(embedded->GetRoots().front()->children().empty());
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100469
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100470 // Makes node21 visible to |embedded|.
Torne (Richard Coles)0de60732014-05-15 12:16:31 +0100471 node1->AddChild(node21);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100472 WaitForTreeSizeToMatch(embedded->GetRoots().front(), 2);
473 EXPECT_FALSE(embedded->GetRoots().front()->children().empty());
474 EXPECT_EQ(embedded->GetRoots().front()->children().front()->id(),
475 node21->id());
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100476}
477
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100478// Window manager has two nodes, N1 and N11. Embeds A at N1. Removes N11 from
479// N1. N11 should disappear from A.
480// TODO(beng): verify whether or not this is a policy we like.
481TEST_F(ViewManagerTest, HierarchyChanged_NodeRemoved) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100482 Node* node = Node::Create(window_manager());
483 window_manager()->GetRoots().front()->AddChild(node);
484 Node* nested = Node::Create(window_manager());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100485 node->AddChild(nested);
Torne (Richard Coles)0de60732014-05-15 12:16:31 +0100486
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100487 ViewManager* embedded = Embed(window_manager(), node);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100488 EXPECT_EQ(embedded->GetRoots().front()->children().front()->id(),
489 nested->id());
Torne (Richard Coles)0de60732014-05-15 12:16:31 +0100490
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100491 node->RemoveChild(nested);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100492 WaitForTreeSizeToMatch(embedded->GetRoots().front(), 1);
493 EXPECT_TRUE(embedded->GetRoots().front()->children().empty());
Torne (Richard Coles)0de60732014-05-15 12:16:31 +0100494}
495
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100496// Window manager has two nodes, N1 and N11. Embeds A at N1. Destroys N11.
497// N11 should disappear from A.
498// TODO(beng): verify whether or not this is a policy we like.
499TEST_F(ViewManagerTest, NodeDestroyed) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100500 Node* node = Node::Create(window_manager());
501 window_manager()->GetRoots().front()->AddChild(node);
502 Node* nested = Node::Create(window_manager());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100503 node->AddChild(nested);
Torne (Richard Coles)0de60732014-05-15 12:16:31 +0100504
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100505 ViewManager* embedded = Embed(window_manager(), node);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100506 EXPECT_EQ(embedded->GetRoots().front()->children().front()->id(),
507 nested->id());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100508
509 // |nested| will be deleted after calling Destroy() below.
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100510 Id id = nested->id();
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100511 nested->Destroy();
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100512
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100513 std::set<Id> nodes;
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100514 nodes.insert(id);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100515 WaitForDestruction(embedded, &nodes, NULL);
Torne (Richard Coles)0de60732014-05-15 12:16:31 +0100516
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100517 EXPECT_TRUE(embedded->GetRoots().front()->children().empty());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100518 EXPECT_EQ(NULL, embedded->GetNodeById(id));
Torne (Richard Coles)0de60732014-05-15 12:16:31 +0100519}
520
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100521TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNode) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100522 Node* node = Node::Create(window_manager());
523 window_manager()->GetRoots().front()->AddChild(node);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100524 ViewManager* embedded = Embed(window_manager(), node);
Torne (Richard Coles)0de60732014-05-15 12:16:31 +0100525
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100526 Id node_id = node->id();
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100527
528 UnloadApplication(GURL(kWindowManagerURL));
529
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100530 std::set<Id> nodes;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100531 nodes.insert(node_id);
532 WaitForDestruction(embedded, &nodes, NULL);
Torne (Richard Coles)0de60732014-05-15 12:16:31 +0100533
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100534 EXPECT_TRUE(embedded->GetRoots().empty());
Torne (Richard Coles)0de60732014-05-15 12:16:31 +0100535}
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100536
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100537TEST_F(ViewManagerTest, SetActiveView) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100538 Node* node = Node::Create(window_manager());
539 window_manager()->GetRoots().front()->AddChild(node);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100540 ViewManager* embedded = Embed(window_manager(), node);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100541
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100542 View* view = View::Create(window_manager());
543 node->SetActiveView(view);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100544
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100545 Node* node_in_embedded = embedded->GetNodeById(node->id());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100546 WaitForActiveViewToChange(node_in_embedded);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100547
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100548 EXPECT_EQ(node_in_embedded->active_view()->id(), view->id());
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100549}
550
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100551TEST_F(ViewManagerTest, DestroyView) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100552 Node* node = Node::Create(window_manager());
553 window_manager()->GetRoots().front()->AddChild(node);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100554 ViewManager* embedded = Embed(window_manager(), node);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100555
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100556 View* view = View::Create(window_manager());
557 node->SetActiveView(view);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100558
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100559 Node* node_in_embedded = embedded->GetNodeById(node->id());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100560 WaitForActiveViewToChange(node_in_embedded);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100561
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100562 EXPECT_EQ(node_in_embedded->active_view()->id(), view->id());
563
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100564 Id view_id = view->id();
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100565 view->Destroy();
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100566
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100567 std::set<Id> views;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100568 views.insert(view_id);
569 WaitForDestruction(embedded, NULL, &views);
570 EXPECT_EQ(NULL, node_in_embedded->active_view());
571 EXPECT_EQ(NULL, embedded->GetViewById(view_id));
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100572}
573
574// Destroying the connection that created a node and view should result in that
575// node and view disappearing from all connections that see them.
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100576TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNodeAndView) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100577 Node* node = Node::Create(window_manager());
578 window_manager()->GetRoots().front()->AddChild(node);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100579 View* view = View::Create(window_manager());
580 node->SetActiveView(view);
581 ViewManager* embedded = Embed(window_manager(), node);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100582
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100583 Id node_id = node->id();
584 Id view_id = view->id();
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100585
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100586 UnloadApplication(GURL(kWindowManagerURL));
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100587
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100588 std::set<Id> observed_nodes;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100589 observed_nodes.insert(node_id);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100590 std::set<Id> observed_views;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100591 observed_views.insert(view_id);
592 WaitForDestruction(embedded, &observed_nodes, &observed_views);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100593
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100594 EXPECT_TRUE(embedded->GetRoots().empty());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100595 EXPECT_EQ(NULL, embedded->GetNodeById(node_id));
596 EXPECT_EQ(NULL, embedded->GetViewById(view_id));
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100597}
598
599// This test validates the following scenario:
600// - a node originating from one connection
601// - a view originating from a second connection
602// + the connection originating the node is destroyed
603// -> the view should still exist (since the second connection is live) but
604// should be disconnected from any nodes.
605TEST_F(ViewManagerTest,
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100606 ViewManagerDestroyed_CleanupNodeAndViewFromDifferentConnections) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100607 Node* node = Node::Create(window_manager());
608 window_manager()->GetRoots().front()->AddChild(node);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100609 ViewManager* embedded = Embed(window_manager(), node);
610 View* view_in_embedded = View::Create(embedded);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100611 Node* node_in_embedded = embedded->GetNodeById(node->id());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100612 node_in_embedded->SetActiveView(view_in_embedded);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100613
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100614 WaitForActiveViewToChange(node);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100615
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100616 Id node_id = node->id();
617 Id view_id = view_in_embedded->id();
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100618
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100619 UnloadApplication(GURL(kWindowManagerURL));
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100620 std::set<Id> nodes;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100621 nodes.insert(node_id);
622 WaitForDestruction(embedded, &nodes, NULL);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100623
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100624 EXPECT_TRUE(embedded->GetRoots().empty());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100625 // node was owned by the window manager, so it should be gone.
626 EXPECT_EQ(NULL, embedded->GetNodeById(node_id));
627 // view_in_embedded was owned by the embedded app, so it should still exist,
628 // but disconnected from the node tree.
629 EXPECT_EQ(view_in_embedded, embedded->GetViewById(view_id));
630 EXPECT_EQ(NULL, view_in_embedded->node());
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100631}
632
633// This test verifies that it is not possible to set the active view to a view
634// defined in a different connection.
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100635// TODO(beng): write these tests for Node::AddChild(), RemoveChild() and
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100636// Contains().
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100637TEST_F(ViewManagerTest, SetActiveViewAcrossConnection) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100638 Node* node = Node::Create(window_manager());
639 window_manager()->GetRoots().front()->AddChild(node);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100640 ViewManager* embedded = Embed(window_manager(), node);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100641
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100642 View* view_in_embedded = View::Create(embedded);
643 EXPECT_DEATH(node->SetActiveView(view_in_embedded), "");
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100644}
645
646// This test verifies that a node hierarchy constructed in one connection
647// becomes entirely visible to the second connection when the hierarchy is
648// attached.
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100649TEST_F(ViewManagerTest, MapSubtreeOnAttach) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100650 Node* node = Node::Create(window_manager());
651 window_manager()->GetRoots().front()->AddChild(node);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100652 ViewManager* embedded = Embed(window_manager(), node);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100653
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100654 // Create a subtree private to the window manager and make some changes to it.
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100655 Node* child1 = Node::Create(window_manager());
656 Node* child11 = Node::Create(window_manager());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100657 child1->AddChild(child11);
658 gfx::Rect child11_bounds(800, 600);
659 child11->SetBounds(child11_bounds);
660 View* view11 = View::Create(window_manager());
661 child11->SetActiveView(view11);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100662 WaitForAllChangesToBeAcked(
663 static_cast<ViewManagerClientImpl*>(window_manager()));
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100664
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100665 // When added to the shared node, the entire hierarchy and all property
666 // changes should become visible to the embedded app.
667 node->AddChild(child1);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100668 WaitForTreeSizeToMatch(embedded->GetRoots().front(), 3);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100669
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100670 Node* child11_in_embedded = embedded->GetNodeById(child11->id());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100671 View* view11_in_embedded = embedded->GetViewById(view11->id());
672 EXPECT_TRUE(child11_in_embedded != NULL);
673 EXPECT_EQ(view11_in_embedded, child11_in_embedded->active_view());
674 EXPECT_EQ(child11_bounds, child11_in_embedded->bounds());
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100675}
676
677// Verifies that bounds changes applied to a node hierarchy in one connection
678// are reflected to another.
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100679TEST_F(ViewManagerTest, SetBounds) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100680 Node* node = Node::Create(window_manager());
681 window_manager()->GetRoots().front()->AddChild(node);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100682 ViewManager* embedded = Embed(window_manager(), node);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100683
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100684 Node* node_in_embedded = embedded->GetNodeById(node->id());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100685 EXPECT_EQ(node->bounds(), node_in_embedded->bounds());
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100686
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100687 node->SetBounds(gfx::Rect(100, 100));
688 EXPECT_NE(node->bounds(), node_in_embedded->bounds());
689 WaitForBoundsToChange(node_in_embedded);
690 EXPECT_EQ(node->bounds(), node_in_embedded->bounds());
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100691}
692
693// Verifies that bounds changes applied to a node owned by a different
694// connection are refused.
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100695TEST_F(ViewManagerTest, SetBoundsSecurity) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100696 Node* node = Node::Create(window_manager());
697 window_manager()->GetRoots().front()->AddChild(node);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100698 ViewManager* embedded = Embed(window_manager(), node);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100699
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100700 Node* node_in_embedded = embedded->GetNodeById(node->id());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100701 node->SetBounds(gfx::Rect(800, 600));
702 WaitForBoundsToChange(node_in_embedded);
703
704 node_in_embedded->SetBounds(gfx::Rect(1024, 768));
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100705 // Bounds change should have been rejected.
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100706 EXPECT_EQ(node->bounds(), node_in_embedded->bounds());
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100707}
708
709// Verifies that a node can only be destroyed by the connection that created it.
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100710TEST_F(ViewManagerTest, DestroySecurity) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100711 Node* node = Node::Create(window_manager());
712 window_manager()->GetRoots().front()->AddChild(node);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100713 ViewManager* embedded = Embed(window_manager(), node);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100714
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100715 Node* node_in_embedded = embedded->GetNodeById(node->id());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100716
717 NodeTracker tracker2(node_in_embedded);
718 node_in_embedded->Destroy();
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100719 // Node should not have been destroyed.
720 EXPECT_TRUE(tracker2.is_valid());
721
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100722 NodeTracker tracker1(node);
723 node->Destroy();
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100724 EXPECT_FALSE(tracker1.is_valid());
725}
726
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100727TEST_F(ViewManagerTest, MultiRoots) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100728 Node* node1 = Node::Create(window_manager());
729 window_manager()->GetRoots().front()->AddChild(node1);
730 Node* node2 = Node::Create(window_manager());
731 window_manager()->GetRoots().front()->AddChild(node2);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100732 ViewManager* embedded1 = Embed(window_manager(), node1);
733 ViewManager* embedded2 = Embed(window_manager(), node2);
734 EXPECT_EQ(embedded1, embedded2);
735}
736
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100737TEST_F(ViewManagerTest, EmbeddingIdentity) {
738 Node* node = Node::Create(window_manager());
739 window_manager()->GetRoots().front()->AddChild(node);
740 ViewManager* embedded = Embed(window_manager(), node);
741 EXPECT_EQ(kWindowManagerURL, embedded->GetEmbedderURL());
742}
743
744TEST_F(ViewManagerTest, Reorder) {
745 Node* node1 = Node::Create(window_manager());
746 window_manager()->GetRoots().front()->AddChild(node1);
747
748 Node* node11 = Node::Create(window_manager());
749 node1->AddChild(node11);
750 Node* node12 = Node::Create(window_manager());
751 node1->AddChild(node12);
752
753 ViewManager* embedded = Embed(window_manager(), node1);
754
755 Node* node1_in_embedded = embedded->GetNodeById(node1->id());
756
757 {
758 node11->MoveToFront();
759 WaitForOrderChange(embedded, embedded->GetNodeById(node11->id()));
760
761 EXPECT_EQ(node1_in_embedded->children().front(),
762 embedded->GetNodeById(node12->id()));
763 EXPECT_EQ(node1_in_embedded->children().back(),
764 embedded->GetNodeById(node11->id()));
765 }
766
767 {
768 node11->MoveToBack();
769 WaitForOrderChange(embedded, embedded->GetNodeById(node11->id()));
770
771 EXPECT_EQ(node1_in_embedded->children().front(),
772 embedded->GetNodeById(node11->id()));
773 EXPECT_EQ(node1_in_embedded->children().back(),
774 embedded->GetNodeById(node12->id()));
775 }
776}
777
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100778} // namespace view_manager
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100779} // namespace mojo