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 #include "mandoline/tab/frame.h"
9 #include "base/stl_util.h"
10 #include "components/view_manager/public/cpp/view.h"
11 #include "components/view_manager/public/cpp/view_property.h"
12 #include "mandoline/tab/frame_tree.h"
13 #include "mandoline/tab/frame_tree_delegate.h"
14 #include "mandoline/tab/frame_user_data.h"
18 DECLARE_VIEW_PROPERTY_TYPE(mandoline::Frame
*);
22 // Used to find the Frame associated with a View.
23 DEFINE_LOCAL_VIEW_PROPERTY_KEY(Frame
*, kFrame
, nullptr);
27 const uint32_t kNoParentId
= 0u;
29 FrameDataPtr
FrameToFrameData(const Frame
* frame
) {
30 FrameDataPtr
frame_data(FrameData::New());
31 frame_data
->frame_id
= frame
->id();
32 frame_data
->parent_id
= frame
->parent() ? frame
->parent()->id() : kNoParentId
;
33 frame_data
->name
= frame
->name();
34 // TODO(sky): implement me.
35 frame_data
->origin
= std::string();
36 return frame_data
.Pass();
41 Frame::Frame(FrameTree
* tree
,
44 ViewOwnership view_ownership
,
45 FrameTreeClient
* frame_tree_client
,
46 scoped_ptr
<FrameUserData
> user_data
)
51 view_ownership_(view_ownership
),
52 user_data_(user_data
.Pass()),
53 frame_tree_client_(frame_tree_client
),
56 frame_tree_server_binding_(this) {
63 view_
->RemoveObserver(this);
64 while (!children_
.empty())
67 parent_
->Remove(this);
69 view_
->ClearLocalProperty(kFrame
);
70 if (view_ownership_
== ViewOwnership::OWNS_VIEW
)
75 void Frame::Init(Frame
* parent
) {
82 void Frame::Swap(FrameTreeClient
* frame_tree_client
,
83 scoped_ptr
<FrameUserData
> user_data
) {
84 while (!children_
.empty())
87 user_data_
= user_data
.Pass();
88 frame_tree_client_
= frame_tree_client
;
89 frame_tree_server_binding_
.Close();
95 Frame
* Frame::FindFirstFrameAncestor(View
* view
) {
96 while (view
&& !view
->GetLocalProperty(kFrame
))
97 view
= view
->parent();
98 return view
? view
->GetLocalProperty(kFrame
) : nullptr;
101 const Frame
* Frame::FindFrame(uint32_t id
) const {
105 for (const Frame
* child
: children_
) {
106 const Frame
* match
= child
->FindFrame(id
);
113 bool Frame::HasAncestor(const Frame
* frame
) const {
114 const Frame
* current
= this;
115 while (current
&& current
!= frame
)
116 current
= current
->parent_
;
117 return current
== frame
;
120 bool Frame::IsLoading() const {
123 for (const Frame
* child
: children_
) {
124 if (child
->IsLoading())
130 double Frame::GatherProgress(int* frame_count
) const {
132 double progress
= progress_
;
133 for (const Frame
* child
: children_
)
134 progress
+= child
->GatherProgress(frame_count
);
138 void Frame::InitClient() {
139 std::vector
<const Frame
*> frames
;
140 tree_
->root()->BuildFrameTree(&frames
);
142 mojo::Array
<FrameDataPtr
> array(frames
.size());
143 for (size_t i
= 0; i
< frames
.size(); ++i
)
144 array
[i
] = FrameToFrameData(frames
[i
]).Pass();
146 // TODO(sky): error handling.
147 FrameTreeServerPtr frame_tree_server_ptr
;
148 frame_tree_server_binding_
.Bind(GetProxy(&frame_tree_server_ptr
).Pass());
149 if (frame_tree_client_
)
150 frame_tree_client_
->OnConnect(frame_tree_server_ptr
.Pass(), array
.Pass());
153 void Frame::SetView(mojo::View
* view
) {
155 DCHECK_EQ(id_
, view
->id());
157 view_
->SetLocalProperty(kFrame
, this);
158 view_
->AddObserver(this);
161 void Frame::BuildFrameTree(std::vector
<const Frame
*>* frames
) const {
162 frames
->push_back(this);
163 for (const Frame
* frame
: children_
)
164 frame
->BuildFrameTree(frames
);
167 void Frame::Add(Frame
* node
) {
168 DCHECK(!node
->parent_
);
170 node
->parent_
= this;
171 children_
.push_back(node
);
173 tree_
->root()->NotifyAdded(this, node
);
176 void Frame::Remove(Frame
* node
) {
177 DCHECK_EQ(node
->parent_
, this);
178 auto iter
= std::find(children_
.begin(), children_
.end(), node
);
179 DCHECK(iter
!= children_
.end());
180 node
->parent_
= nullptr;
181 children_
.erase(iter
);
183 tree_
->root()->NotifyRemoved(this, node
);
186 void Frame::LoadingStartedImpl() {
190 tree_
->LoadingStateChanged();
193 void Frame::LoadingStoppedImpl() {
196 tree_
->LoadingStateChanged();
199 void Frame::ProgressChangedImpl(double progress
) {
201 progress_
= progress
;
202 tree_
->ProgressChanged();
205 void Frame::SetFrameNameImpl(const mojo::String
& name
) {
210 tree_
->FrameNameChanged(this);
213 Frame
* Frame::FindTargetFrame(uint32_t frame_id
) {
215 return this; // Common case.
217 // TODO(sky): I need a way to sanity check frame_id here, but the connection
218 // id isn't known to us.
220 Frame
* frame
= FindFrame(frame_id
);
221 if (frame
->frame_tree_client_
) {
222 // The frame has it's own client/server pair. It should make requests using
223 // the server it has rather than an ancestor.
224 DVLOG(1) << "ignore request for a frame that has its own client.";
231 void Frame::NotifyAdded(const Frame
* source
, const Frame
* added_node
) {
232 if (added_node
== this)
235 if (source
!= this && frame_tree_client_
)
236 frame_tree_client_
->OnFrameAdded(FrameToFrameData(added_node
));
238 for (Frame
* child
: children_
)
239 child
->NotifyAdded(source
, added_node
);
242 void Frame::NotifyRemoved(const Frame
* source
, const Frame
* removed_node
) {
243 if (removed_node
== this)
246 if (source
!= this && frame_tree_client_
)
247 frame_tree_client_
->OnFrameRemoved(removed_node
->id());
249 for (Frame
* child
: children_
)
250 child
->NotifyRemoved(source
, removed_node
);
253 void Frame::NotifyFrameNameChanged(const Frame
* source
) {
254 if (this != source
&& frame_tree_client_
)
255 frame_tree_client_
->OnFrameNameChanged(source
->id(), source
->name_
);
257 for (Frame
* child
: children_
)
258 child
->NotifyFrameNameChanged(source
);
261 void Frame::OnTreeChanged(const TreeChangeParams
& params
) {
262 if (params
.new_parent
&& this == tree_
->root()) {
263 Frame
* child_frame
= FindFrame(params
.target
->id());
264 if (child_frame
&& !child_frame
->view_
)
265 child_frame
->SetView(params
.target
);
269 void Frame::OnViewDestroying(mojo::View
* view
) {
271 parent_
->Remove(this);
273 // Reset |view_ownership_| so we don't attempt to delete |view_| in the
275 view_ownership_
= ViewOwnership::DOESNT_OWN_VIEW
;
277 // TODO(sky): Change browser to create a child for each FrameTree.
278 if (tree_
->root() == this) {
279 view_
->RemoveObserver(this);
287 void Frame::PostMessageEventToFrame(uint32_t frame_id
, MessageEventPtr event
) {
288 Frame
* target
= tree_
->root()->FindFrame(frame_id
);
290 !tree_
->delegate_
->CanPostMessageEventToFrame(this, target
, event
.get()))
296 void Frame::LoadingStarted(uint32_t frame_id
) {
297 Frame
* target_frame
= FindTargetFrame(frame_id
);
299 target_frame
->LoadingStartedImpl();
302 void Frame::LoadingStopped(uint32_t frame_id
) {
303 Frame
* target_frame
= FindTargetFrame(frame_id
);
305 target_frame
->LoadingStoppedImpl();
308 void Frame::ProgressChanged(uint32_t frame_id
, double progress
) {
309 Frame
* target_frame
= FindTargetFrame(frame_id
);
311 target_frame
->ProgressChangedImpl(progress
);
314 void Frame::SetFrameName(uint32_t frame_id
, const mojo::String
& name
) {
315 Frame
* target_frame
= FindTargetFrame(frame_id
);
317 target_frame
->SetFrameNameImpl(name
);
320 void Frame::OnCreatedFrame(uint32_t parent_id
, uint32_t frame_id
) {
321 // TODO(sky): I need a way to verify the id. Unfortunately the code here
322 // doesn't know the connection id of the embedder, so it's not possible to
325 if (FindFrame(frame_id
)) {
326 // TODO(sky): kill connection here?
327 DVLOG(1) << "OnCreatedLocalFrame supplied id of existing frame.";
331 Frame
* parent_frame
= FindFrame(parent_id
);
333 DVLOG(1) << "OnCreatedLocalFrame supplied invalid parent_id.";
337 if (parent_frame
!= this && parent_frame
->frame_tree_client_
) {
338 DVLOG(1) << "OnCreatedLocalFrame supplied parent from another connection.";
342 tree_
->CreateSharedFrame(parent_frame
, frame_id
);
345 void Frame::RequestNavigate(uint32_t frame_id
,
346 mandoline::NavigationTarget target
,
347 mojo::URLRequestPtr request
) {
348 Frame
* frame
= FindFrame(frame_id
);
350 DVLOG(1) << "RequestNavigate for unknown frame " << frame_id
;
353 if (tree_
->delegate_
)
354 tree_
->delegate_
->RequestNavigate(frame
, target
, request
.Pass());
357 void Frame::DidNavigateLocally(uint32_t frame_id
, const mojo::String
& url
) {
361 } // namespace mandoline