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
) {
79 std::vector
<const Frame
*> frames
;
80 tree_
->root()->BuildFrameTree(&frames
);
82 mojo::Array
<FrameDataPtr
> array(frames
.size());
83 for (size_t i
= 0; i
< frames
.size(); ++i
)
84 array
[i
] = FrameToFrameData(frames
[i
]).Pass();
86 // TODO(sky): error handling.
87 FrameTreeServerPtr frame_tree_server_ptr
;
88 frame_tree_server_binding_
.Bind(GetProxy(&frame_tree_server_ptr
).Pass());
89 if (frame_tree_client_
)
90 frame_tree_client_
->OnConnect(frame_tree_server_ptr
.Pass(), array
.Pass());
94 Frame
* Frame::FindFirstFrameAncestor(View
* view
) {
95 while (view
&& !view
->GetLocalProperty(kFrame
))
96 view
= view
->parent();
97 return view
? view
->GetLocalProperty(kFrame
) : nullptr;
100 const Frame
* Frame::FindFrame(uint32_t id
) const {
104 for (const Frame
* child
: children_
) {
105 const Frame
* match
= child
->FindFrame(id
);
112 bool Frame::HasAncestor(const Frame
* frame
) const {
113 const Frame
* current
= this;
114 while (current
&& current
!= frame
)
115 current
= current
->parent_
;
116 return current
== frame
;
119 bool Frame::IsLoading() const {
122 for (const Frame
* child
: children_
) {
123 if (child
->IsLoading())
129 double Frame::GatherProgress(int* frame_count
) const {
131 double progress
= progress_
;
132 for (const Frame
* child
: children_
)
133 progress
+= child
->GatherProgress(frame_count
);
137 void Frame::SetView(mojo::View
* view
) {
139 DCHECK_EQ(id_
, view
->id());
141 view_
->SetLocalProperty(kFrame
, this);
142 view_
->AddObserver(this);
145 void Frame::BuildFrameTree(std::vector
<const Frame
*>* frames
) const {
146 frames
->push_back(this);
147 for (const Frame
* frame
: children_
)
148 frame
->BuildFrameTree(frames
);
151 void Frame::Add(Frame
* node
) {
152 DCHECK(!node
->parent_
);
154 node
->parent_
= this;
155 children_
.push_back(node
);
157 tree_
->root()->NotifyAdded(this, node
);
160 void Frame::Remove(Frame
* node
) {
161 DCHECK_EQ(node
->parent_
, this);
162 auto iter
= std::find(children_
.begin(), children_
.end(), node
);
163 DCHECK(iter
!= children_
.end());
164 node
->parent_
= nullptr;
165 children_
.erase(iter
);
167 tree_
->root()->NotifyRemoved(this, node
);
170 void Frame::LoadingStartedImpl() {
174 tree_
->LoadingStateChanged();
177 void Frame::LoadingStoppedImpl() {
180 tree_
->LoadingStateChanged();
183 void Frame::ProgressChangedImpl(double progress
) {
185 progress_
= progress
;
186 tree_
->ProgressChanged();
189 void Frame::SetFrameNameImpl(const mojo::String
& name
) {
194 tree_
->FrameNameChanged(this);
197 Frame
* Frame::FindTargetFrame(uint32_t frame_id
) {
199 return this; // Common case.
201 // TODO(sky): I need a way to sanity check frame_id here, but the connection
202 // id isn't known to us.
204 Frame
* frame
= FindFrame(frame_id
);
205 if (frame
->frame_tree_client_
) {
206 // The frame has it's own client/server pair. It should make requests using
207 // the server it has rather than an ancestor.
208 DVLOG(1) << "ignore request for a frame that has its own client.";
215 void Frame::NotifyAdded(const Frame
* source
, const Frame
* added_node
) {
216 if (added_node
== this)
219 if (source
!= this && frame_tree_client_
)
220 frame_tree_client_
->OnFrameAdded(FrameToFrameData(added_node
));
222 for (Frame
* child
: children_
)
223 child
->NotifyAdded(source
, added_node
);
226 void Frame::NotifyRemoved(const Frame
* source
, const Frame
* removed_node
) {
227 if (removed_node
== this)
230 if (source
!= this && frame_tree_client_
)
231 frame_tree_client_
->OnFrameRemoved(removed_node
->id());
233 for (Frame
* child
: children_
)
234 child
->NotifyRemoved(source
, removed_node
);
237 void Frame::NotifyFrameNameChanged(const Frame
* source
) {
238 if (this != source
&& frame_tree_client_
)
239 frame_tree_client_
->OnFrameNameChanged(source
->id(), source
->name_
);
241 for (Frame
* child
: children_
)
242 child
->NotifyFrameNameChanged(source
);
245 void Frame::OnTreeChanged(const TreeChangeParams
& params
) {
246 if (params
.new_parent
&& this == tree_
->root()) {
247 Frame
* child_frame
= FindFrame(params
.target
->id());
248 if (child_frame
&& !child_frame
->view_
)
249 child_frame
->SetView(params
.target
);
253 void Frame::OnViewDestroying(mojo::View
* view
) {
255 parent_
->Remove(this);
257 // Reset |view_ownership_| so we don't attempt to delete |view_| in the
259 view_ownership_
= ViewOwnership::DOESNT_OWN_VIEW
;
261 // TODO(sky): Change browser to create a child for each FrameTree.
262 if (tree_
->root() == this) {
263 view_
->RemoveObserver(this);
271 void Frame::PostMessageEventToFrame(uint32_t frame_id
, MessageEventPtr event
) {
272 Frame
* target
= tree_
->root()->FindFrame(frame_id
);
274 !tree_
->delegate_
->CanPostMessageEventToFrame(this, target
, event
.get()))
280 void Frame::LoadingStarted(uint32_t frame_id
) {
281 Frame
* target_frame
= FindTargetFrame(frame_id
);
283 target_frame
->LoadingStartedImpl();
286 void Frame::LoadingStopped(uint32_t frame_id
) {
287 Frame
* target_frame
= FindTargetFrame(frame_id
);
289 target_frame
->LoadingStoppedImpl();
292 void Frame::ProgressChanged(uint32_t frame_id
, double progress
) {
293 Frame
* target_frame
= FindTargetFrame(frame_id
);
295 target_frame
->ProgressChangedImpl(progress
);
298 void Frame::SetFrameName(uint32_t frame_id
, const mojo::String
& name
) {
299 Frame
* target_frame
= FindTargetFrame(frame_id
);
301 target_frame
->SetFrameNameImpl(name
);
304 void Frame::OnCreatedFrame(uint32_t parent_id
, uint32_t frame_id
) {
305 // TODO(sky): I need a way to verify the id. Unfortunately the code here
306 // doesn't know the connection id of the embedder, so it's not possible to
309 if (FindFrame(frame_id
)) {
310 // TODO(sky): kill connection here?
311 DVLOG(1) << "OnCreatedLocalFrame supplied id of existing frame.";
315 Frame
* parent_frame
= FindFrame(parent_id
);
317 DVLOG(1) << "OnCreatedLocalFrame supplied invalid parent_id.";
321 if (parent_frame
!= this && parent_frame
->frame_tree_client_
) {
322 DVLOG(1) << "OnCreatedLocalFrame supplied parent from another connection.";
326 tree_
->CreateSharedFrame(parent_frame
, frame_id
);
329 void Frame::RequestNavigate(uint32_t frame_id
,
330 mandoline::NavigationTarget target
,
331 mojo::URLRequestPtr request
) {
332 Frame
* frame
= FindFrame(frame_id
);
334 DVLOG(1) << "RequestNavigate for unknown frame " << frame_id
;
337 tree_
->delegate_
->RequestNavigate(frame
, target
, request
.Pass());
340 void Frame::DidNavigateLocally(uint32_t frame_id
, const mojo::String
& url
) {
344 } // namespace mandoline