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