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