• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/message_loop/message_loop.h"
9 #include "mojo/public/cpp/application/application.h"
10 #include "mojo/public/cpp/application/connect.h"
11 #include "mojo/public/interfaces/service_provider/service_provider.mojom.h"
12 #include "mojo/services/public/cpp/view_manager/lib/node_private.h"
13 #include "mojo/services/public/cpp/view_manager/lib/view_private.h"
14 #include "mojo/services/public/cpp/view_manager/node_observer.h"
15 #include "mojo/services/public/cpp/view_manager/util.h"
16 #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
17 #include "mojo/services/public/cpp/view_manager/view_observer.h"
18 #include "third_party/skia/include/core/SkBitmap.h"
19 #include "ui/gfx/codec/png_codec.h"
20 
21 namespace mojo {
22 namespace view_manager {
23 
MakeTransportId(ConnectionSpecificId connection_id,ConnectionSpecificId local_id)24 Id MakeTransportId(ConnectionSpecificId connection_id,
25                    ConnectionSpecificId local_id) {
26   return (connection_id << 16) | local_id;
27 }
28 
29 // Helper called to construct a local node/view object from transport data.
AddNodeToViewManager(ViewManagerClientImpl * client,Node * parent,Id node_id,Id view_id,const gfx::Rect & bounds)30 Node* AddNodeToViewManager(ViewManagerClientImpl* client,
31                            Node* parent,
32                            Id node_id,
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 node.
37   Node* node = NodePrivate::LocalCreate();
38   NodePrivate private_node(node);
39   private_node.set_view_manager(client);
40   private_node.set_id(node_id);
41   private_node.LocalSetBounds(gfx::Rect(), bounds);
42   if (parent)
43     NodePrivate(parent).LocalAddChild(node);
44   client->AddNode(node);
45 
46   // View.
47   if (view_id != 0) {
48     View* view = ViewPrivate::LocalCreate();
49     ViewPrivate private_view(view);
50     private_view.set_view_manager(client);
51     private_view.set_id(view_id);
52     private_view.set_node(node);
53     // TODO(beng): this broadcasts notifications locally... do we want this? I
54     //             don't think so. same story for LocalAddChild above!
55     private_node.LocalSetActiveView(view);
56     client->AddView(view);
57   }
58   return node;
59 }
60 
BuildNodeTree(ViewManagerClientImpl * client,const Array<NodeDataPtr> & nodes)61 Node* BuildNodeTree(ViewManagerClientImpl* client,
62                     const Array<NodeDataPtr>& nodes) {
63   std::vector<Node*> parents;
64   Node* root = NULL;
65   Node* last_node = NULL;
66   for (size_t i = 0; i < nodes.size(); ++i) {
67     if (last_node && nodes[i]->parent_id == last_node->id()) {
68       parents.push_back(last_node);
69     } else if (!parents.empty()) {
70       while (parents.back()->id() != nodes[i]->parent_id)
71         parents.pop_back();
72     }
73     Node* node = AddNodeToViewManager(
74         client,
75         !parents.empty() ? parents.back() : NULL,
76         nodes[i]->node_id,
77         nodes[i]->view_id,
78         nodes[i]->bounds.To<gfx::Rect>());
79     if (!last_node)
80       root = node;
81     last_node = node;
82   }
83   return root;
84 }
85 
86 // Responsible for removing a root from the ViewManager when that node is
87 // destroyed.
88 class RootObserver : public NodeObserver {
89  public:
RootObserver(Node * root)90   explicit RootObserver(Node* root) : root_(root) {}
~RootObserver()91   virtual ~RootObserver() {}
92 
93  private:
94   // Overridden from NodeObserver:
OnNodeDestroy(Node * node,DispositionChangePhase phase)95   virtual void OnNodeDestroy(Node* node,
96                              DispositionChangePhase phase) OVERRIDE {
97     DCHECK_EQ(node, root_);
98     if (phase != NodeObserver::DISPOSITION_CHANGED)
99       return;
100     static_cast<ViewManagerClientImpl*>(
101         NodePrivate(root_).view_manager())->RemoveRoot(root_);
102     delete this;
103   }
104 
105   Node* root_;
106 
107   DISALLOW_COPY_AND_ASSIGN(RootObserver);
108 };
109 
110 class ViewManagerTransaction {
111  public:
~ViewManagerTransaction()112   virtual ~ViewManagerTransaction() {}
113 
Commit()114   void Commit() {
115     DCHECK(!committed_);
116     DoCommit();
117     committed_ = true;
118   }
119 
committed() const120   bool committed() const { return committed_; }
121 
122  protected:
ViewManagerTransaction(ViewManagerClientImpl * client)123   explicit ViewManagerTransaction(ViewManagerClientImpl* client)
124       : committed_(false),
125         client_(client) {
126   }
127 
128   // Overridden to perform transaction-specific commit actions.
129   virtual void DoCommit() = 0;
130 
131   // Overridden to perform transaction-specific cleanup on commit ack from the
132   // service.
133   virtual void DoActionCompleted(bool success) = 0;
134 
service()135   ViewManagerService* service() { return client_->service_; }
136 
GetAndAdvanceNextServerChangeId()137   Id GetAndAdvanceNextServerChangeId() {
138     return client_->next_server_change_id_++;
139   }
140 
ActionCompletedCallback()141   base::Callback<void(bool)> ActionCompletedCallback() {
142     return base::Bind(&ViewManagerTransaction::OnActionCompleted,
143                       base::Unretained(this));
144   }
145 
146  private:
147   // General callback to be used for commits to the service.
OnActionCompleted(bool success)148   void OnActionCompleted(bool success) {
149     DCHECK(success);
150     DoActionCompleted(success);
151     client_->RemoveFromPendingQueue(this);
152   }
153 
154   bool committed_;
155   ViewManagerClientImpl* client_;
156 
157   DISALLOW_COPY_AND_ASSIGN(ViewManagerTransaction);
158 };
159 
160 class CreateViewTransaction : public ViewManagerTransaction {
161  public:
CreateViewTransaction(Id view_id,ViewManagerClientImpl * client)162   CreateViewTransaction(Id view_id, ViewManagerClientImpl* client)
163       : ViewManagerTransaction(client),
164         view_id_(view_id) {}
~CreateViewTransaction()165   virtual ~CreateViewTransaction() {}
166 
167  private:
168   // Overridden from ViewManagerTransaction:
DoCommit()169   virtual void DoCommit() OVERRIDE {
170     service()->CreateView(view_id_, ActionCompletedCallback());
171   }
DoActionCompleted(bool success)172   virtual void DoActionCompleted(bool success) OVERRIDE {
173     // TODO(beng): failure.
174   }
175 
176   const Id view_id_;
177 
178   DISALLOW_COPY_AND_ASSIGN(CreateViewTransaction);
179 };
180 
181 class DestroyViewTransaction : public ViewManagerTransaction {
182  public:
DestroyViewTransaction(Id view_id,ViewManagerClientImpl * client)183   DestroyViewTransaction(Id view_id, ViewManagerClientImpl* client)
184       : ViewManagerTransaction(client),
185         view_id_(view_id) {}
~DestroyViewTransaction()186   virtual ~DestroyViewTransaction() {}
187 
188  private:
189   // Overridden from ViewManagerTransaction:
DoCommit()190   virtual void DoCommit() OVERRIDE {
191     service()->DeleteView(view_id_, ActionCompletedCallback());
192   }
DoActionCompleted(bool success)193   virtual void DoActionCompleted(bool success) OVERRIDE {
194     // TODO(beng): recovery?
195   }
196 
197   const Id view_id_;
198 
199   DISALLOW_COPY_AND_ASSIGN(DestroyViewTransaction);
200 };
201 
202 class CreateNodeTransaction : public ViewManagerTransaction {
203  public:
CreateNodeTransaction(Id node_id,ViewManagerClientImpl * client)204   CreateNodeTransaction(Id node_id, ViewManagerClientImpl* client)
205       : ViewManagerTransaction(client),
206         node_id_(node_id) {}
~CreateNodeTransaction()207   virtual ~CreateNodeTransaction() {}
208 
209  private:
210   // Overridden from ViewManagerTransaction:
DoCommit()211   virtual void DoCommit() OVERRIDE {
212     service()->CreateNode(node_id_, ActionCompletedCallback());
213   }
DoActionCompleted(bool success)214   virtual void DoActionCompleted(bool success) OVERRIDE {
215     // TODO(beng): Failure means we tried to create with an extant id for this
216     //             connection. It also could mean we tried to do something
217     //             invalid, or we tried applying a change out of order. Figure
218     //             out what to do.
219   }
220 
221   const Id node_id_;
222 
223   DISALLOW_COPY_AND_ASSIGN(CreateNodeTransaction);
224 };
225 
226 class DestroyNodeTransaction : public ViewManagerTransaction {
227  public:
DestroyNodeTransaction(Id node_id,ViewManagerClientImpl * client)228   DestroyNodeTransaction(Id node_id, ViewManagerClientImpl* client)
229       : ViewManagerTransaction(client),
230         node_id_(node_id) {}
~DestroyNodeTransaction()231   virtual ~DestroyNodeTransaction() {}
232 
233  private:
234   // Overridden from ViewManagerTransaction:
DoCommit()235   virtual void DoCommit() OVERRIDE {
236     service()->DeleteNode(node_id_,
237                           GetAndAdvanceNextServerChangeId(),
238                           ActionCompletedCallback());
239   }
DoActionCompleted(bool success)240   virtual void DoActionCompleted(bool success) OVERRIDE {
241     // TODO(beng): recovery?
242   }
243 
244   const Id node_id_;
245   DISALLOW_COPY_AND_ASSIGN(DestroyNodeTransaction);
246 };
247 
248 class AddChildTransaction : public ViewManagerTransaction {
249  public:
AddChildTransaction(Id child_id,Id parent_id,ViewManagerClientImpl * client)250   AddChildTransaction(Id child_id,
251                       Id parent_id,
252                       ViewManagerClientImpl* client)
253       : ViewManagerTransaction(client),
254         child_id_(child_id),
255         parent_id_(parent_id) {}
~AddChildTransaction()256   virtual ~AddChildTransaction() {}
257 
258  private:
259   // Overridden from ViewManagerTransaction:
DoCommit()260   virtual void DoCommit() OVERRIDE {
261     service()->AddNode(parent_id_,
262                        child_id_,
263                        GetAndAdvanceNextServerChangeId(),
264                        ActionCompletedCallback());
265   }
266 
DoActionCompleted(bool success)267   virtual void DoActionCompleted(bool success) OVERRIDE {
268     // TODO(beng): recovery?
269   }
270 
271   const Id child_id_;
272   const Id parent_id_;
273 
274   DISALLOW_COPY_AND_ASSIGN(AddChildTransaction);
275 };
276 
277 class RemoveChildTransaction : public ViewManagerTransaction {
278  public:
RemoveChildTransaction(Id child_id,ViewManagerClientImpl * client)279   RemoveChildTransaction(Id child_id, ViewManagerClientImpl* client)
280       : ViewManagerTransaction(client),
281         child_id_(child_id) {}
~RemoveChildTransaction()282   virtual ~RemoveChildTransaction() {}
283 
284  private:
285   // Overridden from ViewManagerTransaction:
DoCommit()286   virtual void DoCommit() OVERRIDE {
287     service()->RemoveNodeFromParent(
288         child_id_,
289         GetAndAdvanceNextServerChangeId(),
290         ActionCompletedCallback());
291   }
292 
DoActionCompleted(bool success)293   virtual void DoActionCompleted(bool success) OVERRIDE {
294     // TODO(beng): recovery?
295   }
296 
297   const Id child_id_;
298 
299   DISALLOW_COPY_AND_ASSIGN(RemoveChildTransaction);
300 };
301 
302 class ReorderNodeTransaction : public ViewManagerTransaction {
303  public:
ReorderNodeTransaction(Id node_id,Id relative_id,OrderDirection direction,ViewManagerClientImpl * client)304   ReorderNodeTransaction(Id node_id,
305                          Id relative_id,
306                          OrderDirection direction,
307                          ViewManagerClientImpl* client)
308       : ViewManagerTransaction(client),
309         node_id_(node_id),
310         relative_id_(relative_id),
311         direction_(direction) {}
~ReorderNodeTransaction()312   virtual ~ReorderNodeTransaction() {}
313 
314  private:
315   // Overridden from ViewManagerTransaction:
DoCommit()316   virtual void DoCommit() OVERRIDE {
317     service()->ReorderNode(node_id_,
318                            relative_id_,
319                            direction_,
320                            GetAndAdvanceNextServerChangeId(),
321                            ActionCompletedCallback());
322   }
323 
DoActionCompleted(bool success)324   virtual void DoActionCompleted(bool success) OVERRIDE {
325     // TODO(beng): recovery?
326   }
327 
328   const Id node_id_;
329   const Id relative_id_;
330   const OrderDirection direction_;
331 
332   DISALLOW_COPY_AND_ASSIGN(ReorderNodeTransaction);
333 };
334 
335 class SetActiveViewTransaction : public ViewManagerTransaction {
336  public:
SetActiveViewTransaction(Id node_id,Id view_id,ViewManagerClientImpl * client)337   SetActiveViewTransaction(Id node_id,
338                            Id view_id,
339                            ViewManagerClientImpl* client)
340       : ViewManagerTransaction(client),
341         node_id_(node_id),
342         view_id_(view_id) {}
~SetActiveViewTransaction()343   virtual ~SetActiveViewTransaction() {}
344 
345  private:
346   // Overridden from ViewManagerTransaction:
DoCommit()347   virtual void DoCommit() OVERRIDE {
348     service()->SetView(node_id_, view_id_, ActionCompletedCallback());
349   }
DoActionCompleted(bool success)350   virtual void DoActionCompleted(bool success) OVERRIDE {
351     // TODO(beng): recovery?
352   }
353 
354   const Id node_id_;
355   const Id view_id_;
356 
357   DISALLOW_COPY_AND_ASSIGN(SetActiveViewTransaction);
358 };
359 
360 class SetBoundsTransaction : public ViewManagerTransaction {
361  public:
SetBoundsTransaction(Id node_id,const gfx::Rect & bounds,ViewManagerClientImpl * client)362   SetBoundsTransaction(Id node_id,
363                        const gfx::Rect& bounds,
364                        ViewManagerClientImpl* client)
365       : ViewManagerTransaction(client),
366         node_id_(node_id),
367         bounds_(bounds) {}
~SetBoundsTransaction()368   virtual ~SetBoundsTransaction() {}
369 
370  private:
371   // Overridden from ViewManagerTransaction:
DoCommit()372   virtual void DoCommit() OVERRIDE {
373     service()->SetNodeBounds(
374         node_id_, Rect::From(bounds_), ActionCompletedCallback());
375   }
DoActionCompleted(bool success)376   virtual void DoActionCompleted(bool success) OVERRIDE {
377     // TODO(beng): recovery?
378   }
379 
380   const Id node_id_;
381   const gfx::Rect bounds_;
382 
383   DISALLOW_COPY_AND_ASSIGN(SetBoundsTransaction);
384 };
385 
386 class SetViewContentsTransaction : public ViewManagerTransaction {
387  public:
SetViewContentsTransaction(Id view_id,const SkBitmap & contents,ViewManagerClientImpl * client)388   SetViewContentsTransaction(Id view_id,
389                              const SkBitmap& contents,
390                              ViewManagerClientImpl* client)
391       : ViewManagerTransaction(client),
392         view_id_(view_id),
393         contents_(contents) {}
~SetViewContentsTransaction()394   virtual ~SetViewContentsTransaction() {}
395 
396  private:
397   // Overridden from ViewManagerTransaction:
DoCommit()398   virtual void DoCommit() OVERRIDE {
399     std::vector<unsigned char> data;
400     gfx::PNGCodec::EncodeBGRASkBitmap(contents_, false, &data);
401 
402     void* memory = NULL;
403     ScopedSharedBufferHandle duped;
404     bool result = CreateMapAndDupSharedBuffer(data.size(),
405                                               &memory,
406                                               &shared_state_handle_,
407                                               &duped);
408     if (!result)
409       return;
410 
411     memcpy(memory, &data[0], data.size());
412 
413     service()->SetViewContents(view_id_, duped.Pass(),
414                                static_cast<uint32_t>(data.size()),
415                                ActionCompletedCallback());
416   }
DoActionCompleted(bool success)417   virtual void DoActionCompleted(bool success) OVERRIDE {
418     // TODO(beng): recovery?
419   }
420 
CreateMapAndDupSharedBuffer(size_t size,void ** memory,ScopedSharedBufferHandle * handle,ScopedSharedBufferHandle * duped)421   bool CreateMapAndDupSharedBuffer(size_t size,
422                                    void** memory,
423                                    ScopedSharedBufferHandle* handle,
424                                    ScopedSharedBufferHandle* duped) {
425     MojoResult result = CreateSharedBuffer(NULL, size, handle);
426     if (result != MOJO_RESULT_OK)
427       return false;
428     DCHECK(handle->is_valid());
429 
430     result = DuplicateBuffer(handle->get(), NULL, duped);
431     if (result != MOJO_RESULT_OK)
432       return false;
433     DCHECK(duped->is_valid());
434 
435     result = MapBuffer(
436         handle->get(), 0, size, memory, MOJO_MAP_BUFFER_FLAG_NONE);
437     if (result != MOJO_RESULT_OK)
438       return false;
439     DCHECK(*memory);
440 
441     return true;
442   }
443 
444   const Id view_id_;
445   const SkBitmap contents_;
446   ScopedSharedBufferHandle shared_state_handle_;
447 
448   DISALLOW_COPY_AND_ASSIGN(SetViewContentsTransaction);
449 };
450 
451 class EmbedTransaction : public ViewManagerTransaction {
452  public:
EmbedTransaction(const String & url,Id node_id,ViewManagerClientImpl * client)453   EmbedTransaction(const String& url,
454                    Id node_id,
455                    ViewManagerClientImpl* client)
456       : ViewManagerTransaction(client),
457         url_(url),
458         node_id_(node_id) {}
~EmbedTransaction()459   virtual ~EmbedTransaction() {}
460 
461  private:
462   // Overridden from ViewManagerTransaction:
DoCommit()463   virtual void DoCommit() OVERRIDE {
464     std::vector<Id> ids;
465     ids.push_back(node_id_);
466     service()->Embed(url_, Array<Id>::From(ids), ActionCompletedCallback());
467   }
DoActionCompleted(bool success)468   virtual void DoActionCompleted(bool success) OVERRIDE {
469     // TODO(beng): recovery?
470   }
471 
472   const String url_;
473   const Id node_id_;
474 
475   DISALLOW_COPY_AND_ASSIGN(EmbedTransaction);
476 };
477 
478 class SetFocusTransaction : public ViewManagerTransaction {
479  public:
SetFocusTransaction(Id node_id,ViewManagerClientImpl * client)480   SetFocusTransaction(Id node_id, ViewManagerClientImpl* client)
481       : ViewManagerTransaction(client),
482         node_id_(node_id) {}
~SetFocusTransaction()483   virtual ~SetFocusTransaction() {}
484 
485  private:
486   // Overridden from ViewManagerTransaction:
DoCommit()487   virtual void DoCommit() OVERRIDE {
488     service()->SetFocus(node_id_, ActionCompletedCallback());
489   }
DoActionCompleted(bool success)490   virtual void DoActionCompleted(bool success) OVERRIDE {
491     // TODO(beng): recovery?
492   }
493 
494   const Id node_id_;
495 
496   DISALLOW_COPY_AND_ASSIGN(SetFocusTransaction);
497 };
498 
ViewManagerClientImpl(ViewManagerDelegate * delegate)499 ViewManagerClientImpl::ViewManagerClientImpl(ViewManagerDelegate* delegate)
500     : connected_(false),
501       connection_id_(0),
502       next_id_(1),
503       next_server_change_id_(0),
504       delegate_(delegate) {}
505 
~ViewManagerClientImpl()506 ViewManagerClientImpl::~ViewManagerClientImpl() {
507   while (!nodes_.empty()) {
508     IdToNodeMap::iterator it = nodes_.begin();
509     if (OwnsNode(it->second->id()))
510       it->second->Destroy();
511     else
512       nodes_.erase(it);
513   }
514   while (!views_.empty()) {
515     IdToViewMap::iterator it = views_.begin();
516     if (OwnsView(it->second->id()))
517       it->second->Destroy();
518     else
519       views_.erase(it);
520   }
521 }
522 
CreateNode()523 Id ViewManagerClientImpl::CreateNode() {
524   DCHECK(connected_);
525   const Id node_id(MakeTransportId(connection_id_, ++next_id_));
526   pending_transactions_.push_back(new CreateNodeTransaction(node_id, this));
527   Sync();
528   return node_id;
529 }
530 
DestroyNode(Id node_id)531 void ViewManagerClientImpl::DestroyNode(Id node_id) {
532   DCHECK(connected_);
533   pending_transactions_.push_back(new DestroyNodeTransaction(node_id, this));
534   Sync();
535 }
536 
CreateView()537 Id ViewManagerClientImpl::CreateView() {
538   DCHECK(connected_);
539   const Id view_id(MakeTransportId(connection_id_, ++next_id_));
540   pending_transactions_.push_back(new CreateViewTransaction(view_id, this));
541   Sync();
542   return view_id;
543 }
544 
DestroyView(Id view_id)545 void ViewManagerClientImpl::DestroyView(Id view_id) {
546   DCHECK(connected_);
547   pending_transactions_.push_back(new DestroyViewTransaction(view_id, this));
548   Sync();
549 }
550 
AddChild(Id child_id,Id parent_id)551 void ViewManagerClientImpl::AddChild(Id child_id,
552                                      Id parent_id) {
553   DCHECK(connected_);
554   pending_transactions_.push_back(
555       new AddChildTransaction(child_id, parent_id, this));
556   Sync();
557 }
558 
RemoveChild(Id child_id,Id parent_id)559 void ViewManagerClientImpl::RemoveChild(Id child_id, Id parent_id) {
560   DCHECK(connected_);
561   pending_transactions_.push_back(new RemoveChildTransaction(child_id, this));
562   Sync();
563 }
564 
Reorder(Id node_id,Id relative_node_id,OrderDirection direction)565 void ViewManagerClientImpl::Reorder(
566     Id node_id,
567     Id relative_node_id,
568     OrderDirection direction) {
569   DCHECK(connected_);
570   pending_transactions_.push_back(
571       new ReorderNodeTransaction(node_id, relative_node_id, direction, this));
572   Sync();
573 }
574 
OwnsNode(Id id) const575 bool ViewManagerClientImpl::OwnsNode(Id id) const {
576   return HiWord(id) == connection_id_;
577 }
578 
OwnsView(Id id) const579 bool ViewManagerClientImpl::OwnsView(Id id) const {
580   return HiWord(id) == connection_id_;
581 }
582 
SetActiveView(Id node_id,Id view_id)583 void ViewManagerClientImpl::SetActiveView(Id node_id, Id view_id) {
584   DCHECK(connected_);
585   pending_transactions_.push_back(
586       new SetActiveViewTransaction(node_id, view_id, this));
587   Sync();
588 }
589 
SetBounds(Id node_id,const gfx::Rect & bounds)590 void ViewManagerClientImpl::SetBounds(Id node_id, const gfx::Rect& bounds) {
591   DCHECK(connected_);
592   pending_transactions_.push_back(
593       new SetBoundsTransaction(node_id, bounds, this));
594   Sync();
595 }
596 
SetViewContents(Id view_id,const SkBitmap & contents)597 void ViewManagerClientImpl::SetViewContents(Id view_id,
598                                             const SkBitmap& contents) {
599   DCHECK(connected_);
600   pending_transactions_.push_back(
601       new SetViewContentsTransaction(view_id, contents, this));
602   Sync();
603 }
604 
SetFocus(Id node_id)605 void ViewManagerClientImpl::SetFocus(Id node_id) {
606   DCHECK(connected_);
607   pending_transactions_.push_back(new SetFocusTransaction(node_id, this));
608   Sync();
609 }
610 
Embed(const String & url,Id node_id)611 void ViewManagerClientImpl::Embed(const String& url, Id node_id) {
612   DCHECK(connected_);
613   pending_transactions_.push_back(new EmbedTransaction(url, node_id, this));
614   Sync();
615 }
616 
AddNode(Node * node)617 void ViewManagerClientImpl::AddNode(Node* node) {
618   DCHECK(nodes_.find(node->id()) == nodes_.end());
619   nodes_[node->id()] = node;
620 }
621 
RemoveNode(Id node_id)622 void ViewManagerClientImpl::RemoveNode(Id node_id) {
623   IdToNodeMap::iterator it = nodes_.find(node_id);
624   if (it != nodes_.end())
625     nodes_.erase(it);
626 }
627 
AddView(View * view)628 void ViewManagerClientImpl::AddView(View* view) {
629   DCHECK(views_.find(view->id()) == views_.end());
630   views_[view->id()] = view;
631 }
632 
RemoveView(Id view_id)633 void ViewManagerClientImpl::RemoveView(Id view_id) {
634   IdToViewMap::iterator it = views_.find(view_id);
635   if (it != views_.end())
636     views_.erase(it);
637 }
638 
639 ////////////////////////////////////////////////////////////////////////////////
640 // ViewManagerClientImpl, ViewManager implementation:
641 
GetEmbedderURL() const642 const std::string& ViewManagerClientImpl::GetEmbedderURL() const {
643   return creator_url_;
644 }
645 
GetRoots() const646 const std::vector<Node*>& ViewManagerClientImpl::GetRoots() const {
647   return roots_;
648 }
649 
GetNodeById(Id id)650 Node* ViewManagerClientImpl::GetNodeById(Id id) {
651   IdToNodeMap::const_iterator it = nodes_.find(id);
652   return it != nodes_.end() ? it->second : NULL;
653 }
654 
GetViewById(Id id)655 View* ViewManagerClientImpl::GetViewById(Id id) {
656   IdToViewMap::const_iterator it = views_.find(id);
657   return it != views_.end() ? it->second : NULL;
658 }
659 
660 ////////////////////////////////////////////////////////////////////////////////
661 // ViewManagerClientImpl, InterfaceImpl overrides:
662 
OnConnectionEstablished()663 void ViewManagerClientImpl::OnConnectionEstablished() {
664   service_ = client();
665 }
666 
667 ////////////////////////////////////////////////////////////////////////////////
668 // ViewManagerClientImpl, ViewManagerClient implementation:
669 
OnViewManagerConnectionEstablished(ConnectionSpecificId connection_id,const String & creator_url,Id next_server_change_id,Array<NodeDataPtr> nodes)670 void ViewManagerClientImpl::OnViewManagerConnectionEstablished(
671     ConnectionSpecificId connection_id,
672     const String& creator_url,
673     Id next_server_change_id,
674     Array<NodeDataPtr> nodes) {
675   connected_ = true;
676   connection_id_ = connection_id;
677   creator_url_ = TypeConverter<String, std::string>::ConvertFrom(creator_url);
678   next_server_change_id_ = next_server_change_id;
679 
680   DCHECK(pending_transactions_.empty());
681   AddRoot(BuildNodeTree(this, nodes));
682 }
683 
OnRootsAdded(Array<NodeDataPtr> nodes)684 void ViewManagerClientImpl::OnRootsAdded(Array<NodeDataPtr> nodes) {
685   AddRoot(BuildNodeTree(this, nodes));
686 }
687 
OnServerChangeIdAdvanced(Id next_server_change_id)688 void ViewManagerClientImpl::OnServerChangeIdAdvanced(
689     Id next_server_change_id) {
690   next_server_change_id_ = next_server_change_id;
691 }
692 
OnNodeBoundsChanged(Id node_id,RectPtr old_bounds,RectPtr new_bounds)693 void ViewManagerClientImpl::OnNodeBoundsChanged(Id node_id,
694                                                 RectPtr old_bounds,
695                                                 RectPtr new_bounds) {
696   Node* node = GetNodeById(node_id);
697   NodePrivate(node).LocalSetBounds(old_bounds.To<gfx::Rect>(),
698                                    new_bounds.To<gfx::Rect>());
699 }
700 
OnNodeHierarchyChanged(Id node_id,Id new_parent_id,Id old_parent_id,Id server_change_id,mojo::Array<NodeDataPtr> nodes)701 void ViewManagerClientImpl::OnNodeHierarchyChanged(
702     Id node_id,
703     Id new_parent_id,
704     Id old_parent_id,
705     Id server_change_id,
706     mojo::Array<NodeDataPtr> nodes) {
707   next_server_change_id_ = server_change_id + 1;
708 
709   BuildNodeTree(this, nodes);
710 
711   Node* new_parent = GetNodeById(new_parent_id);
712   Node* old_parent = GetNodeById(old_parent_id);
713   Node* node = GetNodeById(node_id);
714   if (new_parent)
715     NodePrivate(new_parent).LocalAddChild(node);
716   else
717     NodePrivate(old_parent).LocalRemoveChild(node);
718 }
719 
OnNodeReordered(Id node_id,Id relative_node_id,OrderDirection direction,Id server_change_id)720 void ViewManagerClientImpl::OnNodeReordered(Id node_id,
721                                             Id relative_node_id,
722                                             OrderDirection direction,
723                                             Id server_change_id) {
724   next_server_change_id_ = server_change_id + 1;
725 
726   Node* node = GetNodeById(node_id);
727   Node* relative_node = GetNodeById(relative_node_id);
728   if (node && relative_node) {
729     NodePrivate(node).LocalReorder(relative_node, direction);
730   }
731 }
732 
OnNodeDeleted(Id node_id,Id server_change_id)733 void ViewManagerClientImpl::OnNodeDeleted(Id node_id, Id server_change_id) {
734   next_server_change_id_ = server_change_id + 1;
735 
736   Node* node = GetNodeById(node_id);
737   if (node)
738     NodePrivate(node).LocalDestroy();
739 }
740 
OnNodeViewReplaced(Id node_id,Id new_view_id,Id old_view_id)741 void ViewManagerClientImpl::OnNodeViewReplaced(Id node_id,
742                                                Id new_view_id,
743                                                Id old_view_id) {
744   Node* node = GetNodeById(node_id);
745   View* new_view = GetViewById(new_view_id);
746   if (!new_view && new_view_id != 0) {
747     // This client wasn't aware of this View until now.
748     new_view = ViewPrivate::LocalCreate();
749     ViewPrivate private_view(new_view);
750     private_view.set_view_manager(this);
751     private_view.set_id(new_view_id);
752     private_view.set_node(node);
753     AddView(new_view);
754   }
755   View* old_view = GetViewById(old_view_id);
756   DCHECK_EQ(old_view, node->active_view());
757   NodePrivate(node).LocalSetActiveView(new_view);
758 }
759 
OnViewDeleted(Id view_id)760 void ViewManagerClientImpl::OnViewDeleted(Id view_id) {
761   View* view = GetViewById(view_id);
762   if (view)
763     ViewPrivate(view).LocalDestroy();
764 }
765 
OnViewInputEvent(Id view_id,EventPtr event,const Callback<void ()> & ack_callback)766 void ViewManagerClientImpl::OnViewInputEvent(
767     Id view_id,
768     EventPtr event,
769     const Callback<void()>& ack_callback) {
770   View* view = GetViewById(view_id);
771   if (view) {
772     FOR_EACH_OBSERVER(ViewObserver,
773                       *ViewPrivate(view).observers(),
774                       OnViewInputEvent(view, event));
775   }
776   ack_callback.Run();
777 }
778 
DispatchOnViewInputEvent(Id view_id,EventPtr event)779 void ViewManagerClientImpl::DispatchOnViewInputEvent(Id view_id,
780                                                      EventPtr event) {
781   // For now blindly bounce the message back to the server. Doing this means the
782   // event is sent to the correct target (|view_id|).
783   // Note: This function is only invoked on the window manager.
784   service_->DispatchOnViewInputEvent(view_id, event.Pass());
785 }
786 
787 ////////////////////////////////////////////////////////////////////////////////
788 // ViewManagerClientImpl, private:
789 
Sync()790 void ViewManagerClientImpl::Sync() {
791   // The service connection may not be set up yet. OnConnectionEstablished()
792   // will schedule another sync when it is.
793   if (!connected_)
794     return;
795 
796   Transactions::const_iterator it = pending_transactions_.begin();
797   for (; it != pending_transactions_.end(); ++it) {
798     if (!(*it)->committed())
799       (*it)->Commit();
800   }
801 }
802 
RemoveFromPendingQueue(ViewManagerTransaction * transaction)803 void ViewManagerClientImpl::RemoveFromPendingQueue(
804     ViewManagerTransaction* transaction) {
805   DCHECK_EQ(transaction, pending_transactions_.front());
806   pending_transactions_.erase(pending_transactions_.begin());
807   if (pending_transactions_.empty() && !changes_acked_callback_.is_null())
808     changes_acked_callback_.Run();
809 }
810 
AddRoot(Node * root)811 void ViewManagerClientImpl::AddRoot(Node* root) {
812   // A new root must not already exist as a root or be contained by an existing
813   // hierarchy visible to this view manager.
814   std::vector<Node*>::const_iterator it = roots_.begin();
815   for (; it != roots_.end(); ++it) {
816     if (*it == root || (*it)->Contains(root))
817       return;
818   }
819   roots_.push_back(root);
820   root->AddObserver(new RootObserver(root));
821   delegate_->OnRootAdded(this, root);
822 }
823 
RemoveRoot(Node * root)824 void ViewManagerClientImpl::RemoveRoot(Node* root) {
825   std::vector<Node*>::iterator it =
826       std::find(roots_.begin(), roots_.end(), root);
827   if (it != roots_.end())
828     roots_.erase(it);
829 }
830 
831 ////////////////////////////////////////////////////////////////////////////////
832 // ViewManager, public:
833 
834 // static
Create(Application * application,ViewManagerDelegate * delegate)835 void ViewManager::Create(Application* application,
836                          ViewManagerDelegate* delegate) {
837   application->AddService<ViewManagerClientImpl>(delegate);
838 }
839 
840 }  // namespace view_manager
841 }  // namespace mojo
842