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
);