| OLD | NEW |
| (Empty) |
| 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 "view_manager/public/cpp/lib/view_manager_client_impl.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/message_loop/message_loop.h" | |
| 9 #include "base/stl_util.h" | |
| 10 #include "mojo/public/cpp/application/application_impl.h" | |
| 11 #include "mojo/public/cpp/application/connect.h" | |
| 12 #include "mojo/public/cpp/application/service_provider_impl.h" | |
| 13 #include "mojo/public/interfaces/application/service_provider.mojom.h" | |
| 14 #include "mojo/public/interfaces/application/shell.mojom.h" | |
| 15 #include "view_manager/public/cpp/lib/view_private.h" | |
| 16 #include "view_manager/public/cpp/util.h" | |
| 17 #include "view_manager/public/cpp/view_manager_delegate.h" | |
| 18 #include "view_manager/public/cpp/view_observer.h" | |
| 19 | |
| 20 namespace mojo { | |
| 21 | |
| 22 Id MakeTransportId(ConnectionSpecificId connection_id, | |
| 23 ConnectionSpecificId local_id) { | |
| 24 return (connection_id << 16) | local_id; | |
| 25 } | |
| 26 | |
| 27 // Helper called to construct a local view object from transport data. | |
| 28 View* AddViewToViewManager(ViewManagerClientImpl* client, | |
| 29 View* parent, | |
| 30 const ViewDataPtr& view_data) { | |
| 31 // We don't use the ctor that takes a ViewManager here, since it will call | |
| 32 // back to the service and attempt to create a new view. | |
| 33 View* view = ViewPrivate::LocalCreate(); | |
| 34 ViewPrivate private_view(view); | |
| 35 private_view.set_view_manager(client); | |
| 36 private_view.set_id(view_data->view_id); | |
| 37 private_view.set_visible(view_data->visible); | |
| 38 private_view.set_drawn(view_data->drawn); | |
| 39 private_view.LocalSetViewportMetrics(ViewportMetrics(), | |
| 40 *view_data->viewport_metrics); | |
| 41 private_view.set_properties( | |
| 42 view_data->properties.To<std::map<std::string, std::vector<uint8_t>>>()); | |
| 43 client->AddView(view); | |
| 44 private_view.LocalSetBounds(Rect(), *view_data->bounds); | |
| 45 if (parent) | |
| 46 ViewPrivate(parent).LocalAddChild(view); | |
| 47 return view; | |
| 48 } | |
| 49 | |
| 50 View* BuildViewTree(ViewManagerClientImpl* client, | |
| 51 const Array<ViewDataPtr>& views, | |
| 52 View* initial_parent) { | |
| 53 std::vector<View*> parents; | |
| 54 View* root = NULL; | |
| 55 View* last_view = NULL; | |
| 56 if (initial_parent) | |
| 57 parents.push_back(initial_parent); | |
| 58 for (size_t i = 0; i < views.size(); ++i) { | |
| 59 if (last_view && views[i]->parent_id == last_view->id()) { | |
| 60 parents.push_back(last_view); | |
| 61 } else if (!parents.empty()) { | |
| 62 while (parents.back()->id() != views[i]->parent_id) | |
| 63 parents.pop_back(); | |
| 64 } | |
| 65 View* view = AddViewToViewManager( | |
| 66 client, !parents.empty() ? parents.back() : NULL, views[i]); | |
| 67 if (!last_view) | |
| 68 root = view; | |
| 69 last_view = view; | |
| 70 } | |
| 71 return root; | |
| 72 } | |
| 73 | |
| 74 // Responsible for removing a root from the ViewManager when that view is | |
| 75 // destroyed. | |
| 76 class RootObserver : public ViewObserver { | |
| 77 public: | |
| 78 explicit RootObserver(View* root) : root_(root) {} | |
| 79 ~RootObserver() override {} | |
| 80 | |
| 81 private: | |
| 82 // Overridden from ViewObserver: | |
| 83 void OnViewDestroyed(View* view) override { | |
| 84 DCHECK_EQ(view, root_); | |
| 85 static_cast<ViewManagerClientImpl*>(root_->view_manager()) | |
| 86 ->RootDestroyed(root_); | |
| 87 view->RemoveObserver(this); | |
| 88 delete this; | |
| 89 } | |
| 90 | |
| 91 View* root_; | |
| 92 | |
| 93 DISALLOW_COPY_AND_ASSIGN(RootObserver); | |
| 94 }; | |
| 95 | |
| 96 ViewManagerClientImpl::ViewManagerClientImpl(ViewManagerDelegate* delegate, | |
| 97 Shell* shell, | |
| 98 ScopedMessagePipeHandle handle, | |
| 99 bool delete_on_error) | |
| 100 : connected_(false), | |
| 101 connection_id_(0), | |
| 102 next_id_(1), | |
| 103 delegate_(delegate), | |
| 104 root_(nullptr), | |
| 105 capture_view_(nullptr), | |
| 106 focused_view_(nullptr), | |
| 107 activated_view_(nullptr), | |
| 108 binding_(this, handle.Pass()), | |
| 109 service_(binding_.client()), | |
| 110 delete_on_error_(delete_on_error) { | |
| 111 } | |
| 112 | |
| 113 ViewManagerClientImpl::~ViewManagerClientImpl() { | |
| 114 std::vector<View*> non_owned; | |
| 115 while (!views_.empty()) { | |
| 116 IdToViewMap::iterator it = views_.begin(); | |
| 117 if (OwnsView(it->second->id())) { | |
| 118 it->second->Destroy(); | |
| 119 } else { | |
| 120 non_owned.push_back(it->second); | |
| 121 views_.erase(it); | |
| 122 } | |
| 123 } | |
| 124 // Delete the non-owned views last. In the typical case these are roots. The | |
| 125 // exception is the window manager, which may know aboutother random views | |
| 126 // that it doesn't own. | |
| 127 // NOTE: we manually delete as we're a friend. | |
| 128 for (size_t i = 0; i < non_owned.size(); ++i) | |
| 129 delete non_owned[i]; | |
| 130 | |
| 131 delegate_->OnViewManagerDisconnected(this); | |
| 132 } | |
| 133 | |
| 134 void ViewManagerClientImpl::DestroyView(Id view_id) { | |
| 135 DCHECK(connected_); | |
| 136 service_->DeleteView(view_id, ActionCompletedCallback()); | |
| 137 } | |
| 138 | |
| 139 void ViewManagerClientImpl::AddChild(Id child_id, Id parent_id) { | |
| 140 DCHECK(connected_); | |
| 141 service_->AddView(parent_id, child_id, ActionCompletedCallback()); | |
| 142 } | |
| 143 | |
| 144 void ViewManagerClientImpl::RemoveChild(Id child_id, Id parent_id) { | |
| 145 DCHECK(connected_); | |
| 146 service_->RemoveViewFromParent(child_id, ActionCompletedCallback()); | |
| 147 } | |
| 148 | |
| 149 void ViewManagerClientImpl::Reorder( | |
| 150 Id view_id, | |
| 151 Id relative_view_id, | |
| 152 OrderDirection direction) { | |
| 153 DCHECK(connected_); | |
| 154 service_->ReorderView(view_id, relative_view_id, direction, | |
| 155 ActionCompletedCallback()); | |
| 156 } | |
| 157 | |
| 158 bool ViewManagerClientImpl::OwnsView(Id id) const { | |
| 159 return HiWord(id) == connection_id_; | |
| 160 } | |
| 161 | |
| 162 void ViewManagerClientImpl::SetBounds(Id view_id, const Rect& bounds) { | |
| 163 DCHECK(connected_); | |
| 164 service_->SetViewBounds(view_id, bounds.Clone(), ActionCompletedCallback()); | |
| 165 } | |
| 166 | |
| 167 void ViewManagerClientImpl::SetSurfaceId(Id view_id, SurfaceIdPtr surface_id) { | |
| 168 DCHECK(connected_); | |
| 169 if (surface_id.is_null()) | |
| 170 return; | |
| 171 service_->SetViewSurfaceId( | |
| 172 view_id, surface_id.Pass(), ActionCompletedCallback()); | |
| 173 } | |
| 174 | |
| 175 void ViewManagerClientImpl::SetFocus(Id view_id) { | |
| 176 // In order for us to get here we had to have exposed a view, which implies we | |
| 177 // got a connection. | |
| 178 DCHECK(window_manager_.get()); | |
| 179 window_manager_->FocusWindow(view_id, ActionCompletedCallback()); | |
| 180 } | |
| 181 | |
| 182 void ViewManagerClientImpl::SetVisible(Id view_id, bool visible) { | |
| 183 DCHECK(connected_); | |
| 184 service_->SetViewVisibility(view_id, visible, ActionCompletedCallback()); | |
| 185 } | |
| 186 | |
| 187 void ViewManagerClientImpl::SetProperty( | |
| 188 Id view_id, | |
| 189 const std::string& name, | |
| 190 const std::vector<uint8_t>& data) { | |
| 191 DCHECK(connected_); | |
| 192 service_->SetViewProperty(view_id, | |
| 193 String(name), | |
| 194 Array<uint8_t>::From(data), | |
| 195 ActionCompletedCallback()); | |
| 196 } | |
| 197 | |
| 198 void ViewManagerClientImpl::Embed(const String& url, Id view_id) { | |
| 199 Embed(url, view_id, nullptr, nullptr); | |
| 200 } | |
| 201 | |
| 202 void ViewManagerClientImpl::Embed(const String& url, | |
| 203 Id view_id, | |
| 204 InterfaceRequest<ServiceProvider> services, | |
| 205 ServiceProviderPtr exposed_services) { | |
| 206 DCHECK(connected_); | |
| 207 service_->Embed(url, view_id, services.Pass(), exposed_services.Pass(), | |
| 208 ActionCompletedCallback()); | |
| 209 } | |
| 210 | |
| 211 void ViewManagerClientImpl::AddView(View* view) { | |
| 212 DCHECK(views_.find(view->id()) == views_.end()); | |
| 213 views_[view->id()] = view; | |
| 214 } | |
| 215 | |
| 216 void ViewManagerClientImpl::RemoveView(Id view_id) { | |
| 217 IdToViewMap::iterator it = views_.find(view_id); | |
| 218 if (it != views_.end()) | |
| 219 views_.erase(it); | |
| 220 } | |
| 221 | |
| 222 //////////////////////////////////////////////////////////////////////////////// | |
| 223 // ViewManagerClientImpl, ViewManager implementation: | |
| 224 | |
| 225 Id ViewManagerClientImpl::CreateViewOnServer() { | |
| 226 DCHECK(connected_); | |
| 227 const Id view_id = MakeTransportId(connection_id_, ++next_id_); | |
| 228 service_->CreateView(view_id, ActionCompletedCallbackWithErrorCode()); | |
| 229 return view_id; | |
| 230 } | |
| 231 | |
| 232 const std::string& ViewManagerClientImpl::GetEmbedderURL() const { | |
| 233 return creator_url_; | |
| 234 } | |
| 235 | |
| 236 View* ViewManagerClientImpl::GetRoot() { | |
| 237 return root_; | |
| 238 } | |
| 239 | |
| 240 View* ViewManagerClientImpl::GetViewById(Id id) { | |
| 241 IdToViewMap::const_iterator it = views_.find(id); | |
| 242 return it != views_.end() ? it->second : NULL; | |
| 243 } | |
| 244 | |
| 245 View* ViewManagerClientImpl::GetFocusedView() { | |
| 246 return focused_view_; | |
| 247 } | |
| 248 | |
| 249 View* ViewManagerClientImpl::CreateView() { | |
| 250 View* view = new View(this, CreateViewOnServer()); | |
| 251 AddView(view); | |
| 252 return view; | |
| 253 } | |
| 254 | |
| 255 //////////////////////////////////////////////////////////////////////////////// | |
| 256 // ViewManagerClientImpl, ViewManagerClient implementation: | |
| 257 | |
| 258 void ViewManagerClientImpl::OnEmbed( | |
| 259 ConnectionSpecificId connection_id, | |
| 260 const String& creator_url, | |
| 261 ViewDataPtr root_data, | |
| 262 InterfaceRequest<ServiceProvider> services, | |
| 263 ServiceProviderPtr exposed_services, | |
| 264 ScopedMessagePipeHandle window_manager_pipe) { | |
| 265 DCHECK(!connected_); | |
| 266 connected_ = true; | |
| 267 connection_id_ = connection_id; | |
| 268 creator_url_ = String::From(creator_url); | |
| 269 | |
| 270 DCHECK(!root_); | |
| 271 root_ = AddViewToViewManager(this, nullptr, root_data); | |
| 272 root_->AddObserver(new RootObserver(root_)); | |
| 273 | |
| 274 window_manager_.Bind(window_manager_pipe.Pass()); | |
| 275 window_manager_.set_client(this); | |
| 276 // base::Unretained() is safe here as |window_manager_| is bound to our | |
| 277 // lifetime. | |
| 278 window_manager_->GetFocusedAndActiveViews( | |
| 279 base::Bind(&ViewManagerClientImpl::OnGotFocusedAndActiveViews, | |
| 280 base::Unretained(this))); | |
| 281 | |
| 282 delegate_->OnEmbed(root_, services.Pass(), exposed_services.Pass()); | |
| 283 } | |
| 284 | |
| 285 void ViewManagerClientImpl::OnEmbeddedAppDisconnected(Id view_id) { | |
| 286 View* view = GetViewById(view_id); | |
| 287 if (view) { | |
| 288 FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(view).observers(), | |
| 289 OnViewEmbeddedAppDisconnected(view)); | |
| 290 } | |
| 291 } | |
| 292 | |
| 293 void ViewManagerClientImpl::OnViewBoundsChanged(Id view_id, | |
| 294 RectPtr old_bounds, | |
| 295 RectPtr new_bounds) { | |
| 296 View* view = GetViewById(view_id); | |
| 297 ViewPrivate(view).LocalSetBounds(*old_bounds, *new_bounds); | |
| 298 } | |
| 299 | |
| 300 namespace { | |
| 301 | |
| 302 void SetViewportMetricsOnDecendants(View* root, | |
| 303 const ViewportMetrics& old_metrics, | |
| 304 const ViewportMetrics& new_metrics) { | |
| 305 ViewPrivate(root).LocalSetViewportMetrics(old_metrics, new_metrics); | |
| 306 const View::Children& children = root->children(); | |
| 307 for (size_t i = 0; i < children.size(); ++i) | |
| 308 SetViewportMetricsOnDecendants(children[i], old_metrics, new_metrics); | |
| 309 } | |
| 310 } | |
| 311 | |
| 312 void ViewManagerClientImpl::OnViewViewportMetricsChanged( | |
| 313 ViewportMetricsPtr old_metrics, | |
| 314 ViewportMetricsPtr new_metrics) { | |
| 315 View* view = GetRoot(); | |
| 316 if (view) | |
| 317 SetViewportMetricsOnDecendants(view, *old_metrics, *new_metrics); | |
| 318 } | |
| 319 | |
| 320 void ViewManagerClientImpl::OnViewHierarchyChanged( | |
| 321 Id view_id, | |
| 322 Id new_parent_id, | |
| 323 Id old_parent_id, | |
| 324 mojo::Array<ViewDataPtr> views) { | |
| 325 View* initial_parent = views.size() ? | |
| 326 GetViewById(views[0]->parent_id) : NULL; | |
| 327 | |
| 328 BuildViewTree(this, views, initial_parent); | |
| 329 | |
| 330 View* new_parent = GetViewById(new_parent_id); | |
| 331 View* old_parent = GetViewById(old_parent_id); | |
| 332 View* view = GetViewById(view_id); | |
| 333 if (new_parent) | |
| 334 ViewPrivate(new_parent).LocalAddChild(view); | |
| 335 else | |
| 336 ViewPrivate(old_parent).LocalRemoveChild(view); | |
| 337 } | |
| 338 | |
| 339 void ViewManagerClientImpl::OnViewReordered(Id view_id, | |
| 340 Id relative_view_id, | |
| 341 OrderDirection direction) { | |
| 342 View* view = GetViewById(view_id); | |
| 343 View* relative_view = GetViewById(relative_view_id); | |
| 344 if (view && relative_view) | |
| 345 ViewPrivate(view).LocalReorder(relative_view, direction); | |
| 346 } | |
| 347 | |
| 348 void ViewManagerClientImpl::OnViewDeleted(Id view_id) { | |
| 349 View* view = GetViewById(view_id); | |
| 350 if (view) | |
| 351 ViewPrivate(view).LocalDestroy(); | |
| 352 } | |
| 353 | |
| 354 void ViewManagerClientImpl::OnViewVisibilityChanged(Id view_id, bool visible) { | |
| 355 // TODO(sky): there is a race condition here. If this client and another | |
| 356 // client change the visibility at the same time the wrong value may be set. | |
| 357 // Deal with this some how. | |
| 358 View* view = GetViewById(view_id); | |
| 359 if (view) | |
| 360 view->SetVisible(visible); | |
| 361 } | |
| 362 | |
| 363 void ViewManagerClientImpl::OnViewDrawnStateChanged(Id view_id, bool drawn) { | |
| 364 View* view = GetViewById(view_id); | |
| 365 if (view) | |
| 366 ViewPrivate(view).LocalSetDrawn(drawn); | |
| 367 } | |
| 368 | |
| 369 void ViewManagerClientImpl::OnViewSharedPropertyChanged( | |
| 370 Id view_id, | |
| 371 const String& name, | |
| 372 Array<uint8_t> new_data) { | |
| 373 View* view = GetViewById(view_id); | |
| 374 if (view) { | |
| 375 std::vector<uint8_t> data; | |
| 376 std::vector<uint8_t>* data_ptr = NULL; | |
| 377 if (!new_data.is_null()) { | |
| 378 data = new_data.To<std::vector<uint8_t>>(); | |
| 379 data_ptr = &data; | |
| 380 } | |
| 381 | |
| 382 view->SetSharedProperty(name, data_ptr); | |
| 383 } | |
| 384 } | |
| 385 | |
| 386 void ViewManagerClientImpl::OnViewInputEvent( | |
| 387 Id view_id, | |
| 388 EventPtr event, | |
| 389 const Callback<void()>& ack_callback) { | |
| 390 View* view = GetViewById(view_id); | |
| 391 if (view) { | |
| 392 FOR_EACH_OBSERVER(ViewObserver, | |
| 393 *ViewPrivate(view).observers(), | |
| 394 OnViewInputEvent(view, event)); | |
| 395 } | |
| 396 ack_callback.Run(); | |
| 397 } | |
| 398 | |
| 399 //////////////////////////////////////////////////////////////////////////////// | |
| 400 // ViewManagerClientImpl, WindowManagerClient implementation: | |
| 401 | |
| 402 void ViewManagerClientImpl::OnCaptureChanged(Id old_capture_view_id, | |
| 403 Id new_capture_view_id) { | |
| 404 View* gained_capture = GetViewById(new_capture_view_id); | |
| 405 View* lost_capture = GetViewById(old_capture_view_id); | |
| 406 if (lost_capture) { | |
| 407 FOR_EACH_OBSERVER(ViewObserver, | |
| 408 *ViewPrivate(lost_capture).observers(), | |
| 409 OnViewFocusChanged(gained_capture, lost_capture)); | |
| 410 } | |
| 411 capture_view_ = gained_capture; | |
| 412 if (gained_capture) { | |
| 413 FOR_EACH_OBSERVER(ViewObserver, | |
| 414 *ViewPrivate(gained_capture).observers(), | |
| 415 OnViewFocusChanged(gained_capture, lost_capture)); | |
| 416 } | |
| 417 } | |
| 418 | |
| 419 void ViewManagerClientImpl::OnFocusChanged(Id old_focused_view_id, | |
| 420 Id new_focused_view_id) { | |
| 421 View* focused = GetViewById(new_focused_view_id); | |
| 422 View* blurred = GetViewById(old_focused_view_id); | |
| 423 if (blurred) { | |
| 424 FOR_EACH_OBSERVER(ViewObserver, | |
| 425 *ViewPrivate(blurred).observers(), | |
| 426 OnViewFocusChanged(focused, blurred)); | |
| 427 } | |
| 428 focused_view_ = focused; | |
| 429 if (focused) { | |
| 430 FOR_EACH_OBSERVER(ViewObserver, | |
| 431 *ViewPrivate(focused).observers(), | |
| 432 OnViewFocusChanged(focused, blurred)); | |
| 433 } | |
| 434 } | |
| 435 | |
| 436 void ViewManagerClientImpl::OnActiveWindowChanged(Id old_active_view_id, | |
| 437 Id new_active_view_id) { | |
| 438 View* activated = GetViewById(new_active_view_id); | |
| 439 View* deactivated = GetViewById(old_active_view_id); | |
| 440 if (deactivated) { | |
| 441 FOR_EACH_OBSERVER(ViewObserver, | |
| 442 *ViewPrivate(deactivated).observers(), | |
| 443 OnViewActivationChanged(activated, deactivated)); | |
| 444 } | |
| 445 activated_view_ = activated; | |
| 446 if (activated) { | |
| 447 FOR_EACH_OBSERVER(ViewObserver, | |
| 448 *ViewPrivate(activated).observers(), | |
| 449 OnViewActivationChanged(activated, deactivated)); | |
| 450 } | |
| 451 } | |
| 452 | |
| 453 //////////////////////////////////////////////////////////////////////////////// | |
| 454 // OnConnectionError, private: | |
| 455 void ViewManagerClientImpl::OnConnectionError() { | |
| 456 if (delete_on_error_) | |
| 457 delete this; | |
| 458 } | |
| 459 | |
| 460 //////////////////////////////////////////////////////////////////////////////// | |
| 461 // ViewManagerClientImpl, private: | |
| 462 | |
| 463 void ViewManagerClientImpl::RootDestroyed(View* root) { | |
| 464 DCHECK_EQ(root, root_); | |
| 465 root_ = nullptr; | |
| 466 } | |
| 467 | |
| 468 void ViewManagerClientImpl::OnActionCompleted(bool success) { | |
| 469 if (!change_acked_callback_.is_null()) | |
| 470 change_acked_callback_.Run(); | |
| 471 } | |
| 472 | |
| 473 void ViewManagerClientImpl::OnActionCompletedWithErrorCode(ErrorCode code) { | |
| 474 OnActionCompleted(code == ERROR_CODE_NONE); | |
| 475 } | |
| 476 | |
| 477 base::Callback<void(bool)> ViewManagerClientImpl::ActionCompletedCallback() { | |
| 478 return base::Bind(&ViewManagerClientImpl::OnActionCompleted, | |
| 479 base::Unretained(this)); | |
| 480 } | |
| 481 | |
| 482 base::Callback<void(ErrorCode)> | |
| 483 ViewManagerClientImpl::ActionCompletedCallbackWithErrorCode() { | |
| 484 return base::Bind(&ViewManagerClientImpl::OnActionCompletedWithErrorCode, | |
| 485 base::Unretained(this)); | |
| 486 } | |
| 487 | |
| 488 void ViewManagerClientImpl::OnGotFocusedAndActiveViews(uint32 focused_view_id, | |
| 489 uint32 active_view_id) { | |
| 490 if (GetViewById(focused_view_id) != focused_view_) | |
| 491 OnFocusChanged(focused_view_ ? focused_view_->id() : 0, focused_view_id); | |
| 492 if (GetViewById(active_view_id) != activated_view_) { | |
| 493 OnActiveWindowChanged(activated_view_ ? activated_view_->id() : 0, | |
| 494 active_view_id); | |
| 495 } | |
| 496 } | |
| 497 | |
| 498 } // namespace mojo | |
| OLD | NEW |