blob: 9f4729292b5afec4747109194fce360fcbfd22af [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)6e8cce62014-08-19 13:00:08 +010010#include "mojo/application_manager/application_manager.h"
Ben Murdoch116680a2014-07-20 18:25:52 -070011#include "mojo/public/cpp/application/application_connection.h"
12#include "mojo/public/cpp/application/application_delegate.h"
13#include "mojo/public/cpp/application/application_impl.h"
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +010014#include "mojo/public/cpp/application/service_provider_impl.h"
15#include "mojo/public/interfaces/application/service_provider.mojom.h"
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010016#include "mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.h"
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +010017#include "mojo/services/public/cpp/view_manager/lib/view_private.h"
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +010018#include "mojo/services/public/cpp/view_manager/util.h"
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +010019#include "mojo/services/public/cpp/view_manager/view_manager_client_factory.h"
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010020#include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010021#include "mojo/services/public/cpp/view_manager/view_observer.h"
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +010022#include "mojo/shell/shell_test_helper.h"
23#include "testing/gtest/include/gtest/gtest.h"
24
25namespace mojo {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010026namespace {
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +010027
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010028const char kWindowManagerURL[] = "mojo:window_manager";
29const char kEmbeddedApp1URL[] = "mojo:embedded_app_1";
30
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +010031base::RunLoop* current_run_loop = NULL;
32
33void DoRunLoop() {
34 base::RunLoop run_loop;
35 current_run_loop = &run_loop;
36 current_run_loop->Run();
37 current_run_loop = NULL;
38}
39
40void QuitRunLoop() {
41 current_run_loop->Quit();
42}
43
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +010044class ConnectApplicationLoader : public ApplicationLoader,
45 public ApplicationDelegate,
46 public ViewManagerDelegate {
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010047 public:
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +010048 typedef base::Callback<void(ViewManager*, View*)> LoadedCallback;
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010049
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +010050 explicit ConnectApplicationLoader(const LoadedCallback& callback)
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +010051 : callback_(callback), view_manager_client_factory_(this) {}
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +010052 virtual ~ConnectApplicationLoader() {}
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010053
54 private:
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +010055 // Overridden from ApplicationLoader:
56 virtual void Load(ApplicationManager* manager,
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +010057 const GURL& url,
58 scoped_refptr<LoadCallbacks> callbacks) OVERRIDE {
59 ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication();
60 if (!shell_handle.is_valid())
61 return;
Ben Murdoch116680a2014-07-20 18:25:52 -070062 scoped_ptr<ApplicationImpl> app(new ApplicationImpl(this,
63 shell_handle.Pass()));
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010064 apps_.push_back(app.release());
65 }
Ben Murdoch116680a2014-07-20 18:25:52 -070066
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +010067 virtual void OnServiceError(ApplicationManager* manager,
68 const GURL& url) OVERRIDE {}
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010069
Ben Murdoch116680a2014-07-20 18:25:52 -070070 virtual bool ConfigureIncomingConnection(ApplicationConnection* connection)
71 OVERRIDE {
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +010072 connection->AddService(&view_manager_client_factory_);
Ben Murdoch116680a2014-07-20 18:25:52 -070073 return true;
74 }
75
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010076 // Overridden from ViewManagerDelegate:
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +010077 virtual void OnEmbed(ViewManager* view_manager,
78 View* root,
79 ServiceProviderImpl* exported_services,
80 scoped_ptr<ServiceProvider> imported_services) OVERRIDE {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010081 callback_.Run(view_manager, root);
82 }
Ben Murdoch116680a2014-07-20 18:25:52 -070083 virtual void OnViewManagerDisconnected(ViewManager* view_manager) OVERRIDE {}
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010084
Ben Murdoch116680a2014-07-20 18:25:52 -070085 ScopedVector<ApplicationImpl> apps_;
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010086 LoadedCallback callback_;
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +010087 ViewManagerClientFactory view_manager_client_factory_;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010088
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +010089 DISALLOW_COPY_AND_ASSIGN(ConnectApplicationLoader);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010090};
91
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +010092class BoundsChangeObserver : public ViewObserver {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010093 public:
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +010094 explicit BoundsChangeObserver(View* view) : view_(view) {}
Torne (Richard Coles)cedac222014-06-03 10:58:34 +010095 virtual ~BoundsChangeObserver() {}
96
97 private:
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +010098 // Overridden from ViewObserver:
99 virtual void OnViewBoundsChanged(View* view,
Ben Murdoch116680a2014-07-20 18:25:52 -0700100 const gfx::Rect& old_bounds,
101 const gfx::Rect& new_bounds) OVERRIDE {
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100102 DCHECK_EQ(view, view_);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100103 QuitRunLoop();
104 }
105
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100106 View* view_;
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100107
108 DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver);
109};
110
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100111// Wait until the bounds of the supplied view change.
112void WaitForBoundsToChange(View* view) {
113 BoundsChangeObserver observer(view);
114 view->AddObserver(&observer);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100115 DoRunLoop();
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100116 view->RemoveObserver(&observer);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100117}
118
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100119// Spins a runloop until the tree beginning at |root| has |tree_size| views
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100120// (including |root|).
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100121class TreeSizeMatchesObserver : public ViewObserver {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100122 public:
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100123 TreeSizeMatchesObserver(View* tree, size_t tree_size)
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100124 : tree_(tree),
125 tree_size_(tree_size) {}
126 virtual ~TreeSizeMatchesObserver() {}
127
128 bool IsTreeCorrectSize() {
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100129 return CountViews(tree_) == tree_size_;
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100130 }
131
132 private:
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100133 // Overridden from ViewObserver:
Ben Murdoch116680a2014-07-20 18:25:52 -0700134 virtual void OnTreeChanged(const TreeChangeParams& params) OVERRIDE {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100135 if (IsTreeCorrectSize())
136 QuitRunLoop();
137 }
138
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100139 size_t CountViews(const View* view) const {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100140 size_t count = 1;
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100141 View::Children::const_iterator it = view->children().begin();
142 for (; it != view->children().end(); ++it)
143 count += CountViews(*it);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100144 return count;
145 }
146
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100147 View* tree_;
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100148 size_t tree_size_;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100149
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100150 DISALLOW_COPY_AND_ASSIGN(TreeSizeMatchesObserver);
151};
152
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100153void WaitForTreeSizeToMatch(View* view, size_t tree_size) {
154 TreeSizeMatchesObserver observer(view, tree_size);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100155 if (observer.IsTreeCorrectSize())
156 return;
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100157 view->AddObserver(&observer);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100158 DoRunLoop();
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100159 view->RemoveObserver(&observer);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100160}
161
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100162// Utility class that waits for the destruction of some number of views and
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100163// views.
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100164class DestructionObserver : public ViewObserver {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100165 public:
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100166 // |views| or |views| can be NULL.
167 explicit DestructionObserver(std::set<Id>* views) : views_(views) {}
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100168
169 private:
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100170 // Overridden from ViewObserver:
Ben Murdoch116680a2014-07-20 18:25:52 -0700171 virtual void OnViewDestroyed(View* view) OVERRIDE {
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100172 std::set<Id>::iterator it = views_->find(view->id());
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100173 if (it != views_->end())
174 views_->erase(it);
175 if (CanQuit())
176 QuitRunLoop();
177 }
178
179 bool CanQuit() {
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100180 return !views_ || views_->empty();
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100181 }
182
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100183 std::set<Id>* views_;
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100184
185 DISALLOW_COPY_AND_ASSIGN(DestructionObserver);
186};
187
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100188void WaitForDestruction(ViewManager* view_manager, std::set<Id>* views) {
189 DestructionObserver observer(views);
190 DCHECK(views);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100191 if (views) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100192 for (std::set<Id>::const_iterator it = views->begin();
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100193 it != views->end(); ++it) {
194 view_manager->GetViewById(*it)->AddObserver(&observer);
195 }
196 }
197 DoRunLoop();
198}
199
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100200class OrderChangeObserver : public ViewObserver {
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100201 public:
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100202 OrderChangeObserver(View* view) : view_(view) {
203 view_->AddObserver(this);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100204 }
205 virtual ~OrderChangeObserver() {
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100206 view_->RemoveObserver(this);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100207 }
208
209 private:
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100210 // Overridden from ViewObserver:
211 virtual void OnViewReordered(View* view,
212 View* relative_view,
Ben Murdoch116680a2014-07-20 18:25:52 -0700213 OrderDirection direction) OVERRIDE {
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100214 DCHECK_EQ(view, view_);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100215 QuitRunLoop();
216 }
217
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100218 View* view_;
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100219
220 DISALLOW_COPY_AND_ASSIGN(OrderChangeObserver);
221};
222
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100223void WaitForOrderChange(ViewManager* view_manager, View* view) {
224 OrderChangeObserver observer(view);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100225 DoRunLoop();
226}
227
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100228// Tracks a view's destruction. Query is_valid() for current state.
229class ViewTracker : public ViewObserver {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100230 public:
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100231 explicit ViewTracker(View* view) : view_(view) {
232 view_->AddObserver(this);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100233 }
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100234 virtual ~ViewTracker() {
235 if (view_)
236 view_->RemoveObserver(this);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100237 }
238
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100239 bool is_valid() const { return !!view_; }
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100240
241 private:
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100242 // Overridden from ViewObserver:
243 virtual void OnViewDestroyed(View* view) OVERRIDE {
244 DCHECK_EQ(view, view_);
245 view_ = NULL;
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100246 }
247
248 int id_;
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100249 View* view_;
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100250
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100251 DISALLOW_COPY_AND_ASSIGN(ViewTracker);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100252};
253
254} // namespace
255
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100256// ViewManager -----------------------------------------------------------------
257
Torne (Richard Coles)0de60732014-05-15 12:16:31 +0100258// These tests model synchronization of two peer connections to the view manager
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100259// service, that are given access to some root view.
Torne (Richard Coles)0de60732014-05-15 12:16:31 +0100260
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100261class ViewManagerTest : public testing::Test {
262 public:
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100263 ViewManagerTest()
264 : connect_loop_(NULL),
265 loaded_view_manager_(NULL),
266 window_manager_(NULL),
267 commit_count_(0) {}
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100268
269 protected:
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100270 ViewManager* window_manager() { return window_manager_; }
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100271
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100272 View* CreateViewInParent(View* parent) {
273 ViewManager* parent_manager = ViewPrivate(parent).view_manager();
274 View* view = View::Create(parent_manager);
275 parent->AddChild(view);
276 return view;
Torne (Richard Coles)0de60732014-05-15 12:16:31 +0100277 }
278
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100279 // Embeds another version of the test app @ view.
280 ViewManager* Embed(ViewManager* view_manager, View* view) {
281 DCHECK_EQ(view_manager, ViewPrivate(view).view_manager());
282 view->Embed(kEmbeddedApp1URL);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100283 RunRunLoop();
284 return GetLoadedViewManager();
285 }
286
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100287 ViewManager* GetLoadedViewManager() {
288 ViewManager* view_manager = loaded_view_manager_;
289 loaded_view_manager_ = NULL;
290 return view_manager;
291 }
292
293 void UnloadApplication(const GURL& url) {
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100294 test_helper_.SetLoaderForURL(scoped_ptr<ApplicationLoader>(), url);
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100295 }
296
297 private:
298 // Overridden from testing::Test:
299 virtual void SetUp() OVERRIDE {
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100300 ConnectApplicationLoader::LoadedCallback ready_callback = base::Bind(
301 &ViewManagerTest::OnViewManagerLoaded, base::Unretained(this));
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100302 test_helper_.Init();
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100303 test_helper_.SetLoaderForURL(
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100304 scoped_ptr<ApplicationLoader>(
305 new ConnectApplicationLoader(ready_callback)),
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100306 GURL(kWindowManagerURL));
307 test_helper_.SetLoaderForURL(
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100308 scoped_ptr<ApplicationLoader>(
309 new ConnectApplicationLoader(ready_callback)),
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100310 GURL(kEmbeddedApp1URL));
311
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100312 test_helper_.application_manager()->ConnectToService(
Ben Murdoch116680a2014-07-20 18:25:52 -0700313 GURL("mojo:mojo_view_manager"), &view_manager_init_);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100314 ASSERT_TRUE(EmbedRoot(view_manager_init_.get(), kWindowManagerURL));
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100315 }
316
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100317 void EmbedRootCallback(bool* result_cache, bool result) {
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100318 *result_cache = result;
319 }
320
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100321 bool EmbedRoot(ViewManagerInitService* view_manager_init,
322 const std::string& url) {
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100323 bool result = false;
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100324 ServiceProviderPtr sp;
325 BindToProxy(new ServiceProviderImpl, &sp);
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100326 view_manager_init->Embed(
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100327 url, sp.Pass(),
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100328 base::Bind(&ViewManagerTest::EmbedRootCallback, base::Unretained(this),
329 &result));
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100330 RunRunLoop();
331 window_manager_ = GetLoadedViewManager();
332 return result;
333 }
334
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100335 void OnViewManagerLoaded(ViewManager* view_manager, View* root) {
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100336 loaded_view_manager_ = view_manager;
337 connect_loop_->Quit();
338 }
339
340 void RunRunLoop() {
341 base::RunLoop run_loop;
342 connect_loop_ = &run_loop;
343 connect_loop_->Run();
344 connect_loop_ = NULL;
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100345 }
346
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100347 base::RunLoop* connect_loop_;
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100348 shell::ShellTestHelper test_helper_;
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100349 ViewManagerInitServicePtr view_manager_init_;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100350 // Used to receive the most recent view manager loaded by an embed action.
351 ViewManager* loaded_view_manager_;
352 // The View Manager connection held by the window manager (app running at the
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100353 // root view).
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100354 ViewManager* window_manager_;
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100355 int commit_count_;
356
357 DISALLOW_COPY_AND_ASSIGN(ViewManagerTest);
358};
359
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100360TEST_F(ViewManagerTest, SetUp) {}
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100361
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100362TEST_F(ViewManagerTest, Embed) {
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100363 View* view = View::Create(window_manager());
364 window_manager()->GetRoots().front()->AddChild(view);
365 ViewManager* embedded = Embed(window_manager(), view);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100366 EXPECT_TRUE(NULL != embedded);
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100367
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100368 View* view_in_embedded = embedded->GetRoots().front();
369 EXPECT_EQ(view->parent(), window_manager()->GetRoots().front());
370 EXPECT_EQ(NULL, view_in_embedded->parent());
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100371}
372
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100373// Window manager has two views, N1 and N11. Embeds A at N1. A should not see
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100374// N11.
375// TODO(sky): Update client lib to match server.
376TEST_F(ViewManagerTest, DISABLED_EmbeddedDoesntSeeChild) {
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100377 View* view = View::Create(window_manager());
378 window_manager()->GetRoots().front()->AddChild(view);
379 View* nested = View::Create(window_manager());
380 view->AddChild(nested);
Torne (Richard Coles)0de60732014-05-15 12:16:31 +0100381
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100382 ViewManager* embedded = Embed(window_manager(), view);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100383 EXPECT_EQ(embedded->GetRoots().front()->children().front()->id(),
384 nested->id());
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100385 EXPECT_TRUE(embedded->GetRoots().front()->children().empty());
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100386 EXPECT_TRUE(nested->parent() == NULL);
Torne (Richard Coles)0de60732014-05-15 12:16:31 +0100387}
388
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100389// http://crbug.com/396300
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100390TEST_F(ViewManagerTest, DISABLED_ViewManagerDestroyed_CleanupView) {
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100391 View* view = View::Create(window_manager());
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100392 window_manager()->GetRoots().front()->AddChild(view);
393 ViewManager* embedded = Embed(window_manager(), view);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100394
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100395 Id view_id = view->id();
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100396
397 UnloadApplication(GURL(kWindowManagerURL));
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100398
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100399 std::set<Id> views;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100400 views.insert(view_id);
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100401 WaitForDestruction(embedded, &views);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100402
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100403 EXPECT_TRUE(embedded->GetRoots().empty());
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100404}
405
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100406// TODO(beng): write a replacement test for the one that once existed here:
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100407// This test validates the following scenario:
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100408// - a view originating from one connection
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100409// - a view originating from a second connection
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100410// + the connection originating the view is destroyed
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100411// -> the view should still exist (since the second connection is live) but
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100412// should be disconnected from any views.
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100413// http://crbug.com/396300
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100414//
415// TODO(beng): The new test should validate the scenario as described above
416// except that the second connection still has a valid tree.
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100417
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100418// Verifies that bounds changes applied to a view hierarchy in one connection
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100419// are reflected to another.
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100420TEST_F(ViewManagerTest, SetBounds) {
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100421 View* view = View::Create(window_manager());
422 window_manager()->GetRoots().front()->AddChild(view);
423 ViewManager* embedded = Embed(window_manager(), view);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100424
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100425 View* view_in_embedded = embedded->GetViewById(view->id());
426 EXPECT_EQ(view->bounds(), view_in_embedded->bounds());
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100427
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100428 view->SetBounds(gfx::Rect(100, 100));
429 EXPECT_NE(view->bounds(), view_in_embedded->bounds());
430 WaitForBoundsToChange(view_in_embedded);
431 EXPECT_EQ(view->bounds(), view_in_embedded->bounds());
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100432}
433
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100434// Verifies that bounds changes applied to a view owned by a different
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100435// connection are refused.
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100436TEST_F(ViewManagerTest, SetBoundsSecurity) {
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100437 View* view = View::Create(window_manager());
438 window_manager()->GetRoots().front()->AddChild(view);
439 ViewManager* embedded = Embed(window_manager(), view);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100440
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100441 View* view_in_embedded = embedded->GetViewById(view->id());
442 view->SetBounds(gfx::Rect(800, 600));
443 WaitForBoundsToChange(view_in_embedded);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100444
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100445 view_in_embedded->SetBounds(gfx::Rect(1024, 768));
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100446 // Bounds change should have been rejected.
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100447 EXPECT_EQ(view->bounds(), view_in_embedded->bounds());
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100448}
449
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100450// Verifies that a view can only be destroyed by the connection that created it.
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100451TEST_F(ViewManagerTest, DestroySecurity) {
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100452 View* view = View::Create(window_manager());
453 window_manager()->GetRoots().front()->AddChild(view);
454 ViewManager* embedded = Embed(window_manager(), view);
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100455
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100456 View* view_in_embedded = embedded->GetViewById(view->id());
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100457
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100458 ViewTracker tracker2(view_in_embedded);
459 view_in_embedded->Destroy();
460 // View should not have been destroyed.
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100461 EXPECT_TRUE(tracker2.is_valid());
462
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100463 ViewTracker tracker1(view);
464 view->Destroy();
Torne (Richard Coles)cedac222014-06-03 10:58:34 +0100465 EXPECT_FALSE(tracker1.is_valid());
466}
467
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100468TEST_F(ViewManagerTest, MultiRoots) {
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100469 View* view1 = View::Create(window_manager());
470 window_manager()->GetRoots().front()->AddChild(view1);
471 View* view2 = View::Create(window_manager());
472 window_manager()->GetRoots().front()->AddChild(view2);
473 ViewManager* embedded1 = Embed(window_manager(), view1);
474 ViewManager* embedded2 = Embed(window_manager(), view2);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100475 EXPECT_EQ(embedded1, embedded2);
476}
477
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100478TEST_F(ViewManagerTest, EmbeddingIdentity) {
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100479 View* view = View::Create(window_manager());
480 window_manager()->GetRoots().front()->AddChild(view);
481 ViewManager* embedded = Embed(window_manager(), view);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100482 EXPECT_EQ(kWindowManagerURL, embedded->GetEmbedderURL());
483}
484
485TEST_F(ViewManagerTest, Reorder) {
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100486 View* view1 = View::Create(window_manager());
487 window_manager()->GetRoots().front()->AddChild(view1);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100488
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100489 ViewManager* embedded = Embed(window_manager(), view1);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100490
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100491 View* view11 = View::Create(embedded);
492 embedded->GetRoots().front()->AddChild(view11);
493 View* view12 = View::Create(embedded);
494 embedded->GetRoots().front()->AddChild(view12);
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100495
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100496 View* view1_in_wm = window_manager()->GetViewById(view1->id());
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100497
498 {
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100499 WaitForTreeSizeToMatch(view1, 2u);
500 view11->MoveToFront();
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100501 WaitForOrderChange(window_manager(),
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100502 window_manager()->GetViewById(view11->id()));
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100503
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100504 EXPECT_EQ(view1_in_wm->children().front(),
505 window_manager()->GetViewById(view12->id()));
506 EXPECT_EQ(view1_in_wm->children().back(),
507 window_manager()->GetViewById(view11->id()));
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100508 }
509
510 {
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100511 view11->MoveToBack();
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100512 WaitForOrderChange(window_manager(),
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100513 window_manager()->GetViewById(view11->id()));
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100514
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100515 EXPECT_EQ(view1_in_wm->children().front(),
516 window_manager()->GetViewById(view11->id()));
517 EXPECT_EQ(view1_in_wm->children().back(),
518 window_manager()->GetViewById(view12->id()));
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100519 }
520}
521
Ben Murdoch116680a2014-07-20 18:25:52 -0700522// TODO(beng): tests for view event dispatcher.
523// - verify that we see events for all views.
524
525// TODO(beng): tests for focus:
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +0100526// - focus between two views known to a connection
527// - focus between views unknown to one of the connections.
528// - focus between views unknown to either connection.
Ben Murdoch116680a2014-07-20 18:25:52 -0700529
Torne (Richard Coles)010d83a2014-05-14 12:12:37 +0100530} // namespace mojo