Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / mojo / services / public / cpp / view_manager / lib / view_manager_client_impl.cc
blobec4ec6125e49e64a32221d8882b6c50eecc8f67a
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"
7 #include "base/bind.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"
23 namespace mojo {
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,
32 View* parent,
33 Id view_id,
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);
43 if (parent)
44 ViewPrivate(parent).LocalAddChild(view);
45 return view;
48 View* BuildViewTree(ViewManagerClientImpl* client,
49 const Array<ViewDataPtr>& views,
50 View* initial_parent) {
51 std::vector<View*> parents;
52 View* root = NULL;
53 View* last_view = NULL;
54 if (initial_parent)
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)
61 parents.pop_back();
63 View* view = AddViewToViewManager(
64 client,
65 !parents.empty() ? parents.back() : NULL,
66 views[i]->view_id,
67 views[i]->bounds.To<gfx::Rect>());
68 if (!last_view)
69 root = view;
70 last_view = view;
72 return root;
75 // Responsible for removing a root from the ViewManager when that view is
76 // destroyed.
77 class RootObserver : public ViewObserver {
78 public:
79 explicit RootObserver(View* root) : root_(root) {}
80 virtual ~RootObserver() {}
82 private:
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);
89 delete this;
92 View* root_;
94 DISALLOW_COPY_AND_ASSIGN(RootObserver);
97 bool CreateMapAndDupSharedBuffer(size_t size,
98 void** memory,
99 ScopedSharedBufferHandle* handle,
100 ScopedSharedBufferHandle* duped) {
101 MojoResult result = CreateSharedBuffer(NULL, size, handle);
102 if (result != MOJO_RESULT_OK)
103 return false;
104 DCHECK(handle->is_valid());
106 result = DuplicateBuffer(handle->get(), NULL, duped);
107 if (result != MOJO_RESULT_OK)
108 return false;
109 DCHECK(duped->is_valid());
111 result = MapBuffer(
112 handle->get(), 0, size, memory, MOJO_MAP_BUFFER_FLAG_NONE);
113 if (result != MOJO_RESULT_OK)
114 return false;
115 DCHECK(*memory);
117 return true;
120 ViewManagerClientImpl::ViewManagerClientImpl(
121 ViewManagerDelegate* delegate,
122 ApplicationConnection* app_connection)
123 : connected_(false),
124 connection_id_(0),
125 next_id_(1),
126 delegate_(delegate),
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")) {
132 window_manager_url =
133 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
134 "window-manager");
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();
146 } else {
147 non_owned.push_back(it->second);
148 views_.erase(it);
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)
156 delete non_owned[i];
157 delegate_->OnViewManagerDisconnected(this);
160 Id ViewManagerClientImpl::CreateView() {
161 DCHECK(connected_);
162 const Id view_id = MakeTransportId(connection_id_, ++next_id_);
163 service_->CreateView(view_id, ActionCompletedCallbackWithErrorCode());
164 return view_id;
167 void ViewManagerClientImpl::DestroyView(Id view_id) {
168 DCHECK(connected_);
169 service_->DeleteView(view_id, ActionCompletedCallback());
172 void ViewManagerClientImpl::AddChild(Id child_id, Id parent_id) {
173 DCHECK(connected_);
174 service_->AddView(parent_id, child_id, ActionCompletedCallback());
177 void ViewManagerClientImpl::RemoveChild(Id child_id, Id parent_id) {
178 DCHECK(connected_);
179 service_->RemoveViewFromParent(child_id, ActionCompletedCallback());
182 void ViewManagerClientImpl::Reorder(
183 Id view_id,
184 Id relative_view_id,
185 OrderDirection direction) {
186 DCHECK(connected_);
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) {
196 DCHECK(connected_);
197 service_->SetViewBounds(view_id, Rect::From(bounds),
198 ActionCompletedCallback());
201 void ViewManagerClientImpl::SetViewContents(Id view_id,
202 const SkBitmap& contents) {
203 DCHECK(connected_);
204 std::vector<unsigned char> data;
205 gfx::PNGCodec::EncodeBGRASkBitmap(contents, false, &data);
207 void* memory = NULL;
208 ScopedSharedBufferHandle duped, shared_state_handle;
209 bool result = CreateMapAndDupSharedBuffer(data.size(),
210 &memory,
211 &shared_state_handle,
212 &duped);
213 if (!result)
214 return;
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) {
228 DCHECK(connected_);
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(
239 const String& url,
240 Id view_id,
241 ServiceProviderPtr service_provider) {
242 DCHECK(connected_);
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())
255 views_.erase(it);
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 {
274 return creator_url_;
277 const std::vector<View*>& ViewManagerClientImpl::GetRoots() const {
278 return roots_;
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() {
290 service_ = client();
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) {
301 if (!connected_) {
302 connected_ = true;
303 connection_id_ = connection_id;
304 creator_url_ = TypeConverter<String, std::string>::ConvertFrom(creator_url);
305 } else {
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,
326 RectPtr old_bounds,
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(
334 Id view_id,
335 Id new_parent_id,
336 Id old_parent_id,
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);
346 if (new_parent)
347 ViewPrivate(new_parent).LocalAddChild(view);
348 else
349 ViewPrivate(old_parent).LocalRemoveChild(view);
352 void ViewManagerClientImpl::OnViewReordered(Id view_id,
353 Id relative_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);
363 if (view)
364 ViewPrivate(view).LocalDestroy();
367 void ViewManagerClientImpl::OnViewInputEvent(
368 Id view_id,
369 EventPtr event,
370 const Callback<void()>& ack_callback) {
371 View* view = GetViewById(view_id);
372 if (view) {
373 FOR_EACH_OBSERVER(ViewObserver,
374 *ViewPrivate(view).observers(),
375 OnViewInputEvent(view, event));
377 ack_callback.Run();
380 void ViewManagerClientImpl::Embed(
381 const String& url,
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);
403 if (blurred) {
404 FOR_EACH_OBSERVER(ViewObserver,
405 *ViewPrivate(blurred).observers(),
406 OnViewFocusChanged(focused, blurred));
408 if (focused) {
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())
425 roots_.erase(it);
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));
448 } // namespace mojo