OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "components/web_view/frame.h" | |
6 | |
7 #include <stddef.h> | |
8 #include <algorithm> | |
9 #include <utility> | |
10 | |
11 #include "base/auto_reset.h" | |
12 #include "base/bind.h" | |
13 #include "base/callback.h" | |
14 #include "base/stl_util.h" | |
15 #include "base/trace_event/trace_event.h" | |
16 #include "components/mus/public/cpp/window.h" | |
17 #include "components/mus/public/cpp/window_property.h" | |
18 #include "components/web_view/frame_tree.h" | |
19 #include "components/web_view/frame_tree_delegate.h" | |
20 #include "components/web_view/frame_user_data.h" | |
21 #include "components/web_view/frame_utils.h" | |
22 #include "mojo/common/url_type_converters.h" | |
23 #include "mojo/shell/public/interfaces/shell.mojom.h" | |
24 #include "url/gurl.h" | |
25 | |
26 using mus::Window; | |
27 | |
28 MUS_DECLARE_WINDOW_PROPERTY_TYPE(web_view::Frame*); | |
29 | |
30 namespace web_view { | |
31 | |
32 // Used to find the Frame associated with a Window. | |
33 MUS_DEFINE_LOCAL_WINDOW_PROPERTY_KEY(Frame*, kFrame, nullptr); | |
34 | |
35 namespace { | |
36 | |
37 const uint32_t kNoParentId = 0u; | |
38 const mus::ConnectionSpecificId kInvalidConnectionId = 0u; | |
39 | |
40 mojom::FrameDataPtr FrameToFrameData(const Frame* frame) { | |
41 mojom::FrameDataPtr frame_data(mojom::FrameData::New()); | |
42 frame_data->frame_id = frame->id(); | |
43 frame_data->parent_id = frame->parent() ? frame->parent()->id() : kNoParentId; | |
44 frame_data->client_properties = | |
45 mojo::Map<mojo::String, mojo::Array<uint8_t>>::From( | |
46 frame->client_properties()); | |
47 return frame_data; | |
48 } | |
49 | |
50 } // namespace | |
51 | |
52 struct Frame::FrameUserDataAndBinding { | |
53 scoped_ptr<FrameUserData> user_data; | |
54 scoped_ptr<mojo::Binding<mojom::Frame>> frame_binding; | |
55 }; | |
56 | |
57 Frame::Frame(FrameTree* tree, | |
58 Window* window, | |
59 uint32_t frame_id, | |
60 uint32_t app_id, | |
61 WindowOwnership window_ownership, | |
62 mojom::FrameClient* frame_client, | |
63 scoped_ptr<FrameUserData> user_data, | |
64 const ClientPropertyMap& client_properties) | |
65 : tree_(tree), | |
66 window_(nullptr), | |
67 embedded_connection_id_(kInvalidConnectionId), | |
68 id_(frame_id), | |
69 app_id_(app_id), | |
70 parent_(nullptr), | |
71 window_ownership_(window_ownership), | |
72 user_data_(std::move(user_data)), | |
73 frame_client_(frame_client), | |
74 loading_(false), | |
75 progress_(0.f), | |
76 client_properties_(client_properties), | |
77 waiting_for_on_will_navigate_ack_(false), | |
78 embed_weak_ptr_factory_(this), | |
79 navigate_weak_ptr_factory_(this) { | |
80 if (window) | |
81 SetWindow(window); | |
82 } | |
83 | |
84 Frame::~Frame() { | |
85 DVLOG(2) << "~Frame id=" << id_ << " this=" << this; | |
86 if (window_) | |
87 window_->RemoveObserver(this); | |
88 while (!children_.empty()) | |
89 delete children_[0]; | |
90 if (parent_) | |
91 parent_->Remove(this); | |
92 if (window_) { | |
93 window_->ClearLocalProperty(kFrame); | |
94 if (window_ownership_ == WindowOwnership::OWNS_WINDOW) | |
95 window_->Destroy(); | |
96 } | |
97 tree_->delegate_->DidDestroyFrame(this); | |
98 } | |
99 | |
100 void Frame::Init(Frame* parent, | |
101 mus::mojom::WindowTreeClientPtr window_tree_client, | |
102 mojo::InterfaceRequest<mojom::Frame> frame_request, | |
103 base::TimeTicks navigation_start_time) { | |
104 { | |
105 // Set the FrameClient to null so that we don't notify the client of the | |
106 // add before OnConnect(). | |
107 base::AutoReset<mojom::FrameClient*> frame_client_resetter(&frame_client_, | |
108 nullptr); | |
109 if (parent) | |
110 parent->Add(this); | |
111 } | |
112 | |
113 const ClientType client_type = frame_request.is_pending() | |
114 ? ClientType::NEW_CHILD_FRAME | |
115 : ClientType::EXISTING_FRAME_NEW_APP; | |
116 InitClient(client_type, nullptr, std::move(window_tree_client), | |
117 std::move(frame_request), navigation_start_time); | |
118 | |
119 tree_->delegate_->DidCreateFrame(this); | |
120 | |
121 DVLOG(2) << "Frame id=" << id_ << " parent=" << (parent_ ? parent_->id_ : 0) | |
122 << " app_id=" << app_id_ << " this=" << this; | |
123 } | |
124 | |
125 // static | |
126 Frame* Frame::FindFirstFrameAncestor(Window* window) { | |
127 while (window && !window->GetLocalProperty(kFrame)) | |
128 window = window->parent(); | |
129 return window ? window->GetLocalProperty(kFrame) : nullptr; | |
130 } | |
131 | |
132 const Frame* Frame::FindFrame(uint32_t id) const { | |
133 if (id == id_) | |
134 return this; | |
135 | |
136 for (const Frame* child : children_) { | |
137 const Frame* match = child->FindFrame(id); | |
138 if (match) | |
139 return match; | |
140 } | |
141 return nullptr; | |
142 } | |
143 | |
144 bool Frame::HasAncestor(const Frame* frame) const { | |
145 const Frame* current = this; | |
146 while (current && current != frame) | |
147 current = current->parent_; | |
148 return current == frame; | |
149 } | |
150 | |
151 bool Frame::IsLoading() const { | |
152 if (loading_) | |
153 return true; | |
154 for (const Frame* child : children_) { | |
155 if (child->IsLoading()) | |
156 return true; | |
157 } | |
158 return false; | |
159 } | |
160 | |
161 double Frame::GatherProgress(int* frame_count) const { | |
162 ++(*frame_count); | |
163 double progress = progress_; | |
164 for (const Frame* child : children_) | |
165 progress += child->GatherProgress(frame_count); | |
166 return progress_; | |
167 } | |
168 | |
169 void Frame::Find(int32_t request_id, | |
170 const mojo::String& search_text, | |
171 mojom::FindOptionsPtr options, | |
172 bool wrap_within_frame, | |
173 const FindCallback& callback) { | |
174 frame_client_->Find(request_id, search_text, std::move(options), | |
175 wrap_within_frame, callback); | |
176 } | |
177 | |
178 void Frame::StopFinding(bool clear_selection) { | |
179 frame_client_->StopFinding(clear_selection); | |
180 } | |
181 | |
182 void Frame::HighlightFindResults(int32_t request_id, | |
183 const mojo::String& search_text, | |
184 mojom::FindOptionsPtr options, | |
185 bool reset) { | |
186 frame_client_->HighlightFindResults(request_id, search_text, | |
187 std::move(options), reset); | |
188 } | |
189 | |
190 void Frame::StopHighlightingFindResults() { | |
191 frame_client_->StopHighlightingFindResults(); | |
192 } | |
193 | |
194 void Frame::InitClient(ClientType client_type, | |
195 scoped_ptr<FrameUserDataAndBinding> data_and_binding, | |
196 mus::mojom::WindowTreeClientPtr window_tree_client, | |
197 mojo::InterfaceRequest<mojom::Frame> frame_request, | |
198 base::TimeTicks navigation_start_time) { | |
199 if (client_type == ClientType::EXISTING_FRAME_NEW_APP && window_tree_client) { | |
200 embedded_connection_id_ = kInvalidConnectionId; | |
201 embed_weak_ptr_factory_.InvalidateWeakPtrs(); | |
202 window_->Embed( | |
203 std::move(window_tree_client), | |
204 mus::mojom::WindowTree::kAccessPolicyDefault, | |
205 base::Bind(&Frame::OnEmbedAck, embed_weak_ptr_factory_.GetWeakPtr())); | |
206 } | |
207 | |
208 if (client_type == ClientType::NEW_CHILD_FRAME) { | |
209 // Don't install an error handler. We allow for the target to only | |
210 // implement WindowTreeClient. | |
211 // This frame (and client) was created by an existing FrameClient. There | |
212 // is no need to send it OnConnect(). | |
213 frame_binding_.reset( | |
214 new mojo::Binding<mojom::Frame>(this, std::move(frame_request))); | |
215 frame_client_->OnConnect( | |
216 nullptr, tree_->change_id(), id_, mojom::WindowConnectType::USE_NEW, | |
217 mojo::Array<mojom::FrameDataPtr>(), | |
218 navigation_start_time.ToInternalValue(), | |
219 base::Bind(&OnConnectAck, base::Passed(&data_and_binding))); | |
220 } else { | |
221 std::vector<const Frame*> frames; | |
222 tree_->root()->BuildFrameTree(&frames); | |
223 | |
224 mojo::Array<mojom::FrameDataPtr> array(frames.size()); | |
225 for (size_t i = 0; i < frames.size(); ++i) | |
226 array[i] = FrameToFrameData(frames[i]); | |
227 | |
228 mojom::FramePtr frame_ptr; | |
229 // Don't install an error handler. We allow for the target to only | |
230 // implement WindowTreeClient. | |
231 frame_binding_.reset( | |
232 new mojo::Binding<mojom::Frame>(this, GetProxy(&frame_ptr))); | |
233 frame_client_->OnConnect( | |
234 std::move(frame_ptr), tree_->change_id(), id_, | |
235 client_type == ClientType::EXISTING_FRAME_SAME_APP | |
236 ? mojom::WindowConnectType::USE_EXISTING | |
237 : mojom::WindowConnectType::USE_NEW, | |
238 std::move(array), navigation_start_time.ToInternalValue(), | |
239 base::Bind(&OnConnectAck, base::Passed(&data_and_binding))); | |
240 tree_->delegate_->DidStartNavigation(this); | |
241 | |
242 // We need |embedded_connection_id_| is order to validate requests to | |
243 // create a child frame (OnCreatedFrame()). Pause incoming methods until | |
244 // we get the id to prevent race conditions. | |
245 if (embedded_connection_id_ == kInvalidConnectionId) | |
246 frame_binding_->PauseIncomingMethodCallProcessing(); | |
247 } | |
248 } | |
249 | |
250 // static | |
251 void Frame::OnConnectAck(scoped_ptr<FrameUserDataAndBinding> data_and_binding) { | |
252 } | |
253 | |
254 void Frame::ChangeClient(mojom::FrameClient* frame_client, | |
255 scoped_ptr<FrameUserData> user_data, | |
256 mus::mojom::WindowTreeClientPtr window_tree_client, | |
257 uint32_t app_id, | |
258 base::TimeTicks navigation_start_time) { | |
259 while (!children_.empty()) | |
260 delete children_[0]; | |
261 | |
262 ClientType client_type = !window_tree_client | |
263 ? ClientType::EXISTING_FRAME_SAME_APP | |
264 : ClientType::EXISTING_FRAME_NEW_APP; | |
265 scoped_ptr<FrameUserDataAndBinding> data_and_binding; | |
266 | |
267 if (client_type == ClientType::EXISTING_FRAME_SAME_APP) { | |
268 // See comment in InitClient() for details. | |
269 data_and_binding.reset(new FrameUserDataAndBinding); | |
270 data_and_binding->user_data = std::move(user_data_); | |
271 data_and_binding->frame_binding = std::move(frame_binding_); | |
272 } else { | |
273 loading_ = false; | |
274 progress_ = 0.f; | |
275 } | |
276 | |
277 user_data_ = std::move(user_data); | |
278 frame_client_ = frame_client; | |
279 frame_binding_.reset(); | |
280 app_id_ = app_id; | |
281 | |
282 InitClient(client_type, std::move(data_and_binding), | |
283 std::move(window_tree_client), nullptr, navigation_start_time); | |
284 } | |
285 | |
286 void Frame::OnEmbedAck(bool success, mus::ConnectionSpecificId connection_id) { | |
287 if (success) | |
288 embedded_connection_id_ = connection_id; | |
289 if (frame_binding_->is_bound()) | |
290 frame_binding_->ResumeIncomingMethodCallProcessing(); | |
291 } | |
292 | |
293 void Frame::OnWillNavigateAck( | |
294 mojom::FrameClient* frame_client, | |
295 scoped_ptr<FrameUserData> user_data, | |
296 mus::mojom::WindowTreeClientPtr window_tree_client, | |
297 uint32_t app_id, | |
298 base::TimeTicks navigation_start_time) { | |
299 DCHECK(waiting_for_on_will_navigate_ack_); | |
300 DVLOG(2) << "Frame::OnWillNavigateAck id=" << id_; | |
301 waiting_for_on_will_navigate_ack_ = false; | |
302 ChangeClient(frame_client, std::move(user_data), | |
303 std::move(window_tree_client), app_id, navigation_start_time); | |
304 if (pending_navigate_.get()) | |
305 StartNavigate(std::move(pending_navigate_)); | |
306 } | |
307 | |
308 void Frame::SetWindow(mus::Window* window) { | |
309 DCHECK(!window_); | |
310 DCHECK_EQ(id_, window->id()); | |
311 window_ = window; | |
312 window_->SetLocalProperty(kFrame, this); | |
313 window_->AddObserver(this); | |
314 if (pending_navigate_.get()) | |
315 StartNavigate(std::move(pending_navigate_)); | |
316 } | |
317 | |
318 void Frame::BuildFrameTree(std::vector<const Frame*>* frames) const { | |
319 frames->push_back(this); | |
320 for (const Frame* frame : children_) | |
321 frame->BuildFrameTree(frames); | |
322 } | |
323 | |
324 void Frame::Add(Frame* node) { | |
325 DCHECK(!node->parent_); | |
326 | |
327 node->parent_ = this; | |
328 children_.push_back(node); | |
329 | |
330 tree_->root()->NotifyAdded(this, node, tree_->AdvanceChangeID()); | |
331 } | |
332 | |
333 void Frame::Remove(Frame* node) { | |
334 DCHECK_EQ(node->parent_, this); | |
335 auto iter = std::find(children_.begin(), children_.end(), node); | |
336 DCHECK(iter != children_.end()); | |
337 node->parent_ = nullptr; | |
338 children_.erase(iter); | |
339 | |
340 tree_->root()->NotifyRemoved(this, node, tree_->AdvanceChangeID()); | |
341 } | |
342 | |
343 void Frame::StartNavigate(mojo::URLRequestPtr request) { | |
344 if (waiting_for_on_will_navigate_ack_) { | |
345 // We're waiting for OnWillNavigate(). We need to wait until that completes | |
346 // before attempting any other loads. | |
347 pending_navigate_ = std::move(request); | |
348 return; | |
349 } | |
350 | |
351 pending_navigate_.reset(); | |
352 | |
353 // We need a Window to navigate. When we get the Window we'll complete the | |
354 // navigation. | |
355 if (!window_) { | |
356 pending_navigate_ = std::move(request); | |
357 return; | |
358 } | |
359 | |
360 // Drop any pending navigation requests. | |
361 navigate_weak_ptr_factory_.InvalidateWeakPtrs(); | |
362 | |
363 DVLOG(2) << "Frame::StartNavigate id=" << id_ << " url=" << request->url; | |
364 | |
365 const GURL requested_url(request->url.get()); | |
366 base::TimeTicks navigation_start_time = | |
367 base::TimeTicks::FromInternalValue(request->originating_time_ticks); | |
368 tree_->delegate_->CanNavigateFrame( | |
369 this, std::move(request), | |
370 base::Bind(&Frame::OnCanNavigateFrame, | |
371 navigate_weak_ptr_factory_.GetWeakPtr(), requested_url, | |
372 navigation_start_time)); | |
373 } | |
374 | |
375 void Frame::OnCanNavigateFrame( | |
376 const GURL& url, | |
377 base::TimeTicks navigation_start_time, | |
378 uint32_t app_id, | |
379 mojom::FrameClient* frame_client, | |
380 scoped_ptr<FrameUserData> user_data, | |
381 mus::mojom::WindowTreeClientPtr window_tree_client) { | |
382 TRACE_EVENT1("web_view", "Frame::OnCanNavigateFrame", | |
383 "url", url.possibly_invalid_spec()); | |
384 | |
385 DVLOG(2) << "Frame::OnCanNavigateFrame id=" << id_ | |
386 << " equal=" << (AreAppIdsEqual(app_id, app_id_) ? "true" : "false"); | |
387 if (AreAppIdsEqual(app_id, app_id_)) { | |
388 // The app currently rendering the frame will continue rendering it. In this | |
389 // case we do not use the WindowTreeClient (because the app has a Window | |
390 // already | |
391 // and ends up reusing it). | |
392 DCHECK(!window_tree_client); | |
393 ChangeClient(frame_client, std::move(user_data), | |
394 std::move(window_tree_client), app_id, navigation_start_time); | |
395 } else { | |
396 waiting_for_on_will_navigate_ack_ = true; | |
397 DCHECK(window_tree_client); | |
398 // TODO(sky): url isn't correct here, it should be a security origin. | |
399 frame_client_->OnWillNavigate( | |
400 url.spec(), | |
401 base::Bind(&Frame::OnWillNavigateAck, base::Unretained(this), | |
402 frame_client, base::Passed(&user_data), | |
403 base::Passed(&window_tree_client), app_id, | |
404 navigation_start_time)); | |
405 } | |
406 } | |
407 | |
408 void Frame::NotifyAdded(const Frame* source, | |
409 const Frame* added_node, | |
410 uint32_t change_id) { | |
411 // |frame_client_| may be null during initial frame creation and parenting. | |
412 if (frame_client_) | |
413 frame_client_->OnFrameAdded(change_id, FrameToFrameData(added_node)); | |
414 | |
415 for (Frame* child : children_) | |
416 child->NotifyAdded(source, added_node, change_id); | |
417 } | |
418 | |
419 void Frame::NotifyRemoved(const Frame* source, | |
420 const Frame* removed_node, | |
421 uint32_t change_id) { | |
422 frame_client_->OnFrameRemoved(change_id, removed_node->id()); | |
423 | |
424 for (Frame* child : children_) | |
425 child->NotifyRemoved(source, removed_node, change_id); | |
426 } | |
427 | |
428 void Frame::NotifyClientPropertyChanged(const Frame* source, | |
429 const mojo::String& name, | |
430 const mojo::Array<uint8_t>& value) { | |
431 if (this != source) | |
432 frame_client_->OnFrameClientPropertyChanged(source->id(), name, | |
433 value.Clone()); | |
434 | |
435 for (Frame* child : children_) | |
436 child->NotifyClientPropertyChanged(source, name, value); | |
437 } | |
438 | |
439 void Frame::NotifyFrameLoadingStateChanged(const Frame* frame, bool loading) { | |
440 frame_client_->OnFrameLoadingStateChanged(frame->id(), loading); | |
441 } | |
442 | |
443 void Frame::NotifyDispatchFrameLoadEvent(const Frame* frame) { | |
444 frame_client_->OnDispatchFrameLoadEvent(frame->id()); | |
445 } | |
446 | |
447 void Frame::OnTreeChanged(const TreeChangeParams& params) { | |
448 if (params.new_parent && this == tree_->root()) { | |
449 Frame* child_frame = FindFrame(params.target->id()); | |
450 if (child_frame && !child_frame->window_) | |
451 child_frame->SetWindow(params.target); | |
452 } | |
453 } | |
454 | |
455 void Frame::OnWindowDestroying(mus::Window* window) { | |
456 if (parent_) | |
457 parent_->Remove(this); | |
458 | |
459 // Reset |window_ownership_| so we don't attempt to delete |window_| in the | |
460 // destructor. | |
461 window_ownership_ = WindowOwnership::DOESNT_OWN_WINDOW; | |
462 | |
463 if (tree_->root() == this) { | |
464 window_->RemoveObserver(this); | |
465 window_ = nullptr; | |
466 return; | |
467 } | |
468 | |
469 delete this; | |
470 } | |
471 | |
472 void Frame::OnWindowEmbeddedAppDisconnected(mus::Window* window) { | |
473 // See FrameTreeDelegate::OnWindowEmbeddedAppDisconnected() for details of | |
474 // when | |
475 // this happens. | |
476 // | |
477 // Currently we have no way to distinguish between the cases that lead to this | |
478 // being called, so we assume we can continue on. Continuing on is important | |
479 // for html as it's entirely possible for a page to create a frame, navigate | |
480 // to a bogus url and expect the frame to still exist. | |
481 tree_->delegate_->OnWindowEmbeddedInFrameDisconnected(this); | |
482 } | |
483 | |
484 void Frame::PostMessageEventToFrame(uint32_t target_frame_id, | |
485 mojom::HTMLMessageEventPtr event) { | |
486 // NOTE: |target_frame_id| is allowed to be from another connection. | |
487 Frame* target = tree_->root()->FindFrame(target_frame_id); | |
488 if (!target || target == this || | |
489 !tree_->delegate_->CanPostMessageEventToFrame(this, target, event.get())) | |
490 return; | |
491 | |
492 target->frame_client_->OnPostMessageEvent(id_, target_frame_id, | |
493 std::move(event)); | |
494 } | |
495 | |
496 void Frame::LoadingStateChanged(bool loading, double progress) { | |
497 bool loading_state_changed = loading_ != loading; | |
498 loading_ = loading; | |
499 progress_ = progress; | |
500 tree_->LoadingStateChanged(); | |
501 | |
502 if (loading_state_changed && parent_ && | |
503 !AreAppIdsEqual(app_id_, parent_->app_id_)) { | |
504 // We need to notify the parent if it is in a different app, so that it can | |
505 // keep track of this frame's loading state. If the parent is in the same | |
506 // app, we assume that the loading state is propagated directly within the | |
507 // app itself and no notification is needed from our side. | |
508 parent_->NotifyFrameLoadingStateChanged(this, loading_); | |
509 } | |
510 } | |
511 | |
512 void Frame::TitleChanged(const mojo::String& title) { | |
513 // Only care about title changes on the root frame. | |
514 if (!parent_) | |
515 tree_->TitleChanged(title); | |
516 } | |
517 | |
518 void Frame::DidCommitProvisionalLoad() { | |
519 tree_->DidCommitProvisionalLoad(this); | |
520 } | |
521 | |
522 void Frame::SetClientProperty(const mojo::String& name, | |
523 mojo::Array<uint8_t> value) { | |
524 auto iter = client_properties_.find(name); | |
525 const bool already_in_map = (iter != client_properties_.end()); | |
526 if (value.is_null()) { | |
527 if (!already_in_map) | |
528 return; | |
529 client_properties_.erase(iter); | |
530 } else { | |
531 std::vector<uint8_t> as_vector(value.To<std::vector<uint8_t>>()); | |
532 if (already_in_map && iter->second == as_vector) | |
533 return; | |
534 client_properties_[name] = as_vector; | |
535 } | |
536 tree_->ClientPropertyChanged(this, name, value); | |
537 } | |
538 | |
539 void Frame::OnCreatedFrame( | |
540 mojo::InterfaceRequest<mojom::Frame> frame_request, | |
541 mojom::FrameClientPtr client, | |
542 uint32_t frame_id, | |
543 mojo::Map<mojo::String, mojo::Array<uint8_t>> client_properties) { | |
544 if ((frame_id >> 16) != embedded_connection_id_) { | |
545 // TODO(sky): kill connection here? | |
546 DVLOG(1) << "OnCreatedFrame supplied invalid frame id, expecting" | |
547 << embedded_connection_id_; | |
548 return; | |
549 } | |
550 | |
551 if (FindFrame(frame_id)) { | |
552 // TODO(sky): kill connection here? | |
553 DVLOG(1) << "OnCreatedFrame supplied id of existing frame."; | |
554 return; | |
555 } | |
556 | |
557 Frame* child_frame = tree_->CreateChildFrame( | |
558 this, std::move(frame_request), std::move(client), frame_id, app_id_, | |
559 client_properties.To<ClientPropertyMap>()); | |
560 child_frame->embedded_connection_id_ = embedded_connection_id_; | |
561 } | |
562 | |
563 void Frame::RequestNavigate(mojom::NavigationTargetType target_type, | |
564 uint32_t target_frame_id, | |
565 mojo::URLRequestPtr request) { | |
566 if (target_type == mojom::NavigationTargetType::EXISTING_FRAME) { | |
567 // |target_frame| is allowed to come from another connection. | |
568 Frame* target_frame = tree_->root()->FindFrame(target_frame_id); | |
569 if (!target_frame) { | |
570 DVLOG(1) << "RequestNavigate EXISTING_FRAME with no matching frame"; | |
571 return; | |
572 } | |
573 if (target_frame != tree_->root()) { | |
574 target_frame->StartNavigate(std::move(request)); | |
575 return; | |
576 } | |
577 // Else case if |target_frame| == root. Treat at top level request. | |
578 } | |
579 tree_->delegate_->NavigateTopLevel(this, std::move(request)); | |
580 } | |
581 | |
582 void Frame::DidNavigateLocally(const mojo::String& url) { | |
583 tree_->DidNavigateLocally(this, url.To<GURL>()); | |
584 } | |
585 | |
586 void Frame::DispatchLoadEventToParent() { | |
587 if (parent_ && !AreAppIdsEqual(app_id_, parent_->app_id_)) { | |
588 // Send notification to fire a load event in the parent, if the parent is in | |
589 // a different app. If the parent is in the same app, we assume that the app | |
590 // itself handles firing load event directly and no notification is needed | |
591 // from our side. | |
592 parent_->NotifyDispatchFrameLoadEvent(this); | |
593 } | |
594 } | |
595 | |
596 void Frame::OnFindInFrameCountUpdated(int32_t request_id, | |
597 int32_t count, | |
598 bool final_update) { | |
599 tree_->delegate_->OnFindInFrameCountUpdated(request_id, this, count, | |
600 final_update); | |
601 } | |
602 | |
603 void Frame::OnFindInPageSelectionUpdated(int32_t request_id, | |
604 int32_t active_match_ordinal) { | |
605 tree_->delegate_->OnFindInPageSelectionUpdated(request_id, this, | |
606 active_match_ordinal); | |
607 } | |
608 | |
609 } // namespace web_view | |
OLD | NEW |