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.
6 #include "base/memory/scoped_vector.h"
7 #include "mojo/application_manager/application_manager.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/service_provider_impl.h"
11 #include "mojo/public/interfaces/application/service_provider.mojom.h"
12 #include "mojo/services/public/cpp/view_manager/types.h"
13 #include "mojo/services/public/cpp/view_manager/view.h"
14 #include "mojo/services/public/cpp/view_manager/view_manager.h"
15 #include "mojo/services/public/cpp/view_manager/view_manager_client_factory.h"
16 #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
17 #include "mojo/services/public/interfaces/view_manager/view_manager.mojom.h"
18 #include "mojo/services/public/interfaces/window_manager/window_manager.mojom.h"
19 #include "mojo/shell/shell_test_helper.h"
20 #include "testing/gtest/include/gtest/gtest.h"
25 const char kTestServiceURL[] = "mojo:test_url";
27 void EmptyResultCallback(bool result) {}
29 // Callback from Embed(). |result| is the result of the Embed() call and
30 // |run_loop| the nested RunLoop.
31 void ResultCallback(bool* result_cache, base::RunLoop* run_loop, bool result) {
32 *result_cache = result;
36 // Responsible for establishing the initial ViewManagerService connection.
37 // Blocks until result is determined.
38 bool InitEmbed(ViewManagerInitService* view_manager_init,
39 const std::string& url) {
41 base::RunLoop run_loop;
42 ServiceProviderPtr sp;
43 BindToProxy(new ServiceProviderImpl, &sp);
44 view_manager_init->Embed(url, sp.Pass(),
45 base::Bind(&ResultCallback, &result, &run_loop));
50 class TestWindowManagerClient : public WindowManagerClient {
52 typedef base::Callback<void(Id, Id)>
55 explicit TestWindowManagerClient(base::RunLoop* run_loop)
56 : run_loop_(run_loop) {}
57 virtual ~TestWindowManagerClient() {}
59 void set_focus_changed_callback(const TwoNodeCallback& callback) {
60 focus_changed_callback_ = callback;
62 void set_active_window_changed_callback(const TwoNodeCallback& callback) {
63 active_window_changed_callback_ = callback;
67 // Overridden from WindowManagerClient:
68 virtual void OnWindowManagerReady() MOJO_OVERRIDE {
71 virtual void OnCaptureChanged(
72 Id old_capture_node_id,
73 Id new_capture_node_id) MOJO_OVERRIDE {
75 virtual void OnFocusChanged(
76 Id old_focused_node_id,
77 Id new_focused_node_id) MOJO_OVERRIDE {
78 if (!focus_changed_callback_.is_null())
79 focus_changed_callback_.Run(old_focused_node_id, new_focused_node_id);
81 virtual void OnActiveWindowChanged(
83 Id new_active_window) MOJO_OVERRIDE {
84 if (!active_window_changed_callback_.is_null())
85 active_window_changed_callback_.Run(old_active_window, new_active_window);
88 base::RunLoop* run_loop_;
89 TwoNodeCallback focus_changed_callback_;
90 TwoNodeCallback active_window_changed_callback_;
92 DISALLOW_COPY_AND_ASSIGN(TestWindowManagerClient);
95 class TestApplicationLoader : public ApplicationLoader,
96 public ApplicationDelegate,
97 public ViewManagerDelegate {
99 typedef base::Callback<void(View*)> RootAddedCallback;
101 explicit TestApplicationLoader(const RootAddedCallback& root_added_callback)
102 : root_added_callback_(root_added_callback) {}
103 virtual ~TestApplicationLoader() {}
106 // Overridden from ApplicationLoader:
107 virtual void Load(ApplicationManager* application_manager,
109 scoped_refptr<LoadCallbacks> callbacks) MOJO_OVERRIDE {
110 ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication();
111 if (!shell_handle.is_valid())
113 scoped_ptr<ApplicationImpl> app(
114 new ApplicationImpl(this, shell_handle.Pass()));
115 apps_.push_back(app.release());
117 virtual void OnApplicationError(ApplicationManager* application_manager,
118 const GURL& url) MOJO_OVERRIDE {}
120 // Overridden from ApplicationDelegate:
121 virtual void Initialize(ApplicationImpl* app) MOJO_OVERRIDE {
122 view_manager_client_factory_.reset(
123 new ViewManagerClientFactory(app->shell(), this));
126 virtual bool ConfigureIncomingConnection(
127 ApplicationConnection* connection) MOJO_OVERRIDE {
128 connection->AddService(view_manager_client_factory_.get());
132 // Overridden from ViewManagerDelegate:
133 virtual void OnEmbed(
134 ViewManager* view_manager,
136 ServiceProviderImpl* exported_services,
137 scoped_ptr<ServiceProvider> imported_services) MOJO_OVERRIDE {
138 root_added_callback_.Run(root);
140 virtual void OnViewManagerDisconnected(
141 ViewManager* view_manager) MOJO_OVERRIDE {
144 RootAddedCallback root_added_callback_;
146 ScopedVector<ApplicationImpl> apps_;
147 scoped_ptr<ViewManagerClientFactory> view_manager_client_factory_;
149 DISALLOW_COPY_AND_ASSIGN(TestApplicationLoader);
154 class WindowManagerApiTest : public testing::Test {
156 WindowManagerApiTest() {}
157 virtual ~WindowManagerApiTest() {}
160 typedef std::pair<Id, Id> TwoIds;
164 base::RunLoop run_loop;
165 root_added_callback_ = base::Bind(&WindowManagerApiTest::OnEmbed,
166 base::Unretained(this), &id, &run_loop);
171 TwoIds WaitForFocusChange() {
173 base::RunLoop run_loop;
174 window_manager_client()->set_focus_changed_callback(
175 base::Bind(&WindowManagerApiTest::OnFocusChanged,
176 base::Unretained(this), &old_and_new, &run_loop));
181 TwoIds WaitForActiveWindowChange() {
183 base::RunLoop run_loop;
184 window_manager_client()->set_active_window_changed_callback(
185 base::Bind(&WindowManagerApiTest::OnActiveWindowChanged,
186 base::Unretained(this), &old_and_new, &run_loop));
192 return OpenWindowWithURL(kTestServiceURL);
195 Id OpenWindowWithURL(const std::string& url) {
196 InitEmbed(view_manager_init_.get(), url);
197 return WaitForEmbed();
200 TestWindowManagerClient* window_manager_client() {
201 return window_manager_client_.get();
204 WindowManagerServicePtr window_manager_;
207 // Overridden from testing::Test:
208 virtual void SetUp() MOJO_OVERRIDE {
210 test_helper_.SetLoaderForURL(
211 scoped_ptr<ApplicationLoader>(new TestApplicationLoader(base::Bind(
212 &WindowManagerApiTest::OnRootAdded, base::Unretained(this)))),
213 GURL(kTestServiceURL));
214 test_helper_.application_manager()->ConnectToService(
215 GURL("mojo:mojo_view_manager"), &view_manager_init_);
216 ASSERT_TRUE(InitEmbed(view_manager_init_.get(),
217 "mojo:mojo_core_window_manager"));
218 ConnectToWindowManager();
220 virtual void TearDown() MOJO_OVERRIDE {}
222 void ConnectToWindowManager() {
223 test_helper_.application_manager()->ConnectToService(
224 GURL("mojo:mojo_core_window_manager"), &window_manager_);
225 base::RunLoop connect_loop;
226 window_manager_client_.reset(new TestWindowManagerClient(&connect_loop));
227 window_manager_.set_client(window_manager_client());
231 void OnRootAdded(View* root) {
232 if (!root_added_callback_.is_null())
233 root_added_callback_.Run(root);
236 void OnEmbed(Id* root_id,
239 *root_id = root->id();
243 void OnFocusChanged(TwoIds* old_and_new,
244 base::RunLoop* run_loop,
245 Id old_focused_node_id,
246 Id new_focused_node_id) {
248 old_and_new->first = old_focused_node_id;
249 old_and_new->second = new_focused_node_id;
253 void OnActiveWindowChanged(TwoIds* old_and_new,
254 base::RunLoop* run_loop,
255 Id old_focused_node_id,
256 Id new_focused_node_id) {
258 old_and_new->first = old_focused_node_id;
259 old_and_new->second = new_focused_node_id;
263 shell::ShellTestHelper test_helper_;
264 ViewManagerInitServicePtr view_manager_init_;
265 scoped_ptr<TestWindowManagerClient> window_manager_client_;
266 TestApplicationLoader::RootAddedCallback root_added_callback_;
268 DISALLOW_COPY_AND_ASSIGN(WindowManagerApiTest);
271 TEST_F(WindowManagerApiTest, FocusAndActivateWindow) {
272 Id first_window = OpenWindow();
273 window_manager_->FocusWindow(first_window,
274 base::Bind(&EmptyResultCallback));
275 TwoIds ids = WaitForFocusChange();
276 EXPECT_TRUE(ids.first == 0);
277 EXPECT_EQ(ids.second, first_window);
279 Id second_window = OpenWindow();
280 window_manager_->ActivateWindow(second_window,
281 base::Bind(&EmptyResultCallback));
282 ids = WaitForActiveWindowChange();
283 EXPECT_EQ(ids.first, first_window);
284 EXPECT_EQ(ids.second, second_window);