Process Alt-Svc headers.
[chromium-blink-merge.git] / mandoline / tab / frame.cc
blob070361c3b3e8a567700143afb383dd6676703497
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 InitClient();
82 void Frame::Swap(FrameTreeClient* frame_tree_client,
83 scoped_ptr<FrameUserData> user_data) {
84 while (!children_.empty())
85 delete children_[0];
87 user_data_ = user_data.Pass();
88 frame_tree_client_ = frame_tree_client;
89 frame_tree_server_binding_.Close();
91 InitClient();
94 // static
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 {
102 if (id == id_)
103 return this;
105 for (const Frame* child : children_) {
106 const Frame* match = child->FindFrame(id);
107 if (match)
108 return match;
110 return nullptr;
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 {
121 if (loading_)
122 return true;
123 for (const Frame* child : children_) {
124 if (child->IsLoading())
125 return true;
127 return false;
130 double Frame::GatherProgress(int* frame_count) const {
131 ++(*frame_count);
132 double progress = progress_;
133 for (const Frame* child : children_)
134 progress += child->GatherProgress(frame_count);
135 return progress_;
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) {
154 DCHECK(!view_);
155 DCHECK_EQ(id_, view->id());
156 view_ = view;
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() {
187 DCHECK(!loading_);
188 loading_ = true;
189 progress_ = 0.f;
190 tree_->LoadingStateChanged();
193 void Frame::LoadingStoppedImpl() {
194 DCHECK(loading_);
195 loading_ = false;
196 tree_->LoadingStateChanged();
199 void Frame::ProgressChangedImpl(double progress) {
200 DCHECK(loading_);
201 progress_ = progress;
202 tree_->ProgressChanged();
205 void Frame::SetFrameNameImpl(const mojo::String& name) {
206 if (name_ == name)
207 return;
209 name_ = name;
210 tree_->FrameNameChanged(this);
213 Frame* Frame::FindTargetFrame(uint32_t frame_id) {
214 if (frame_id == 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.";
225 return nullptr;
228 return frame;
231 void Frame::NotifyAdded(const Frame* source, const Frame* added_node) {
232 if (added_node == this)
233 return;
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)
244 return;
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) {
270 if (parent_)
271 parent_->Remove(this);
273 // Reset |view_ownership_| so we don't attempt to delete |view_| in the
274 // destructor.
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);
280 view_ = nullptr;
281 return;
284 delete this;
287 void Frame::PostMessageEventToFrame(uint32_t frame_id, MessageEventPtr event) {
288 Frame* target = tree_->root()->FindFrame(frame_id);
289 if (!target ||
290 !tree_->delegate_->CanPostMessageEventToFrame(this, target, event.get()))
291 return;
293 NOTIMPLEMENTED();
296 void Frame::LoadingStarted(uint32_t frame_id) {
297 Frame* target_frame = FindTargetFrame(frame_id);
298 if (target_frame)
299 target_frame->LoadingStartedImpl();
302 void Frame::LoadingStopped(uint32_t frame_id) {
303 Frame* target_frame = FindTargetFrame(frame_id);
304 if (target_frame)
305 target_frame->LoadingStoppedImpl();
308 void Frame::ProgressChanged(uint32_t frame_id, double progress) {
309 Frame* target_frame = FindTargetFrame(frame_id);
310 if (target_frame)
311 target_frame->ProgressChangedImpl(progress);
314 void Frame::SetFrameName(uint32_t frame_id, const mojo::String& name) {
315 Frame* target_frame = FindTargetFrame(frame_id);
316 if (target_frame)
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
323 // do it.
325 if (FindFrame(frame_id)) {
326 // TODO(sky): kill connection here?
327 DVLOG(1) << "OnCreatedLocalFrame supplied id of existing frame.";
328 return;
331 Frame* parent_frame = FindFrame(parent_id);
332 if (!parent_frame) {
333 DVLOG(1) << "OnCreatedLocalFrame supplied invalid parent_id.";
334 return;
337 if (parent_frame != this && parent_frame->frame_tree_client_) {
338 DVLOG(1) << "OnCreatedLocalFrame supplied parent from another connection.";
339 return;
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);
349 if (!frame) {
350 DVLOG(1) << "RequestNavigate for unknown frame " << frame_id;
351 return;
353 if (tree_->delegate_)
354 tree_->delegate_->RequestNavigate(frame, target, request.Pass());
357 void Frame::DidNavigateLocally(uint32_t frame_id, const mojo::String& url) {
358 NOTIMPLEMENTED();
361 } // namespace mandoline