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#ifndef MOJO_SERVICES_VIEW_MANAGER_CONNECTION_MANAGER_H_
6#define MOJO_SERVICES_VIEW_MANAGER_CONNECTION_MANAGER_H_
7
8#include <map>
9#include <set>
10
11#include "base/basictypes.h"
12#include "mojo/public/cpp/bindings/array.h"
13#include "mojo/services/view_manager/display_manager.h"
14#include "mojo/services/view_manager/ids.h"
15#include "mojo/services/view_manager/server_view.h"
16#include "mojo/services/view_manager/server_view_delegate.h"
17#include "mojo/services/view_manager/view_manager_export.h"
18
19namespace ui {
20class Event;
21}
22
23namespace mojo {
24
25class ApplicationConnection;
26
27namespace service {
28
29class ViewManagerServiceImpl;
30
31// ConnectionManager manages the set of connections to the ViewManager (all the
32// ViewManagerServiceImpls) as well as providing the root of the hierarchy.
33class MOJO_VIEW_MANAGER_EXPORT ConnectionManager : public ServerViewDelegate {
34 public:
35  // Create when a ViewManagerServiceImpl is about to make a change. Ensures
36  // clients are notified correctly.
37  class ScopedChange {
38   public:
39    ScopedChange(ViewManagerServiceImpl* connection,
40                 ConnectionManager* connection_manager,
41                 bool is_delete_view);
42    ~ScopedChange();
43
44    ConnectionSpecificId connection_id() const { return connection_id_; }
45    bool is_delete_view() const { return is_delete_view_; }
46
47    // Marks the connection with the specified id as having seen a message.
48    void MarkConnectionAsMessaged(ConnectionSpecificId connection_id) {
49      message_ids_.insert(connection_id);
50    }
51
52    // Returns true if MarkConnectionAsMessaged(connection_id) was invoked.
53    bool DidMessageConnection(ConnectionSpecificId connection_id) const {
54      return message_ids_.count(connection_id) > 0;
55    }
56
57   private:
58    ConnectionManager* connection_manager_;
59    const ConnectionSpecificId connection_id_;
60    const bool is_delete_view_;
61
62    // See description of MarkConnectionAsMessaged/DidMessageConnection.
63    std::set<ConnectionSpecificId> message_ids_;
64
65    DISALLOW_COPY_AND_ASSIGN(ScopedChange);
66  };
67
68  ConnectionManager(ApplicationConnection* app_connection,
69                    const Callback<void()>& native_viewport_closed_callback);
70  virtual ~ConnectionManager();
71
72  // Returns the id for the next ViewManagerServiceImpl.
73  ConnectionSpecificId GetAndAdvanceNextConnectionId();
74
75  void AddConnection(ViewManagerServiceImpl* connection);
76  void RemoveConnection(ViewManagerServiceImpl* connection);
77
78  // Establishes the initial client. Similar to Connect(), but the resulting
79  // client is allowed to do anything.
80  void EmbedRoot(const std::string& url,
81                 InterfaceRequest<ServiceProvider> service_provider);
82
83  // See description of ViewManagerService::Embed() for details. This assumes
84  // |transport_view_id| is valid.
85  void Embed(ConnectionSpecificId creator_id,
86             const String& url,
87             Id transport_view_id,
88             InterfaceRequest<ServiceProvider> service_provider);
89
90  // Returns the connection by id.
91  ViewManagerServiceImpl* GetConnection(ConnectionSpecificId connection_id);
92
93  // Returns the View identified by |id|.
94  ServerView* GetView(const ViewId& id);
95
96  ServerView* root() { return root_.get(); }
97
98  bool IsProcessingChange() const { return current_change_ != NULL; }
99
100  bool is_processing_delete_view() const {
101    return current_change_ && current_change_->is_delete_view();
102  }
103
104  // Invoked when a connection messages a client about the change. This is used
105  // to avoid sending ServerChangeIdAdvanced() unnecessarily.
106  void OnConnectionMessagedClient(ConnectionSpecificId id);
107
108  // Returns true if OnConnectionMessagedClient() was invoked for id.
109  bool DidConnectionMessageClient(ConnectionSpecificId id) const;
110
111  // Returns the ViewManagerServiceImpl that has |id| as a root.
112  ViewManagerServiceImpl* GetConnectionWithRoot(const ViewId& id) {
113    return const_cast<ViewManagerServiceImpl*>(
114        const_cast<const ConnectionManager*>(this)->GetConnectionWithRoot(id));
115  }
116  const ViewManagerServiceImpl* GetConnectionWithRoot(const ViewId& id) const;
117
118  void DispatchViewInputEventToWindowManager(EventPtr event);
119
120  // These functions trivially delegate to all ViewManagerServiceImpls, which in
121  // term notify their clients.
122  void ProcessViewDestroyed(ServerView* view);
123  void ProcessViewBoundsChanged(const ServerView* view,
124                                const gfx::Rect& old_bounds,
125                                const gfx::Rect& new_bounds);
126  void ProcessWillChangeViewHierarchy(const ServerView* view,
127                                      const ServerView* new_parent,
128                                      const ServerView* old_parent);
129  void ProcessViewHierarchyChanged(const ServerView* view,
130                                   const ServerView* new_parent,
131                                   const ServerView* old_parent);
132  void ProcessViewReorder(const ServerView* view,
133                          const ServerView* relative_view,
134                          const OrderDirection direction);
135  void ProcessViewDeleted(const ViewId& view);
136
137 private:
138  typedef std::map<ConnectionSpecificId, ViewManagerServiceImpl*> ConnectionMap;
139
140  // Invoked when a connection is about to make a change.  Subsequently followed
141  // by FinishChange() once the change is done.
142  //
143  // Changes should never nest, meaning each PrepareForChange() must be
144  // balanced with a call to FinishChange() with no PrepareForChange()
145  // in between.
146  void PrepareForChange(ScopedChange* change);
147
148  // Balances a call to PrepareForChange().
149  void FinishChange();
150
151  // Returns true if the specified connection originated the current change.
152  bool IsChangeSource(ConnectionSpecificId connection_id) const {
153    return current_change_ && current_change_->connection_id() == connection_id;
154  }
155
156  // Implementation of the two embed variants.
157  ViewManagerServiceImpl* EmbedImpl(
158      ConnectionSpecificId creator_id,
159      const String& url,
160      const ViewId& root_id,
161      InterfaceRequest<ServiceProvider> service_provider);
162
163  // Overridden from ServerViewDelegate:
164  virtual void OnViewDestroyed(const ServerView* view) OVERRIDE;
165  virtual void OnWillChangeViewHierarchy(const ServerView* view,
166                                         const ServerView* new_parent,
167                                         const ServerView* old_parent) OVERRIDE;
168  virtual void OnViewHierarchyChanged(const ServerView* view,
169                                      const ServerView* new_parent,
170                                      const ServerView* old_parent) OVERRIDE;
171  virtual void OnViewBoundsChanged(const ServerView* view,
172                                   const gfx::Rect& old_bounds,
173                                   const gfx::Rect& new_bounds) OVERRIDE;
174  virtual void OnViewSurfaceIdChanged(const ServerView* view) OVERRIDE;
175  virtual void OnWillChangeViewVisibility(const ServerView* view) OVERRIDE;
176
177  ApplicationConnection* app_connection_;
178
179  // ID to use for next ViewManagerServiceImpl.
180  ConnectionSpecificId next_connection_id_;
181
182  // Set of ViewManagerServiceImpls.
183  ConnectionMap connection_map_;
184
185  DisplayManager display_manager_;
186
187  scoped_ptr<ServerView> root_;
188
189  // Set of ViewManagerServiceImpls created by way of Connect(). These have to
190  // be explicitly destroyed.
191  std::set<ViewManagerServiceImpl*> connections_created_by_connect_;
192
193  // If non-null we're processing a change. The ScopedChange is not owned by us
194  // (it's created on the stack by ViewManagerServiceImpl).
195  ScopedChange* current_change_;
196
197  DISALLOW_COPY_AND_ASSIGN(ConnectionManager);
198};
199
200}  // namespace service
201}  // namespace mojo
202
203#endif  // MOJO_SERVICES_VIEW_MANAGER_CONNECTION_MANAGER_H_
204