Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / mandoline / tab / frame.cc
bloba2b4d49fb78a7dbde3ca3de81c51f2354606cdcf
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"
7 #include <algorithm>
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"
16 using mojo::View;
18 DECLARE_VIEW_PROPERTY_TYPE(mandoline::Frame*);
20 namespace mandoline {
22 // Used to find the Frame associated with a View.
23 DEFINE_LOCAL_VIEW_PROPERTY_KEY(Frame*, kFrame, nullptr);
25 namespace {
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();
39 } // namespace
41 Frame::Frame(FrameTree* tree,
42 View* view,
43 uint32_t id,
44 ViewOwnership view_ownership,
45 FrameTreeClient* frame_tree_client,
46 scoped_ptr<FrameUserData> user_data)
47 : tree_(tree),
48 view_(nullptr),
49 id_(id),
50 parent_(nullptr),
51 view_ownership_(view_ownership),
52 user_data_(user_data.Pass()),
53 frame_tree_client_(frame_tree_client),
54 loading_(false),
55 progress_(0.f),
56 frame_tree_server_binding_(this) {
57 if (view)
58 SetView(view);
61 Frame::~Frame() {
62 if (view_)
63 view_->RemoveObserver(this);
64 while (!children_.empty())
65 delete children_[0];
66 if (parent_)
67 parent_->Remove(this);
68 if (view_) {
69 view_->ClearLocalProperty(kFrame);
70 if (view_ownership_ == ViewOwnership::OWNS_VIEW)
71 view_->Destroy();
75 void Frame::Init(Frame* parent) {
76 if (parent)
77 parent->Add(this);
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());
93 // static
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 {
101 if (id == id_)
102 return this;
104 for (const Frame* child : children_) {
105 const Frame* match = child->FindFrame(id);
106 if (match)
107 return match;
109 return nullptr;
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 {
120 if (loading_)
121 return true;
122 for (const Frame* child : children_) {
123 if (child->IsLoading())
124 return true;
126 return false;
129 double Frame::GatherProgress(int* frame_count) const {
130 ++(*frame_count);
131 double progress = progress_;
132 for (const Frame* child : children_)
133 progress += child->GatherProgress(frame_count);
134 return progress_;
137 void Frame::SetView(mojo::View* view) {
138 DCHECK(!view_);
139 DCHECK_EQ(id_, view->id());
140 view_ = view;
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() {
171 DCHECK(!loading_);
172 loading_ = true;
173 progress_ = 0.f;
174 tree_->LoadingStateChanged();
177 void Frame::LoadingStoppedImpl() {
178 DCHECK(loading_);
179 loading_ = false;
180 tree_->LoadingStateChanged();
183 void Frame::ProgressChangedImpl(double progress) {
184 DCHECK(loading_);
185 progress_ = progress;
186 tree_->ProgressChanged();
189 void Frame::SetFrameNameImpl(const mojo::String& name) {
190 if (name_ == name)
191 return;
193 name_ = name;
194 tree_->FrameNameChanged(this);
197 Frame* Frame::FindTargetFrame(uint32_t frame_id) {
198 if (frame_id == 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.";
209 return nullptr;
212 return frame;
215 void Frame::NotifyAdded(const Frame* source, const Frame* added_node) {
216 if (added_node == this)
217 return;
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)
228 return;
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) {
254 if (parent_)
255 parent_->Remove(this);
257 // Reset |view_ownership_| so we don't attempt to delete |view_| in the
258 // destructor.
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);
264 view_ = nullptr;
265 return;
268 delete this;
271 void Frame::PostMessageEventToFrame(uint32_t frame_id, MessageEventPtr event) {
272 Frame* target = tree_->root()->FindFrame(frame_id);
273 if (!target ||
274 !tree_->delegate_->CanPostMessageEventToFrame(this, target, event.get()))
275 return;
277 NOTIMPLEMENTED();
280 void Frame::LoadingStarted(uint32_t frame_id) {
281 Frame* target_frame = FindTargetFrame(frame_id);
282 if (target_frame)
283 target_frame->LoadingStartedImpl();
286 void Frame::LoadingStopped(uint32_t frame_id) {
287 Frame* target_frame = FindTargetFrame(frame_id);
288 if (target_frame)
289 target_frame->LoadingStoppedImpl();
292 void Frame::ProgressChanged(uint32_t frame_id, double progress) {
293 Frame* target_frame = FindTargetFrame(frame_id);
294 if (target_frame)
295 target_frame->ProgressChangedImpl(progress);
298 void Frame::SetFrameName(uint32_t frame_id, const mojo::String& name) {
299 Frame* target_frame = FindTargetFrame(frame_id);
300 if (target_frame)
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
307 // do it.
309 if (FindFrame(frame_id)) {
310 // TODO(sky): kill connection here?
311 DVLOG(1) << "OnCreatedLocalFrame supplied id of existing frame.";
312 return;
315 Frame* parent_frame = FindFrame(parent_id);
316 if (!parent_frame) {
317 DVLOG(1) << "OnCreatedLocalFrame supplied invalid parent_id.";
318 return;
321 if (parent_frame != this && parent_frame->frame_tree_client_) {
322 DVLOG(1) << "OnCreatedLocalFrame supplied parent from another connection.";
323 return;
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);
333 if (!frame) {
334 DVLOG(1) << "RequestNavigate for unknown frame " << frame_id;
335 return;
337 tree_->delegate_->RequestNavigate(frame, target, request.Pass());
340 void Frame::DidNavigateLocally(uint32_t frame_id, const mojo::String& url) {
341 NOTIMPLEMENTED();
344 } // namespace mandoline