OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/web_view/frame.h" | 5 #include "components/web_view/frame.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 DECLARE_VIEW_PROPERTY_TYPE(web_view::Frame*); | 22 DECLARE_VIEW_PROPERTY_TYPE(web_view::Frame*); |
23 | 23 |
24 namespace web_view { | 24 namespace web_view { |
25 | 25 |
26 // Used to find the Frame associated with a View. | 26 // Used to find the Frame associated with a View. |
27 DEFINE_LOCAL_VIEW_PROPERTY_KEY(Frame*, kFrame, nullptr); | 27 DEFINE_LOCAL_VIEW_PROPERTY_KEY(Frame*, kFrame, nullptr); |
28 | 28 |
29 namespace { | 29 namespace { |
30 | 30 |
31 const uint32_t kNoParentId = 0u; | 31 const uint32_t kNoParentId = 0u; |
| 32 const mojo::ConnectionSpecificId kInvalidConnectionId = 0u; |
32 | 33 |
33 FrameDataPtr FrameToFrameData(const Frame* frame) { | 34 FrameDataPtr FrameToFrameData(const Frame* frame) { |
34 FrameDataPtr frame_data(FrameData::New()); | 35 FrameDataPtr frame_data(FrameData::New()); |
35 frame_data->frame_id = frame->id(); | 36 frame_data->frame_id = frame->id(); |
36 frame_data->parent_id = frame->parent() ? frame->parent()->id() : kNoParentId; | 37 frame_data->parent_id = frame->parent() ? frame->parent()->id() : kNoParentId; |
37 frame_data->client_properties = | 38 frame_data->client_properties = |
38 mojo::Map<mojo::String, mojo::Array<uint8_t>>::From( | 39 mojo::Map<mojo::String, mojo::Array<uint8_t>>::From( |
39 frame->client_properties()); | 40 frame->client_properties()); |
40 return frame_data.Pass(); | 41 return frame_data.Pass(); |
41 } | 42 } |
42 | 43 |
43 } // namespace | 44 } // namespace |
44 | 45 |
45 struct Frame::FrameTreeServerBinding { | 46 struct Frame::FrameTreeServerBinding { |
46 scoped_ptr<FrameUserData> user_data; | 47 scoped_ptr<FrameUserData> user_data; |
47 scoped_ptr<mojo::Binding<FrameTreeServer>> frame_tree_server_binding; | 48 scoped_ptr<mojo::Binding<FrameTreeServer>> frame_tree_server_binding; |
48 }; | 49 }; |
49 | 50 |
50 Frame::Frame(FrameTree* tree, | 51 Frame::Frame(FrameTree* tree, |
51 View* view, | 52 View* view, |
52 uint32_t frame_id, | 53 uint32_t frame_id, |
53 uint32_t app_id, | 54 uint32_t app_id, |
54 ViewOwnership view_ownership, | 55 ViewOwnership view_ownership, |
55 FrameTreeClient* frame_tree_client, | 56 FrameTreeClient* frame_tree_client, |
56 scoped_ptr<FrameUserData> user_data, | 57 scoped_ptr<FrameUserData> user_data, |
57 const ClientPropertyMap& client_properties) | 58 const ClientPropertyMap& client_properties) |
58 : tree_(tree), | 59 : tree_(tree), |
59 view_(nullptr), | 60 view_(nullptr), |
| 61 embedded_connection_id_(kInvalidConnectionId), |
60 id_(frame_id), | 62 id_(frame_id), |
61 app_id_(app_id), | 63 app_id_(app_id), |
62 parent_(nullptr), | 64 parent_(nullptr), |
63 view_ownership_(view_ownership), | 65 view_ownership_(view_ownership), |
64 user_data_(user_data.Pass()), | 66 user_data_(user_data.Pass()), |
65 frame_tree_client_(frame_tree_client), | 67 frame_tree_client_(frame_tree_client), |
66 loading_(false), | 68 loading_(false), |
67 progress_(0.f), | 69 progress_(0.f), |
68 client_properties_(client_properties), | 70 client_properties_(client_properties), |
69 weak_factory_(this), | 71 embed_weak_ptr_factory_(this), |
70 navigate_weak_ptr_factory_(this) { | 72 navigate_weak_ptr_factory_(this) { |
71 if (view) | 73 if (view) |
72 SetView(view); | 74 SetView(view); |
73 } | 75 } |
74 | 76 |
75 Frame::~Frame() { | 77 Frame::~Frame() { |
76 if (view_) | 78 if (view_) |
77 view_->RemoveObserver(this); | 79 view_->RemoveObserver(this); |
78 while (!children_.empty()) | 80 while (!children_.empty()) |
79 delete children_[0]; | 81 delete children_[0]; |
80 if (parent_) | 82 if (parent_) |
81 parent_->Remove(this); | 83 parent_->Remove(this); |
82 if (view_) { | 84 if (view_) { |
83 view_->ClearLocalProperty(kFrame); | 85 view_->ClearLocalProperty(kFrame); |
84 if (view_ownership_ == ViewOwnership::OWNS_VIEW) | 86 if (view_ownership_ == ViewOwnership::OWNS_VIEW) |
85 view_->Destroy(); | 87 view_->Destroy(); |
86 } | 88 } |
87 } | 89 } |
88 | 90 |
89 void Frame::Init(Frame* parent) { | 91 void Frame::Init(Frame* parent, mojo::ViewTreeClientPtr view_tree_client) { |
90 { | 92 { |
91 // Set the FrameTreeClient to null so that we don't notify the client of the | 93 // Set the FrameTreeClient to null so that we don't notify the client of the |
92 // add before OnConnect(). | 94 // add before OnConnect(). |
93 base::AutoReset<FrameTreeClient*> frame_tree_client_resetter( | 95 base::AutoReset<FrameTreeClient*> frame_tree_client_resetter( |
94 &frame_tree_client_, nullptr); | 96 &frame_tree_client_, nullptr); |
95 if (parent) | 97 if (parent) |
96 parent->Add(this); | 98 parent->Add(this); |
97 } | 99 } |
98 | 100 |
99 InitClient(ClientType::NEW_APP, nullptr); | 101 InitClient(ClientType::NEW_APP, nullptr, view_tree_client.Pass()); |
100 } | 102 } |
101 | 103 |
102 // static | 104 // static |
103 Frame* Frame::FindFirstFrameAncestor(View* view) { | 105 Frame* Frame::FindFirstFrameAncestor(View* view) { |
104 while (view && !view->GetLocalProperty(kFrame)) | 106 while (view && !view->GetLocalProperty(kFrame)) |
105 view = view->parent(); | 107 view = view->parent(); |
106 return view ? view->GetLocalProperty(kFrame) : nullptr; | 108 return view ? view->GetLocalProperty(kFrame) : nullptr; |
107 } | 109 } |
108 | 110 |
109 const Frame* Frame::FindFrame(uint32_t id) const { | 111 const Frame* Frame::FindFrame(uint32_t id) const { |
(...skipping 28 matching lines...) Expand all Loading... |
138 double Frame::GatherProgress(int* frame_count) const { | 140 double Frame::GatherProgress(int* frame_count) const { |
139 ++(*frame_count); | 141 ++(*frame_count); |
140 double progress = progress_; | 142 double progress = progress_; |
141 for (const Frame* child : children_) | 143 for (const Frame* child : children_) |
142 progress += child->GatherProgress(frame_count); | 144 progress += child->GatherProgress(frame_count); |
143 return progress_; | 145 return progress_; |
144 } | 146 } |
145 | 147 |
146 void Frame::InitClient( | 148 void Frame::InitClient( |
147 ClientType client_type, | 149 ClientType client_type, |
148 scoped_ptr<FrameTreeServerBinding> frame_tree_server_binding) { | 150 scoped_ptr<FrameTreeServerBinding> frame_tree_server_binding, |
| 151 mojo::ViewTreeClientPtr view_tree_client) { |
| 152 if (client_type == ClientType::NEW_APP && view_tree_client.get()) { |
| 153 embedded_connection_id_ = kInvalidConnectionId; |
| 154 embed_weak_ptr_factory_.InvalidateWeakPtrs(); |
| 155 view_->Embed( |
| 156 view_tree_client.Pass(), |
| 157 base::Bind(&Frame::OnEmbedAck, embed_weak_ptr_factory_.GetWeakPtr())); |
| 158 } |
| 159 |
149 std::vector<const Frame*> frames; | 160 std::vector<const Frame*> frames; |
150 tree_->root()->BuildFrameTree(&frames); | 161 tree_->root()->BuildFrameTree(&frames); |
151 | 162 |
152 mojo::Array<FrameDataPtr> array(frames.size()); | 163 mojo::Array<FrameDataPtr> array(frames.size()); |
153 for (size_t i = 0; i < frames.size(); ++i) | 164 for (size_t i = 0; i < frames.size(); ++i) |
154 array[i] = FrameToFrameData(frames[i]).Pass(); | 165 array[i] = FrameToFrameData(frames[i]).Pass(); |
155 | 166 |
156 // TODO(sky): error handling. | 167 // TODO(sky): error handling. |
157 FrameTreeServerPtr frame_tree_server_ptr; | 168 FrameTreeServerPtr frame_tree_server_ptr; |
158 frame_tree_server_binding_.reset(new mojo::Binding<FrameTreeServer>( | 169 frame_tree_server_binding_.reset(new mojo::Binding<FrameTreeServer>( |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 frame_tree_server_binding_.Pass(); | 203 frame_tree_server_binding_.Pass(); |
193 } | 204 } |
194 | 205 |
195 user_data_ = user_data.Pass(); | 206 user_data_ = user_data.Pass(); |
196 frame_tree_client_ = frame_tree_client; | 207 frame_tree_client_ = frame_tree_client; |
197 frame_tree_server_binding_.reset(); | 208 frame_tree_server_binding_.reset(); |
198 loading_ = false; | 209 loading_ = false; |
199 progress_ = 0.f; | 210 progress_ = 0.f; |
200 app_id_ = app_id; | 211 app_id_ = app_id; |
201 | 212 |
202 if (client_type == ClientType::NEW_APP) | 213 InitClient(client_type, frame_tree_server_binding.Pass(), |
203 view_->Embed(view_tree_client.Pass()); | 214 view_tree_client.Pass()); |
| 215 } |
204 | 216 |
205 InitClient(client_type, frame_tree_server_binding.Pass()); | 217 void Frame::OnEmbedAck(bool success, mojo::ConnectionSpecificId connection_id) { |
| 218 if (success) |
| 219 embedded_connection_id_ = connection_id; |
206 } | 220 } |
207 | 221 |
208 void Frame::SetView(mojo::View* view) { | 222 void Frame::SetView(mojo::View* view) { |
209 DCHECK(!view_); | 223 DCHECK(!view_); |
210 DCHECK_EQ(id_, view->id()); | 224 DCHECK_EQ(id_, view->id()); |
211 view_ = view; | 225 view_ = view; |
212 view_->SetLocalProperty(kFrame, this); | 226 view_->SetLocalProperty(kFrame, this); |
213 view_->AddObserver(this); | 227 view_->AddObserver(this); |
214 if (pending_navigate_.get()) | 228 if (pending_navigate_.get()) |
215 StartNavigate(pending_navigate_.Pass()); | 229 StartNavigate(pending_navigate_.Pass()); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 } | 407 } |
394 | 408 |
395 void Frame::OnViewDestroying(mojo::View* view) { | 409 void Frame::OnViewDestroying(mojo::View* view) { |
396 if (parent_) | 410 if (parent_) |
397 parent_->Remove(this); | 411 parent_->Remove(this); |
398 | 412 |
399 // Reset |view_ownership_| so we don't attempt to delete |view_| in the | 413 // Reset |view_ownership_| so we don't attempt to delete |view_| in the |
400 // destructor. | 414 // destructor. |
401 view_ownership_ = ViewOwnership::DOESNT_OWN_VIEW; | 415 view_ownership_ = ViewOwnership::DOESNT_OWN_VIEW; |
402 | 416 |
403 // TODO(sky): Change browser to create a child for each FrameTree. | |
404 if (tree_->root() == this) { | 417 if (tree_->root() == this) { |
405 view_->RemoveObserver(this); | 418 view_->RemoveObserver(this); |
406 view_ = nullptr; | 419 view_ = nullptr; |
407 return; | 420 return; |
408 } | 421 } |
409 | 422 |
410 delete this; | 423 delete this; |
411 } | 424 } |
412 | 425 |
413 void Frame::PostMessageEventToFrame(uint32_t source_frame_id, | 426 void Frame::PostMessageEventToFrame(uint32_t source_frame_id, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 mojo::Array<uint8_t> value) { | 469 mojo::Array<uint8_t> value) { |
457 Frame* target_frame = FindFrameWithIdFromSameApp(frame_id); | 470 Frame* target_frame = FindFrameWithIdFromSameApp(frame_id); |
458 if (target_frame) | 471 if (target_frame) |
459 target_frame->SetClientPropertyImpl(name, value.Pass()); | 472 target_frame->SetClientPropertyImpl(name, value.Pass()); |
460 } | 473 } |
461 | 474 |
462 void Frame::OnCreatedFrame( | 475 void Frame::OnCreatedFrame( |
463 uint32_t parent_id, | 476 uint32_t parent_id, |
464 uint32_t frame_id, | 477 uint32_t frame_id, |
465 mojo::Map<mojo::String, mojo::Array<uint8_t>> client_properties) { | 478 mojo::Map<mojo::String, mojo::Array<uint8_t>> client_properties) { |
466 // TODO(sky): I need a way to verify the frame_id. Unfortunately the code here | 479 if ((frame_id >> 16) != embedded_connection_id_) { |
467 // doesn't know the connection id of the embedder, so it's not possible to | 480 // TODO(sky): kill connection here? |
468 // do it. | 481 // TODO(sky): there is a race in that there is no guarantee we received the |
| 482 // connection id before the frame tries to create a new frame. Ideally we |
| 483 // could pause the frame until we get the connection id, but bindings don't |
| 484 // offer such an API. |
| 485 DVLOG(1) << "OnCreatedFrame supplied invalid frame id, expecting" |
| 486 << embedded_connection_id_; |
| 487 return; |
| 488 } |
469 | 489 |
470 if (FindFrame(frame_id)) { | 490 if (FindFrame(frame_id)) { |
471 // TODO(sky): kill connection here? | 491 // TODO(sky): kill connection here? |
472 DVLOG(1) << "OnCreatedLocalFrame supplied id of existing frame."; | 492 DVLOG(1) << "OnCreatedFrame supplied id of existing frame."; |
473 return; | 493 return; |
474 } | 494 } |
475 | 495 |
476 Frame* parent_frame = FindFrameWithIdFromSameApp(parent_id); | 496 Frame* parent_frame = FindFrameWithIdFromSameApp(parent_id); |
477 if (!parent_frame) { | 497 if (!parent_frame) { |
478 DVLOG(1) << "OnCreatedLocalFrame supplied invalid parent_id."; | 498 DVLOG(1) << "OnCreatedFrame supplied invalid parent_id."; |
479 return; | 499 return; |
480 } | 500 } |
481 | 501 |
482 if (parent_frame != this && parent_frame->frame_tree_client_) { | 502 Frame* child_frame = |
483 DVLOG(1) << "OnCreatedLocalFrame supplied parent from another connection."; | 503 tree_->CreateSharedFrame(parent_frame, frame_id, app_id_, |
484 return; | 504 client_properties.To<ClientPropertyMap>()); |
485 } | 505 child_frame->embedded_connection_id_ = embedded_connection_id_; |
486 | |
487 tree_->CreateSharedFrame(parent_frame, frame_id, app_id_, | |
488 client_properties.To<ClientPropertyMap>()); | |
489 } | 506 } |
490 | 507 |
491 void Frame::RequestNavigate(NavigationTargetType target_type, | 508 void Frame::RequestNavigate(NavigationTargetType target_type, |
492 uint32_t target_frame_id, | 509 uint32_t target_frame_id, |
493 mojo::URLRequestPtr request) { | 510 mojo::URLRequestPtr request) { |
494 if (target_type == NAVIGATION_TARGET_TYPE_EXISTING_FRAME) { | 511 if (target_type == NAVIGATION_TARGET_TYPE_EXISTING_FRAME) { |
495 // |target_frame| is allowed to come from another connection. | 512 // |target_frame| is allowed to come from another connection. |
496 Frame* target_frame = tree_->root()->FindFrame(target_frame_id); | 513 Frame* target_frame = tree_->root()->FindFrame(target_frame_id); |
497 if (!target_frame) { | 514 if (!target_frame) { |
498 DVLOG(1) << "RequestNavigate EXIT_FRAME with no matching frame"; | 515 DVLOG(1) << "RequestNavigate EXIT_FRAME with no matching frame"; |
499 return; | 516 return; |
500 } | 517 } |
501 if (target_frame != tree_->root()) { | 518 if (target_frame != tree_->root()) { |
502 target_frame->StartNavigate(request.Pass()); | 519 target_frame->StartNavigate(request.Pass()); |
503 return; | 520 return; |
504 } | 521 } |
505 // Else case if |target_frame| == root. Treat at top level request. | 522 // Else case if |target_frame| == root. Treat at top level request. |
506 } | 523 } |
507 tree_->delegate_->NavigateTopLevel(this, request.Pass()); | 524 tree_->delegate_->NavigateTopLevel(this, request.Pass()); |
508 } | 525 } |
509 | 526 |
510 void Frame::DidNavigateLocally(uint32_t frame_id, const mojo::String& url) { | 527 void Frame::DidNavigateLocally(uint32_t frame_id, const mojo::String& url) { |
511 NOTIMPLEMENTED(); | 528 NOTIMPLEMENTED(); |
512 } | 529 } |
513 | 530 |
514 } // namespace web_view | 531 } // namespace web_view |
OLD | NEW |