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. 4 5 #include "mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.h" 6 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_impl.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/public/interfaces/application/shell.mojom.h" 16 #include "mojo/services/public/cpp/view_manager/lib/view_private.h" 17 #include "mojo/services/public/cpp/view_manager/util.h" 18 #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h" 19 #include "mojo/services/public/cpp/view_manager/view_observer.h" 20 #include "mojo/services/public/cpp/view_manager/window_manager_delegate.h" 21 #include "third_party/skia/include/core/SkBitmap.h" 22 #include "ui/gfx/codec/png_codec.h" 23 24 namespace mojo { 25 26 Id MakeTransportId(ConnectionSpecificId connection_id, 27 ConnectionSpecificId local_id) { 28 return (connection_id << 16) | local_id; 29 } 30 31 // Helper called to construct a local view object from transport data. 32 View* AddViewToViewManager(ViewManagerClientImpl* client, 33 View* parent, 34 Id view_id, 35 const gfx::Rect& bounds) { 36 // We don't use the ctor that takes a ViewManager here, since it will call 37 // back to the service and attempt to create a new view. 38 View* view = ViewPrivate::LocalCreate(); 39 ViewPrivate private_view(view); 40 private_view.set_view_manager(client); 41 private_view.set_id(view_id); 42 client->AddView(view); 43 private_view.LocalSetBounds(gfx::Rect(), bounds); 44 if (parent) 45 ViewPrivate(parent).LocalAddChild(view); 46 return view; 47 } 48 49 View* BuildViewTree(ViewManagerClientImpl* client, 50 const Array<ViewDataPtr>& views, 51 View* initial_parent) { 52 std::vector<View*> parents; 53 View* root = NULL; 54 View* last_view = NULL; 55 if (initial_parent) 56 parents.push_back(initial_parent); 57 for (size_t i = 0; i < views.size(); ++i) { 58 if (last_view && views[i]->parent_id == last_view->id()) { 59 parents.push_back(last_view); 60 } else if (!parents.empty()) { 61 while (parents.back()->id() != views[i]->parent_id) 62 parents.pop_back(); 63 } 64 View* view = AddViewToViewManager( 65 client, 66 !parents.empty() ? parents.back() : NULL, 67 views[i]->view_id, 68 views[i]->bounds.To<gfx::Rect>()); 69 if (!last_view) 70 root = view; 71 last_view = view; 72 } 73 return root; 74 } 75 76 // Responsible for removing a root from the ViewManager when that view is 77 // destroyed. 78 class RootObserver : public ViewObserver { 79 public: 80 explicit RootObserver(View* root) : root_(root) {} 81 virtual ~RootObserver() {} 82 83 private: 84 // Overridden from ViewObserver: 85 virtual void OnViewDestroyed(View* view) OVERRIDE { 86 DCHECK_EQ(view, root_); 87 static_cast<ViewManagerClientImpl*>( 88 ViewPrivate(root_).view_manager())->RemoveRoot(root_); 89 view->RemoveObserver(this); 90 delete this; 91 } 92 93 View* root_; 94 95 DISALLOW_COPY_AND_ASSIGN(RootObserver); 96 }; 97 98 ViewManagerClientImpl::ViewManagerClientImpl(ViewManagerDelegate* delegate, 99 Shell* shell) 100 : connected_(false), 101 connection_id_(0), 102 next_id_(1), 103 delegate_(delegate), 104 window_manager_delegate_(NULL), 105 shell_(shell) { 106 // TODO(beng): Come up with a better way of establishing a configuration for 107 // what the active window manager is. 108 std::string window_manager_url = "mojo:mojo_window_manager"; 109 if (base::CommandLine::ForCurrentProcess()->HasSwitch("window-manager")) { 110 window_manager_url = 111 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 112 "window-manager"); 113 } 114 InterfacePtr<ServiceProvider> sp; 115 shell->ConnectToApplication(window_manager_url, Get(&sp)); 116 ConnectToService(sp.get(), &window_manager_); 117 window_manager_.set_client(this); 118 } 119 120 ViewManagerClientImpl::~ViewManagerClientImpl() { 121 std::vector<View*> non_owned; 122 while (!views_.empty()) { 123 IdToViewMap::iterator it = views_.begin(); 124 if (OwnsView(it->second->id())) { 125 it->second->Destroy(); 126 } else { 127 non_owned.push_back(it->second); 128 views_.erase(it); 129 } 130 } 131 // Delete the non-owned views last. In the typical case these are roots. The 132 // exception is the window manager, which may know aboutother random views 133 // that it doesn't own. 134 // NOTE: we manually delete as we're a friend. 135 for (size_t i = 0; i < non_owned.size(); ++i) 136 delete non_owned[i]; 137 138 delegate_->OnViewManagerDisconnected(this); 139 } 140 141 Id ViewManagerClientImpl::CreateView() { 142 DCHECK(connected_); 143 const Id view_id = MakeTransportId(connection_id_, ++next_id_); 144 service_->CreateView(view_id, ActionCompletedCallbackWithErrorCode()); 145 return view_id; 146 } 147 148 void ViewManagerClientImpl::DestroyView(Id view_id) { 149 DCHECK(connected_); 150 service_->DeleteView(view_id, ActionCompletedCallback()); 151 } 152 153 void ViewManagerClientImpl::AddChild(Id child_id, Id parent_id) { 154 DCHECK(connected_); 155 service_->AddView(parent_id, child_id, ActionCompletedCallback()); 156 } 157 158 void ViewManagerClientImpl::RemoveChild(Id child_id, Id parent_id) { 159 DCHECK(connected_); 160 service_->RemoveViewFromParent(child_id, ActionCompletedCallback()); 161 } 162 163 void ViewManagerClientImpl::Reorder( 164 Id view_id, 165 Id relative_view_id, 166 OrderDirection direction) { 167 DCHECK(connected_); 168 service_->ReorderView(view_id, relative_view_id, direction, 169 ActionCompletedCallback()); 170 } 171 172 bool ViewManagerClientImpl::OwnsView(Id id) const { 173 return HiWord(id) == connection_id_; 174 } 175 176 void ViewManagerClientImpl::SetBounds(Id view_id, const gfx::Rect& bounds) { 177 DCHECK(connected_); 178 service_->SetViewBounds(view_id, Rect::From(bounds), 179 ActionCompletedCallback()); 180 } 181 182 void ViewManagerClientImpl::SetSurfaceId(Id view_id, SurfaceIdPtr surface_id) { 183 DCHECK(connected_); 184 if (surface_id.is_null()) 185 return; 186 service_->SetViewSurfaceId( 187 view_id, surface_id.Pass(), ActionCompletedCallback()); 188 } 189 190 void ViewManagerClientImpl::SetFocus(Id view_id) { 191 window_manager_->FocusWindow(view_id, ActionCompletedCallback()); 192 } 193 194 void ViewManagerClientImpl::SetVisible(Id view_id, bool visible) { 195 DCHECK(connected_); 196 service_->SetViewVisibility(view_id, visible, ActionCompletedCallback()); 197 } 198 199 void ViewManagerClientImpl::Embed(const String& url, Id view_id) { 200 ServiceProviderPtr sp; 201 BindToProxy(new ServiceProviderImpl, &sp); 202 Embed(url, view_id, sp.Pass()); 203 } 204 205 void ViewManagerClientImpl::Embed( 206 const String& url, 207 Id view_id, 208 ServiceProviderPtr service_provider) { 209 DCHECK(connected_); 210 service_->Embed(url, view_id, service_provider.Pass(), 211 ActionCompletedCallback()); 212 } 213 214 void ViewManagerClientImpl::AddView(View* view) { 215 DCHECK(views_.find(view->id()) == views_.end()); 216 views_[view->id()] = view; 217 } 218 219 void ViewManagerClientImpl::RemoveView(Id view_id) { 220 IdToViewMap::iterator it = views_.find(view_id); 221 if (it != views_.end()) 222 views_.erase(it); 223 } 224 225 //////////////////////////////////////////////////////////////////////////////// 226 // ViewManagerClientImpl, ViewManager implementation: 227 228 void ViewManagerClientImpl::SetWindowManagerDelegate( 229 WindowManagerDelegate* window_manager_delegate) { 230 CHECK(NULL != GetViewById(1)); 231 CHECK(!window_manager_delegate_); 232 window_manager_delegate_ = window_manager_delegate; 233 } 234 235 void ViewManagerClientImpl::DispatchEvent(View* target, EventPtr event) { 236 CHECK(window_manager_delegate_); 237 service_->DispatchOnViewInputEvent(target->id(), event.Pass()); 238 } 239 240 const std::string& ViewManagerClientImpl::GetEmbedderURL() const { 241 return creator_url_; 242 } 243 244 const std::vector<View*>& ViewManagerClientImpl::GetRoots() const { 245 return roots_; 246 } 247 248 View* ViewManagerClientImpl::GetViewById(Id id) { 249 IdToViewMap::const_iterator it = views_.find(id); 250 return it != views_.end() ? it->second : NULL; 251 } 252 253 //////////////////////////////////////////////////////////////////////////////// 254 // ViewManagerClientImpl, InterfaceImpl overrides: 255 256 void ViewManagerClientImpl::OnConnectionEstablished() { 257 service_ = client(); 258 } 259 260 //////////////////////////////////////////////////////////////////////////////// 261 // ViewManagerClientImpl, ViewManagerClient implementation: 262 263 void ViewManagerClientImpl::OnEmbed( 264 ConnectionSpecificId connection_id, 265 const String& creator_url, 266 ViewDataPtr root_data, 267 InterfaceRequest<ServiceProvider> service_provider) { 268 if (!connected_) { 269 connected_ = true; 270 connection_id_ = connection_id; 271 creator_url_ = String::From(creator_url); 272 } else { 273 DCHECK_EQ(connection_id_, connection_id); 274 DCHECK_EQ(creator_url_, creator_url); 275 } 276 277 // A new root must not already exist as a root or be contained by an existing 278 // hierarchy visible to this view manager. 279 View* root = AddViewToViewManager(this, NULL, root_data->view_id, 280 root_data->bounds.To<gfx::Rect>()); 281 roots_.push_back(root); 282 root->AddObserver(new RootObserver(root)); 283 284 // BindToRequest() binds the lifetime of |exported_services| to the pipe. 285 ServiceProviderImpl* exported_services = new ServiceProviderImpl; 286 BindToRequest(exported_services, &service_provider); 287 scoped_ptr<ServiceProvider> remote( 288 exported_services->CreateRemoteServiceProvider()); 289 delegate_->OnEmbed(this, root, exported_services, remote.Pass()); 290 } 291 292 void ViewManagerClientImpl::OnViewBoundsChanged(Id view_id, 293 RectPtr old_bounds, 294 RectPtr new_bounds) { 295 View* view = GetViewById(view_id); 296 ViewPrivate(view).LocalSetBounds(old_bounds.To<gfx::Rect>(), 297 new_bounds.To<gfx::Rect>()); 298 } 299 300 void ViewManagerClientImpl::OnViewHierarchyChanged( 301 Id view_id, 302 Id new_parent_id, 303 Id old_parent_id, 304 mojo::Array<ViewDataPtr> views) { 305 View* initial_parent = views.size() ? 306 GetViewById(views[0]->parent_id) : NULL; 307 308 BuildViewTree(this, views, initial_parent); 309 310 View* new_parent = GetViewById(new_parent_id); 311 View* old_parent = GetViewById(old_parent_id); 312 View* view = GetViewById(view_id); 313 if (new_parent) 314 ViewPrivate(new_parent).LocalAddChild(view); 315 else 316 ViewPrivate(old_parent).LocalRemoveChild(view); 317 } 318 319 void ViewManagerClientImpl::OnViewReordered(Id view_id, 320 Id relative_view_id, 321 OrderDirection direction) { 322 View* view = GetViewById(view_id); 323 View* relative_view = GetViewById(relative_view_id); 324 if (view && relative_view) 325 ViewPrivate(view).LocalReorder(relative_view, direction); 326 } 327 328 void ViewManagerClientImpl::OnViewDeleted(Id view_id) { 329 View* view = GetViewById(view_id); 330 if (view) 331 ViewPrivate(view).LocalDestroy(); 332 } 333 334 void ViewManagerClientImpl::OnViewVisibilityChanged(Id view_id, bool visible) { 335 // TODO(sky): implement me. 336 NOTIMPLEMENTED(); 337 } 338 339 void ViewManagerClientImpl::OnViewDrawnStateChanged(Id view_id, bool drawn) { 340 // TODO(sky): implement me. 341 NOTIMPLEMENTED(); 342 } 343 344 void ViewManagerClientImpl::OnViewInputEvent( 345 Id view_id, 346 EventPtr event, 347 const Callback<void()>& ack_callback) { 348 View* view = GetViewById(view_id); 349 if (view) { 350 FOR_EACH_OBSERVER(ViewObserver, 351 *ViewPrivate(view).observers(), 352 OnViewInputEvent(view, event)); 353 } 354 ack_callback.Run(); 355 } 356 357 void ViewManagerClientImpl::Embed( 358 const String& url, 359 InterfaceRequest<ServiceProvider> service_provider) { 360 if (window_manager_delegate_) 361 window_manager_delegate_->Embed(url, service_provider.Pass()); 362 } 363 364 void ViewManagerClientImpl::DispatchOnViewInputEvent(EventPtr event) { 365 if (window_manager_delegate_) 366 window_manager_delegate_->DispatchEvent(event.Pass()); 367 } 368 369 //////////////////////////////////////////////////////////////////////////////// 370 // ViewManagerClientImpl, WindowManagerClient implementation: 371 372 void ViewManagerClientImpl::OnWindowManagerReady() {} 373 374 void ViewManagerClientImpl::OnCaptureChanged(Id old_capture_view_id, 375 Id new_capture_view_id) {} 376 377 void ViewManagerClientImpl::OnFocusChanged(Id old_focused_view_id, 378 Id new_focused_view_id) { 379 View* focused = GetViewById(new_focused_view_id); 380 View* blurred = GetViewById(old_focused_view_id); 381 if (blurred) { 382 FOR_EACH_OBSERVER(ViewObserver, 383 *ViewPrivate(blurred).observers(), 384 OnViewFocusChanged(focused, blurred)); 385 } 386 if (focused) { 387 FOR_EACH_OBSERVER(ViewObserver, 388 *ViewPrivate(focused).observers(), 389 OnViewFocusChanged(focused, blurred)); 390 } 391 } 392 393 void ViewManagerClientImpl::OnActiveWindowChanged(Id old_focused_window, 394 Id new_focused_window) {} 395 396 //////////////////////////////////////////////////////////////////////////////// 397 // ViewManagerClientImpl, private: 398 399 void ViewManagerClientImpl::RemoveRoot(View* root) { 400 std::vector<View*>::iterator it = 401 std::find(roots_.begin(), roots_.end(), root); 402 if (it != roots_.end()) 403 roots_.erase(it); 404 } 405 406 void ViewManagerClientImpl::OnActionCompleted(bool success) { 407 if (!change_acked_callback_.is_null()) 408 change_acked_callback_.Run(); 409 } 410 411 void ViewManagerClientImpl::OnActionCompletedWithErrorCode(ErrorCode code) { 412 OnActionCompleted(code == ERROR_CODE_NONE); 413 } 414 415 base::Callback<void(bool)> ViewManagerClientImpl::ActionCompletedCallback() { 416 return base::Bind(&ViewManagerClientImpl::OnActionCompleted, 417 base::Unretained(this)); 418 } 419 420 base::Callback<void(ErrorCode)> 421 ViewManagerClientImpl::ActionCompletedCallbackWithErrorCode() { 422 return base::Bind(&ViewManagerClientImpl::OnActionCompletedWithErrorCode, 423 base::Unretained(this)); 424 } 425 426 } // namespace mojo 427