summaryrefslogtreecommitdiffstats
path: root/components/view_manager/view_tree_impl.h
blob: 3db118c190e58b47fcd04ef734aa00235c82e21d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_VIEW_MANAGER_VIEW_TREE_IMPL_H_
#define COMPONENTS_VIEW_MANAGER_VIEW_TREE_IMPL_H_

#include <set>
#include <string>
#include <vector>

#include "base/basictypes.h"
#include "base/containers/hash_tables.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "components/view_manager/access_policy_delegate.h"
#include "components/view_manager/ids.h"
#include "components/view_manager/public/interfaces/surface_id.mojom.h"
#include "components/view_manager/public/interfaces/view_tree.mojom.h"

namespace gfx {
class Rect;
}

namespace view_manager {

class AccessPolicy;
class ConnectionManager;
class ServerView;

// An instance of ViewTreeImpl is created for every ViewTree request.
// ViewTreeImpl tracks all the state and views created by a client. ViewTreeImpl
// coordinates with ConnectionManager to update the client (and internal state)
// as necessary.
class ViewTreeImpl : public mojo::ViewTree, public AccessPolicyDelegate {
 public:
   ViewTreeImpl(ConnectionManager* connection_manager,
                mojo::ConnectionSpecificId creator_id,
                const ViewId& root_id);
   ~ViewTreeImpl() override;

  // |services| and |exposed_services| are the ServiceProviders to pass to the
  // client via OnEmbed().
  void Init(mojo::ViewTreeClient* client, mojo::ViewTreePtr tree);

  mojo::ConnectionSpecificId id() const { return id_; }
  mojo::ConnectionSpecificId creator_id() const { return creator_id_; }

  mojo::ViewTreeClient* client() { return client_; }

  // Returns the View with the specified id.
  ServerView* GetView(const ViewId& id) {
    return const_cast<ServerView*>(
        const_cast<const ViewTreeImpl*>(this)->GetView(id));
  }
  const ServerView* GetView(const ViewId& id) const;

  // Returns true if this connection's root is |id|.
  bool IsRoot(const ViewId& id) const;

  // Returns the id of the root node. This is null if the root has been
  // destroyed but the connection is still valid.
  const ViewId* root() const { return root_.get(); }

  bool is_embed_root() const { return is_embed_root_; }

  // Invoked when a connection is about to be destroyed.
  void OnWillDestroyViewTreeImpl(ViewTreeImpl* connection);

  // These functions are synchronous variants of those defined in the mojom. The
  // ViewTree implementations all call into these. See the mojom for details.
  mojo::ErrorCode CreateView(const ViewId& view_id);
  bool AddView(const ViewId& parent_id, const ViewId& child_id);
  std::vector<const ServerView*> GetViewTree(const ViewId& view_id) const;
  bool SetViewVisibility(const ViewId& view_id, bool visible);
  bool Embed(const ViewId& view_id, mojo::ViewTreeClientPtr client);
  void Embed(const ViewId& view_id, mojo::URLRequestPtr request);

  // The following methods are invoked after the corresponding change has been
  // processed. They do the appropriate bookkeeping and update the client as
  // necessary.
  void ProcessViewBoundsChanged(const ServerView* view,
                                const gfx::Rect& old_bounds,
                                const gfx::Rect& new_bounds,
                                bool originated_change);
  void ProcessViewportMetricsChanged(const mojo::ViewportMetrics& old_metrics,
                                     const mojo::ViewportMetrics& new_metrics,
                                     bool originated_change);
  void ProcessWillChangeViewHierarchy(const ServerView* view,
                                      const ServerView* new_parent,
                                      const ServerView* old_parent,
                                      bool originated_change);
  void ProcessViewPropertyChanged(const ServerView* view,
                                  const std::string& name,
                                  const std::vector<uint8_t>* new_data,
                                  bool originated_change);
  void ProcessViewHierarchyChanged(const ServerView* view,
                                   const ServerView* new_parent,
                                   const ServerView* old_parent,
                                   bool originated_change);
  void ProcessViewReorder(const ServerView* view,
                          const ServerView* relative_view,
                          mojo::OrderDirection direction,
                          bool originated_change);
  void ProcessViewDeleted(const ViewId& view, bool originated_change);
  void ProcessWillChangeViewVisibility(const ServerView* view,
                                       bool originated_change);
  void ProcessFocusChanged(const ServerView* old_focused_view,
                           const ServerView* new_focused_view);

 private:
  using ViewIdSet = base::hash_set<mojo::Id>;
  using ViewMap = std::map<mojo::ConnectionSpecificId, ServerView*>;

  bool IsViewKnown(const ServerView* view) const;

  // These functions return true if the corresponding mojom function is allowed
  // for this connection.
  bool CanReorderView(const ServerView* view,
                      const ServerView* relative_view,
                      mojo::OrderDirection direction) const;

  // Deletes a view owned by this connection. Returns true on success. |source|
  // is the connection that originated the change.
  bool DeleteViewImpl(ViewTreeImpl* source, ServerView* view);

  // If |view| is known (in |known_views_|) does nothing. Otherwise adds |view|
  // to |views|, marks |view| as known and recurses.
  void GetUnknownViewsFrom(const ServerView* view,
                           std::vector<const ServerView*>* views);

  // Removes |view| and all its descendants from |known_views_|. This does not
  // recurse through views that were created by this connection. All views owned
  // by this connection are added to |local_views|.
  void RemoveFromKnown(const ServerView* view,
                       std::vector<ServerView*>* local_views);

  // Resets the root of this connection.
  void RemoveRoot();

  // Converts View(s) to ViewData(s) for transport. This assumes all the views
  // are valid for the client. The parent of views the client is not allowed to
  // see are set to NULL (in the returned ViewData(s)).
  mojo::Array<mojo::ViewDataPtr> ViewsToViewDatas(
      const std::vector<const ServerView*>& views);
  mojo::ViewDataPtr ViewToViewData(const ServerView* view);

  // Implementation of GetViewTree(). Adds |view| to |views| and recurses if
  // CanDescendIntoViewForViewTree() returns true.
  void GetViewTreeImpl(const ServerView* view,
                       std::vector<const ServerView*>* views) const;

  // Notify the client if the drawn state of any of the roots changes.
  // |view| is the view that is changing to the drawn state |new_drawn_value|.
  void NotifyDrawnStateChanged(const ServerView* view, bool new_drawn_value);

  // Deletes all Views we own.
  void DestroyViews();

  bool CanEmbed(const ViewId& view_id) const;
  void PrepareForEmbed(const ViewId& view_id);
  void RemoveChildrenAsPartOfEmbed(const ViewId& view_id);

  // ViewTree:
  void CreateView(
      mojo::Id transport_view_id,
      const mojo::Callback<void(mojo::ErrorCode)>& callback) override;
  void DeleteView(mojo::Id transport_view_id,
                  const mojo::Callback<void(bool)>& callback) override;
  void AddView(mojo::Id parent_id,
               mojo::Id child_id,
               const mojo::Callback<void(bool)>& callback) override;
  void RemoveViewFromParent(
      mojo::Id view_id,
      const mojo::Callback<void(bool)>& callback) override;
  void ReorderView(mojo::Id view_id,
                   mojo::Id relative_view_id,
                   mojo::OrderDirection direction,
                   const mojo::Callback<void(bool)>& callback) override;
  void GetViewTree(mojo::Id view_id,
                   const mojo::Callback<void(mojo::Array<mojo::ViewDataPtr>)>&
                       callback) override;
  void SetViewBounds(mojo::Id view_id,
                     mojo::RectPtr bounds,
                     const mojo::Callback<void(bool)>& callback) override;
  void SetViewVisibility(mojo::Id view_id,
                         bool visible,
                         const mojo::Callback<void(bool)>& callback) override;
  void SetViewProperty(mojo::Id view_id,
                       const mojo::String& name,
                       mojo::Array<uint8_t> value,
                       const mojo::Callback<void(bool)>& callback) override;
  void RequestSurface(
      mojo::Id view_id,
      mojo::InterfaceRequest<mojo::Surface> surface,
      mojo::SurfaceClientPtr client) override;
  void SetEmbedRoot() override;
  void Embed(mojo::Id transport_view_id,
             mojo::ViewTreeClientPtr client,
             const mojo::Callback<void(bool)>& callback) override;
  void SetFocus(uint32_t view_id, const SetFocusCallback& callback) override;
  void SetViewTextInputState(uint32_t view_id,
                             mojo::TextInputStatePtr state) override;
  void SetImeVisibility(uint32_t view_id,
                        bool visible,
                        mojo::TextInputStatePtr state) override;


  // AccessPolicyDelegate:
  bool IsRootForAccessPolicy(const ViewId& id) const override;
  bool IsViewKnownForAccessPolicy(const ServerView* view) const override;
  bool IsViewRootOfAnotherConnectionForAccessPolicy(
      const ServerView* view) const override;
  bool IsDescendantOfEmbedRoot(const ServerView* view) override;

  ConnectionManager* connection_manager_;

  // Id of this connection as assigned by ConnectionManager.
  const mojo::ConnectionSpecificId id_;

  // ID of the connection that created us. If 0 it indicates either we were
  // created by the root, or the connection that created us has been destroyed.
  mojo::ConnectionSpecificId creator_id_;

  mojo::ViewTreeClient* client_;

  scoped_ptr<AccessPolicy> access_policy_;

  // The views created by this connection. This connection owns these objects.
  ViewMap view_map_;

  // The set of views that has been communicated to the client.
  ViewIdSet known_views_;

  // The root of this connection. This is a scoped_ptr to reinforce the
  // connection may have no root. A connection has no root if either the root
  // is destroyed or Embed() is invoked on the root.
  scoped_ptr<ViewId> root_;

  bool is_embed_root_;

  DISALLOW_COPY_AND_ASSIGN(ViewTreeImpl);
};

}  // namespace view_manager

#endif  // COMPONENTS_VIEW_MANAGER_VIEW_TREE_IMPL_H_