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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 if (view_) { | 89 if (view_) { |
90 view_->ClearLocalProperty(kFrame); | 90 view_->ClearLocalProperty(kFrame); |
91 if (view_ownership_ == ViewOwnership::OWNS_VIEW) | 91 if (view_ownership_ == ViewOwnership::OWNS_VIEW) |
92 view_->Destroy(); | 92 view_->Destroy(); |
93 } | 93 } |
94 tree_->delegate_->DidDestroyFrame(this); | 94 tree_->delegate_->DidDestroyFrame(this); |
95 } | 95 } |
96 | 96 |
97 void Frame::Init(Frame* parent, | 97 void Frame::Init(Frame* parent, |
98 mojo::ViewTreeClientPtr view_tree_client, | 98 mojo::ViewTreeClientPtr view_tree_client, |
99 mojo::InterfaceRequest<mojom::Frame> frame_request) { | 99 mojo::InterfaceRequest<mojom::Frame> frame_request, |
| 100 base::TimeTicks navigation_start_time) { |
100 { | 101 { |
101 // Set the FrameClient to null so that we don't notify the client of the | 102 // Set the FrameClient to null so that we don't notify the client of the |
102 // add before OnConnect(). | 103 // add before OnConnect(). |
103 base::AutoReset<mojom::FrameClient*> frame_client_resetter(&frame_client_, | 104 base::AutoReset<mojom::FrameClient*> frame_client_resetter(&frame_client_, |
104 nullptr); | 105 nullptr); |
105 if (parent) | 106 if (parent) |
106 parent->Add(this); | 107 parent->Add(this); |
107 } | 108 } |
108 | 109 |
109 const ClientType client_type = frame_request.is_pending() | 110 const ClientType client_type = frame_request.is_pending() |
110 ? ClientType::NEW_CHILD_FRAME | 111 ? ClientType::NEW_CHILD_FRAME |
111 : ClientType::EXISTING_FRAME_NEW_APP; | 112 : ClientType::EXISTING_FRAME_NEW_APP; |
112 InitClient(client_type, nullptr, view_tree_client.Pass(), | 113 InitClient(client_type, nullptr, view_tree_client.Pass(), |
113 frame_request.Pass()); | 114 frame_request.Pass(), navigation_start_time); |
114 | 115 |
115 tree_->delegate_->DidCreateFrame(this); | 116 tree_->delegate_->DidCreateFrame(this); |
116 | 117 |
117 DVLOG(2) << "Frame id=" << id_ << " parent=" << (parent_ ? parent_->id_ : 0) | 118 DVLOG(2) << "Frame id=" << id_ << " parent=" << (parent_ ? parent_->id_ : 0) |
118 << " app_id=" << app_id_ << " this=" << this; | 119 << " app_id=" << app_id_ << " this=" << this; |
119 } | 120 } |
120 | 121 |
121 // static | 122 // static |
122 Frame* Frame::FindFirstFrameAncestor(View* view) { | 123 Frame* Frame::FindFirstFrameAncestor(View* view) { |
123 while (view && !view->GetLocalProperty(kFrame)) | 124 while (view && !view->GetLocalProperty(kFrame)) |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 reset); | 184 reset); |
184 } | 185 } |
185 | 186 |
186 void Frame::StopHighlightingFindResults() { | 187 void Frame::StopHighlightingFindResults() { |
187 frame_client_->StopHighlightingFindResults(); | 188 frame_client_->StopHighlightingFindResults(); |
188 } | 189 } |
189 | 190 |
190 void Frame::InitClient(ClientType client_type, | 191 void Frame::InitClient(ClientType client_type, |
191 scoped_ptr<FrameUserDataAndBinding> data_and_binding, | 192 scoped_ptr<FrameUserDataAndBinding> data_and_binding, |
192 mojo::ViewTreeClientPtr view_tree_client, | 193 mojo::ViewTreeClientPtr view_tree_client, |
193 mojo::InterfaceRequest<mojom::Frame> frame_request) { | 194 mojo::InterfaceRequest<mojom::Frame> frame_request, |
| 195 base::TimeTicks navigation_start_time) { |
194 if (client_type == ClientType::EXISTING_FRAME_NEW_APP && | 196 if (client_type == ClientType::EXISTING_FRAME_NEW_APP && |
195 view_tree_client.get()) { | 197 view_tree_client.get()) { |
196 embedded_connection_id_ = kInvalidConnectionId; | 198 embedded_connection_id_ = kInvalidConnectionId; |
197 embed_weak_ptr_factory_.InvalidateWeakPtrs(); | 199 embed_weak_ptr_factory_.InvalidateWeakPtrs(); |
198 view_->Embed( | 200 view_->Embed( |
199 view_tree_client.Pass(), mojo::ViewTree::ACCESS_POLICY_DEFAULT, | 201 view_tree_client.Pass(), mojo::ViewTree::ACCESS_POLICY_DEFAULT, |
200 base::Bind(&Frame::OnEmbedAck, embed_weak_ptr_factory_.GetWeakPtr())); | 202 base::Bind(&Frame::OnEmbedAck, embed_weak_ptr_factory_.GetWeakPtr())); |
201 } | 203 } |
202 | 204 |
203 if (client_type == ClientType::NEW_CHILD_FRAME) { | 205 if (client_type == ClientType::NEW_CHILD_FRAME) { |
204 // Don't install an error handler. We allow for the target to only | 206 // Don't install an error handler. We allow for the target to only |
205 // implement ViewTreeClient. | 207 // implement ViewTreeClient. |
206 // This frame (and client) was created by an existing FrameClient. There | 208 // This frame (and client) was created by an existing FrameClient. There |
207 // is no need to send it OnConnect(). | 209 // is no need to send it OnConnect(). |
208 frame_binding_.reset( | 210 frame_binding_.reset( |
209 new mojo::Binding<mojom::Frame>(this, frame_request.Pass())); | 211 new mojo::Binding<mojom::Frame>(this, frame_request.Pass())); |
210 frame_client_->OnConnect( | 212 frame_client_->OnConnect( |
211 nullptr, tree_->change_id(), id_, mojom::VIEW_CONNECT_TYPE_USE_NEW, | 213 nullptr, tree_->change_id(), id_, mojom::VIEW_CONNECT_TYPE_USE_NEW, |
212 mojo::Array<mojom::FrameDataPtr>(), | 214 mojo::Array<mojom::FrameDataPtr>(), |
| 215 navigation_start_time.ToInternalValue(), |
213 base::Bind(&OnConnectAck, base::Passed(&data_and_binding))); | 216 base::Bind(&OnConnectAck, base::Passed(&data_and_binding))); |
214 } else { | 217 } else { |
215 std::vector<const Frame*> frames; | 218 std::vector<const Frame*> frames; |
216 tree_->root()->BuildFrameTree(&frames); | 219 tree_->root()->BuildFrameTree(&frames); |
217 | 220 |
218 mojo::Array<mojom::FrameDataPtr> array(frames.size()); | 221 mojo::Array<mojom::FrameDataPtr> array(frames.size()); |
219 for (size_t i = 0; i < frames.size(); ++i) | 222 for (size_t i = 0; i < frames.size(); ++i) |
220 array[i] = FrameToFrameData(frames[i]).Pass(); | 223 array[i] = FrameToFrameData(frames[i]).Pass(); |
221 | 224 |
222 mojom::FramePtr frame_ptr; | 225 mojom::FramePtr frame_ptr; |
223 // Don't install an error handler. We allow for the target to only | 226 // Don't install an error handler. We allow for the target to only |
224 // implement ViewTreeClient. | 227 // implement ViewTreeClient. |
225 frame_binding_.reset( | 228 frame_binding_.reset( |
226 new mojo::Binding<mojom::Frame>(this, GetProxy(&frame_ptr).Pass())); | 229 new mojo::Binding<mojom::Frame>(this, GetProxy(&frame_ptr).Pass())); |
227 frame_client_->OnConnect( | 230 frame_client_->OnConnect( |
228 frame_ptr.Pass(), tree_->change_id(), id_, | 231 frame_ptr.Pass(), tree_->change_id(), id_, |
229 client_type == ClientType::EXISTING_FRAME_SAME_APP | 232 client_type == ClientType::EXISTING_FRAME_SAME_APP |
230 ? mojom::VIEW_CONNECT_TYPE_USE_EXISTING | 233 ? mojom::VIEW_CONNECT_TYPE_USE_EXISTING |
231 : mojom::VIEW_CONNECT_TYPE_USE_NEW, | 234 : mojom::VIEW_CONNECT_TYPE_USE_NEW, |
232 array.Pass(), | 235 array.Pass(), navigation_start_time.ToInternalValue(), |
233 base::Bind(&OnConnectAck, base::Passed(&data_and_binding))); | 236 base::Bind(&OnConnectAck, base::Passed(&data_and_binding))); |
234 tree_->delegate_->DidStartNavigation(this); | 237 tree_->delegate_->DidStartNavigation(this); |
235 | 238 |
236 // We need |embedded_connection_id_| is order to validate requests to | 239 // We need |embedded_connection_id_| is order to validate requests to |
237 // create a child frame (OnCreatedFrame()). Pause incoming methods until | 240 // create a child frame (OnCreatedFrame()). Pause incoming methods until |
238 // we get the id to prevent race conditions. | 241 // we get the id to prevent race conditions. |
239 if (embedded_connection_id_ == kInvalidConnectionId) | 242 if (embedded_connection_id_ == kInvalidConnectionId) |
240 frame_binding_->PauseIncomingMethodCallProcessing(); | 243 frame_binding_->PauseIncomingMethodCallProcessing(); |
241 } | 244 } |
242 } | 245 } |
243 | 246 |
244 // static | 247 // static |
245 void Frame::OnConnectAck(scoped_ptr<FrameUserDataAndBinding> data_and_binding) { | 248 void Frame::OnConnectAck(scoped_ptr<FrameUserDataAndBinding> data_and_binding) { |
246 } | 249 } |
247 | 250 |
248 void Frame::ChangeClient(mojom::FrameClient* frame_client, | 251 void Frame::ChangeClient(mojom::FrameClient* frame_client, |
249 scoped_ptr<FrameUserData> user_data, | 252 scoped_ptr<FrameUserData> user_data, |
250 mojo::ViewTreeClientPtr view_tree_client, | 253 mojo::ViewTreeClientPtr view_tree_client, |
251 uint32_t app_id) { | 254 uint32_t app_id, |
| 255 base::TimeTicks navigation_start_time) { |
252 while (!children_.empty()) | 256 while (!children_.empty()) |
253 delete children_[0]; | 257 delete children_[0]; |
254 | 258 |
255 ClientType client_type = view_tree_client.get() == nullptr | 259 ClientType client_type = view_tree_client.get() == nullptr |
256 ? ClientType::EXISTING_FRAME_SAME_APP | 260 ? ClientType::EXISTING_FRAME_SAME_APP |
257 : ClientType::EXISTING_FRAME_NEW_APP; | 261 : ClientType::EXISTING_FRAME_NEW_APP; |
258 scoped_ptr<FrameUserDataAndBinding> data_and_binding; | 262 scoped_ptr<FrameUserDataAndBinding> data_and_binding; |
259 | 263 |
260 if (client_type == ClientType::EXISTING_FRAME_SAME_APP) { | 264 if (client_type == ClientType::EXISTING_FRAME_SAME_APP) { |
261 // See comment in InitClient() for details. | 265 // See comment in InitClient() for details. |
262 data_and_binding.reset(new FrameUserDataAndBinding); | 266 data_and_binding.reset(new FrameUserDataAndBinding); |
263 data_and_binding->user_data = user_data_.Pass(); | 267 data_and_binding->user_data = user_data_.Pass(); |
264 data_and_binding->frame_binding = frame_binding_.Pass(); | 268 data_and_binding->frame_binding = frame_binding_.Pass(); |
265 } else { | 269 } else { |
266 loading_ = false; | 270 loading_ = false; |
267 progress_ = 0.f; | 271 progress_ = 0.f; |
268 } | 272 } |
269 | 273 |
270 user_data_ = user_data.Pass(); | 274 user_data_ = user_data.Pass(); |
271 frame_client_ = frame_client; | 275 frame_client_ = frame_client; |
272 frame_binding_.reset(); | 276 frame_binding_.reset(); |
273 app_id_ = app_id; | 277 app_id_ = app_id; |
274 | 278 |
275 InitClient(client_type, data_and_binding.Pass(), view_tree_client.Pass(), | 279 InitClient(client_type, data_and_binding.Pass(), view_tree_client.Pass(), |
276 nullptr); | 280 nullptr, navigation_start_time); |
277 } | 281 } |
278 | 282 |
279 void Frame::OnEmbedAck(bool success, mus::ConnectionSpecificId connection_id) { | 283 void Frame::OnEmbedAck(bool success, mus::ConnectionSpecificId connection_id) { |
280 if (success) | 284 if (success) |
281 embedded_connection_id_ = connection_id; | 285 embedded_connection_id_ = connection_id; |
282 if (frame_binding_->is_bound()) | 286 if (frame_binding_->is_bound()) |
283 frame_binding_->ResumeIncomingMethodCallProcessing(); | 287 frame_binding_->ResumeIncomingMethodCallProcessing(); |
284 } | 288 } |
285 | 289 |
286 void Frame::OnWillNavigateAck(mojom::FrameClient* frame_client, | 290 void Frame::OnWillNavigateAck(mojom::FrameClient* frame_client, |
287 scoped_ptr<FrameUserData> user_data, | 291 scoped_ptr<FrameUserData> user_data, |
288 mojo::ViewTreeClientPtr view_tree_client, | 292 mojo::ViewTreeClientPtr view_tree_client, |
289 uint32 app_id) { | 293 uint32 app_id, |
| 294 base::TimeTicks navigation_start_time) { |
290 DCHECK(waiting_for_on_will_navigate_ack_); | 295 DCHECK(waiting_for_on_will_navigate_ack_); |
291 DVLOG(2) << "Frame::OnWillNavigateAck id=" << id_; | 296 DVLOG(2) << "Frame::OnWillNavigateAck id=" << id_; |
292 waiting_for_on_will_navigate_ack_ = false; | 297 waiting_for_on_will_navigate_ack_ = false; |
293 ChangeClient(frame_client, user_data.Pass(), view_tree_client.Pass(), app_id); | 298 ChangeClient(frame_client, user_data.Pass(), view_tree_client.Pass(), app_id, |
| 299 navigation_start_time); |
294 if (pending_navigate_.get()) | 300 if (pending_navigate_.get()) |
295 StartNavigate(pending_navigate_.Pass()); | 301 StartNavigate(pending_navigate_.Pass()); |
296 } | 302 } |
297 | 303 |
298 void Frame::SetView(mus::View* view) { | 304 void Frame::SetView(mus::View* view) { |
299 DCHECK(!view_); | 305 DCHECK(!view_); |
300 DCHECK_EQ(id_, view->id()); | 306 DCHECK_EQ(id_, view->id()); |
301 view_ = view; | 307 view_ = view; |
302 view_->SetLocalProperty(kFrame, this); | 308 view_->SetLocalProperty(kFrame, this); |
303 view_->AddObserver(this); | 309 view_->AddObserver(this); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 pending_navigate_ = request.Pass(); | 352 pending_navigate_ = request.Pass(); |
347 return; | 353 return; |
348 } | 354 } |
349 | 355 |
350 // Drop any pending navigation requests. | 356 // Drop any pending navigation requests. |
351 navigate_weak_ptr_factory_.InvalidateWeakPtrs(); | 357 navigate_weak_ptr_factory_.InvalidateWeakPtrs(); |
352 | 358 |
353 DVLOG(2) << "Frame::StartNavigate id=" << id_ << " url=" << request->url; | 359 DVLOG(2) << "Frame::StartNavigate id=" << id_ << " url=" << request->url; |
354 | 360 |
355 const GURL requested_url(request->url); | 361 const GURL requested_url(request->url); |
| 362 base::TimeTicks navigation_start_time = |
| 363 base::TimeTicks::FromInternalValue(request->originating_time_ticks); |
356 tree_->delegate_->CanNavigateFrame( | 364 tree_->delegate_->CanNavigateFrame( |
357 this, request.Pass(), | 365 this, request.Pass(), base::Bind(&Frame::OnCanNavigateFrame, |
358 base::Bind(&Frame::OnCanNavigateFrame, | 366 navigate_weak_ptr_factory_.GetWeakPtr(), |
359 navigate_weak_ptr_factory_.GetWeakPtr(), requested_url)); | 367 requested_url, navigation_start_time)); |
360 } | 368 } |
361 | 369 |
362 void Frame::OnCanNavigateFrame(const GURL& url, | 370 void Frame::OnCanNavigateFrame(const GURL& url, |
| 371 base::TimeTicks navigation_start_time, |
363 uint32_t app_id, | 372 uint32_t app_id, |
364 mojom::FrameClient* frame_client, | 373 mojom::FrameClient* frame_client, |
365 scoped_ptr<FrameUserData> user_data, | 374 scoped_ptr<FrameUserData> user_data, |
366 mojo::ViewTreeClientPtr view_tree_client) { | 375 mojo::ViewTreeClientPtr view_tree_client) { |
367 DVLOG(2) << "Frame::OnCanNavigateFrame id=" << id_ | 376 DVLOG(2) << "Frame::OnCanNavigateFrame id=" << id_ |
368 << " equal=" << (AreAppIdsEqual(app_id, app_id_) ? "true" : "false"); | 377 << " equal=" << (AreAppIdsEqual(app_id, app_id_) ? "true" : "false"); |
369 if (AreAppIdsEqual(app_id, app_id_)) { | 378 if (AreAppIdsEqual(app_id, app_id_)) { |
370 // The app currently rendering the frame will continue rendering it. In this | 379 // The app currently rendering the frame will continue rendering it. In this |
371 // case we do not use the ViewTreeClient (because the app has a View already | 380 // case we do not use the ViewTreeClient (because the app has a View already |
372 // and ends up reusing it). | 381 // and ends up reusing it). |
373 DCHECK(!view_tree_client.get()); | 382 DCHECK(!view_tree_client.get()); |
374 ChangeClient(frame_client, user_data.Pass(), view_tree_client.Pass(), | 383 ChangeClient(frame_client, user_data.Pass(), view_tree_client.Pass(), |
375 app_id); | 384 app_id, navigation_start_time); |
376 } else { | 385 } else { |
377 waiting_for_on_will_navigate_ack_ = true; | 386 waiting_for_on_will_navigate_ack_ = true; |
378 DCHECK(view_tree_client.get()); | 387 DCHECK(view_tree_client.get()); |
379 // TODO(sky): url isn't correct here, it should be a security origin. | 388 // TODO(sky): url isn't correct here, it should be a security origin. |
380 frame_client_->OnWillNavigate(url.spec(), base::Bind( | 389 frame_client_->OnWillNavigate( |
381 &Frame::OnWillNavigateAck, base::Unretained(this), frame_client, | 390 url.spec(), |
382 base::Passed(&user_data), base::Passed(&view_tree_client), app_id)); | 391 base::Bind(&Frame::OnWillNavigateAck, base::Unretained(this), |
| 392 frame_client, base::Passed(&user_data), |
| 393 base::Passed(&view_tree_client), app_id, |
| 394 navigation_start_time)); |
383 } | 395 } |
384 } | 396 } |
385 | 397 |
386 void Frame::NotifyAdded(const Frame* source, | 398 void Frame::NotifyAdded(const Frame* source, |
387 const Frame* added_node, | 399 const Frame* added_node, |
388 uint32_t change_id) { | 400 uint32_t change_id) { |
389 // |frame_client_| may be null during initial frame creation and parenting. | 401 // |frame_client_| may be null during initial frame creation and parenting. |
390 if (frame_client_) | 402 if (frame_client_) |
391 frame_client_->OnFrameAdded(change_id, FrameToFrameData(added_node)); | 403 frame_client_->OnFrameAdded(change_id, FrameToFrameData(added_node)); |
392 | 404 |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 final_update); | 588 final_update); |
577 } | 589 } |
578 | 590 |
579 void Frame::OnFindInPageSelectionUpdated(int32_t request_id, | 591 void Frame::OnFindInPageSelectionUpdated(int32_t request_id, |
580 int32_t active_match_ordinal) { | 592 int32_t active_match_ordinal) { |
581 tree_->delegate_->OnFindInPageSelectionUpdated(request_id, this, | 593 tree_->delegate_->OnFindInPageSelectionUpdated(request_id, this, |
582 active_match_ordinal); | 594 active_match_ordinal); |
583 } | 595 } |
584 | 596 |
585 } // namespace web_view | 597 } // namespace web_view |
OLD | NEW |