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/mus/public/cpp/types.h"
14 #include "components/mus/public/cpp/view_observer.h"
15 #include "components/web_view/public/interfaces/frame.mojom.h"
16 #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
28 enum class ViewOwnership
{
33 // Frame represents an embedding in a frame. Frames own their children.
34 // Frames automatically delete themself if the View the frame is associated
37 // In general each Frame has a View. When a new Frame is created by a client
38 // there may be a small amount of time where the View is not yet known
39 // (separate pipes are used for the view and frame, resulting in undefined
40 // message ordering). In this case the view is null and will be set once we
41 // see the view (OnTreeChanged()).
43 // Each frame has an identifier of the app providing the FrameClient
44 // (|app_id|). This id is used when servicing a request to navigate the frame.
45 // When navigating, if the id of the new app matches that of the existing app,
46 // then it is expected that the new FrameClient will take over rendering to the
47 // existing view. Because of this a new ViewTreeClient is not obtained and
48 // Embed() is not invoked on the View. The FrameClient can detect this case by
49 // the argument |reuse_existing_view| supplied to OnConnect(). Typically the id
50 // is that of content handler id, but this is left up to the FrameTreeDelegate
52 class Frame
: public mus::ViewObserver
, public mojom::Frame
{
54 using ClientPropertyMap
= std::map
<std::string
, std::vector
<uint8_t>>;
56 Frame(FrameTree
* tree
,
60 ViewOwnership view_ownership
,
61 mojom::FrameClient
* frame_client
,
62 scoped_ptr
<FrameUserData
> user_data
,
63 const ClientPropertyMap
& client_properties
);
66 void Init(Frame
* parent
,
67 mojo::ViewTreeClientPtr view_tree_client
,
68 mojo::InterfaceRequest
<mojom::Frame
> frame_request
);
70 // Walks the View tree starting at |view| going up returning the first
71 // Frame that is associated with |view|. For example, if |view|
72 // has a Frame associated with it, then that is returned. Otherwise
73 // this checks view->parent() and so on.
74 static Frame
* FindFirstFrameAncestor(mus::View
* view
);
76 FrameTree
* tree() { return tree_
; }
78 Frame
* parent() { return parent_
; }
79 const Frame
* parent() const { return parent_
; }
81 mus::View
* view() { return view_
; }
82 const mus::View
* view() const { return view_
; }
84 uint32_t id() const { return id_
; }
86 uint32_t app_id() const { return app_id_
; }
88 const ClientPropertyMap
& client_properties() const {
89 return client_properties_
;
92 // Finds the descendant with the specified id.
93 Frame
* FindFrame(uint32_t id
) {
94 return const_cast<Frame
*>(const_cast<const Frame
*>(this)->FindFrame(id
));
96 const Frame
* FindFrame(uint32_t id
) const;
98 bool HasAncestor(const Frame
* frame
) const;
100 FrameUserData
* user_data() { return user_data_
.get(); }
102 const std::vector
<Frame
*>& children() const { return children_
; }
104 // Returns true if this Frame or any child Frame is loading.
105 bool IsLoading() const;
107 // Returns the sum total of loading progress from this Frame and all of its
108 // children, as well as the number of Frames accumulated.
109 double GatherProgress(int* frame_count
) const;
112 friend class FrameTest
;
113 friend class FrameTree
;
115 // Identifies whether the FrameClient is from the same app or a different
117 enum class ClientType
{
118 // The client is either the root frame, or navigating an existing frame
119 // to a different app.
120 EXISTING_FRAME_NEW_APP
,
122 // The client is the result of navigating an existing frame to a new app.
123 EXISTING_FRAME_SAME_APP
,
125 // The client is the result of a new frame (not the root).
129 struct FrameUserDataAndBinding
;
131 // Initializes the client by sending it the state of the tree.
132 // |data_and_binding| contains the current FrameUserDataAndBinding (if any)
133 // and is destroyed after the connection responds to OnConnect().
135 // If |client_type| is SAME_APP we can't destroy the existing client
136 // (and related data) until we get back the ack from OnConnect(). This way
137 // we know the client has completed the switch. If we did not do this it
138 // would be possible for the app to see it's existing Frame connection lost
139 // (and assume the frame is being torn down) before the OnConnect().
140 void InitClient(ClientType client_type
,
141 scoped_ptr
<FrameUserDataAndBinding
> data_and_binding
,
142 mojo::ViewTreeClientPtr view_tree_client
,
143 mojo::InterfaceRequest
<mojom::Frame
> frame_request
);
145 // Callback from OnConnect(). This does nothing (other than destroying
146 // |data_and_binding|). See InitClient() for details as to why destruction of
147 // |data_and_binding| happens after OnConnect().
148 static void OnConnectAck(
149 scoped_ptr
<FrameUserDataAndBinding
> data_and_binding
);
151 // Callback from OnEmbed().
152 void OnEmbedAck(bool success
, mus::ConnectionSpecificId connection_id
);
154 // Completes a navigation request; swapping the existing FrameClient to the
155 // supplied arguments.
156 void ChangeClient(mojom::FrameClient
* frame_client
,
157 scoped_ptr
<FrameUserData
> user_data
,
158 mojo::ViewTreeClientPtr view_tree_client
,
161 void SetView(mus::View
* view
);
163 // Adds this to |frames| and recurses through the children calling the
165 void BuildFrameTree(std::vector
<const Frame
*>* frames
) const;
167 void Add(Frame
* node
);
168 void Remove(Frame
* node
);
170 // Starts a new navigation to |request|. The navigation proceeds as long
171 // as there is a View and once OnWillNavigate() has returned. If there is
172 // no View the navigation waits until the View is available.
173 void StartNavigate(mojo::URLRequestPtr request
);
174 void OnCanNavigateFrame(uint32_t app_id
,
175 mojom::FrameClient
* frame_client
,
176 scoped_ptr
<FrameUserData
> user_data
,
177 mojo::ViewTreeClientPtr view_tree_client
);
179 // Notifies the client and all descendants as appropriate.
180 void NotifyAdded(const Frame
* source
,
181 const Frame
* added_node
,
183 void NotifyRemoved(const Frame
* source
,
184 const Frame
* removed_node
,
186 void NotifyClientPropertyChanged(const Frame
* source
,
187 const mojo::String
& name
,
188 const mojo::Array
<uint8_t>& value
);
189 void NotifyFrameLoadingStateChanged(const Frame
* frame
, bool loading
);
190 void NotifyDispatchFrameLoadEvent(const Frame
* frame
);
192 // mus::ViewObserver:
193 void OnTreeChanged(const TreeChangeParams
& params
) override
;
194 void OnViewDestroying(mus::View
* view
) override
;
195 void OnViewEmbeddedAppDisconnected(mus::View
* view
) override
;
198 void PostMessageEventToFrame(uint32_t target_frame_id
,
199 mojom::HTMLMessageEventPtr event
) override
;
200 void LoadingStateChanged(bool loading
, double progress
) override
;
201 void TitleChanged(const mojo::String
& title
) override
;
202 void DidCommitProvisionalLoad() override
;
203 void SetClientProperty(const mojo::String
& name
,
204 mojo::Array
<uint8_t> value
) override
;
206 mojo::InterfaceRequest
<mojom::Frame
> frame_request
,
207 mojom::FrameClientPtr client
,
209 mojo::Map
<mojo::String
, mojo::Array
<uint8_t>> client_properties
) override
;
210 void RequestNavigate(mojom::NavigationTargetType target_type
,
211 uint32_t target_frame_id
,
212 mojo::URLRequestPtr request
) override
;
213 void DidNavigateLocally(const mojo::String
& url
) override
;
214 void DispatchLoadEventToParent() override
;
216 FrameTree
* const tree_
;
217 // WARNING: this may be null. See class description for details.
219 // The connection id returned from ViewManager::Embed(). Frames created by
220 // way of OnCreatedFrame() inherit the id from the parent.
221 mus::ConnectionSpecificId embedded_connection_id_
;
222 // ID for the frame, which is the same as that of the view.
224 // ID of the app providing the FrameClient and ViewTreeClient.
227 ViewOwnership view_ownership_
;
228 std::vector
<Frame
*> children_
;
229 scoped_ptr
<FrameUserData
> user_data_
;
231 mojom::FrameClient
* frame_client_
;
236 ClientPropertyMap client_properties_
;
238 // StartNavigate() stores the request here if the view isn't available at
239 // the time of StartNavigate().
240 mojo::URLRequestPtr pending_navigate_
;
242 scoped_ptr
<mojo::Binding
<mojom::Frame
>> frame_binding_
;
244 base::WeakPtrFactory
<Frame
> embed_weak_ptr_factory_
;
246 base::WeakPtrFactory
<Frame
> navigate_weak_ptr_factory_
;
248 DISALLOW_COPY_AND_ASSIGN(Frame
);
251 } // namespace web_view
253 #endif // COMPONENTS_WEB_VIEW_FRAME_H_