1 // Copyright 2015 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.
5 #ifndef COMPONENTS_WEB_VIEW_FRAME_H_
6 #define COMPONENTS_WEB_VIEW_FRAME_H_
11 #include "base/basictypes.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "components/view_manager/public/cpp/types.h"
14 #include "components/view_manager/public/cpp/view_observer.h"
15 #include "components/web_view/public/interfaces/frame_tree.mojom.h"
16 #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
21 class FrameTreeClient
;
24 enum class ViewOwnership
{
29 // Frame represents an embedding in a frame. Frames own their children.
30 // Frames automatically delete themself if the View the frame is associated
33 // In general each Frame has a View. When a new Frame is created by a client
34 // there may be a small amount of time where the View is not yet known to us
35 // (separate pipes are used for the view and frame, resulting in undefined
36 // message ordering). In this case the view is null and will be set once we
37 // see the view (OnTreeChanged()).
39 // When the FrameTreeClient creates a new Frame there is no associated
40 // FrameTreeClient for the child Frame.
42 // Each frame has an identifier of the app providing the FrameTreeClient
43 // (|app_id|). This id is used when servicing a request to navigate the frame.
44 // When navigating, if the id of the new app matches that of the existing app,
45 // then it is expected that the new FrameTreeClient will take over rendering to
46 // the existing view. Because of this a new ViewTreeClient is not obtained and
47 // Embed() is not invoked on the View. The FrameTreeClient can detect this case
48 // by the argument |reuse_existing_view| supplied to OnConnect(). Typically the
49 // id is that of content handler id, but this is left up to the
50 // FrameTreeDelegate to decide.
51 class Frame
: public mojo::ViewObserver
, public FrameTreeServer
{
53 using ClientPropertyMap
= std::map
<std::string
, std::vector
<uint8_t>>;
55 Frame(FrameTree
* tree
,
59 ViewOwnership view_ownership
,
60 FrameTreeClient
* frame_tree_client
,
61 scoped_ptr
<FrameUserData
> user_data
,
62 const ClientPropertyMap
& client_properties
);
65 void Init(Frame
* parent
, mojo::ViewTreeClientPtr view_tree_client
);
67 // Walks the View tree starting at |view| going up returning the first
68 // Frame that is associated with |view|. For example, if |view|
69 // has a Frame associated with it, then that is returned. Otherwise
70 // this checks view->parent() and so on.
71 static Frame
* FindFirstFrameAncestor(mojo::View
* view
);
73 FrameTree
* tree() { return tree_
; }
75 Frame
* parent() { return parent_
; }
76 const Frame
* parent() const { return parent_
; }
78 mojo::View
* view() { return view_
; }
79 const mojo::View
* view() const { return view_
; }
81 uint32_t id() const { return id_
; }
83 uint32_t app_id() const { return app_id_
; }
85 const ClientPropertyMap
& client_properties() const {
86 return client_properties_
;
89 // Finds the descendant with the specified id.
90 Frame
* FindFrame(uint32_t id
) {
91 return const_cast<Frame
*>(const_cast<const Frame
*>(this)->FindFrame(id
));
93 const Frame
* FindFrame(uint32_t id
) const;
95 bool HasAncestor(const Frame
* frame
) const;
97 FrameUserData
* user_data() { return user_data_
.get(); }
99 const std::vector
<Frame
*>& children() const { return children_
; }
101 // Returns true if this Frame or any child Frame is loading.
102 bool IsLoading() const;
104 // Returns the sum total of loading progress from this Frame and all of its
105 // children, as well as the number of Frames accumulated.
106 double GatherProgress(int* frame_count
) const;
109 friend class FrameTree
;
111 // Identifies whether the FrameTreeClient is from the same app or a different
113 enum class ClientType
{ SAME_APP
, NEW_APP
};
115 struct FrameTreeServerBinding
;
117 // Initializes the client by sending it the state of the tree.
118 // |frame_tree_server_binding| contains the current FrameTreeServerBinding
119 // (if any) and is destroyed after the connection responds to OnConnect().
121 // If |client_type| is SAME_APP we can't destroy the existing client
122 // (and related data) until we get back the ack from OnConnect(). This way
123 // we know the client has completed the switch. If we did not do this it
124 // would be possible for the app to see it's existing FrameTreeServer
125 // connection lost (and assume the frame is being torn down) before the
127 void InitClient(ClientType client_type
,
128 scoped_ptr
<FrameTreeServerBinding
> frame_tree_server_binding
,
129 mojo::ViewTreeClientPtr view_tree_client
);
131 // Callback from OnConnect(). This does nothing (other than destroying
132 // |frame_tree_server_binding|). See InitClient() for details as to why
133 // destruction of |frame_tree_server_binding| happens after OnConnect().
134 static void OnConnectAck(
135 scoped_ptr
<FrameTreeServerBinding
> frame_tree_server_binding
);
137 // Callback from OnEmbed().
138 void OnEmbedAck(bool success
, mojo::ConnectionSpecificId connection_id
);
140 // Completes a navigation request; swapping the existing FrameTreeClient to
141 // the supplied arguments.
142 void ChangeClient(FrameTreeClient
* frame_tree_client
,
143 scoped_ptr
<FrameUserData
> user_data
,
144 mojo::ViewTreeClientPtr view_tree_client
,
147 void SetView(mojo::View
* view
);
149 // Returns the first ancestor (starting at |this|) that has a
151 Frame
* GetAncestorWithFrameTreeClient();
153 // Adds this to |frames| and recurses through the children calling the
155 void BuildFrameTree(std::vector
<const Frame
*>* frames
) const;
157 void Add(Frame
* node
);
158 void Remove(Frame
* node
);
160 // Starts a new navigation to |request|. The navigation proceeds as long
161 // as there is a View and once OnWillNavigate() has returned. If there is
162 // no View the navigation waits until the View is available.
163 void StartNavigate(mojo::URLRequestPtr request
);
164 void OnCanNavigateFrame(uint32_t app_id
,
165 FrameTreeClient
* frame_tree_client
,
166 scoped_ptr
<FrameUserData
> user_data
,
167 mojo::ViewTreeClientPtr view_tree_client
);
169 // The implementation of the various FrameTreeServer functions that take
170 // frame_id call into these.
171 void LoadingStartedImpl();
172 void LoadingStoppedImpl();
173 void ProgressChangedImpl(double progress
);
174 void TitleChangedImpl(const mojo::String
& title
);
175 void SetClientPropertyImpl(const mojo::String
& name
,
176 mojo::Array
<uint8_t> value
);
178 // Returns the Frame whose id is |frame_id|. Returns nullptr if |frame_id| is
179 // not from the same connection as this.
180 Frame
* FindFrameWithIdFromSameApp(uint32_t frame_id
);
182 // Notifies the client and all descendants as appropriate.
183 void NotifyAdded(const Frame
* source
,
184 const Frame
* added_node
,
186 void NotifyRemoved(const Frame
* source
,
187 const Frame
* removed_node
,
189 void NotifyClientPropertyChanged(const Frame
* source
,
190 const mojo::String
& name
,
191 const mojo::Array
<uint8_t>& value
);
193 // mojo::ViewObserver:
194 void OnTreeChanged(const TreeChangeParams
& params
) override
;
195 void OnViewDestroying(mojo::View
* view
) override
;
196 void OnViewEmbeddedAppDisconnected(mojo::View
* view
) override
;
199 void PostMessageEventToFrame(uint32_t source_frame_id
,
200 uint32_t target_frame_id
,
201 HTMLMessageEventPtr event
) override
;
202 void LoadingStarted(uint32_t frame_id
) override
;
203 void LoadingStopped(uint32_t frame_id
) override
;
204 void ProgressChanged(uint32_t frame_id
, double progress
) override
;
205 void TitleChanged(uint32_t frame_id
, const mojo::String
& title
) override
;
206 void SetClientProperty(uint32_t frame_id
,
207 const mojo::String
& name
,
208 mojo::Array
<uint8_t> value
) override
;
212 mojo::Map
<mojo::String
, mojo::Array
<uint8_t>> client_properties
) override
;
213 void RequestNavigate(NavigationTargetType target_type
,
214 uint32_t target_frame_id
,
215 mojo::URLRequestPtr request
) override
;
216 void DidNavigateLocally(uint32_t frame_id
, const mojo::String
& url
) override
;
218 FrameTree
* const tree_
;
219 // WARNING: this may be null. See class description for details.
221 // The connection id returned from ViewManager::Embed(). Frames created by
222 // way of OnCreatedFrame() inherit the id from the parent.
223 mojo::ConnectionSpecificId embedded_connection_id_
;
224 // ID for the frame, which is the same as that of the view.
226 // ID of the app providing the FrameTreeClient and ViewTreeClient.
229 ViewOwnership view_ownership_
;
230 std::vector
<Frame
*> children_
;
231 scoped_ptr
<FrameUserData
> user_data_
;
233 // WARNING: this may be null. See class description for details.
234 FrameTreeClient
* frame_tree_client_
;
239 ClientPropertyMap client_properties_
;
241 // StartNavigate() stores the request here if the view isn't available at
242 // the time of StartNavigate().
243 mojo::URLRequestPtr pending_navigate_
;
245 scoped_ptr
<mojo::Binding
<FrameTreeServer
>> frame_tree_server_binding_
;
247 base::WeakPtrFactory
<Frame
> embed_weak_ptr_factory_
;
249 base::WeakPtrFactory
<Frame
> navigate_weak_ptr_factory_
;
251 DISALLOW_COPY_AND_ASSIGN(Frame
);
254 } // namespace web_view
256 #endif // COMPONENTS_WEB_VIEW_FRAME_H_