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.
5 #include "mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.h"
8 #include "base/command_line.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/stl_util.h"
11 #include "mojo/public/cpp/application/application_connection.h"
12 #include "mojo/public/cpp/application/connect.h"
13 #include "mojo/public/cpp/application/service_provider_impl.h"
14 #include "mojo/public/interfaces/application/service_provider.mojom.h"
15 #include "mojo/services/public/cpp/view_manager/lib/view_private.h"
16 #include "mojo/services/public/cpp/view_manager/util.h"
17 #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
18 #include "mojo/services/public/cpp/view_manager/view_observer.h"
19 #include "mojo/services/public/cpp/view_manager/window_manager_delegate.h"
20 #include "third_party/skia/include/core/SkBitmap.h"
21 #include "ui/gfx/codec/png_codec.h"
25 Id
MakeTransportId(ConnectionSpecificId connection_id
,
26 ConnectionSpecificId local_id
) {
27 return (connection_id
<< 16) | local_id
;
30 // Helper called to construct a local view object from transport data.
31 View
* AddViewToViewManager(ViewManagerClientImpl
* client
,
34 const gfx::Rect
& bounds
) {
35 // We don't use the ctor that takes a ViewManager here, since it will call
36 // back to the service and attempt to create a new view.
37 View
* view
= ViewPrivate::LocalCreate();
38 ViewPrivate
private_view(view
);
39 private_view
.set_view_manager(client
);
40 private_view
.set_id(view_id
);
41 client
->AddView(view
);
42 private_view
.LocalSetBounds(gfx::Rect(), bounds
);
44 ViewPrivate(parent
).LocalAddChild(view
);
48 View
* BuildViewTree(ViewManagerClientImpl
* client
,
49 const Array
<ViewDataPtr
>& views
,
50 View
* initial_parent
) {
51 std::vector
<View
*> parents
;
53 View
* last_view
= NULL
;
55 parents
.push_back(initial_parent
);
56 for (size_t i
= 0; i
< views
.size(); ++i
) {
57 if (last_view
&& views
[i
]->parent_id
== last_view
->id()) {
58 parents
.push_back(last_view
);
59 } else if (!parents
.empty()) {
60 while (parents
.back()->id() != views
[i
]->parent_id
)
63 View
* view
= AddViewToViewManager(
65 !parents
.empty() ? parents
.back() : NULL
,
67 views
[i
]->bounds
.To
<gfx::Rect
>());
75 // Responsible for removing a root from the ViewManager when that view is
77 class RootObserver
: public ViewObserver
{
79 explicit RootObserver(View
* root
) : root_(root
) {}
80 virtual ~RootObserver() {}
83 // Overridden from ViewObserver:
84 virtual void OnViewDestroyed(View
* view
) OVERRIDE
{
85 DCHECK_EQ(view
, root_
);
86 static_cast<ViewManagerClientImpl
*>(
87 ViewPrivate(root_
).view_manager())->RemoveRoot(root_
);
88 view
->RemoveObserver(this);
94 DISALLOW_COPY_AND_ASSIGN(RootObserver
);
97 bool CreateMapAndDupSharedBuffer(size_t size
,
99 ScopedSharedBufferHandle
* handle
,
100 ScopedSharedBufferHandle
* duped
) {
101 MojoResult result
= CreateSharedBuffer(NULL
, size
, handle
);
102 if (result
!= MOJO_RESULT_OK
)
104 DCHECK(handle
->is_valid());
106 result
= DuplicateBuffer(handle
->get(), NULL
, duped
);
107 if (result
!= MOJO_RESULT_OK
)
109 DCHECK(duped
->is_valid());
112 handle
->get(), 0, size
, memory
, MOJO_MAP_BUFFER_FLAG_NONE
);
113 if (result
!= MOJO_RESULT_OK
)
120 ViewManagerClientImpl::ViewManagerClientImpl(
121 ViewManagerDelegate
* delegate
,
122 ApplicationConnection
* app_connection
)
127 window_manager_delegate_(NULL
) {
128 // TODO(beng): Come up with a better way of establishing a configuration for
129 // what the active window manager is.
130 std::string window_manager_url
= "mojo:mojo_window_manager";
131 if (base::CommandLine::ForCurrentProcess()->HasSwitch("window-manager")) {
133 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
136 app_connection
->ConnectToService(window_manager_url
, &window_manager_
);
137 window_manager_
.set_client(this);
140 ViewManagerClientImpl::~ViewManagerClientImpl() {
141 std::vector
<View
*> non_owned
;
142 while (!views_
.empty()) {
143 IdToViewMap::iterator it
= views_
.begin();
144 if (OwnsView(it
->second
->id())) {
145 it
->second
->Destroy();
147 non_owned
.push_back(it
->second
);
151 // Delete the non-owned views last. In the typical case these are roots. The
152 // exception is the window manager, which may know aboutother random views
153 // that it doesn't own.
154 // NOTE: we manually delete as we're a friend.
155 for (size_t i
= 0; i
< non_owned
.size(); ++i
)
157 delegate_
->OnViewManagerDisconnected(this);
160 Id
ViewManagerClientImpl::CreateView() {
162 const Id view_id
= MakeTransportId(connection_id_
, ++next_id_
);
163 service_
->CreateView(view_id
, ActionCompletedCallbackWithErrorCode());
167 void ViewManagerClientImpl::DestroyView(Id view_id
) {
169 service_
->DeleteView(view_id
, ActionCompletedCallback());
172 void ViewManagerClientImpl::AddChild(Id child_id
, Id parent_id
) {
174 service_
->AddView(parent_id
, child_id
, ActionCompletedCallback());
177 void ViewManagerClientImpl::RemoveChild(Id child_id
, Id parent_id
) {
179 service_
->RemoveViewFromParent(child_id
, ActionCompletedCallback());
182 void ViewManagerClientImpl::Reorder(
185 OrderDirection direction
) {
187 service_
->ReorderView(view_id
, relative_view_id
, direction
,
188 ActionCompletedCallback());
191 bool ViewManagerClientImpl::OwnsView(Id id
) const {
192 return HiWord(id
) == connection_id_
;
195 void ViewManagerClientImpl::SetBounds(Id view_id
, const gfx::Rect
& bounds
) {
197 service_
->SetViewBounds(view_id
, Rect::From(bounds
),
198 ActionCompletedCallback());
201 void ViewManagerClientImpl::SetViewContents(Id view_id
,
202 const SkBitmap
& contents
) {
204 std::vector
<unsigned char> data
;
205 gfx::PNGCodec::EncodeBGRASkBitmap(contents
, false, &data
);
208 ScopedSharedBufferHandle duped
, shared_state_handle
;
209 bool result
= CreateMapAndDupSharedBuffer(data
.size(),
211 &shared_state_handle
,
216 memcpy(memory
, &data
[0], data
.size());
218 service_
->SetViewContents(view_id
, duped
.Pass(),
219 static_cast<uint32_t>(data
.size()),
220 ActionCompletedCallback());
223 void ViewManagerClientImpl::SetFocus(Id view_id
) {
224 window_manager_
->FocusWindow(view_id
, ActionCompletedCallback());
227 void ViewManagerClientImpl::SetVisible(Id view_id
, bool visible
) {
229 service_
->SetViewVisibility(view_id
, visible
, ActionCompletedCallback());
232 void ViewManagerClientImpl::Embed(const String
& url
, Id view_id
) {
233 ServiceProviderPtr sp
;
234 BindToProxy(new ServiceProviderImpl
, &sp
);
235 Embed(url
, view_id
, sp
.Pass());
238 void ViewManagerClientImpl::Embed(
241 ServiceProviderPtr service_provider
) {
243 service_
->Embed(url
, view_id
, service_provider
.Pass(),
244 ActionCompletedCallback());
247 void ViewManagerClientImpl::AddView(View
* view
) {
248 DCHECK(views_
.find(view
->id()) == views_
.end());
249 views_
[view
->id()] = view
;
252 void ViewManagerClientImpl::RemoveView(Id view_id
) {
253 IdToViewMap::iterator it
= views_
.find(view_id
);
254 if (it
!= views_
.end())
258 ////////////////////////////////////////////////////////////////////////////////
259 // ViewManagerClientImpl, ViewManager implementation:
261 void ViewManagerClientImpl::SetWindowManagerDelegate(
262 WindowManagerDelegate
* window_manager_delegate
) {
263 CHECK(NULL
!= GetViewById(1));
264 CHECK(!window_manager_delegate_
);
265 window_manager_delegate_
= window_manager_delegate
;
268 void ViewManagerClientImpl::DispatchEvent(View
* target
, EventPtr event
) {
269 CHECK(window_manager_delegate_
);
270 service_
->DispatchOnViewInputEvent(target
->id(), event
.Pass());
273 const std::string
& ViewManagerClientImpl::GetEmbedderURL() const {
277 const std::vector
<View
*>& ViewManagerClientImpl::GetRoots() const {
281 View
* ViewManagerClientImpl::GetViewById(Id id
) {
282 IdToViewMap::const_iterator it
= views_
.find(id
);
283 return it
!= views_
.end() ? it
->second
: NULL
;
286 ////////////////////////////////////////////////////////////////////////////////
287 // ViewManagerClientImpl, InterfaceImpl overrides:
289 void ViewManagerClientImpl::OnConnectionEstablished() {
293 ////////////////////////////////////////////////////////////////////////////////
294 // ViewManagerClientImpl, ViewManagerClient implementation:
296 void ViewManagerClientImpl::OnEmbed(
297 ConnectionSpecificId connection_id
,
298 const String
& creator_url
,
299 ViewDataPtr root_data
,
300 InterfaceRequest
<ServiceProvider
> service_provider
) {
303 connection_id_
= connection_id
;
304 creator_url_
= TypeConverter
<String
, std::string
>::ConvertFrom(creator_url
);
306 DCHECK_EQ(connection_id_
, connection_id
);
307 DCHECK_EQ(creator_url_
, creator_url
);
310 // A new root must not already exist as a root or be contained by an existing
311 // hierarchy visible to this view manager.
312 View
* root
= AddViewToViewManager(this, NULL
, root_data
->view_id
,
313 root_data
->bounds
.To
<gfx::Rect
>());
314 roots_
.push_back(root
);
315 root
->AddObserver(new RootObserver(root
));
317 // BindToRequest() binds the lifetime of |exported_services| to the pipe.
318 ServiceProviderImpl
* exported_services
= new ServiceProviderImpl
;
319 BindToRequest(exported_services
, &service_provider
);
320 scoped_ptr
<ServiceProvider
> remote(
321 exported_services
->CreateRemoteServiceProvider());
322 delegate_
->OnEmbed(this, root
, exported_services
, remote
.Pass());
325 void ViewManagerClientImpl::OnViewBoundsChanged(Id view_id
,
327 RectPtr new_bounds
) {
328 View
* view
= GetViewById(view_id
);
329 ViewPrivate(view
).LocalSetBounds(old_bounds
.To
<gfx::Rect
>(),
330 new_bounds
.To
<gfx::Rect
>());
333 void ViewManagerClientImpl::OnViewHierarchyChanged(
337 mojo::Array
<ViewDataPtr
> views
) {
338 View
* initial_parent
= views
.size() ?
339 GetViewById(views
[0]->parent_id
) : NULL
;
341 BuildViewTree(this, views
, initial_parent
);
343 View
* new_parent
= GetViewById(new_parent_id
);
344 View
* old_parent
= GetViewById(old_parent_id
);
345 View
* view
= GetViewById(view_id
);
347 ViewPrivate(new_parent
).LocalAddChild(view
);
349 ViewPrivate(old_parent
).LocalRemoveChild(view
);
352 void ViewManagerClientImpl::OnViewReordered(Id view_id
,
354 OrderDirection direction
) {
355 View
* view
= GetViewById(view_id
);
356 View
* relative_view
= GetViewById(relative_view_id
);
357 if (view
&& relative_view
)
358 ViewPrivate(view
).LocalReorder(relative_view
, direction
);
361 void ViewManagerClientImpl::OnViewDeleted(Id view_id
) {
362 View
* view
= GetViewById(view_id
);
364 ViewPrivate(view
).LocalDestroy();
367 void ViewManagerClientImpl::OnViewInputEvent(
370 const Callback
<void()>& ack_callback
) {
371 View
* view
= GetViewById(view_id
);
373 FOR_EACH_OBSERVER(ViewObserver
,
374 *ViewPrivate(view
).observers(),
375 OnViewInputEvent(view
, event
));
380 void ViewManagerClientImpl::Embed(
382 InterfaceRequest
<ServiceProvider
> service_provider
) {
383 window_manager_delegate_
->Embed(url
, service_provider
.Pass());
386 void ViewManagerClientImpl::DispatchOnViewInputEvent(EventPtr event
) {
387 if (window_manager_delegate_
)
388 window_manager_delegate_
->DispatchEvent(event
.Pass());
391 ////////////////////////////////////////////////////////////////////////////////
392 // ViewManagerClientImpl, WindowManagerClient implementation:
394 void ViewManagerClientImpl::OnWindowManagerReady() {}
396 void ViewManagerClientImpl::OnCaptureChanged(Id old_capture_view_id
,
397 Id new_capture_view_id
) {}
399 void ViewManagerClientImpl::OnFocusChanged(Id old_focused_view_id
,
400 Id new_focused_view_id
) {
401 View
* focused
= GetViewById(new_focused_view_id
);
402 View
* blurred
= GetViewById(old_focused_view_id
);
404 FOR_EACH_OBSERVER(ViewObserver
,
405 *ViewPrivate(blurred
).observers(),
406 OnViewFocusChanged(focused
, blurred
));
409 FOR_EACH_OBSERVER(ViewObserver
,
410 *ViewPrivate(focused
).observers(),
411 OnViewFocusChanged(focused
, blurred
));
415 void ViewManagerClientImpl::OnActiveWindowChanged(Id old_focused_window
,
416 Id new_focused_window
) {}
418 ////////////////////////////////////////////////////////////////////////////////
419 // ViewManagerClientImpl, private:
421 void ViewManagerClientImpl::RemoveRoot(View
* root
) {
422 std::vector
<View
*>::iterator it
=
423 std::find(roots_
.begin(), roots_
.end(), root
);
424 if (it
!= roots_
.end())
428 void ViewManagerClientImpl::OnActionCompleted(bool success
) {
429 if (!change_acked_callback_
.is_null())
430 change_acked_callback_
.Run();
433 void ViewManagerClientImpl::OnActionCompletedWithErrorCode(ErrorCode code
) {
434 OnActionCompleted(code
== ERROR_CODE_NONE
);
437 base::Callback
<void(bool)> ViewManagerClientImpl::ActionCompletedCallback() {
438 return base::Bind(&ViewManagerClientImpl::OnActionCompleted
,
439 base::Unretained(this));
442 base::Callback
<void(ErrorCode
)>
443 ViewManagerClientImpl::ActionCompletedCallbackWithErrorCode() {
444 return base::Bind(&ViewManagerClientImpl::OnActionCompletedWithErrorCode
,
445 base::Unretained(this));