1 /*
2  * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3  *                     1999 Lars Knoll <knoll@kde.org>
4  *                     1999 Antti Koivisto <koivisto@kde.org>
5  *                     2000 Simon Hausmann <hausmann@kde.org>
6  *                     2000 Stefan Schimanski <1Stein@gmx.de>
7  *                     2001 George Staikos <staikos@kde.org>
8  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All
9  * rights reserved.
10  * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com>
11  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
12  * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
13  * Copyright (C) 2008 Google Inc.
14  *
15  * This library is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU Library General Public
17  * License as published by the Free Software Foundation; either
18  * version 2 of the License, or (at your option) any later version.
19  *
20  * This library is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * Library General Public License for more details.
24  *
25  * You should have received a copy of the GNU Library General Public License
26  * along with this library; see the file COPYING.LIB.  If not, write to
27  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
28  * Boston, MA 02110-1301, USA.
29  */
30 
31 #include "third_party/blink/renderer/core/frame/local_frame.h"
32 
33 #include <limits>
34 #include <memory>
35 #include <utility>
36 
37 #include "base/metrics/histogram_functions.h"
38 #include "base/unguessable_token.h"
39 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
40 #include "mojo/public/cpp/system/message_pipe.h"
41 #include "services/data_decoder/public/mojom/resource_snapshot_for_web_bundle.mojom-blink.h"
42 #include "services/network/public/cpp/features.h"
43 #include "services/network/public/mojom/content_security_policy.mojom-blink.h"
44 #include "services/network/public/mojom/source_location.mojom-blink.h"
45 #include "skia/public/mojom/skcolor.mojom-blink.h"
46 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
47 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
48 #include "third_party/blink/public/common/features.h"
49 #include "third_party/blink/public/common/input/web_input_event_attribution.h"
50 #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
51 #include "third_party/blink/public/mojom/ad_tagging/ad_frame.mojom-blink.h"
52 #include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink.h"
53 #include "third_party/blink/public/mojom/favicon/favicon_url.mojom-blink.h"
54 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
55 #include "third_party/blink/public/mojom/frame/blocked_navigation_types.mojom-blink.h"
56 #include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
57 #include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-blink.h"
58 #include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink.h"
59 #include "third_party/blink/public/mojom/frame/media_player_action.mojom-blink.h"
60 #include "third_party/blink/public/mojom/frame/reporting_observer.mojom-blink.h"
61 #include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h"
62 #include "third_party/blink/public/platform/interface_registry.h"
63 #include "third_party/blink/public/platform/scheduler/web_resource_loading_task_runner_handle.h"
64 #include "third_party/blink/public/platform/url_conversion.h"
65 #include "third_party/blink/public/platform/web_content_settings_client.h"
66 #include "third_party/blink/public/platform/web_string.h"
67 #include "third_party/blink/public/platform/web_url_request.h"
68 #include "third_party/blink/public/platform/web_vector.h"
69 #include "third_party/blink/public/web/web_content_capture_client.h"
70 #include "third_party/blink/public/web/web_frame.h"
71 #include "third_party/blink/public/web/web_local_frame_client.h"
72 #include "third_party/blink/public/web/web_plugin.h"
73 #include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
74 #include "third_party/blink/renderer/bindings/core/v8/source_location.h"
75 #include "third_party/blink/renderer/core/content_capture/content_capture_manager.h"
76 #include "third_party/blink/renderer/core/core_initializer.h"
77 #include "third_party/blink/renderer/core/core_probe_sink.h"
78 #include "third_party/blink/renderer/core/css/document_style_environment_variables.h"
79 #include "third_party/blink/renderer/core/css/style_change_reason.h"
80 #include "third_party/blink/renderer/core/dom/child_frame_disconnector.h"
81 #include "third_party/blink/renderer/core/dom/document_init.h"
82 #include "third_party/blink/renderer/core/dom/document_parser.h"
83 #include "third_party/blink/renderer/core/dom/document_type.h"
84 #include "third_party/blink/renderer/core/dom/dom_node_ids.h"
85 #include "third_party/blink/renderer/core/dom/events/event.h"
86 #include "third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h"
87 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
88 #include "third_party/blink/renderer/core/editing/editor.h"
89 #include "third_party/blink/renderer/core/editing/frame_selection.h"
90 #include "third_party/blink/renderer/core/editing/ime/input_method_controller.h"
91 #include "third_party/blink/renderer/core/editing/serializers/serialization.h"
92 #include "third_party/blink/renderer/core/editing/spellcheck/spell_checker.h"
93 #include "third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h"
94 #include "third_party/blink/renderer/core/editing/surrounding_text.h"
95 #include "third_party/blink/renderer/core/execution_context/window_agent.h"
96 #include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
97 #include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
98 #include "third_party/blink/renderer/core/frame/ad_tracker.h"
99 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
100 #include "third_party/blink/renderer/core/frame/event_handler_registry.h"
101 #include "third_party/blink/renderer/core/frame/frame_console.h"
102 #include "third_party/blink/renderer/core/frame/frame_overlay.h"
103 #include "third_party/blink/renderer/core/frame/frame_serializer.h"
104 #include "third_party/blink/renderer/core/frame/frame_serializer_delegate_impl.h"
105 #include "third_party/blink/renderer/core/frame/intervention.h"
106 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
107 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
108 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
109 #include "third_party/blink/renderer/core/frame/page_scale_constraints_set.h"
110 #include "third_party/blink/renderer/core/frame/performance_monitor.h"
111 #include "third_party/blink/renderer/core/frame/picture_in_picture_controller.h"
112 #include "third_party/blink/renderer/core/frame/remote_frame.h"
113 #include "third_party/blink/renderer/core/frame/remote_frame_owner.h"
114 #include "third_party/blink/renderer/core/frame/report.h"
115 #include "third_party/blink/renderer/core/frame/reporting_context.h"
116 #include "third_party/blink/renderer/core/frame/root_frame_viewport.h"
117 #include "third_party/blink/renderer/core/frame/savable_resources.h"
118 #include "third_party/blink/renderer/core/frame/settings.h"
119 #include "third_party/blink/renderer/core/frame/user_activation.h"
120 #include "third_party/blink/renderer/core/frame/virtual_keyboard_overlay_changed_observer.h"
121 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
122 #include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
123 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
124 #include "third_party/blink/renderer/core/fullscreen/scoped_allow_fullscreen.h"
125 #include "third_party/blink/renderer/core/html/html_frame_element_base.h"
126 #include "third_party/blink/renderer/core/html/html_plugin_element.h"
127 #include "third_party/blink/renderer/core/html/media/html_media_element.h"
128 #include "third_party/blink/renderer/core/html/media/html_video_element.h"
129 #include "third_party/blink/renderer/core/html/plugin_document.h"
130 #include "third_party/blink/renderer/core/html/portal/dom_window_portal_host.h"
131 #include "third_party/blink/renderer/core/html/portal/portal_activate_event.h"
132 #include "third_party/blink/renderer/core/html/portal/portal_host.h"
133 #include "third_party/blink/renderer/core/input/event_handler.h"
134 #include "third_party/blink/renderer/core/inspector/console_message.h"
135 #include "third_party/blink/renderer/core/inspector/inspector_issue_reporter.h"
136 #include "third_party/blink/renderer/core/inspector/inspector_issue_storage.h"
137 #include "third_party/blink/renderer/core/inspector/inspector_task_runner.h"
138 #include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
139 #include "third_party/blink/renderer/core/inspector/main_thread_debugger.h"
140 #include "third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h"
141 #include "third_party/blink/renderer/core/layout/hit_test_result.h"
142 #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
143 #include "third_party/blink/renderer/core/layout/layout_view.h"
144 #include "third_party/blink/renderer/core/layout/text_autosizer.h"
145 #include "third_party/blink/renderer/core/loader/document_loader.h"
146 #include "third_party/blink/renderer/core/loader/frame_load_request.h"
147 #include "third_party/blink/renderer/core/loader/idleness_detector.h"
148 #include "third_party/blink/renderer/core/loader/mixed_content_checker.h"
149 #include "third_party/blink/renderer/core/messaging/message_port.h"
150 #include "third_party/blink/renderer/core/page/chrome_client.h"
151 #include "third_party/blink/renderer/core/page/drag_controller.h"
152 #include "third_party/blink/renderer/core/page/focus_controller.h"
153 #include "third_party/blink/renderer/core/page/page.h"
154 #include "third_party/blink/renderer/core/page/plugin_data.h"
155 #include "third_party/blink/renderer/core/page/plugin_script_forbidden_scope.h"
156 #include "third_party/blink/renderer/core/page/pointer_lock_controller.h"
157 #include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
158 #include "third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.h"
159 #include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
160 #include "third_party/blink/renderer/core/paint/object_painter.h"
161 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
162 #include "third_party/blink/renderer/core/paint/paint_timing.h"
163 #include "third_party/blink/renderer/core/probe/core_probes.h"
164 #include "third_party/blink/renderer/core/scroll/smooth_scroll_sequencer.h"
165 #include "third_party/blink/renderer/core/svg/svg_document_extensions.h"
166 #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
167 #include "third_party/blink/renderer/platform/blob/blob_data.h"
168 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
169 #include "third_party/blink/renderer/platform/graphics/graphics_layer_tree_as_text.h"
170 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
171 #include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
172 #include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
173 #include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
174 #include "third_party/blink/renderer/platform/heap/heap.h"
175 #include "third_party/blink/renderer/platform/heap/persistent.h"
176 #include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h"
177 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
178 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
179 #include "third_party/blink/renderer/platform/json/json_values.h"
180 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
181 #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
182 #include "third_party/blink/renderer/platform/mhtml/serialized_resource.h"
183 #include "third_party/blink/renderer/platform/network/network_state_notifier.h"
184 #include "third_party/blink/renderer/platform/network/network_utils.h"
185 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
186 #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
187 #include "third_party/blink/renderer/platform/wtf/casting.h"
188 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
189 #include "third_party/blink/renderer/platform/wtf/vector.h"
190 #include "ui/gfx/geometry/point.h"
191 #include "ui/gfx/geometry/rect.h"
192 #include "ui/gfx/geometry/rect_f.h"
193 #include "ui/gfx/transform.h"
194 
195 #if defined(OS_MAC)
196 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
197 #include "third_party/blink/renderer/core/editing/substring_util.h"
198 #include "third_party/blink/renderer/platform/fonts/mac/attributed_string_type_converter.h"
199 #include "ui/base/mojom/attributed_string.mojom-blink.h"
200 #include "ui/gfx/range/range.h"
201 #endif
202 
203 namespace blink {
204 
205 namespace {
206 
207 // Maintain a global (statically-allocated) hash map indexed by the the result
208 // of hashing the |frame_token| passed on creation of a LocalFrame object.
209 using LocalFramesByTokenMap = HeapHashMap<uint64_t, WeakMember<LocalFrame>>;
GetLocalFramesMap()210 static LocalFramesByTokenMap& GetLocalFramesMap() {
211   DEFINE_STATIC_LOCAL(Persistent<LocalFramesByTokenMap>, map,
212                       (MakeGarbageCollected<LocalFramesByTokenMap>()));
213   return *map;
214 }
215 
216 // Maximum number of burst download requests allowed.
217 const int kBurstDownloadLimit = 10;
218 
ParentPageZoomFactor(LocalFrame * frame)219 inline float ParentPageZoomFactor(LocalFrame* frame) {
220   auto* parent_local_frame = DynamicTo<LocalFrame>(frame->Tree().Parent());
221   return parent_local_frame ? parent_local_frame->PageZoomFactor() : 1;
222 }
223 
ParentTextZoomFactor(LocalFrame * frame)224 inline float ParentTextZoomFactor(LocalFrame* frame) {
225   auto* parent_local_frame = DynamicTo<LocalFrame>(frame->Tree().Parent());
226   return parent_local_frame ? parent_local_frame->TextZoomFactor() : 1;
227 }
228 
229 #if defined(OS_MAC)
GetCurrentCursorPositionInFrame(LocalFrame * local_frame)230 uint32_t GetCurrentCursorPositionInFrame(LocalFrame* local_frame) {
231   blink::WebRange range =
232       WebLocalFrameImpl::FromFrame(local_frame)->SelectionRange();
233   return range.IsNull() ? 0U : static_cast<uint32_t>(range.StartOffset());
234 }
235 #endif
236 
237 // Convert a data url to a message pipe handle that corresponds to a remote
238 // blob, so that it can be passed across processes.
DataURLToBlob(const String & data_url)239 mojo::PendingRemote<mojom::blink::Blob> DataURLToBlob(const String& data_url) {
240   auto blob_data = std::make_unique<BlobData>();
241   StringUTF8Adaptor data_url_utf8(data_url);
242   blob_data->AppendBytes(data_url_utf8.data(), data_url_utf8.size());
243   scoped_refptr<BlobDataHandle> blob_data_handle =
244       BlobDataHandle::Create(std::move(blob_data), data_url_utf8.size());
245   return blob_data_handle->CloneBlobRemote();
246 }
247 
HitTestResultForRootFramePos(LocalFrame * main_frame,const PhysicalOffset & pos_in_root_frame)248 HitTestResult HitTestResultForRootFramePos(
249     LocalFrame* main_frame,
250     const PhysicalOffset& pos_in_root_frame) {
251   DCHECK(main_frame->IsMainFrame());
252 
253   HitTestLocation location(
254       main_frame->View()->ConvertFromRootFrame(pos_in_root_frame));
255   HitTestResult result = main_frame->GetEventHandler().HitTestResultAtLocation(
256       location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
257   result.SetToShadowHostIfInRestrictedShadowRoot();
258   return result;
259 }
260 
SourceFrameForOptionalToken(const base::Optional<base::UnguessableToken> & source_frame_token)261 RemoteFrame* SourceFrameForOptionalToken(
262     const base::Optional<base::UnguessableToken>& source_frame_token) {
263   if (!source_frame_token)
264     return nullptr;
265   return RemoteFrame::FromFrameToken(source_frame_token.value());
266 }
267 
268 class WebBundleGenerationDelegate
269     : public WebFrameSerializer::MHTMLPartsGenerationDelegate {
270   STACK_ALLOCATED();
271 
272  public:
273   WebBundleGenerationDelegate() = default;
274   ~WebBundleGenerationDelegate() = default;
275 
276   WebBundleGenerationDelegate(const WebBundleGenerationDelegate&) = delete;
277   WebBundleGenerationDelegate& operator=(const WebBundleGenerationDelegate&) =
278       delete;
279 
ShouldSkipResource(const WebURL & url)280   bool ShouldSkipResource(const WebURL& url) override { return false; }
UseBinaryEncoding()281   bool UseBinaryEncoding() override { return false; }
RemovePopupOverlay()282   bool RemovePopupOverlay() override { return false; }
UsePageProblemDetectors()283   bool UsePageProblemDetectors() override { return false; }
284 };
285 
286 class ResourceSnapshotForWebBundleImpl
287     : public data_decoder::mojom::blink::ResourceSnapshotForWebBundle {
288  public:
ResourceSnapshotForWebBundleImpl(Deque<SerializedResource> resources)289   explicit ResourceSnapshotForWebBundleImpl(Deque<SerializedResource> resources)
290       : resources_(std::move(resources)) {}
291   ~ResourceSnapshotForWebBundleImpl() override = default;
292 
293   ResourceSnapshotForWebBundleImpl(const ResourceSnapshotForWebBundleImpl&) =
294       delete;
295   ResourceSnapshotForWebBundleImpl& operator=(
296       const ResourceSnapshotForWebBundleImpl&) = delete;
297 
298   // data_decoder::mojom::blink::ResourceSnapshotForWebBundle:
GetResourceCount(GetResourceCountCallback callback)299   void GetResourceCount(GetResourceCountCallback callback) override {
300     std::move(callback).Run(resources_.size());
301   }
GetResourceInfo(uint64_t index,GetResourceInfoCallback callback)302   void GetResourceInfo(uint64_t index,
303                        GetResourceInfoCallback callback) override {
304     if (index >= resources_.size()) {
305       std::move(callback).Run(nullptr);
306       return;
307     }
308     const auto& resource = resources_.at(SafeCast<WTF::wtf_size_t>(index));
309     auto info = data_decoder::mojom::blink::SerializedResourceInfo::New();
310     info->url = resource.url;
311     info->mime_type = resource.mime_type;
312     info->size = resource.data ? resource.data->size() : 0;
313     std::move(callback).Run(std::move(info));
314   }
GetResourceBody(uint64_t index,GetResourceBodyCallback callback)315   void GetResourceBody(uint64_t index,
316                        GetResourceBodyCallback callback) override {
317     if (index >= resources_.size()) {
318       std::move(callback).Run(base::nullopt);
319       return;
320     }
321     const auto& resource = resources_.at(SafeCast<WTF::wtf_size_t>(index));
322     if (!resource.data) {
323       std::move(callback).Run(base::nullopt);
324       return;
325     }
326     std::move(callback).Run(
327         mojo_base::BigBuffer(resource.data->CopyAs<std::vector<uint8_t>>()));
328   }
329 
330  private:
331   const Deque<SerializedResource> resources_;
332 };
333 
334 class ActiveURLMessageFilter : public mojo::MessageFilter {
335  public:
ActiveURLMessageFilter(LocalFrame * local_frame)336   explicit ActiveURLMessageFilter(LocalFrame* local_frame)
337       : local_frame_(local_frame) {}
338 
~ActiveURLMessageFilter()339   ~ActiveURLMessageFilter() override {
340     if (debug_url_set_) {
341       Platform::Current()->SetActiveURL(WebURL(), WebString());
342     }
343   }
344 
345   // mojo::MessageFilter overrides.
WillDispatch(mojo::Message * message)346   bool WillDispatch(mojo::Message* message) override {
347     // We expect local_frame_ always to be set because this MessageFilter
348     // is owned by the LocalFrame. We do not want to introduce a Persistent
349     // reference so we don't cause a cycle. If you hit this CHECK then you
350     // likely didn't reset your mojo receiver in Detach.
351     CHECK(local_frame_);
352     debug_url_set_ = true;
353     Platform::Current()->SetActiveURL(local_frame_->GetDocument()->Url(),
354                                       local_frame_->Top()
355                                           ->GetSecurityContext()
356                                           ->GetSecurityOrigin()
357                                           ->ToString());
358     return true;
359   }
360 
DidDispatchOrReject(mojo::Message * message,bool accepted)361   void DidDispatchOrReject(mojo::Message* message, bool accepted) override {
362     Platform::Current()->SetActiveURL(WebURL(), WebString());
363     debug_url_set_ = false;
364   }
365 
366  private:
367   WeakPersistent<LocalFrame> local_frame_;
368   bool debug_url_set_ = false;
369 };
370 
371 }  // namespace
372 
373 template class CORE_TEMPLATE_EXPORT Supplement<LocalFrame>;
374 
375 // static
FromFrameToken(const base::UnguessableToken & frame_token)376 LocalFrame* LocalFrame::FromFrameToken(
377     const base::UnguessableToken& frame_token) {
378   LocalFramesByTokenMap& local_frames_map = GetLocalFramesMap();
379   auto it = local_frames_map.find(base::UnguessableTokenHash()(frame_token));
380   return it == local_frames_map.end() ? nullptr : it->value.Get();
381 }
382 
383 // static
FromFrameToken(const LocalFrameToken & frame_token)384 LocalFrame* LocalFrame::FromFrameToken(const LocalFrameToken& frame_token) {
385   return FromFrameToken(frame_token.value());
386 }
387 
Init(Frame * opener)388 void LocalFrame::Init(Frame* opener) {
389   CoreInitializer::GetInstance().InitLocalFrame(*this);
390 
391   GetRemoteNavigationAssociatedInterfaces()->GetInterface(
392       local_frame_host_remote_.BindNewEndpointAndPassReceiver(
393           GetTaskRunner(blink::TaskType::kInternalDefault)));
394   GetRemoteNavigationAssociatedInterfaces()->GetInterface(
395       back_forward_cache_controller_host_remote_.BindNewEndpointAndPassReceiver(
396           GetTaskRunner(blink::TaskType::kInternalDefault)));
397   GetInterfaceRegistry()->AddAssociatedInterface(WTF::BindRepeating(
398       &LocalFrame::BindToReceiver, WrapWeakPersistent(this)));
399   GetInterfaceRegistry()->AddInterface(
400       WTF::BindRepeating(&LocalFrame::BindToHighPriorityReceiver,
401                          WrapWeakPersistent(this)),
402       GetTaskRunner(blink::TaskType::kInternalHighPriorityLocalFrame));
403 
404   if (IsMainFrame()) {
405     GetInterfaceRegistry()->AddInterface(
406         WTF::BindRepeating(&LocalFrame::BindTextFragmentSelectorProducer,
407                            WrapWeakPersistent(this)));
408   }
409 
410   SetOpenerDoNotNotify(opener);
411   loader_.Init();
412 }
413 
SetView(LocalFrameView * view)414 void LocalFrame::SetView(LocalFrameView* view) {
415   DCHECK(!view_ || view_ != view);
416   DCHECK(!GetDocument() || !GetDocument()->IsActive());
417   if (view_)
418     view_->WillBeRemovedFromFrame();
419   view_ = view;
420 }
421 
CreateView(const IntSize & viewport_size,const Color & background_color)422 void LocalFrame::CreateView(const IntSize& viewport_size,
423                             const Color& background_color) {
424   DCHECK(this);
425   DCHECK(GetPage());
426 
427   bool is_local_root = this->IsLocalRoot();
428 
429   if (is_local_root && View())
430     View()->SetParentVisible(false);
431 
432   SetView(nullptr);
433 
434   LocalFrameView* frame_view = nullptr;
435   if (is_local_root) {
436     frame_view = MakeGarbageCollected<LocalFrameView>(*this, viewport_size);
437 
438     // The layout size is set by WebViewImpl to support @viewport
439     frame_view->SetLayoutSizeFixedToFrameSize(false);
440   } else {
441     frame_view = MakeGarbageCollected<LocalFrameView>(*this);
442   }
443 
444   SetView(frame_view);
445 
446   frame_view->UpdateBaseBackgroundColorRecursively(background_color);
447 
448   if (is_local_root)
449     frame_view->SetParentVisible(true);
450 
451   // FIXME: Not clear what the right thing for OOPI is here.
452   if (OwnerLayoutObject()) {
453     HTMLFrameOwnerElement* owner = DeprecatedLocalOwner();
454     DCHECK(owner);
455     // FIXME: OOPI might lead to us temporarily lying to a frame and telling it
456     // that it's owned by a FrameOwner that knows nothing about it. If we're
457     // lying to this frame, don't let it clobber the existing
458     // EmbeddedContentView.
459     if (owner->ContentFrame() == this)
460       owner->SetEmbeddedContentView(frame_view);
461   }
462 
463   if (Owner()) {
464     View()->SetCanHaveScrollbars(Owner()->ScrollbarMode() !=
465                                  mojom::blink::ScrollbarMode::kAlwaysOff);
466   }
467 }
468 
~LocalFrame()469 LocalFrame::~LocalFrame() {
470   // Verify that the LocalFrameView has been cleared as part of detaching
471   // the frame owner.
472   DCHECK(!view_);
473   if (IsAdSubframe())
474     InstanceCounters::DecrementCounter(InstanceCounters::kAdSubframeCounter);
475 }
476 
Trace(Visitor * visitor) const477 void LocalFrame::Trace(Visitor* visitor) const {
478   visitor->Trace(ad_tracker_);
479   visitor->Trace(probe_sink_);
480   visitor->Trace(performance_monitor_);
481   visitor->Trace(idleness_detector_);
482   visitor->Trace(inspector_issue_reporter_);
483   visitor->Trace(inspector_trace_events_);
484   visitor->Trace(loader_);
485   visitor->Trace(view_);
486   visitor->Trace(dom_window_);
487   visitor->Trace(page_popup_owner_);
488   visitor->Trace(editor_);
489   visitor->Trace(selection_);
490   visitor->Trace(event_handler_);
491   visitor->Trace(console_);
492   visitor->Trace(smooth_scroll_sequencer_);
493   visitor->Trace(content_capture_manager_);
494   visitor->Trace(system_clipboard_);
495   visitor->Trace(raw_system_clipboard_);
496   visitor->Trace(virtual_keyboard_overlay_changed_observers_);
497   visitor->Trace(pause_handle_receivers_);
498   visitor->Trace(reporting_service_);
499 #if defined(OS_MAC)
500   visitor->Trace(text_input_host_);
501 #endif
502   visitor->Trace(local_frame_host_remote_);
503   visitor->Trace(back_forward_cache_controller_host_remote_);
504   visitor->Trace(receiver_);
505   visitor->Trace(main_frame_receiver_);
506   visitor->Trace(high_priority_frame_receiver_);
507   visitor->Trace(text_fragment_selector_generator_);
508   visitor->Trace(saved_scroll_offsets_);
509   Frame::Trace(visitor);
510   Supplementable<LocalFrame>::Trace(visitor);
511 }
512 
IsLocalRoot() const513 bool LocalFrame::IsLocalRoot() const {
514   if (!Tree().Parent())
515     return true;
516 
517   return Tree().Parent()->IsRemoteFrame();
518 }
519 
Navigate(FrameLoadRequest & request,WebFrameLoadType frame_load_type)520 void LocalFrame::Navigate(FrameLoadRequest& request,
521                           WebFrameLoadType frame_load_type) {
522   if (HTMLFrameOwnerElement* element = DeprecatedLocalOwner())
523     element->CancelPendingLazyLoad();
524 
525   if (!navigation_rate_limiter().CanProceed())
526     return;
527 
528   TRACE_EVENT2("navigation", "LocalFrame::Navigate", "url",
529                request.GetResourceRequest().Url().GetString().Utf8(),
530                "load_type", static_cast<int>(frame_load_type));
531 
532   if (request.ClientRedirectReason() != ClientNavigationReason::kNone) {
533     probe::FrameScheduledNavigation(this, request.GetResourceRequest().Url(),
534                                     base::TimeDelta(),
535                                     request.ClientRedirectReason());
536     // Non-user navigation before the page has finished firing onload should not
537     // create a new back/forward item. The spec only explicitly mentions this in
538     // the context of navigating an iframe.
539     if (!GetDocument()->LoadEventFinished() &&
540         !HasTransientUserActivation(this) &&
541         request.ClientRedirectReason() !=
542             ClientNavigationReason::kAnchorClick) {
543       frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
544     }
545   }
546 
547   // Navigations in portal contexts do not create back/forward entries.
548   // TODO(mcnee): Similarly, we need to restrict orphaned contexts.
549   if (GetPage()->InsidePortal() &&
550       frame_load_type == WebFrameLoadType::kStandard) {
551     frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
552   }
553 
554   const ClientNavigationReason client_redirect_reason =
555       request.ClientRedirectReason();
556   loader_.StartNavigation(request, frame_load_type);
557 
558   if (client_redirect_reason != ClientNavigationReason::kNone)
559     probe::FrameClearedScheduledNavigation(this);
560 }
561 
DetachImpl(FrameDetachType type)562 void LocalFrame::DetachImpl(FrameDetachType type) {
563   // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
564   // BEGIN RE-ENTRANCY SAFE BLOCK
565   // Starting here, the code must be safe against re-entrancy. Dispatching
566   // events, et cetera can run Javascript, which can reenter Detach().
567   // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
568   frame_color_overlay_.reset();
569 
570   if (IsLocalRoot()) {
571     performance_monitor_->Shutdown();
572     if (ad_tracker_)
573       ad_tracker_->Shutdown();
574   }
575   idleness_detector_->Shutdown();
576   if (inspector_issue_reporter_)
577     probe_sink_->RemoveInspectorIssueReporter(inspector_issue_reporter_);
578   if (inspector_trace_events_)
579     probe_sink_->RemoveInspectorTraceEvents(inspector_trace_events_);
580   inspector_task_runner_->Dispose();
581 
582   PluginScriptForbiddenScope forbid_plugin_destructor_scripting;
583   // In a kSwap detach, if we have a navigation going, its moved to the frame
584   // being swapped in, so we don't need to notify the client about the
585   // navigation stopping here. That will be up to the provisional frame being
586   // swapped in, which knows the actual state of the navigation.
587   loader_.StopAllLoaders(/*abort_client=*/type == FrameDetachType::kRemove);
588   // Don't allow any new child frames to load in this frame: attaching a new
589   // child frame during or after detaching children results in an attached
590   // frame on a detached DOM tree, which is bad.
591   SubframeLoadingDisabler disabler(*GetDocument());
592   // https://html.spec.whatwg.org/C/browsing-the-web.html#unload-a-document
593   // The ignore-opens-during-unload counter of a Document must be incremented
594   // both when unloading itself and when unloading its descendants.
595   IgnoreOpensDuringUnloadCountIncrementer ignore_opens_during_unload(
596       GetDocument());
597   loader_.DispatchUnloadEvent(nullptr, nullptr);
598   DetachChildren();
599 
600   // All done if detaching the subframes brought about a detach of this frame
601   // also.
602   if (!Client())
603     return;
604 
605   // Detach() needs to be called after detachChildren(), because
606   // detachChildren() will trigger the unload event handlers of any child
607   // frames, and those event handlers might start a new subresource load in this
608   // frame which should be stopped by Detach.
609   loader_.Detach();
610   DomWindow()->FrameDestroyed();
611 
612   if (content_capture_manager_) {
613     content_capture_manager_->Shutdown();
614     content_capture_manager_ = nullptr;
615   }
616 
617   // Verify here that any LocalFrameView has been detached by now.
618   if (view_ && view_->IsAttached()) {
619     DCHECK(DeprecatedLocalOwner());
620     DCHECK(DeprecatedLocalOwner()->OwnedEmbeddedContentView());
621     DCHECK_EQ(view_, DeprecatedLocalOwner()->OwnedEmbeddedContentView());
622   }
623   DCHECK(!view_ || !view_->IsAttached());
624 
625   // This is the earliest that scripting can be disabled:
626   // - FrameLoader::Detach() can fire XHR abort events
627   // - Document::Shutdown() can dispose plugins which can run script.
628   ScriptForbiddenScope forbid_script;
629   if (!Client())
630     return;
631 
632   // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
633   // END RE-ENTRANCY SAFE BLOCK
634   // Past this point, no script should be executed. If this method was
635   // re-entered, then check for a non-null Client() above should have already
636   // returned.
637   // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
638   DCHECK(!IsDetached());
639 
640   DCHECK(!view_->IsAttached());
641   Client()->WillBeDetached();
642   // Notify WindowProxyManager that the frame is closing, since its cleanup ends
643   // up calling back to LocalFrameClient via WindowProxy.
644   GetWindowProxyManager()->ClearForClose();
645 
646   // TODO(crbug.com/729196): Trace why LocalFrameView::DetachFromLayout crashes.
647   CHECK(!view_->IsAttached());
648   SetView(nullptr);
649 
650   GetEventHandlerRegistry().DidRemoveAllEventHandlers(*DomWindow());
651 
652   probe::FrameDetachedFromParent(this, type);
653 
654   supplements_.clear();
655   frame_scheduler_.reset();
656   receiver_.reset();
657   main_frame_receiver_.reset();
658   high_priority_frame_receiver_.reset();
659   WeakIdentifierMap<LocalFrame>::NotifyObjectDestroyed(this);
660 }
661 
DetachDocument()662 bool LocalFrame::DetachDocument() {
663   return Loader().DetachDocument(nullptr, nullptr);
664 }
665 
CheckCompleted()666 void LocalFrame::CheckCompleted() {
667   GetDocument()->CheckCompleted();
668 }
669 
GetSecurityContext() const670 const SecurityContext* LocalFrame::GetSecurityContext() const {
671   return DomWindow() ? &DomWindow()->GetSecurityContext() : nullptr;
672 }
673 
PrintNavigationErrorMessage(const Frame & target_frame,const char * reason)674 void LocalFrame::PrintNavigationErrorMessage(const Frame& target_frame,
675                                              const char* reason) {
676   // URLs aren't available for RemoteFrames, so the error message uses their
677   // origin instead.
678   auto* target_local_frame = DynamicTo<LocalFrame>(&target_frame);
679   String target_frame_description =
680       target_local_frame
681           ? "with URL '" +
682                 target_local_frame->GetDocument()->Url().GetString() + "'"
683           : "with origin '" +
684                 target_frame.GetSecurityContext()
685                     ->GetSecurityOrigin()
686                     ->ToString() +
687                 "'";
688   String message =
689       "Unsafe JavaScript attempt to initiate navigation for frame " +
690       target_frame_description + " from frame with URL '" +
691       GetDocument()->Url().GetString() + "'. " + reason + "\n";
692 
693   DomWindow()->PrintErrorMessage(message);
694 }
695 
PrintNavigationWarning(const String & message)696 void LocalFrame::PrintNavigationWarning(const String& message) {
697   console_->AddMessage(MakeGarbageCollected<ConsoleMessage>(
698       mojom::ConsoleMessageSource::kJavaScript,
699       mojom::ConsoleMessageLevel::kWarning, message));
700 }
701 
ShouldClose()702 bool LocalFrame::ShouldClose() {
703   // TODO(dcheng): This should be fixed to dispatch beforeunload events to
704   // both local and remote frames.
705   return loader_.ShouldClose();
706 }
707 
DetachChildren()708 void LocalFrame::DetachChildren() {
709   DCHECK(GetDocument());
710   ChildFrameDisconnector(*GetDocument()).Disconnect();
711 }
712 
DidAttachDocument()713 void LocalFrame::DidAttachDocument() {
714   Document* document = GetDocument();
715   DCHECK(document);
716   GetEditor().Clear();
717   // Clearing the event handler clears many events, but notably can ensure that
718   // for a drag started on an element in a frame that was moved (likely via
719   // appendChild()), the drag source will detach and stop firing drag events
720   // even after the frame reattaches.
721   GetEventHandler().Clear();
722   Selection().DidAttachDocument(document);
723 }
724 
CanAccessEvent(const WebInputEventAttribution & attribution) const725 bool LocalFrame::CanAccessEvent(
726     const WebInputEventAttribution& attribution) const {
727   switch (attribution.type()) {
728     case WebInputEventAttribution::kTargetedFrame: {
729       auto* frame_document = GetDocument();
730       if (!frame_document)
731         return false;
732 
733       Document* target_document = nullptr;
734       if (auto* page = frame_document->GetPage()) {
735         auto& pointer_lock_controller = page->GetPointerLockController();
736         if (auto* element = pointer_lock_controller.GetElement()) {
737           // If a pointer lock is held, we can expect all events to be
738           // dispatched to the frame containing the locked element.
739           target_document = &element->GetDocument();
740         } else if (cc::ElementId element_id = attribution.target_frame_id()) {
741           DOMNodeId target_document_id =
742               DOMNodeIdFromCompositorElementId(element_id);
743           target_document =
744               DynamicTo<Document>(DOMNodeIds::NodeForId(target_document_id));
745         }
746       }
747 
748       if (!target_document || !target_document->domWindow())
749         return false;
750 
751       return GetSecurityContext()->GetSecurityOrigin()->CanAccess(
752           target_document->domWindow()->GetSecurityOrigin());
753     }
754     case WebInputEventAttribution::kFocusedFrame:
755       return GetPage() ? GetPage()->GetFocusController().FocusedFrame() == this
756                        : false;
757     case WebInputEventAttribution::kUnknown:
758       return false;
759   }
760 }
761 
IsTransientAllowFullscreenActive() const762 bool LocalFrame::IsTransientAllowFullscreenActive() const {
763   return transient_allow_fullscreen_.IsActive();
764 }
765 
SetOptimizationGuideHints(mojom::blink::BlinkOptimizationGuideHintsPtr hints)766 void LocalFrame::SetOptimizationGuideHints(
767     mojom::blink::BlinkOptimizationGuideHintsPtr hints) {
768   DCHECK(hints);
769   optimization_guide_hints_ = std::move(hints);
770   if (optimization_guide_hints_->delay_competing_low_priority_requests_hints) {
771     GetDocument()->Fetcher()->SetOptimizationGuideHints(
772         std::move(optimization_guide_hints_
773                       ->delay_competing_low_priority_requests_hints));
774   }
775 }
776 
SetPolicyContainer(std::unique_ptr<PolicyContainer> container)777 void LocalFrame::SetPolicyContainer(
778     std::unique_ptr<PolicyContainer> container) {
779   policy_container_ = std::move(container);
780 }
781 
Reload(WebFrameLoadType load_type)782 void LocalFrame::Reload(WebFrameLoadType load_type) {
783   DCHECK(IsReloadLoadType(load_type));
784   if (!loader_.GetDocumentLoader()->GetHistoryItem())
785     return;
786   TRACE_EVENT1("navigation", "LocalFrame::Reload", "load_type",
787                static_cast<int>(load_type));
788 
789   FrameLoadRequest request(
790       nullptr, loader_.ResourceRequestForReload(
791                    load_type, ClientRedirectPolicy::kClientRedirect));
792   request.SetClientRedirectReason(ClientNavigationReason::kReload);
793   probe::FrameScheduledNavigation(this, request.GetResourceRequest().Url(),
794                                   base::TimeDelta(),
795                                   ClientNavigationReason::kReload);
796   loader_.StartNavigation(request, load_type);
797   probe::FrameClearedScheduledNavigation(this);
798 }
799 
WindowProxy(DOMWrapperWorld & world)800 LocalWindowProxy* LocalFrame::WindowProxy(DOMWrapperWorld& world) {
801   return To<LocalWindowProxy>(Frame::GetWindowProxy(world));
802 }
803 
DomWindow() const804 LocalDOMWindow* LocalFrame::DomWindow() const {
805   return To<LocalDOMWindow>(dom_window_.Get());
806 }
807 
SetDOMWindow(LocalDOMWindow * dom_window)808 void LocalFrame::SetDOMWindow(LocalDOMWindow* dom_window) {
809   DCHECK(dom_window);
810   if (this->DomWindow()) {
811     this->DomWindow()->Reset();
812     // SystemClipboard and RawSystemClipboard uses HeapMojo wrappers. HeapMojo
813     // wrappers uses LocalDOMWindow (ExecutionContext) to reset the mojo
814     // objects when the ExecutionContext was destroyed. So when new
815     // LocalDOMWindow was set, we need to create new SystemClipboard and
816     // RawSystemClipboard.
817     system_clipboard_ = nullptr;
818     raw_system_clipboard_ = nullptr;
819   }
820   GetWindowProxyManager()->ClearForNavigation();
821   dom_window_ = dom_window;
822   dom_window->Initialize();
823 }
824 
GetDocument() const825 Document* LocalFrame::GetDocument() const {
826   return DomWindow() ? DomWindow()->document() : nullptr;
827 }
828 
SetPagePopupOwner(Element & owner)829 void LocalFrame::SetPagePopupOwner(Element& owner) {
830   page_popup_owner_ = &owner;
831 }
832 
ContentLayoutObject() const833 LayoutView* LocalFrame::ContentLayoutObject() const {
834   return GetDocument() ? GetDocument()->GetLayoutView() : nullptr;
835 }
836 
DidChangeVisibilityState()837 void LocalFrame::DidChangeVisibilityState() {
838   if (GetDocument())
839     GetDocument()->DidChangeVisibilityState();
840 
841   Frame::DidChangeVisibilityState();
842 }
843 
IsCaretBrowsingEnabled() const844 bool LocalFrame::IsCaretBrowsingEnabled() const {
845   return GetSettings() ? GetSettings()->GetCaretBrowsingEnabled() : false;
846 }
847 
HookBackForwardCacheEviction()848 void LocalFrame::HookBackForwardCacheEviction() {
849   // Register a callback dispatched when JavaScript is executed on the frame.
850   // The callback evicts the frame. If a frame is frozen by BackForwardCache,
851   // the frame must not be mutated e.g., by JavaScript execution, then the
852   // frame must be evicted in such cases.
853   DCHECK(RuntimeEnabledFeatures::BackForwardCacheEnabled());
854   static_cast<LocalWindowProxyManager*>(GetWindowProxyManager())
855       ->SetAbortScriptExecution(
856           [](v8::Isolate* isolate, v8::Local<v8::Context> context) {
857             ScriptState* script_state = ScriptState::From(context);
858             LocalDOMWindow* window = LocalDOMWindow::From(script_state);
859             DCHECK(window);
860             LocalFrame* frame = window->GetFrame();
861             if (frame) {
862               frame->EvictFromBackForwardCache(
863                   mojom::blink::RendererEvictionReason::kJavaScriptExecution);
864             }
865           });
866 }
867 
RemoveBackForwardCacheEviction()868 void LocalFrame::RemoveBackForwardCacheEviction() {
869   DCHECK(RuntimeEnabledFeatures::BackForwardCacheEnabled());
870   static_cast<LocalWindowProxyManager*>(GetWindowProxyManager())
871       ->SetAbortScriptExecution(nullptr);
872 }
873 
SetTextDirection(base::i18n::TextDirection direction)874 void LocalFrame::SetTextDirection(base::i18n::TextDirection direction) {
875   // The Editor::SetBaseWritingDirection() function checks if we can change
876   // the text direction of the selected node and updates its DOM "dir"
877   // attribute and its CSS "direction" property.
878   // So, we just call the function as Safari does.
879   Editor& editor = GetEditor();
880   if (!editor.CanEdit())
881     return;
882 
883   switch (direction) {
884     case base::i18n::TextDirection::UNKNOWN_DIRECTION:
885       editor.SetBaseWritingDirection(
886           mojo_base::mojom::blink::TextDirection::UNKNOWN_DIRECTION);
887       break;
888 
889     case base::i18n::TextDirection::LEFT_TO_RIGHT:
890       editor.SetBaseWritingDirection(
891           mojo_base::mojom::blink::TextDirection::LEFT_TO_RIGHT);
892       break;
893 
894     case base::i18n::TextDirection::RIGHT_TO_LEFT:
895       editor.SetBaseWritingDirection(
896           mojo_base::mojom::blink::TextDirection::RIGHT_TO_LEFT);
897       break;
898 
899     default:
900       NOTIMPLEMENTED();
901       break;
902   }
903 }
904 
SetIsInert(bool inert)905 void LocalFrame::SetIsInert(bool inert) {
906   is_inert_ = inert;
907   PropagateInertToChildFrames();
908 }
909 
PropagateInertToChildFrames()910 void LocalFrame::PropagateInertToChildFrames() {
911   for (Frame* child = Tree().FirstChild(); child;
912        child = child->Tree().NextSibling()) {
913     // is_inert_ means that this Frame is inert because of a modal dialog or
914     // inert element in an ancestor Frame. Otherwise, decide whether a child
915     // Frame element is inert because of an element in this Frame.
916     child->SetIsInert(is_inert_ ||
917                       To<HTMLFrameOwnerElement>(child->Owner())->IsInert());
918   }
919 }
920 
SetInheritedEffectiveTouchAction(TouchAction touch_action)921 void LocalFrame::SetInheritedEffectiveTouchAction(TouchAction touch_action) {
922   if (inherited_effective_touch_action_ == touch_action)
923     return;
924   inherited_effective_touch_action_ = touch_action;
925   GetDocument()->GetStyleEngine().MarkAllElementsForStyleRecalc(
926       StyleChangeReasonForTracing::Create(
927           style_change_reason::kInheritedStyleChangeFromParentFrame));
928 }
929 
BubbleLogicalScrollFromChildFrame(mojom::blink::ScrollDirection direction,ScrollGranularity granularity,Frame * child)930 bool LocalFrame::BubbleLogicalScrollFromChildFrame(
931     mojom::blink::ScrollDirection direction,
932     ScrollGranularity granularity,
933     Frame* child) {
934   FrameOwner* owner = child->Owner();
935   auto* owner_element = DynamicTo<HTMLFrameOwnerElement>(owner);
936   DCHECK(owner_element);
937 
938   return GetEventHandler().BubblingScroll(direction, granularity,
939                                           owner_element);
940 }
941 
942 mojom::blink::SuddenTerminationDisablerType
SuddenTerminationDisablerTypeForEventType(const AtomicString & event_type)943 SuddenTerminationDisablerTypeForEventType(const AtomicString& event_type) {
944   if (event_type == event_type_names::kUnload) {
945     return mojom::blink::SuddenTerminationDisablerType::kUnloadHandler;
946   }
947   if (event_type == event_type_names::kBeforeunload) {
948     return mojom::blink::SuddenTerminationDisablerType::kBeforeUnloadHandler;
949   }
950   if (event_type == event_type_names::kPagehide) {
951     return mojom::blink::SuddenTerminationDisablerType::kPageHideHandler;
952   }
953   if (event_type == event_type_names::kVisibilitychange) {
954     return mojom::blink::SuddenTerminationDisablerType::
955         kVisibilityChangeHandler;
956   }
957   NOTREACHED();
958   return mojom::blink::SuddenTerminationDisablerType::kUnloadHandler;
959 }
960 
NumberOfSuddenTerminationEventListeners(const EventTarget & event_target,const AtomicString & event_type)961 int NumberOfSuddenTerminationEventListeners(const EventTarget& event_target,
962                                             const AtomicString& event_type) {
963   if (event_type != event_type_names::kVisibilitychange)
964     return event_target.NumberOfEventListeners(event_type);
965   // For visibilitychange, we need to count the number of event listeners that
966   // are registered on the document and the window, as the event is initially
967   // dispatched on the document but might bubble up to the window.
968   // The other events (beforeunload, unload, pagehide) are dispatched on the
969   // window and won't bubble up anywhere, so we don't need to check for
970   // listeners the document for those events.
971   int total_listeners_count = event_target.NumberOfEventListeners(event_type);
972   if (auto* dom_window = event_target.ToLocalDOMWindow()) {
973     // |event_target| is the window, so get the count for listeners registered
974     // on the document.
975     total_listeners_count +=
976         dom_window->document()->NumberOfEventListeners(event_type);
977   } else {
978     auto* node = const_cast<EventTarget*>(&event_target)->ToNode();
979     DCHECK(node);
980     DCHECK(node->IsDocumentNode());
981     DCHECK(node->GetDocument().domWindow());
982     // |event_target| is the document, so get the count for listeners registered
983     // on the window.
984     total_listeners_count +=
985         node->GetDocument().domWindow()->NumberOfEventListeners(event_type);
986   }
987   return total_listeners_count;
988 }
989 
UpdateSuddenTerminationStatus(bool added_listener,mojom::blink::SuddenTerminationDisablerType disabler_type)990 void LocalFrame::UpdateSuddenTerminationStatus(
991     bool added_listener,
992     mojom::blink::SuddenTerminationDisablerType disabler_type) {
993   Platform::Current()->SuddenTerminationChanged(!added_listener);
994   GetLocalFrameHostRemote().SuddenTerminationDisablerChanged(added_listener,
995                                                              disabler_type);
996 }
997 
AddedSuddenTerminationDisablerListener(const EventTarget & event_target,const AtomicString & event_type)998 void LocalFrame::AddedSuddenTerminationDisablerListener(
999     const EventTarget& event_target,
1000     const AtomicString& event_type) {
1001   if (NumberOfSuddenTerminationEventListeners(event_target, event_type) == 1) {
1002     // The first handler of this type was added.
1003     UpdateSuddenTerminationStatus(
1004         true, SuddenTerminationDisablerTypeForEventType(event_type));
1005   }
1006 }
1007 
RemovedSuddenTerminationDisablerListener(const EventTarget & event_target,const AtomicString & event_type)1008 void LocalFrame::RemovedSuddenTerminationDisablerListener(
1009     const EventTarget& event_target,
1010     const AtomicString& event_type) {
1011   if (NumberOfSuddenTerminationEventListeners(event_target, event_type) == 0) {
1012     // The last handler of this type was removed.
1013     UpdateSuddenTerminationStatus(
1014         false, SuddenTerminationDisablerTypeForEventType(event_type));
1015   }
1016 }
1017 
DidFocus()1018 void LocalFrame::DidFocus() {
1019   GetLocalFrameHostRemote().DidFocusFrame();
1020 }
1021 
DidChangeThemeColor()1022 void LocalFrame::DidChangeThemeColor() {
1023   if (Tree().Parent())
1024     return;
1025 
1026   base::Optional<Color> color = GetDocument()->ThemeColor();
1027   base::Optional<SkColor> sk_color;
1028   if (color)
1029     sk_color = color->Rgb();
1030 
1031   GetLocalFrameHostRemote().DidChangeThemeColor(sk_color);
1032 }
1033 
DidChangeBackgroundColor(SkColor background_color,bool color_adjust)1034 void LocalFrame::DidChangeBackgroundColor(SkColor background_color,
1035                                           bool color_adjust) {
1036   DCHECK(!Tree().Parent());
1037   GetLocalFrameHostRemote().DidChangeBackgroundColor(background_color,
1038                                                      color_adjust);
1039 }
1040 
LocalFrameRoot() const1041 LocalFrame& LocalFrame::LocalFrameRoot() const {
1042   const LocalFrame* cur_frame = this;
1043   while (cur_frame && IsA<LocalFrame>(cur_frame->Tree().Parent()))
1044     cur_frame = To<LocalFrame>(cur_frame->Tree().Parent());
1045 
1046   return const_cast<LocalFrame&>(*cur_frame);
1047 }
1048 
GetInspectorTaskRunner()1049 scoped_refptr<InspectorTaskRunner> LocalFrame::GetInspectorTaskRunner() {
1050   return inspector_task_runner_;
1051 }
1052 
StartPrinting(const FloatSize & page_size,const FloatSize & original_page_size,float maximum_shrink_ratio)1053 void LocalFrame::StartPrinting(const FloatSize& page_size,
1054                                const FloatSize& original_page_size,
1055                                float maximum_shrink_ratio) {
1056   DCHECK(!saved_scroll_offsets_);
1057   SetPrinting(true, page_size, original_page_size, maximum_shrink_ratio);
1058 }
1059 
EndPrinting()1060 void LocalFrame::EndPrinting() {
1061   RestoreScrollOffsets();
1062   SetPrinting(false, FloatSize(), FloatSize(), 0);
1063 }
1064 
SetPrinting(bool printing,const FloatSize & page_size,const FloatSize & original_page_size,float maximum_shrink_ratio)1065 void LocalFrame::SetPrinting(bool printing,
1066                              const FloatSize& page_size,
1067                              const FloatSize& original_page_size,
1068                              float maximum_shrink_ratio) {
1069   // In setting printing, we should not validate resources already cached for
1070   // the document.  See https://bugs.webkit.org/show_bug.cgi?id=43704
1071   ResourceCacheValidationSuppressor validation_suppressor(
1072       GetDocument()->Fetcher());
1073 
1074   GetDocument()->SetPrinting(printing ? Document::kPrinting
1075                                       : Document::kFinishingPrinting);
1076   View()->AdjustMediaTypeForPrinting(printing);
1077 
1078   if (TextAutosizer* text_autosizer = GetDocument()->GetTextAutosizer())
1079     text_autosizer->UpdatePageInfo();
1080 
1081   if (ShouldUsePrintingLayout()) {
1082     View()->ForceLayoutForPagination(page_size, original_page_size,
1083                                      maximum_shrink_ratio);
1084   } else {
1085     if (LayoutView* layout_view = View()->GetLayoutView()) {
1086       layout_view->SetIntrinsicLogicalWidthsDirty();
1087       layout_view->SetNeedsLayout(layout_invalidation_reason::kPrintingChanged);
1088       layout_view->InvalidatePaintForViewAndDescendants();
1089     }
1090     View()->UpdateLayout();
1091     View()->AdjustViewSize();
1092   }
1093 
1094   // Subframes of the one we're printing don't lay out to the page size.
1095   for (Frame* child = Tree().FirstChild(); child;
1096        child = child->Tree().NextSibling()) {
1097     if (auto* child_local_frame = DynamicTo<LocalFrame>(child)) {
1098       if (printing)
1099         child_local_frame->StartPrinting();
1100       else
1101         child_local_frame->EndPrinting();
1102     }
1103   }
1104 
1105   if (auto* layout_view = View()->GetLayoutView()) {
1106     layout_view->AddSubtreePaintPropertyUpdateReason(
1107         SubtreePaintPropertyUpdateReason::kPrinting);
1108   }
1109 
1110   if (!printing)
1111     GetDocument()->SetPrinting(Document::kNotPrinting);
1112 }
1113 
ShouldUsePrintingLayout() const1114 bool LocalFrame::ShouldUsePrintingLayout() const {
1115   if (!GetDocument()->Printing())
1116     return false;
1117 
1118   // Only the top frame being printed should be fitted to page size.
1119   // Subframes should be constrained by parents only.
1120   // This function considers the following two kinds of frames as top frames:
1121   // -- frame with no parent;
1122   // -- frame's parent is not in printing mode.
1123   // For the second type, it is a bit complicated when its parent is a remote
1124   // frame. In such case, we can not check its document or other internal
1125   // status. However, if the parent is in printing mode, this frame's printing
1126   // must have started with |use_printing_layout| as false in print context.
1127   auto* parent = Tree().Parent();
1128   if (!parent)
1129     return true;
1130   auto* local_parent = DynamicTo<LocalFrame>(parent);
1131   return local_parent ? !local_parent->GetDocument()->Printing()
1132                       : Client()->UsePrintingLayout();
1133 }
1134 
EnsureSaveScrollOffset(Node & node)1135 void LocalFrame::EnsureSaveScrollOffset(Node& node) {
1136   const auto* scrollable_area = PaintLayerScrollableArea::FromNode(node);
1137   if (!scrollable_area)
1138     return;
1139   if (!saved_scroll_offsets_)
1140     saved_scroll_offsets_ = MakeGarbageCollected<SavedScrollOffsets>();
1141   // Retain the first scroll offset saved for each scrollable area.
1142   if (!saved_scroll_offsets_->Contains(&node))
1143     saved_scroll_offsets_->Set(&node, scrollable_area->GetScrollOffset());
1144 }
1145 
RestoreScrollOffsets()1146 void LocalFrame::RestoreScrollOffsets() {
1147   if (!saved_scroll_offsets_)
1148     return;
1149 
1150   // Restore scroll offsets unconditionally (i.e. without clamping) in case
1151   // layout or view sizes haven't been updated yet.
1152   for (auto& entry : *saved_scroll_offsets_) {
1153     auto* scrollable_area = PaintLayerScrollableArea::FromNode(*entry.key);
1154     if (!scrollable_area)
1155       continue;
1156     scrollable_area->SetScrollOffsetUnconditionally(
1157         entry.value, mojom::blink::ScrollType::kProgrammatic);
1158   }
1159   saved_scroll_offsets_ = nullptr;
1160 }
1161 
ResizePageRectsKeepingRatio(const FloatSize & original_size,const FloatSize & expected_size) const1162 FloatSize LocalFrame::ResizePageRectsKeepingRatio(
1163     const FloatSize& original_size,
1164     const FloatSize& expected_size) const {
1165   auto* layout_object = ContentLayoutObject();
1166   if (!layout_object)
1167     return FloatSize();
1168 
1169   bool is_horizontal = layout_object->StyleRef().IsHorizontalWritingMode();
1170   float width = original_size.Width();
1171   float height = original_size.Height();
1172   if (!is_horizontal)
1173     std::swap(width, height);
1174   DCHECK_GT(fabs(width), std::numeric_limits<float>::epsilon());
1175   float ratio = height / width;
1176 
1177   float result_width =
1178       floorf(is_horizontal ? expected_size.Width() : expected_size.Height());
1179   float result_height = floorf(result_width * ratio);
1180   if (!is_horizontal)
1181     std::swap(result_width, result_height);
1182   return FloatSize(result_width, result_height);
1183 }
1184 
SetPageZoomFactor(float factor)1185 void LocalFrame::SetPageZoomFactor(float factor) {
1186   SetPageAndTextZoomFactors(factor, text_zoom_factor_);
1187 }
1188 
SetTextZoomFactor(float factor)1189 void LocalFrame::SetTextZoomFactor(float factor) {
1190   SetPageAndTextZoomFactors(page_zoom_factor_, factor);
1191 }
1192 
SetPageAndTextZoomFactors(float page_zoom_factor,float text_zoom_factor)1193 void LocalFrame::SetPageAndTextZoomFactors(float page_zoom_factor,
1194                                            float text_zoom_factor) {
1195   if (page_zoom_factor_ == page_zoom_factor &&
1196       text_zoom_factor_ == text_zoom_factor)
1197     return;
1198 
1199   Page* page = this->GetPage();
1200   if (!page)
1201     return;
1202 
1203   Document* document = this->GetDocument();
1204   if (!document)
1205     return;
1206 
1207   // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents.
1208   // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG
1209   // WG clarification.
1210   if (document->IsSVGDocument()) {
1211     if (!document->AccessSVGExtensions().ZoomAndPanEnabled())
1212       return;
1213   }
1214 
1215   page_zoom_factor_ = page_zoom_factor;
1216   text_zoom_factor_ = text_zoom_factor;
1217 
1218   for (Frame* child = Tree().FirstChild(); child;
1219        child = child->Tree().NextSibling()) {
1220     if (auto* child_local_frame = DynamicTo<LocalFrame>(child)) {
1221       child_local_frame->SetPageAndTextZoomFactors(page_zoom_factor_,
1222                                                    text_zoom_factor_);
1223     }
1224   }
1225 
1226   document->MediaQueryAffectingValueChanged(MediaValueChange::kOther);
1227   document->GetStyleEngine().MarkViewportStyleDirty();
1228   document->GetStyleEngine().MarkAllElementsForStyleRecalc(
1229       StyleChangeReasonForTracing::Create(style_change_reason::kZoom));
1230   if (View() && View()->DidFirstLayout())
1231     document->UpdateStyleAndLayout(DocumentUpdateReason::kSizeChange);
1232 }
1233 
DeviceScaleFactorChanged()1234 void LocalFrame::DeviceScaleFactorChanged() {
1235   GetDocument()->MediaQueryAffectingValueChanged(MediaValueChange::kOther);
1236   GetDocument()->GetStyleEngine().MarkViewportStyleDirty();
1237   GetDocument()->GetStyleEngine().MarkAllElementsForStyleRecalc(
1238       StyleChangeReasonForTracing::Create(style_change_reason::kZoom));
1239   for (Frame* child = Tree().FirstChild(); child;
1240        child = child->Tree().NextSibling()) {
1241     if (auto* child_local_frame = DynamicTo<LocalFrame>(child))
1242       child_local_frame->DeviceScaleFactorChanged();
1243   }
1244 }
1245 
MediaQueryAffectingValueChangedForLocalSubtree(MediaValueChange value)1246 void LocalFrame::MediaQueryAffectingValueChangedForLocalSubtree(
1247     MediaValueChange value) {
1248   GetDocument()->MediaQueryAffectingValueChanged(value);
1249   for (Frame* child = Tree().FirstChild(); child;
1250        child = child->Tree().NextSibling()) {
1251     if (auto* child_local_frame = DynamicTo<LocalFrame>(child))
1252       child_local_frame->MediaQueryAffectingValueChangedForLocalSubtree(value);
1253   }
1254 }
1255 
WindowSegmentsChanged(const WebVector<WebRect> & window_segments)1256 void LocalFrame::WindowSegmentsChanged(
1257     const WebVector<WebRect>& window_segments) {
1258   if (!RuntimeEnabledFeatures::CSSFoldablesEnabled())
1259     return;
1260 
1261   DCHECK(IsLocalRoot());
1262 
1263   // A change in the window segments requires re-evaluation of media queries
1264   // for the local frame subtree (the segments affect the "screen-spanning"
1265   // feature).
1266   MediaQueryAffectingValueChangedForLocalSubtree(MediaValueChange::kOther);
1267 
1268   // Also need to update the environment variables related to window segments.
1269   UpdateCSSFoldEnvironmentVariables(window_segments);
1270 }
1271 
UpdateCSSFoldEnvironmentVariables(const WebVector<WebRect> & window_segments)1272 void LocalFrame::UpdateCSSFoldEnvironmentVariables(
1273     const WebVector<WebRect>& window_segments) {
1274   DCHECK(RuntimeEnabledFeatures::CSSFoldablesEnabled());
1275 
1276   // Update the variable values on the root instance so that documents that
1277   // are created after the values change automatically have the right values.
1278   StyleEnvironmentVariables& vars =
1279       StyleEnvironmentVariables::GetRootInstance();
1280 
1281   // CSS environment variables related to window segments currently only
1282   // expose values for a single fold (i.e. if there are two segments). In all
1283   // other cases, these variables will not be defined - see the else clause for
1284   // where these are unset.
1285   if (window_segments.size() == 2) {
1286     // We need to determine the rectangle between the two segments, which
1287     // describes the fold area (note that this may have a zero width or height,
1288     // but not negative).
1289     gfx::Rect fold_rect;
1290     if (window_segments[0].y == window_segments[1].y) {
1291       int fold_width = window_segments[1].x - window_segments[0].width;
1292       DCHECK_GE(fold_width, 0);
1293       fold_rect.SetRect(window_segments[0].width, window_segments[0].y,
1294                         fold_width, window_segments[0].height);
1295     } else if (window_segments[0].x == window_segments[1].x) {
1296       int fold_height = window_segments[1].y - window_segments[0].height;
1297       DCHECK_GE(fold_height, 0);
1298       fold_rect.SetRect(window_segments[0].x, window_segments[0].height,
1299                         window_segments[0].width, fold_height);
1300     }
1301 
1302     vars.SetVariable(UADefinedVariable::kFoldTop,
1303                      StyleEnvironmentVariables::FormatPx(fold_rect.y()));
1304     vars.SetVariable(UADefinedVariable::kFoldRight,
1305                      StyleEnvironmentVariables::FormatPx(fold_rect.right()));
1306     vars.SetVariable(UADefinedVariable::kFoldBottom,
1307                      StyleEnvironmentVariables::FormatPx(fold_rect.bottom()));
1308     vars.SetVariable(UADefinedVariable::kFoldLeft,
1309                      StyleEnvironmentVariables::FormatPx(fold_rect.x()));
1310     vars.SetVariable(UADefinedVariable::kFoldWidth,
1311                      StyleEnvironmentVariables::FormatPx(fold_rect.width()));
1312     vars.SetVariable(UADefinedVariable::kFoldHeight,
1313                      StyleEnvironmentVariables::FormatPx(fold_rect.height()));
1314   } else {
1315     // If there is not a single fold, we treat the variable as undefined
1316     // (i.e. the fallback value specified in the env() function).
1317     const UADefinedVariable vars_to_remove[] = {
1318         UADefinedVariable::kFoldTop,    UADefinedVariable::kFoldRight,
1319         UADefinedVariable::kFoldBottom, UADefinedVariable::kFoldLeft,
1320         UADefinedVariable::kFoldWidth,  UADefinedVariable::kFoldHeight,
1321     };
1322     for (auto var : vars_to_remove)
1323       vars.RemoveVariable(StyleEnvironmentVariables::GetVariableName(var));
1324   }
1325 }
1326 
DevicePixelRatio() const1327 double LocalFrame::DevicePixelRatio() const {
1328   if (!page_)
1329     return 0;
1330 
1331   double ratio = page_->DeviceScaleFactorDeprecated();
1332   ratio *= PageZoomFactor();
1333   return ratio;
1334 }
1335 
SelectedText() const1336 String LocalFrame::SelectedText() const {
1337   return Selection().SelectedText();
1338 }
1339 
SelectedTextForClipboard() const1340 String LocalFrame::SelectedTextForClipboard() const {
1341   if (!GetDocument())
1342     return g_empty_string;
1343   DCHECK(!GetDocument()->NeedsLayoutTreeUpdate());
1344   return Selection().SelectedTextForClipboard();
1345 }
1346 
TextSelectionChanged(const WTF::String & selection_text,uint32_t offset,const gfx::Range & range) const1347 void LocalFrame::TextSelectionChanged(const WTF::String& selection_text,
1348                                       uint32_t offset,
1349                                       const gfx::Range& range) const {
1350   GetLocalFrameHostRemote().TextSelectionChanged(selection_text, offset, range);
1351 }
1352 
PositionForPoint(const PhysicalOffset & frame_point)1353 PositionWithAffinity LocalFrame::PositionForPoint(
1354     const PhysicalOffset& frame_point) {
1355   HitTestLocation location(frame_point);
1356   HitTestResult result = GetEventHandler().HitTestResultAtLocation(location);
1357   Node* node = result.InnerPossiblyPseudoNode();
1358   if (node && !node->IsPseudoElement())
1359     node = result.InnerNodeOrImageMapImage();
1360   if (!node)
1361     return PositionWithAffinity();
1362   LayoutObject* layout_object = node->GetLayoutObject();
1363   if (!layout_object)
1364     return PositionWithAffinity();
1365   const PositionWithAffinity position =
1366       layout_object->PositionForPoint(result.LocalPoint());
1367   if (position.IsNull())
1368     return PositionWithAffinity(FirstPositionInOrBeforeNode(*node));
1369   return position;
1370 }
1371 
DocumentAtPoint(const PhysicalOffset & point_in_root_frame)1372 Document* LocalFrame::DocumentAtPoint(
1373     const PhysicalOffset& point_in_root_frame) {
1374   if (!View())
1375     return nullptr;
1376 
1377   HitTestLocation location(View()->ConvertFromRootFrame(point_in_root_frame));
1378 
1379   if (!ContentLayoutObject())
1380     return nullptr;
1381   HitTestResult result = GetEventHandler().HitTestResultAtLocation(
1382       location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
1383   return result.InnerNode() ? &result.InnerNode()->GetDocument() : nullptr;
1384 }
1385 
RemoveSpellingMarkersUnderWords(const Vector<String> & words)1386 void LocalFrame::RemoveSpellingMarkersUnderWords(const Vector<String>& words) {
1387   GetSpellChecker().RemoveSpellingMarkersUnderWords(words);
1388 }
1389 
GetLayerTreeAsTextForTesting(unsigned flags) const1390 String LocalFrame::GetLayerTreeAsTextForTesting(unsigned flags) const {
1391   if (!ContentLayoutObject())
1392     return String();
1393 
1394   std::unique_ptr<JSONObject> layers;
1395   if (!(flags & kOutputAsLayerTree)) {
1396     layers = View()->CompositedLayersAsJSON(static_cast<LayerTreeFlags>(flags));
1397   } else {
1398     if (const auto* root_layer =
1399             ContentLayoutObject()->Compositor()->RootGraphicsLayer()) {
1400       if (flags & kLayerTreeIncludesAllLayers && IsMainFrame()) {
1401         while (root_layer->Parent())
1402           root_layer = root_layer->Parent();
1403       }
1404       layers = GraphicsLayerTreeAsJSON(root_layer,
1405                                        static_cast<LayerTreeFlags>(flags));
1406     }
1407   }
1408   return layers ? layers->ToPrettyJSONString() : String();
1409 }
1410 
ShouldThrottleRendering() const1411 bool LocalFrame::ShouldThrottleRendering() const {
1412   return View() && View()->ShouldThrottleRendering();
1413 }
1414 
LocalFrame(LocalFrameClient * client,Page & page,FrameOwner * owner,Frame * parent,Frame * previous_sibling,FrameInsertType insert_type,const base::UnguessableToken & frame_token,WindowAgentFactory * inheriting_agent_factory,InterfaceRegistry * interface_registry,std::unique_ptr<PolicyContainer> policy_container,const base::TickClock * clock)1415 LocalFrame::LocalFrame(LocalFrameClient* client,
1416                        Page& page,
1417                        FrameOwner* owner,
1418                        Frame* parent,
1419                        Frame* previous_sibling,
1420                        FrameInsertType insert_type,
1421                        const base::UnguessableToken& frame_token,
1422                        WindowAgentFactory* inheriting_agent_factory,
1423                        InterfaceRegistry* interface_registry,
1424                        std::unique_ptr<PolicyContainer> policy_container,
1425                        const base::TickClock* clock)
1426     : Frame(client,
1427             page,
1428             owner,
1429             parent,
1430             previous_sibling,
1431             insert_type,
1432             frame_token,
1433             MakeGarbageCollected<LocalWindowProxyManager>(*this),
1434             inheriting_agent_factory),
1435       frame_scheduler_(page.GetPageScheduler()->CreateFrameScheduler(
1436           this,
1437           client->GetFrameBlameContext(),
1438           IsMainFrame() ? FrameScheduler::FrameType::kMainFrame
1439                         : FrameScheduler::FrameType::kSubframe)),
1440       loader_(this),
1441       editor_(MakeGarbageCollected<Editor>(*this)),
1442       selection_(MakeGarbageCollected<FrameSelection>(*this)),
1443       event_handler_(MakeGarbageCollected<EventHandler>(*this)),
1444       console_(MakeGarbageCollected<FrameConsole>(*this)),
1445       navigation_disable_count_(0),
1446       should_send_resource_timing_info_to_parent_(true),
1447       in_view_source_mode_(false),
1448       frozen_(false),
1449       paused_(false),
1450       hidden_(false),
1451       page_zoom_factor_(ParentPageZoomFactor(this)),
1452       text_zoom_factor_(ParentTextZoomFactor(this)),
1453       inspector_task_runner_(InspectorTaskRunner::Create(
1454           GetTaskRunner(TaskType::kInternalInspector))),
1455       interface_registry_(interface_registry
1456                               ? interface_registry
1457                               : InterfaceRegistry::GetEmptyInterfaceRegistry()),
1458       is_save_data_enabled_(GetNetworkStateNotifier().SaveDataEnabled()),
1459       lifecycle_state_(mojom::FrameLifecycleState::kRunning),
1460       policy_container_(std::move(policy_container)) {
1461   auto frame_tracking_result = GetLocalFramesMap().insert(
1462       base::UnguessableTokenHash()(frame_token), this);
1463   CHECK(frame_tracking_result.stored_value) << "Inserting a duplicate item.";
1464   if (IsLocalRoot()) {
1465     probe_sink_ = MakeGarbageCollected<CoreProbeSink>();
1466     performance_monitor_ = MakeGarbageCollected<PerformanceMonitor>(this);
1467     inspector_issue_reporter_ = MakeGarbageCollected<InspectorIssueReporter>(
1468         &page.GetInspectorIssueStorage());
1469     probe_sink_->AddInspectorIssueReporter(inspector_issue_reporter_);
1470     inspector_trace_events_ = MakeGarbageCollected<InspectorTraceEvents>();
1471     probe_sink_->AddInspectorTraceEvents(inspector_trace_events_);
1472     if (RuntimeEnabledFeatures::AdTaggingEnabled()) {
1473       ad_tracker_ = MakeGarbageCollected<AdTracker>(this);
1474     }
1475   } else {
1476     // Inertness only needs to be updated if this frame might inherit the
1477     // inert state from a higher-level frame. If this is an OOPIF local root,
1478     // it will be updated later.
1479     UpdateInertIfPossible();
1480     UpdateInheritedEffectiveTouchActionIfPossible();
1481     probe_sink_ = LocalFrameRoot().probe_sink_;
1482     ad_tracker_ = LocalFrameRoot().ad_tracker_;
1483     performance_monitor_ = LocalFrameRoot().performance_monitor_;
1484   }
1485   idleness_detector_ = MakeGarbageCollected<IdlenessDetector>(this, clock);
1486   inspector_task_runner_->InitIsolate(V8PerIsolateData::MainThreadIsolate());
1487 
1488   if (ad_tracker_) {
1489     SetIsAdSubframeIfNecessary();
1490   }
1491   DCHECK(ad_tracker_ ? RuntimeEnabledFeatures::AdTaggingEnabled()
1492                      : !RuntimeEnabledFeatures::AdTaggingEnabled());
1493   if (IsMainFrame()) {
1494     text_fragment_selector_generator_ =
1495         MakeGarbageCollected<TextFragmentSelectorGenerator>();
1496   }
1497 
1498   Initialize();
1499 
1500   probe::FrameAttachedToParent(this);
1501 #if defined(OS_MAC)
1502   // It should be bound before accessing TextInputHost which is the interface to
1503   // respond to GetCharacterIndexAtPoint.
1504   GetBrowserInterfaceBroker().GetInterface(
1505       text_input_host_.BindNewPipeAndPassReceiver(
1506           GetTaskRunner(blink::TaskType::kInternalDefault)));
1507 #endif
1508 }
1509 
GetFrameScheduler()1510 FrameScheduler* LocalFrame::GetFrameScheduler() {
1511   return frame_scheduler_.get();
1512 }
1513 
GetEventHandlerRegistry() const1514 EventHandlerRegistry& LocalFrame::GetEventHandlerRegistry() const {
1515   return event_handler_->GetEventHandlerRegistry();
1516 }
1517 
GetTaskRunner(TaskType type)1518 scoped_refptr<base::SingleThreadTaskRunner> LocalFrame::GetTaskRunner(
1519     TaskType type) {
1520   DCHECK(IsMainThread());
1521   return frame_scheduler_->GetTaskRunner(type);
1522 }
1523 
ScheduleVisualUpdateUnlessThrottled()1524 void LocalFrame::ScheduleVisualUpdateUnlessThrottled() {
1525   if (ShouldThrottleRendering())
1526     return;
1527   GetPage()->Animator().ScheduleVisualUpdate(this);
1528 }
1529 
CanAccessAncestor(const SecurityOrigin & active_security_origin,const Frame * target_frame)1530 static bool CanAccessAncestor(const SecurityOrigin& active_security_origin,
1531                               const Frame* target_frame) {
1532   // targetFrame can be 0 when we're trying to navigate a top-level frame
1533   // that has a 0 opener.
1534   if (!target_frame)
1535     return false;
1536 
1537   const bool is_local_active_origin = active_security_origin.IsLocal();
1538   for (const Frame* ancestor_frame = target_frame; ancestor_frame;
1539        ancestor_frame = ancestor_frame->Tree().Parent()) {
1540     const SecurityOrigin* ancestor_security_origin =
1541         ancestor_frame->GetSecurityContext()->GetSecurityOrigin();
1542     if (active_security_origin.CanAccess(ancestor_security_origin))
1543       return true;
1544 
1545     // Allow file URL descendant navigation even when
1546     // allowFileAccessFromFileURLs is false.
1547     // FIXME: It's a bit strange to special-case local origins here. Should we
1548     // be doing something more general instead?
1549     if (is_local_active_origin && ancestor_security_origin->IsLocal())
1550       return true;
1551   }
1552 
1553   return false;
1554 }
1555 
CanNavigate(const Frame & target_frame,const KURL & destination_url)1556 bool LocalFrame::CanNavigate(const Frame& target_frame,
1557                              const KURL& destination_url) {
1558   if (&target_frame == this)
1559     return true;
1560 
1561   // Navigating window.opener cross origin, without user activation. See
1562   // https://crbug.com/813643.
1563   if (Opener() == target_frame && !HasTransientUserActivation(this) &&
1564       !target_frame.GetSecurityContext()->GetSecurityOrigin()->CanAccess(
1565           SecurityOrigin::Create(destination_url).get())) {
1566     UseCounter::Count(GetDocument(),
1567                       WebFeature::kOpenerNavigationWithoutGesture);
1568   }
1569 
1570   if (destination_url.ProtocolIsJavaScript() &&
1571       !GetSecurityContext()->GetSecurityOrigin()->CanAccess(
1572           target_frame.GetSecurityContext()->GetSecurityOrigin())) {
1573     PrintNavigationErrorMessage(
1574         target_frame,
1575         "The frame attempting navigation must be same-origin with the target "
1576         "if navigating to a javascript: url");
1577     return false;
1578   }
1579 
1580   if (GetSecurityContext()->IsSandboxed(
1581           network::mojom::blink::WebSandboxFlags::kNavigation)) {
1582     if (!target_frame.Tree().IsDescendantOf(this) &&
1583         !target_frame.IsMainFrame()) {
1584       PrintNavigationErrorMessage(
1585           target_frame,
1586           "The frame attempting navigation is sandboxed, and is therefore "
1587           "disallowed from navigating its ancestors.");
1588       return false;
1589     }
1590 
1591     // Sandboxed frames can also navigate popups, if the
1592     // 'allow-sandbox-escape-via-popup' flag is specified, or if
1593     // 'allow-popups' flag is specified, or if the
1594     if (target_frame.IsMainFrame() && target_frame != Tree().Top() &&
1595         GetSecurityContext()->IsSandboxed(
1596             network::mojom::blink::WebSandboxFlags::
1597                 kPropagatesToAuxiliaryBrowsingContexts) &&
1598         (GetSecurityContext()->IsSandboxed(
1599              network::mojom::blink::WebSandboxFlags::kPopups) ||
1600          target_frame.Opener() != this)) {
1601       PrintNavigationErrorMessage(
1602           target_frame,
1603           "The frame attempting navigation is sandboxed and is trying "
1604           "to navigate a popup, but is not the popup's opener and is not "
1605           "set to propagate sandboxing to popups.");
1606       return false;
1607     }
1608 
1609     // Top navigation is forbidden unless opted-in. allow-top-navigation or
1610     // allow-top-navigation-by-user-activation will also skips origin checks.
1611     if (target_frame == Tree().Top()) {
1612       if (GetSecurityContext()->IsSandboxed(
1613               network::mojom::blink::WebSandboxFlags::kTopNavigation) &&
1614           GetSecurityContext()->IsSandboxed(
1615               network::mojom::blink::WebSandboxFlags::
1616                   kTopNavigationByUserActivation)) {
1617         PrintNavigationErrorMessage(
1618             target_frame,
1619             "The frame attempting navigation of the top-level window is "
1620             "sandboxed, but the flag of 'allow-top-navigation' or "
1621             "'allow-top-navigation-by-user-activation' is not set.");
1622         return false;
1623       }
1624 
1625       if (GetSecurityContext()->IsSandboxed(
1626               network::mojom::blink::WebSandboxFlags::kTopNavigation) &&
1627           !GetSecurityContext()->IsSandboxed(
1628               network::mojom::blink::WebSandboxFlags::
1629                   kTopNavigationByUserActivation) &&
1630           !LocalFrame::HasTransientUserActivation(this)) {
1631         // With only 'allow-top-navigation-by-user-activation' (but not
1632         // 'allow-top-navigation'), top navigation requires a user gesture.
1633         GetLocalFrameHostRemote().DidBlockNavigation(
1634             destination_url, GetDocument()->Url(),
1635             mojom::NavigationBlockedReason::kRedirectWithNoUserGestureSandbox);
1636         PrintNavigationErrorMessage(
1637             target_frame,
1638             "The frame attempting navigation of the top-level window is "
1639             "sandboxed with the 'allow-top-navigation-by-user-activation' "
1640             "flag, but has no user activation (aka gesture). See "
1641             "https://www.chromestatus.com/feature/5629582019395584.");
1642         return false;
1643       }
1644       return true;
1645     }
1646   }
1647 
1648   DCHECK(GetSecurityContext()->GetSecurityOrigin());
1649   const SecurityOrigin& origin = *GetSecurityContext()->GetSecurityOrigin();
1650 
1651   // This is the normal case. A document can navigate its decendant frames,
1652   // or, more generally, a document can navigate a frame if the document is
1653   // in the same origin as any of that frame's ancestors (in the frame
1654   // hierarchy).
1655   //
1656   // See http://www.adambarth.com/papers/2008/barth-jackson-mitchell.pdf for
1657   // historical information about this security check.
1658   if (CanAccessAncestor(origin, &target_frame))
1659     return true;
1660 
1661   // Top-level frames are easier to navigate than other frames because they
1662   // display their URLs in the address bar (in most browsers). However, there
1663   // are still some restrictions on navigation to avoid nuisance attacks.
1664   // Specifically, a document can navigate a top-level frame if that frame
1665   // opened the document or if the document is the same-origin with any of
1666   // the top-level frame's opener's ancestors (in the frame hierarchy).
1667   //
1668   // In both of these cases, the document performing the navigation is in
1669   // some way related to the frame being navigate (e.g., by the "opener"
1670   // and/or "parent" relation). Requiring some sort of relation prevents a
1671   // document from navigating arbitrary, unrelated top-level frames.
1672   if (!target_frame.Tree().Parent()) {
1673     if (target_frame == Opener())
1674       return true;
1675     if (CanAccessAncestor(origin, target_frame.Opener()))
1676       return true;
1677   }
1678 
1679   if (target_frame == Tree().Top()) {
1680     // A frame navigating its top may blocked if the document initiating
1681     // the navigation has never received a user gesture and the navigation
1682     // isn't same-origin with the target.
1683     if (HasStickyUserActivation() ||
1684         target_frame.GetSecurityContext()->GetSecurityOrigin()->CanAccess(
1685             SecurityOrigin::Create(destination_url).get())) {
1686       return true;
1687     }
1688 
1689     String target_domain = network_utils::GetDomainAndRegistry(
1690         target_frame.GetSecurityContext()->GetSecurityOrigin()->Domain(),
1691         network_utils::kIncludePrivateRegistries);
1692     String destination_domain = network_utils::GetDomainAndRegistry(
1693         destination_url.Host(), network_utils::kIncludePrivateRegistries);
1694     if (!target_domain.IsEmpty() && !destination_domain.IsEmpty() &&
1695         target_domain == destination_domain) {
1696       return true;
1697     }
1698     if (auto* settings_client = Client()->GetContentSettingsClient()) {
1699       if (settings_client->AllowPopupsAndRedirects(false /* default_value*/))
1700         return true;
1701     }
1702     PrintNavigationErrorMessage(
1703         target_frame,
1704         "The frame attempting navigation is targeting its top-level window, "
1705         "but is neither same-origin with its target nor has it received a "
1706         "user gesture. See "
1707         "https://www.chromestatus.com/features/5851021045661696.");
1708     GetLocalFrameHostRemote().DidBlockNavigation(
1709         destination_url, GetDocument()->Url(),
1710         mojom::NavigationBlockedReason::kRedirectWithNoUserGesture);
1711 
1712   } else {
1713     PrintNavigationErrorMessage(target_frame,
1714                                 "The frame attempting navigation is neither "
1715                                 "same-origin with the target, "
1716                                 "nor is it the target's parent or opener.");
1717   }
1718   return false;
1719 }
1720 
SetIsAdSubframeIfNecessary()1721 void LocalFrame::SetIsAdSubframeIfNecessary() {
1722   DCHECK(ad_tracker_);
1723   if (IsAdSubframe())
1724     return;
1725 
1726   Frame* parent = Tree().Parent();
1727   if (!parent)
1728     return;
1729 
1730   bool parent_is_ad = parent->IsAdSubframe();
1731 
1732   if (parent_is_ad ||
1733       ad_tracker_->IsAdScriptInStack(AdTracker::StackType::kBottomAndTop)) {
1734     SetIsAdSubframe(parent_is_ad ? blink::mojom::AdFrameType::kChildAd
1735                                  : blink::mojom::AdFrameType::kRootAd);
1736   }
1737 }
1738 
GetContentCaptureManager()1739 ContentCaptureManager* LocalFrame::GetContentCaptureManager() {
1740   DCHECK(Client());
1741   if (!IsLocalRoot())
1742     return nullptr;
1743 
1744   if (auto* content_capture_client = Client()->GetWebContentCaptureClient()) {
1745     if (!content_capture_manager_) {
1746       content_capture_manager_ =
1747           MakeGarbageCollected<ContentCaptureManager>(*this);
1748     }
1749   } else if (content_capture_manager_) {
1750     content_capture_manager_->Shutdown();
1751     content_capture_manager_ = nullptr;
1752   }
1753   return content_capture_manager_;
1754 }
1755 
GetBrowserInterfaceBroker()1756 BrowserInterfaceBrokerProxy& LocalFrame::GetBrowserInterfaceBroker() {
1757   DCHECK(Client());
1758   return Client()->GetBrowserInterfaceBroker();
1759 }
1760 
1761 AssociatedInterfaceProvider*
GetRemoteNavigationAssociatedInterfaces()1762 LocalFrame::GetRemoteNavigationAssociatedInterfaces() {
1763   DCHECK(Client());
1764   return Client()->GetRemoteNavigationAssociatedInterfaces();
1765 }
1766 
Client() const1767 LocalFrameClient* LocalFrame::Client() const {
1768   return static_cast<LocalFrameClient*>(Frame::Client());
1769 }
1770 
GetWidgetForLocalRoot()1771 FrameWidget* LocalFrame::GetWidgetForLocalRoot() {
1772   WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame(this);
1773   if (!web_frame)
1774     return nullptr;
1775   // This WebFrameWidgetBase upcasts to a FrameWidget which is the interface
1776   // exposed to Blink core.
1777   return web_frame->LocalRootFrameWidget();
1778 }
1779 
GetContentSettingsClient()1780 WebContentSettingsClient* LocalFrame::GetContentSettingsClient() {
1781   return Client() ? Client()->GetContentSettingsClient() : nullptr;
1782 }
1783 
GetPluginData() const1784 PluginData* LocalFrame::GetPluginData() const {
1785   if (!Loader().AllowPlugins(kNotAboutToInstantiatePlugin))
1786     return nullptr;
1787   return GetPage()->GetPluginData(
1788       Tree().Top().GetSecurityContext()->GetSecurityOrigin());
1789 }
1790 
SetAdTrackerForTesting(AdTracker * ad_tracker)1791 void LocalFrame::SetAdTrackerForTesting(AdTracker* ad_tracker) {
1792   if (ad_tracker_)
1793     ad_tracker_->Shutdown();
1794   ad_tracker_ = ad_tracker;
1795 }
1796 
DEFINE_WEAK_IDENTIFIER_MAP(LocalFrame)1797 DEFINE_WEAK_IDENTIFIER_MAP(LocalFrame)
1798 
1799 FrameNavigationDisabler::FrameNavigationDisabler(LocalFrame& frame)
1800     : frame_(&frame) {
1801   frame_->DisableNavigation();
1802 }
1803 
~FrameNavigationDisabler()1804 FrameNavigationDisabler::~FrameNavigationDisabler() {
1805   frame_->EnableNavigation();
1806 }
1807 
1808 namespace {
1809 
IsScopedFrameBlamerEnabled()1810 bool IsScopedFrameBlamerEnabled() {
1811   // Must match the category used in content::FrameBlameContext.
1812   static const auto* enabled =
1813       TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED("blink");
1814   return *enabled;
1815 }
1816 
1817 }  // namespace
1818 
ScopedFrameBlamer(LocalFrame * frame)1819 ScopedFrameBlamer::ScopedFrameBlamer(LocalFrame* frame)
1820     : frame_(IsScopedFrameBlamerEnabled() ? frame : nullptr) {
1821   if (LIKELY(!frame_))
1822     return;
1823   LocalFrameClient* client = frame_->Client();
1824   if (!client)
1825     return;
1826   if (BlameContext* context = client->GetFrameBlameContext())
1827     context->Enter();
1828 }
1829 
LeaveContext()1830 void ScopedFrameBlamer::LeaveContext() {
1831   LocalFrameClient* client = frame_->Client();
1832   if (!client)
1833     return;
1834   if (BlameContext* context = client->GetFrameBlameContext())
1835     context->Leave();
1836 }
1837 
GetLazyLoadImageSetting() const1838 LocalFrame::LazyLoadImageSetting LocalFrame::GetLazyLoadImageSetting() const {
1839   DCHECK(GetSettings());
1840   if (!RuntimeEnabledFeatures::LazyImageLoadingEnabled() ||
1841       !GetSettings()->GetLazyLoadEnabled()) {
1842     return LocalFrame::LazyLoadImageSetting::kDisabled;
1843   }
1844   // Disable explicit and automatic lazyload for backgrounded or prerendered
1845   // pages.
1846   if (!GetDocument()->IsPageVisible() || GetDocument()->IsPrefetchOnly()) {
1847     return LocalFrame::LazyLoadImageSetting::kDisabled;
1848   }
1849 
1850   if (!RuntimeEnabledFeatures::AutomaticLazyImageLoadingEnabled())
1851     return LocalFrame::LazyLoadImageSetting::kEnabledExplicit;
1852   if (RuntimeEnabledFeatures::
1853           RestrictAutomaticLazyImageLoadingToDataSaverEnabled() &&
1854       !is_save_data_enabled_) {
1855     return LocalFrame::LazyLoadImageSetting::kEnabledExplicit;
1856   }
1857 
1858   // Skip automatic lazyload when reloading a page.
1859   if (!RuntimeEnabledFeatures::AutoLazyLoadOnReloadsEnabled() &&
1860       Loader().GetDocumentLoader() &&
1861       IsReloadLoadType(Loader().GetDocumentLoader()->LoadType())) {
1862     return LocalFrame::LazyLoadImageSetting::kEnabledExplicit;
1863   }
1864 
1865   if (Owner() && !Owner()->ShouldLazyLoadChildren())
1866     return LocalFrame::LazyLoadImageSetting::kEnabledExplicit;
1867   return LocalFrame::LazyLoadImageSetting::kEnabledAutomatic;
1868 }
1869 
ShouldForceDeferScript() const1870 bool LocalFrame::ShouldForceDeferScript() const {
1871   // Check if we should not defer script in subframe.
1872   if (base::FeatureList::IsEnabled(features::kDisableForceDeferInChildFrames) &&
1873       !IsLocalRoot()) {
1874     return false;
1875   }
1876 
1877   // Check if enabled by runtime feature (for testing/evaluation) or if enabled
1878   // by PreviewsState (for live intervention).
1879   return RuntimeEnabledFeatures::ForceDeferScriptInterventionEnabled() ||
1880          (Loader().GetDocumentLoader() &&
1881           Loader().GetDocumentLoader()->GetPreviewsState() ==
1882               PreviewsTypes::kDeferAllScriptOn);
1883 }
1884 
GetURLLoaderFactory()1885 WebURLLoaderFactory* LocalFrame::GetURLLoaderFactory() {
1886   if (!url_loader_factory_)
1887     url_loader_factory_ = Client()->CreateURLLoaderFactory();
1888   return url_loader_factory_.get();
1889 }
1890 
GetWebPluginContainer(Node * node) const1891 WebPluginContainerImpl* LocalFrame::GetWebPluginContainer(Node* node) const {
1892   if (auto* plugin_document = DynamicTo<PluginDocument>(GetDocument())) {
1893     return plugin_document->GetPluginView();
1894   }
1895   if (!node) {
1896     DCHECK(GetDocument());
1897     node = GetDocument()->FocusedElement();
1898   }
1899 
1900   if (node) {
1901     return node->GetWebPluginContainer();
1902   }
1903   return nullptr;
1904 }
1905 
WasHidden()1906 void LocalFrame::WasHidden() {
1907   if (hidden_)
1908     return;
1909   hidden_ = true;
1910 
1911   if (content_capture_manager_) {
1912     content_capture_manager_->OnFrameWasHidden();
1913   }
1914 
1915   // An iframe may get a "was hidden" notification before it has been attached
1916   // to the frame tree; in that case, skip further processing.
1917   if (!Owner() || IsProvisional())
1918     return;
1919 
1920   // Mark intersections as dirty, so that child frames will reevaluate their
1921   // render throttling status on the next lifecycle update.
1922   LocalFrameView* frame_view = View();
1923   if (frame_view)
1924     frame_view->SetIntersectionObservationState(LocalFrameView::kDesired);
1925 
1926   // If we are tracking occlusion for this frame, and it was not previously
1927   // known to be occluded, then we need to force "not visible" notifications to
1928   // be sent, since it's unknown whether this frame will run lifecycle updates.
1929 
1930   // Frame was already occluded, nothing more to do.
1931   if (intersection_state_.occlusion_state ==
1932       mojom::blink::FrameOcclusionState::kPossiblyOccluded) {
1933     return;
1934   }
1935 
1936   Document* document = GetDocument();
1937   if (frame_view && document && document->IsActive()) {
1938     if (auto* controller = GetDocument()->GetIntersectionObserverController()) {
1939       if (controller->NeedsOcclusionTracking()) {
1940         View()->ForceUpdateViewportIntersections();
1941       }
1942     }
1943   }
1944 }
1945 
WasShown()1946 void LocalFrame::WasShown() {
1947   if (!hidden_)
1948     return;
1949   hidden_ = false;
1950   if (LocalFrameView* frame_view = View())
1951     frame_view->ScheduleAnimation();
1952 
1953   if (content_capture_manager_) {
1954     content_capture_manager_->OnFrameWasShown();
1955   }
1956 }
1957 
ClipsContent() const1958 bool LocalFrame::ClipsContent() const {
1959   // A paint preview shouldn't clip to the viewport. Each frame paints to a
1960   // separate canvas in full to allow scrolling.
1961   if (GetDocument()->IsPaintingPreview())
1962     return false;
1963 
1964   if (IsMainFrame())
1965     return GetSettings()->GetMainFrameClipsContent();
1966   // By default clip to viewport.
1967   return true;
1968 }
1969 
SetViewportIntersectionFromParent(const mojom::blink::ViewportIntersectionState & intersection_state)1970 void LocalFrame::SetViewportIntersectionFromParent(
1971     const mojom::blink::ViewportIntersectionState& intersection_state) {
1972   DCHECK(IsLocalRoot());
1973   // Notify the render frame observers when the main frame intersection changes.
1974   if (intersection_state_.main_frame_intersection !=
1975       intersection_state.main_frame_intersection) {
1976     gfx::RectF transform_rect =
1977         gfx::RectF(gfx::Rect(intersection_state.main_frame_intersection));
1978 
1979     intersection_state.main_frame_transform.TransformRect(&transform_rect);
1980     IntRect rect = EnclosingIntRect(
1981         FloatRect(transform_rect.x(), transform_rect.y(),
1982                   transform_rect.width(), transform_rect.height()));
1983 
1984     // Return <0, 0, 0, 0> if there is no area.
1985     if (rect.IsEmpty())
1986       rect.SetLocation(IntPoint(0, 0));
1987     Client()->OnMainFrameIntersectionChanged(rect);
1988   }
1989 
1990   // We only schedule an update if the viewport intersection or occlusion state
1991   // has changed; neither the viewport offset nor the compositing bounds will
1992   // affect IntersectionObserver.
1993   bool needs_update =
1994       intersection_state_.viewport_intersection !=
1995           intersection_state.viewport_intersection ||
1996       intersection_state_.occlusion_state != intersection_state.occlusion_state;
1997   intersection_state_ = intersection_state;
1998   if (needs_update) {
1999     if (LocalFrameView* frame_view = View()) {
2000       frame_view->SetIntersectionObservationState(LocalFrameView::kRequired);
2001       frame_view->ScheduleAnimation();
2002     }
2003   }
2004 }
2005 
GetMainFrameViewportSize() const2006 IntSize LocalFrame::GetMainFrameViewportSize() const {
2007   LocalFrame& local_root = LocalFrameRoot();
2008   return local_root.IsMainFrame()
2009              ? local_root.View()
2010                    ->GetScrollableArea()
2011                    ->VisibleContentRect()
2012                    .Size()
2013              : IntSize(local_root.intersection_state_.main_frame_viewport_size);
2014 }
2015 
GetMainFrameScrollOffset() const2016 IntPoint LocalFrame::GetMainFrameScrollOffset() const {
2017   LocalFrame& local_root = LocalFrameRoot();
2018   return local_root.IsMainFrame()
2019              ? FlooredIntPoint(
2020                    local_root.View()->GetScrollableArea()->GetScrollOffset())
2021              : IntPoint(
2022                    local_root.intersection_state_.main_frame_scroll_offset);
2023 }
2024 
SetOpener(Frame * opener_frame)2025 void LocalFrame::SetOpener(Frame* opener_frame) {
2026   // Only a local frame should be able to update another frame's opener.
2027   DCHECK(!opener_frame || opener_frame->IsLocalFrame());
2028 
2029   auto* web_frame = WebFrame::FromFrame(this);
2030   if (web_frame && Opener() != opener_frame) {
2031     GetLocalFrameHostRemote().DidChangeOpener(
2032         opener_frame ? base::Optional<base::UnguessableToken>(
2033                            opener_frame->GetFrameToken())
2034                      : base::nullopt);
2035   }
2036   SetOpenerDoNotNotify(opener_frame);
2037 }
2038 
GetOcclusionState() const2039 mojom::blink::FrameOcclusionState LocalFrame::GetOcclusionState() const {
2040   if (hidden_)
2041     return mojom::blink::FrameOcclusionState::kPossiblyOccluded;
2042   // TODO(dcheng): Get rid of this branch for the main frame.
2043   if (IsMainFrame())
2044     return mojom::blink::FrameOcclusionState::kGuaranteedNotOccluded;
2045   if (IsLocalRoot())
2046     return intersection_state_.occlusion_state;
2047   return LocalFrameRoot().GetOcclusionState();
2048 }
2049 
NeedsOcclusionTracking() const2050 bool LocalFrame::NeedsOcclusionTracking() const {
2051   if (Document* document = GetDocument()) {
2052     if (IntersectionObserverController* controller =
2053             document->GetIntersectionObserverController()) {
2054       return controller->NeedsOcclusionTracking();
2055     }
2056   }
2057   return false;
2058 }
2059 
ForceSynchronousDocumentInstall(const AtomicString & mime_type,scoped_refptr<SharedBuffer> data)2060 void LocalFrame::ForceSynchronousDocumentInstall(
2061     const AtomicString& mime_type,
2062     scoped_refptr<SharedBuffer> data) {
2063   CHECK(GetDocument()->IsInitialEmptyDocument());
2064   DCHECK(!Client()->IsLocalFrameClientImpl());
2065 
2066   // Any Document requires Shutdown() before detach, even the initial empty
2067   // document.
2068   GetDocument()->Shutdown();
2069   DomWindow()->ClearForReuse();
2070 
2071   DomWindow()->InstallNewDocument(DocumentInit::Create()
2072                                       .WithWindow(DomWindow(), nullptr)
2073                                       .WithTypeFrom(mime_type));
2074 
2075   GetDocument()->OpenForNavigation(kForceSynchronousParsing, mime_type,
2076                                    AtomicString("UTF-8"));
2077   for (const auto& segment : *data)
2078     GetDocument()->Parser()->AppendBytes(segment.data(), segment.size());
2079   GetDocument()->Parser()->Finish();
2080 
2081   // Upon loading of SVGImages, log PageVisits in UseCounter.
2082   // Do not track PageVisits for inspector, web page popups, and validation
2083   // message overlays (the other callers of this method).
2084   if (GetDocument()->IsSVGDocument())
2085     loader_.GetDocumentLoader()->GetUseCounterHelper().DidCommitLoad(this);
2086 }
2087 
IsProvisional() const2088 bool LocalFrame::IsProvisional() const {
2089   // Calling this after the frame is marked as completely detached is a bug, as
2090   // this state can no longer be accurately calculated.
2091   CHECK(!IsDetached());
2092 
2093   if (IsMainFrame()) {
2094     return GetPage()->MainFrame() != this;
2095   }
2096 
2097   DCHECK(Owner());
2098   return Owner()->ContentFrame() != this;
2099 }
2100 
SetIsAdSubframe(blink::mojom::AdFrameType ad_frame_type)2101 void LocalFrame::SetIsAdSubframe(blink::mojom::AdFrameType ad_frame_type) {
2102   DCHECK(!IsMainFrame());
2103 
2104   // Once |ad_frame_type_| has been set to an ad type on this frame, it cannot
2105   // be changed.
2106   if (ad_frame_type == blink::mojom::AdFrameType::kNonAd)
2107     return;
2108   if (ad_frame_type_ != blink::mojom::AdFrameType::kNonAd)
2109     return;
2110   if (auto* document = GetDocument()) {
2111     // TODO(fdoray): It is possible for the document not to be installed when
2112     // this method is called. Consider inheriting frame bit in the graph instead
2113     // of sending an IPC.
2114     auto* document_resource_coordinator = document->GetResourceCoordinator();
2115     if (document_resource_coordinator)
2116       document_resource_coordinator->SetIsAdFrame();
2117   }
2118   ad_frame_type_ = ad_frame_type;
2119   UpdateAdHighlight();
2120   frame_scheduler_->SetIsAdFrame();
2121 
2122   UseCounter::Count(DomWindow(), WebFeature::kAdFrameDetected);
2123   InstanceCounters::IncrementCounter(InstanceCounters::kAdSubframeCounter);
2124 }
2125 
UpdateAdHighlight()2126 void LocalFrame::UpdateAdHighlight() {
2127   if (!IsAdRoot()) {
2128     // Verify that non root ad subframes do not have an overlay.
2129     DCHECK(IsMainFrame() || !frame_color_overlay_);
2130     return;
2131   }
2132   if (GetPage()->GetSettings().GetHighlightAds())
2133     SetSubframeColorOverlay(SkColorSetARGB(128, 255, 0, 0));
2134   else
2135     SetSubframeColorOverlay(Color::kTransparent);
2136 }
2137 
PauseSubresourceLoading(mojo::PendingReceiver<blink::mojom::blink::PauseSubresourceLoadingHandle> receiver)2138 void LocalFrame::PauseSubresourceLoading(
2139     mojo::PendingReceiver<blink::mojom::blink::PauseSubresourceLoadingHandle>
2140         receiver) {
2141   auto handle = GetFrameScheduler()->GetPauseSubresourceLoadingHandle();
2142   if (!handle)
2143     return;
2144   pause_handle_receivers_.Add(std::move(handle), std::move(receiver),
2145                               GetTaskRunner(blink::TaskType::kInternalDefault));
2146 }
2147 
ResumeSubresourceLoading()2148 void LocalFrame::ResumeSubresourceLoading() {
2149   pause_handle_receivers_.Clear();
2150 }
2151 
AnimateSnapFling(base::TimeTicks monotonic_time)2152 void LocalFrame::AnimateSnapFling(base::TimeTicks monotonic_time) {
2153   GetEventHandler().AnimateSnapFling(monotonic_time);
2154 }
2155 
GetSmoothScrollSequencer()2156 SmoothScrollSequencer& LocalFrame::GetSmoothScrollSequencer() {
2157   if (!IsLocalRoot())
2158     return LocalFrameRoot().GetSmoothScrollSequencer();
2159   if (!smooth_scroll_sequencer_)
2160     smooth_scroll_sequencer_ = MakeGarbageCollected<SmoothScrollSequencer>();
2161   return *smooth_scroll_sequencer_;
2162 }
2163 
GetUkmRecorder()2164 ukm::UkmRecorder* LocalFrame::GetUkmRecorder() {
2165   Document* document = GetDocument();
2166   if (!document)
2167     return nullptr;
2168   return document->UkmRecorder();
2169 }
2170 
GetUkmSourceId()2171 int64_t LocalFrame::GetUkmSourceId() {
2172   Document* document = GetDocument();
2173   if (!document)
2174     return ukm::kInvalidSourceId;
2175   return document->UkmSourceID();
2176 }
2177 
UpdateTaskTime(base::TimeDelta time)2178 void LocalFrame::UpdateTaskTime(base::TimeDelta time) {
2179   Client()->DidChangeCpuTiming(time);
2180 }
2181 
UpdateActiveSchedulerTrackedFeatures(uint64_t features_mask)2182 void LocalFrame::UpdateActiveSchedulerTrackedFeatures(uint64_t features_mask) {
2183   GetLocalFrameHostRemote().DidChangeActiveSchedulerTrackedFeatures(
2184       features_mask);
2185 }
2186 
GetAgentClusterId() const2187 const base::UnguessableToken& LocalFrame::GetAgentClusterId() const {
2188   if (LocalDOMWindow* window = DomWindow()) {
2189     return window->GetAgentClusterID();
2190   }
2191   return base::UnguessableToken::Null();
2192 }
2193 
GetReportingService()2194 mojom::blink::ReportingServiceProxy* LocalFrame::GetReportingService() {
2195   if (!reporting_service_.is_bound()) {
2196     Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
2197         reporting_service_.BindNewPipeAndPassReceiver(
2198             GetTaskRunner(blink::TaskType::kInternalDefault)));
2199   }
2200   return reporting_service_.get();
2201 }
2202 
2203 // static
NotifyUserActivation(LocalFrame * frame,mojom::blink::UserActivationNotificationType notification_type,bool need_browser_verification)2204 void LocalFrame::NotifyUserActivation(
2205     LocalFrame* frame,
2206     mojom::blink::UserActivationNotificationType notification_type,
2207     bool need_browser_verification) {
2208   if (frame)
2209     frame->NotifyUserActivation(notification_type, need_browser_verification);
2210 }
2211 
2212 // static
HasTransientUserActivation(LocalFrame * frame)2213 bool LocalFrame::HasTransientUserActivation(LocalFrame* frame) {
2214   return frame ? frame->Frame::HasTransientUserActivation() : false;
2215 }
2216 
2217 // static
ConsumeTransientUserActivation(LocalFrame * frame,UserActivationUpdateSource update_source)2218 bool LocalFrame::ConsumeTransientUserActivation(
2219     LocalFrame* frame,
2220     UserActivationUpdateSource update_source) {
2221   return frame ? frame->ConsumeTransientUserActivation(update_source) : false;
2222 }
2223 
NotifyUserActivation(mojom::blink::UserActivationNotificationType notification_type,bool need_browser_verification)2224 void LocalFrame::NotifyUserActivation(
2225     mojom::blink::UserActivationNotificationType notification_type,
2226     bool need_browser_verification) {
2227   mojom::blink::UserActivationUpdateType update_type =
2228       need_browser_verification
2229           ? mojom::blink::UserActivationUpdateType::
2230                 kNotifyActivationPendingBrowserVerification
2231           : mojom::blink::UserActivationUpdateType::kNotifyActivation;
2232 
2233   GetLocalFrameHostRemote().UpdateUserActivationState(update_type,
2234                                                       notification_type);
2235   Client()->NotifyUserActivation();
2236   NotifyUserActivationInFrameTree(notification_type);
2237 }
2238 
ConsumeTransientUserActivation(UserActivationUpdateSource update_source)2239 bool LocalFrame::ConsumeTransientUserActivation(
2240     UserActivationUpdateSource update_source) {
2241   if (update_source == UserActivationUpdateSource::kRenderer) {
2242     GetLocalFrameHostRemote().UpdateUserActivationState(
2243         mojom::blink::UserActivationUpdateType::kConsumeTransientActivation,
2244         mojom::blink::UserActivationNotificationType::kNone);
2245   }
2246   return ConsumeTransientUserActivationInFrameTree();
2247 }
2248 
2249 namespace {
2250 
2251 class FrameColorOverlay final : public FrameOverlay::Delegate {
2252  public:
FrameColorOverlay(LocalFrame * frame,SkColor color)2253   explicit FrameColorOverlay(LocalFrame* frame, SkColor color)
2254       : color_(color), frame_(frame) {}
2255 
2256  private:
PaintFrameOverlay(const FrameOverlay & frame_overlay,GraphicsContext & graphics_context,const IntSize &) const2257   void PaintFrameOverlay(const FrameOverlay& frame_overlay,
2258                          GraphicsContext& graphics_context,
2259                          const IntSize&) const override {
2260     const auto* view = frame_->View();
2261     DCHECK(view);
2262     if (view->Width() == 0 || view->Height() == 0)
2263       return;
2264     ScopedPaintChunkProperties properties(
2265         graphics_context.GetPaintController(),
2266         view->GetLayoutView()->FirstFragment().LocalBorderBoxProperties(),
2267         frame_overlay, DisplayItem::kFrameOverlay);
2268     if (DrawingRecorder::UseCachedDrawingIfPossible(
2269             graphics_context, frame_overlay, DisplayItem::kFrameOverlay))
2270       return;
2271     DrawingRecorder recorder(graphics_context, frame_overlay,
2272                              DisplayItem::kFrameOverlay,
2273                              IntRect(IntPoint(), view->Size()));
2274     FloatRect rect(0, 0, view->Width(), view->Height());
2275     graphics_context.FillRect(rect, color_);
2276   }
2277 
2278   SkColor color_;
2279   Persistent<LocalFrame> frame_;
2280 };
2281 
2282 }  // namespace
2283 
SetMainFrameColorOverlay(SkColor color)2284 void LocalFrame::SetMainFrameColorOverlay(SkColor color) {
2285   DCHECK(IsMainFrame());
2286   SetFrameColorOverlay(color);
2287 }
2288 
SetSubframeColorOverlay(SkColor color)2289 void LocalFrame::SetSubframeColorOverlay(SkColor color) {
2290   DCHECK(!IsMainFrame());
2291   SetFrameColorOverlay(color);
2292 }
2293 
SetFrameColorOverlay(SkColor color)2294 void LocalFrame::SetFrameColorOverlay(SkColor color) {
2295   frame_color_overlay_.reset();
2296 
2297   if (color == Color::kTransparent)
2298     return;
2299 
2300   frame_color_overlay_ = std::make_unique<FrameOverlay>(
2301       this, std::make_unique<FrameColorOverlay>(this, color));
2302 }
2303 
UpdateFrameColorOverlayPrePaint()2304 void LocalFrame::UpdateFrameColorOverlayPrePaint() {
2305   if (frame_color_overlay_)
2306     frame_color_overlay_->UpdatePrePaint();
2307 }
2308 
PaintFrameColorOverlay(GraphicsContext & context)2309 void LocalFrame::PaintFrameColorOverlay(GraphicsContext& context) {
2310   DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
2311   if (frame_color_overlay_)
2312     frame_color_overlay_->Paint(context);
2313 }
2314 
ForciblyPurgeV8Memory()2315 void LocalFrame::ForciblyPurgeV8Memory() {
2316   DomWindow()->NotifyContextDestroyed();
2317 
2318   WindowProxyManager* window_proxy_manager = GetWindowProxyManager();
2319   window_proxy_manager->ClearForV8MemoryPurge();
2320   Loader().StopAllLoaders(/*abort_client=*/true);
2321 }
2322 
OnPageLifecycleStateUpdated()2323 void LocalFrame::OnPageLifecycleStateUpdated() {
2324   if (frozen_ != GetPage()->Frozen()) {
2325     frozen_ = GetPage()->Frozen();
2326     if (frozen_) {
2327       DidFreeze();
2328     } else {
2329       DidResume();
2330     }
2331     // The event handlers might have detached the frame.
2332     if (!IsAttached())
2333       return;
2334   }
2335   SetContextPaused(GetPage()->Paused());
2336 
2337   mojom::blink::FrameLifecycleState frame_lifecycle_state =
2338       mojom::blink::FrameLifecycleState::kRunning;
2339   if (GetPage()->Paused()) {
2340     frame_lifecycle_state = mojom::blink::FrameLifecycleState::kPaused;
2341   } else if (GetPage()->Frozen()) {
2342     frame_lifecycle_state = mojom::blink::FrameLifecycleState::kFrozen;
2343   }
2344 
2345   DomWindow()->SetLifecycleState(frame_lifecycle_state);
2346 }
2347 
SetContextPaused(bool is_paused)2348 void LocalFrame::SetContextPaused(bool is_paused) {
2349   if (is_paused == paused_)
2350     return;
2351   paused_ = is_paused;
2352 
2353   GetDocument()->Fetcher()->SetDefersLoading(GetLoadDeferType());
2354   Loader().SetDefersLoading(GetLoadDeferType());
2355   // TODO(altimin): Move this to PageScheduler level.
2356   GetFrameScheduler()->SetPaused(is_paused);
2357 }
2358 
IsLoadDeferred()2359 bool LocalFrame::IsLoadDeferred() {
2360   return frozen_ || paused_;
2361 }
2362 
GetLoadDeferType()2363 WebURLLoader::DeferType LocalFrame::GetLoadDeferType() {
2364   if (GetPage()->GetPageScheduler()->IsInBackForwardCache() &&
2365       base::FeatureList::IsEnabled(features::kLoadingTasksUnfreezable)) {
2366     return WebURLLoader::DeferType::kDeferredWithBackForwardCache;
2367   }
2368   if (paused_ || frozen_)
2369     return WebURLLoader::DeferType::kDeferred;
2370   return WebURLLoader::DeferType::kNotDeferred;
2371 }
2372 
DidFreeze()2373 void LocalFrame::DidFreeze() {
2374   DCHECK(IsAttached());
2375   GetDocument()->DispatchFreezeEvent();
2376   // DispatchFreezeEvent dispatches JS events, which may detach |this|.
2377   if (!IsAttached())
2378     return;
2379   // TODO(fmeawad): Move the following logic to the page once we have a
2380   // PageResourceCoordinator in Blink. http://crbug.com/838415
2381   if (auto* document_resource_coordinator =
2382           GetDocument()->GetResourceCoordinator()) {
2383     document_resource_coordinator->SetLifecycleState(
2384         performance_manager::mojom::LifecycleState::kFrozen);
2385   }
2386 
2387   if (GetPage()->GetPageScheduler()->IsInBackForwardCache()) {
2388     DomWindow()->SetIsInBackForwardCache(true);
2389   }
2390 
2391   WebURLLoader::DeferType defer = GetLoadDeferType();
2392   GetDocument()->Fetcher()->SetDefersLoading(defer);
2393   Loader().SetDefersLoading(defer);
2394 }
2395 
DidResume()2396 void LocalFrame::DidResume() {
2397   DCHECK(IsAttached());
2398   const base::TimeTicks resume_event_start = base::TimeTicks::Now();
2399   GetDocument()->DispatchEvent(*Event::Create(event_type_names::kResume));
2400   const base::TimeTicks resume_event_end = base::TimeTicks::Now();
2401   base::UmaHistogramMicrosecondsTimes("DocumentEventTiming.ResumeDuration",
2402                                       resume_event_end - resume_event_start);
2403   // TODO(fmeawad): Move the following logic to the page once we have a
2404   // PageResourceCoordinator in Blink
2405   if (auto* document_resource_coordinator =
2406           GetDocument()->GetResourceCoordinator()) {
2407     document_resource_coordinator->SetLifecycleState(
2408         performance_manager::mojom::LifecycleState::kRunning);
2409   }
2410 
2411   // TODO(yuzus): Figure out if we should call GetLoadDeferType().
2412   GetDocument()->Fetcher()->SetDefersLoading(
2413       WebURLLoader::DeferType::kNotDeferred);
2414   Loader().SetDefersLoading(WebURLLoader::DeferType::kNotDeferred);
2415 
2416   DomWindow()->SetIsInBackForwardCache(false);
2417 }
2418 
MaybeLogAdClickNavigation()2419 void LocalFrame::MaybeLogAdClickNavigation() {
2420   if (HasTransientUserActivation(this) && IsAdSubframe())
2421     UseCounter::Count(GetDocument(), WebFeature::kAdClickNavigation);
2422 }
2423 
CountUseIfFeatureWouldBeBlockedByFeaturePolicy(mojom::WebFeature blocked_cross_origin,mojom::WebFeature blocked_same_origin)2424 void LocalFrame::CountUseIfFeatureWouldBeBlockedByFeaturePolicy(
2425     mojom::WebFeature blocked_cross_origin,
2426     mojom::WebFeature blocked_same_origin) {
2427   // Get the origin of the top-level document
2428   const SecurityOrigin* topOrigin =
2429       Tree().Top().GetSecurityContext()->GetSecurityOrigin();
2430 
2431   // Check if this frame is same-origin with the top-level
2432   if (!GetSecurityContext()->GetSecurityOrigin()->CanAccess(topOrigin)) {
2433     // This frame is cross-origin with the top-level frame, and so would be
2434     // blocked without a feature policy.
2435     UseCounter::Count(GetDocument(), blocked_cross_origin);
2436     return;
2437   }
2438 
2439   // Walk up the frame tree looking for any cross-origin embeds. Even if this
2440   // frame is same-origin with the top-level, if it is embedded by a cross-
2441   // origin frame (like A->B->A) it would be blocked without a feature policy.
2442   const Frame* f = this;
2443   while (!f->IsMainFrame()) {
2444     if (!f->GetSecurityContext()->GetSecurityOrigin()->CanAccess(topOrigin)) {
2445       UseCounter::Count(GetDocument(), blocked_same_origin);
2446       return;
2447     }
2448     f = f->Tree().Parent();
2449   }
2450 }
2451 
FinishedLoading(FrameLoader::NavigationFinishState state)2452 void LocalFrame::FinishedLoading(FrameLoader::NavigationFinishState state) {
2453   DomWindow()->FinishedLoading(state);
2454 }
2455 
UpdateFaviconURL()2456 void LocalFrame::UpdateFaviconURL() {
2457   if (!IsMainFrame())
2458     return;
2459 
2460   // The URL to the icon may be in the header. As such, only
2461   // ask the loader for the icon if it's finished loading.
2462   if (!GetDocument()->LoadEventFinished())
2463     return;
2464 
2465   int icon_types_mask =
2466       1 << static_cast<int>(mojom::blink::FaviconIconType::kFavicon) |
2467       1 << static_cast<int>(mojom::blink::FaviconIconType::kTouchIcon) |
2468       1 << static_cast<int>(
2469           mojom::blink::FaviconIconType::kTouchPrecomposedIcon);
2470   Vector<IconURL> icon_urls = GetDocument()->IconURLs(icon_types_mask);
2471   if (icon_urls.IsEmpty())
2472     return;
2473 
2474   Vector<mojom::blink::FaviconURLPtr> urls;
2475   urls.ReserveCapacity(icon_urls.size());
2476   for (const auto& icon_url : icon_urls) {
2477     urls.push_back(mojom::blink::FaviconURL::New(
2478         icon_url.icon_url_, icon_url.icon_type_, icon_url.sizes_));
2479   }
2480   DCHECK_EQ(icon_urls.size(), urls.size());
2481 
2482   GetLocalFrameHostRemote().UpdateFaviconURL(std::move(urls));
2483 
2484   if (GetPage())
2485     GetPage()->GetPageScheduler()->OnTitleOrFaviconUpdated();
2486 }
2487 
SetIsCapturingMediaCallback(IsCapturingMediaCallback callback)2488 void LocalFrame::SetIsCapturingMediaCallback(
2489     IsCapturingMediaCallback callback) {
2490   is_capturing_media_callback_ = std::move(callback);
2491 }
2492 
IsCapturingMedia() const2493 bool LocalFrame::IsCapturingMedia() const {
2494   return is_capturing_media_callback_ ? is_capturing_media_callback_.Run()
2495                                       : false;
2496 }
2497 
GetSystemClipboard()2498 SystemClipboard* LocalFrame::GetSystemClipboard() {
2499   if (!system_clipboard_)
2500     system_clipboard_ = MakeGarbageCollected<SystemClipboard>(this);
2501 
2502   return system_clipboard_.Get();
2503 }
2504 
GetRawSystemClipboard()2505 RawSystemClipboard* LocalFrame::GetRawSystemClipboard() {
2506   if (!raw_system_clipboard_)
2507     raw_system_clipboard_ = MakeGarbageCollected<RawSystemClipboard>(this);
2508 
2509   return raw_system_clipboard_.Get();
2510 }
2511 
WasAttachedAsLocalMainFrame()2512 void LocalFrame::WasAttachedAsLocalMainFrame() {
2513   GetInterfaceRegistry()->AddAssociatedInterface(WTF::BindRepeating(
2514       &LocalFrame::BindToMainFrameReceiver, WrapWeakPersistent(this)));
2515 }
2516 
EvictFromBackForwardCache(mojom::blink::RendererEvictionReason reason)2517 void LocalFrame::EvictFromBackForwardCache(
2518     mojom::blink::RendererEvictionReason reason) {
2519   GetBackForwardCacheControllerHostRemote().EvictFromBackForwardCache(reason);
2520 }
2521 
AnimateDoubleTapZoom(const gfx::Point & point,const gfx::Rect & rect)2522 void LocalFrame::AnimateDoubleTapZoom(const gfx::Point& point,
2523                                       const gfx::Rect& rect) {
2524   GetPage()->GetChromeClient().AnimateDoubleTapZoom(point, rect);
2525 }
2526 
SetScaleFactor(float scale_factor)2527 void LocalFrame::SetScaleFactor(float scale_factor) {
2528   DCHECK(IsMainFrame());
2529 
2530   const PageScaleConstraints& constraints =
2531       GetPage()->GetPageScaleConstraintsSet().FinalConstraints();
2532   scale_factor = constraints.ClampToConstraints(scale_factor);
2533   if (scale_factor == GetPage()->GetVisualViewport().Scale())
2534     return;
2535   GetPage()->GetVisualViewport().SetScale(scale_factor);
2536 }
2537 
ClosePage(mojom::blink::LocalMainFrame::ClosePageCallback completion_callback)2538 void LocalFrame::ClosePage(
2539     mojom::blink::LocalMainFrame::ClosePageCallback completion_callback) {
2540   SECURITY_CHECK(IsMainFrame());
2541 
2542   // There are two ways to close a page:
2543   //
2544   // 1/ Via webview()->Close() that currently sets the WebView's delegate_ to
2545   // NULL, and prevent any JavaScript dialogs in the onunload handler from
2546   // appearing.
2547   //
2548   // 2/ Calling the FrameLoader's CloseURL method directly.
2549   //
2550   // TODO(creis): Having a single way to close that can run onunload is also
2551   // useful for fixing http://b/issue?id=753080.
2552 
2553   SubframeLoadingDisabler disabler(GetDocument());
2554   // https://html.spec.whatwg.org/C/browsing-the-web.html#unload-a-document
2555   // The ignore-opens-during-unload counter of a Document must be incremented
2556   // when unloading itself.
2557   IgnoreOpensDuringUnloadCountIncrementer ignore_opens_during_unload(
2558       GetDocument());
2559   Loader().DispatchUnloadEvent(nullptr, nullptr);
2560 
2561   std::move(completion_callback).Run();
2562 }
2563 
PluginActionAt(const gfx::Point & location,mojom::blink::PluginActionType action)2564 void LocalFrame::PluginActionAt(const gfx::Point& location,
2565                                 mojom::blink::PluginActionType action) {
2566   SECURITY_CHECK(IsMainFrame());
2567 
2568   // TODO(bokan): Location is probably in viewport coordinates
2569   HitTestResult result =
2570       HitTestResultForRootFramePos(this, PhysicalOffset(IntPoint(location)));
2571   Node* node = result.InnerNode();
2572   if (!IsA<HTMLObjectElement>(*node) && !IsA<HTMLEmbedElement>(*node))
2573     return;
2574 
2575   auto* embedded = DynamicTo<LayoutEmbeddedContent>(node->GetLayoutObject());
2576   if (!embedded)
2577     return;
2578 
2579   WebPluginContainerImpl* plugin_view = embedded->Plugin();
2580   if (!plugin_view)
2581     return;
2582 
2583   switch (action) {
2584     case mojom::blink::PluginActionType::kRotate90Clockwise:
2585       plugin_view->Plugin()->RotateView(WebPlugin::kRotationType90Clockwise);
2586       return;
2587     case mojom::blink::PluginActionType::kRotate90Counterclockwise:
2588       plugin_view->Plugin()->RotateView(
2589           WebPlugin::kRotationType90Counterclockwise);
2590       return;
2591   }
2592   NOTREACHED();
2593 }
2594 
SetInitialFocus(bool reverse)2595 void LocalFrame::SetInitialFocus(bool reverse) {
2596   GetDocument()->ClearFocusedElement();
2597   GetPage()->GetFocusController().SetInitialFocus(
2598       reverse ? mojom::blink::FocusType::kBackward
2599               : mojom::blink::FocusType::kForward);
2600 }
2601 
EnablePreferredSizeChangedMode()2602 void LocalFrame::EnablePreferredSizeChangedMode() {
2603   GetPage()->GetChromeClient().EnablePreferredSizeChangedMode();
2604 }
2605 
ZoomToFindInPageRect(const gfx::Rect & rect_in_root_frame)2606 void LocalFrame::ZoomToFindInPageRect(const gfx::Rect& rect_in_root_frame) {
2607   GetPage()->GetChromeClient().ZoomToFindInPageRect(
2608       WebRect(rect_in_root_frame));
2609 }
2610 
2611 #if defined(OS_MAC)
GetCharacterIndexAtPoint(const gfx::Point & point)2612 void LocalFrame::GetCharacterIndexAtPoint(const gfx::Point& point) {
2613   HitTestLocation location(View()->ViewportToFrame(IntPoint(point)));
2614   HitTestResult result = GetEventHandler().HitTestResultAtLocation(
2615       location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
2616   uint32_t index =
2617       Selection().CharacterIndexForPoint(result.RoundedPointInInnerNodeFrame());
2618   GetTextInputHost().GotCharacterIndexAtPoint(index);
2619 }
2620 
GetFirstRectForRange(const gfx::Range & range)2621 void LocalFrame::GetFirstRectForRange(const gfx::Range& range) {
2622   gfx::Rect rect;
2623   WebLocalFrameClient* client = WebLocalFrameImpl::FromFrame(this)->Client();
2624   if (!client)
2625     return;
2626 
2627   if (!client->GetCaretBoundsFromFocusedPlugin(rect)) {
2628     blink::WebRect web_rect;
2629     // When request range is invalid we will try to obtain it from current
2630     // frame selection. The fallback value will be 0.
2631     uint32_t start =
2632         range.IsValid() ? range.start() : GetCurrentCursorPositionInFrame(this);
2633 
2634     WebLocalFrameImpl::FromFrame(this)->FirstRectForCharacterRange(
2635         start, range.length(), web_rect);
2636     rect.SetRect(web_rect.x, web_rect.y, web_rect.width, web_rect.height);
2637   }
2638 
2639   GetTextInputHost().GotFirstRectForRange(rect);
2640 }
2641 
GetStringForRange(const gfx::Range & range,GetStringForRangeCallback callback)2642 void LocalFrame::GetStringForRange(const gfx::Range& range,
2643                                    GetStringForRangeCallback callback) {
2644   gfx::Point baseline_point;
2645   ui::mojom::blink::AttributedStringPtr attributed_string = nullptr;
2646   NSAttributedString* string = SubstringUtil::AttributedSubstringInRange(
2647       this, range.start(), range.length(), &baseline_point);
2648   if (string)
2649     attributed_string = ui::mojom::blink::AttributedString::From(string);
2650 
2651   std::move(callback).Run(std::move(attributed_string), baseline_point);
2652 }
2653 #endif
2654 
InstallCoopAccessMonitor(network::mojom::blink::CoopAccessReportType report_type,const base::UnguessableToken & accessed_window,mojo::PendingRemote<network::mojom::blink::CrossOriginOpenerPolicyReporter> reporter,bool endpoint_defined,const WTF::String & reported_window_url)2655 void LocalFrame::InstallCoopAccessMonitor(
2656     network::mojom::blink::CoopAccessReportType report_type,
2657     const base::UnguessableToken& accessed_window,
2658     mojo::PendingRemote<network::mojom::blink::CrossOriginOpenerPolicyReporter>
2659         reporter,
2660     bool endpoint_defined,
2661     const WTF::String& reported_window_url) {
2662   blink::Frame* accessed_frame = Frame::ResolveFrame(accessed_window);
2663   // The Frame might have been deleted during the cross-process communication.
2664   if (!accessed_frame)
2665     return;
2666 
2667   accessed_frame->DomWindow()->InstallCoopAccessMonitor(
2668       report_type, this, std::move(reporter), endpoint_defined,
2669       std::move(reported_window_url));
2670 }
2671 
OnPortalActivated(const PortalToken & portal_token,mojo::PendingAssociatedRemote<mojom::blink::Portal> portal,mojo::PendingAssociatedReceiver<mojom::blink::PortalClient> portal_client,BlinkTransferableMessage data,uint64_t trace_id,OnPortalActivatedCallback callback)2672 void LocalFrame::OnPortalActivated(
2673     const PortalToken& portal_token,
2674     mojo::PendingAssociatedRemote<mojom::blink::Portal> portal,
2675     mojo::PendingAssociatedReceiver<mojom::blink::PortalClient> portal_client,
2676     BlinkTransferableMessage data,
2677     uint64_t trace_id,
2678     OnPortalActivatedCallback callback) {
2679   DCHECK(GetDocument());
2680   PaintTiming::From(*GetDocument()).OnPortalActivate();
2681 
2682   TRACE_EVENT_WITH_FLOW0("navigation", "LocalFrame::OnPortalActivated",
2683                          TRACE_ID_GLOBAL(trace_id), TRACE_EVENT_FLAG_FLOW_IN);
2684 
2685   DOMWindowPortalHost::portalHost(*DomWindow())->OnPortalActivated();
2686   GetPage()->SetInsidePortal(false);
2687 
2688   DCHECK(!data.locked_agent_cluster_id)
2689       << "portal activation is always cross-agent-cluster and should be "
2690          "diagnosed early";
2691   MessagePortArray* ports =
2692       MessagePort::EntanglePorts(*DomWindow(), std::move(data.ports));
2693 
2694   PortalActivateEvent* event = PortalActivateEvent::Create(
2695       this, portal_token, std::move(portal), std::move(portal_client),
2696       std::move(data.message), ports, std::move(callback));
2697 
2698   ThreadDebugger* debugger = MainThreadDebugger::Instance();
2699   if (debugger)
2700     debugger->ExternalAsyncTaskStarted(data.sender_stack_trace_id);
2701   DomWindow()->DispatchEvent(*event);
2702   if (debugger)
2703     debugger->ExternalAsyncTaskFinished(data.sender_stack_trace_id);
2704   event->ExpireAdoptionLifetime();
2705 }
2706 
ForwardMessageFromHost(BlinkTransferableMessage message,const scoped_refptr<const SecurityOrigin> & source_origin)2707 void LocalFrame::ForwardMessageFromHost(
2708     BlinkTransferableMessage message,
2709     const scoped_refptr<const SecurityOrigin>& source_origin) {
2710   PortalHost::From(*DomWindow())
2711       .ReceiveMessage(std::move(message), source_origin);
2712 }
2713 
HitTestResultForVisualViewportPos(const IntPoint & pos_in_viewport)2714 HitTestResult LocalFrame::HitTestResultForVisualViewportPos(
2715     const IntPoint& pos_in_viewport) {
2716   IntPoint root_frame_point(
2717       GetPage()->GetVisualViewport().ViewportToRootFrame(pos_in_viewport));
2718   HitTestLocation location(View()->ConvertFromRootFrame(root_frame_point));
2719   HitTestResult result = GetEventHandler().HitTestResultAtLocation(
2720       location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
2721   result.SetToShadowHostIfInRestrictedShadowRoot();
2722   return result;
2723 }
2724 
DidChangeVisibleToHitTesting()2725 void LocalFrame::DidChangeVisibleToHitTesting() {
2726   // LayoutEmbeddedContent does not propagate style updates to descendants.
2727   // Need to update the field manually.
2728   for (Frame* child = Tree().FirstChild(); child;
2729        child = child->Tree().NextSibling()) {
2730     child->UpdateVisibleToHitTesting();
2731   }
2732 
2733   // The transform property tree node depends on visibility.
2734   if (auto* view = View()->GetLayoutView()) {
2735     view->SetNeedsPaintPropertyUpdate();
2736   }
2737 }
2738 
PrescientNetworking()2739 WebPrescientNetworking* LocalFrame::PrescientNetworking() {
2740   if (!prescient_networking_) {
2741     WebLocalFrameImpl* web_local_frame = WebLocalFrameImpl::FromFrame(this);
2742     // There is no valid WebLocalFrame, return a nullptr to ignore pre* hints.
2743     if (!web_local_frame)
2744       return nullptr;
2745     prescient_networking_ =
2746         web_local_frame->Client()->CreatePrescientNetworking();
2747   }
2748   return prescient_networking_.get();
2749 }
2750 
SetPrescientNetworkingForTesting(std::unique_ptr<WebPrescientNetworking> prescient_networking)2751 void LocalFrame::SetPrescientNetworkingForTesting(
2752     std::unique_ptr<WebPrescientNetworking> prescient_networking) {
2753   prescient_networking_ = std::move(prescient_networking);
2754 }
2755 
GetLocalFrameHostRemote() const2756 mojom::blink::LocalFrameHost& LocalFrame::GetLocalFrameHostRemote() const {
2757   return *local_frame_host_remote_.get();
2758 }
2759 
2760 mojom::blink::BackForwardCacheControllerHost&
GetBackForwardCacheControllerHostRemote()2761 LocalFrame::GetBackForwardCacheControllerHostRemote() {
2762   return *back_forward_cache_controller_host_remote_.get();
2763 }
2764 
GetTextSurroundingSelection(uint32_t max_length,GetTextSurroundingSelectionCallback callback)2765 void LocalFrame::GetTextSurroundingSelection(
2766     uint32_t max_length,
2767     GetTextSurroundingSelectionCallback callback) {
2768   blink::SurroundingText surrounding_text(this, max_length);
2769 
2770   // |surrounding_text| might not be correctly initialized, for example if
2771   // |frame_->SelectionRange().IsNull()|, in other words, if there was no
2772   // selection.
2773   if (surrounding_text.IsEmpty()) {
2774     // Don't use WTF::String's default constructor so that we make sure that we
2775     // always send a valid empty string over the wire instead of a null pointer.
2776     std::move(callback).Run(g_empty_string, 0, 0);
2777     return;
2778   }
2779 
2780   std::move(callback).Run(surrounding_text.TextContent(),
2781                           surrounding_text.StartOffsetInTextContent(),
2782                           surrounding_text.EndOffsetInTextContent());
2783 }
2784 
SendInterventionReport(const String & id,const String & message)2785 void LocalFrame::SendInterventionReport(const String& id,
2786                                         const String& message) {
2787   Intervention::GenerateReport(this, id, message);
2788 }
2789 
SetFrameOwnerProperties(mojom::blink::FrameOwnerPropertiesPtr properties)2790 void LocalFrame::SetFrameOwnerProperties(
2791     mojom::blink::FrameOwnerPropertiesPtr properties) {
2792   GetDocument()->WillChangeFrameOwnerProperties(
2793       properties->margin_width, properties->margin_height,
2794       properties->scrollbar_mode, properties->is_display_none,
2795       properties->color_scheme);
2796 
2797   Frame::ApplyFrameOwnerProperties(std::move(properties));
2798 }
2799 
NotifyUserActivation(mojom::blink::UserActivationNotificationType notification_type)2800 void LocalFrame::NotifyUserActivation(
2801     mojom::blink::UserActivationNotificationType notification_type) {
2802   NotifyUserActivation(notification_type, false);
2803 }
2804 
RegisterVirtualKeyboardOverlayChangedObserver(VirtualKeyboardOverlayChangedObserver * observer)2805 void LocalFrame::RegisterVirtualKeyboardOverlayChangedObserver(
2806     VirtualKeyboardOverlayChangedObserver* observer) {
2807   virtual_keyboard_overlay_changed_observers_.insert(observer);
2808 }
2809 
NotifyVirtualKeyboardOverlayRectObservers(const gfx::Rect & rect) const2810 void LocalFrame::NotifyVirtualKeyboardOverlayRectObservers(
2811     const gfx::Rect& rect) const {
2812   HeapVector<Member<VirtualKeyboardOverlayChangedObserver>, 32> observers;
2813   CopyToVector(virtual_keyboard_overlay_changed_observers_, observers);
2814   for (VirtualKeyboardOverlayChangedObserver* observer : observers)
2815     observer->VirtualKeyboardOverlayChanged(rect);
2816 }
2817 
NotifyVirtualKeyboardOverlayRect(const gfx::Rect & keyboard_rect)2818 void LocalFrame::NotifyVirtualKeyboardOverlayRect(
2819     const gfx::Rect& keyboard_rect) {
2820   Page* page = this->GetPage();
2821   if (!page)
2822     return;
2823 
2824   // The rect passed to us from content is in DIP, relative to the main frame.
2825   // This doesn't take the page's zoom factor into account so we must scale by
2826   // the inverse of the page zoom in order to get correct client coordinates.
2827   // Note that when use-zoom-for-dsf is enabled, WindowToViewportScalar will
2828   // be the true device scale factor, and PageZoomFactor will be the combination
2829   // of the device scale factor and the zoom percent of the page.
2830   LocalFrame& local_frame_root = LocalFrameRoot();
2831   const float window_to_viewport_factor =
2832       page->GetChromeClient().WindowToViewportScalar(&local_frame_root, 1.0f);
2833   const float zoom_factor = local_frame_root.PageZoomFactor();
2834   const float scale_factor = zoom_factor / window_to_viewport_factor;
2835   gfx::Rect scaled_rect(keyboard_rect.x() / scale_factor,
2836                         keyboard_rect.y() / scale_factor,
2837                         keyboard_rect.width() / scale_factor,
2838                         keyboard_rect.height() / scale_factor);
2839 
2840   NotifyVirtualKeyboardOverlayRectObservers(scaled_rect);
2841 }
2842 
AddMessageToConsole(mojom::blink::ConsoleMessageLevel level,const WTF::String & message,bool discard_duplicates)2843 void LocalFrame::AddMessageToConsole(mojom::blink::ConsoleMessageLevel level,
2844                                      const WTF::String& message,
2845                                      bool discard_duplicates) {
2846   GetDocument()->AddConsoleMessage(
2847       MakeGarbageCollected<ConsoleMessage>(mojom::ConsoleMessageSource::kOther,
2848                                            level, message),
2849       discard_duplicates);
2850 }
2851 
AddInspectorIssue(mojom::blink::InspectorIssueInfoPtr info)2852 void LocalFrame::AddInspectorIssue(mojom::blink::InspectorIssueInfoPtr info) {
2853   if (GetPage()) {
2854     GetPage()->GetInspectorIssueStorage().AddInspectorIssue(DomWindow(),
2855                                                             std::move(info));
2856   }
2857 }
2858 
StopLoading()2859 void LocalFrame::StopLoading() {
2860   Loader().StopAllLoaders(/*abort_client=*/true);
2861 
2862   // The stopLoading handler may run script, which may cause this frame to be
2863   // detached/deleted. If that happens, return immediately.
2864   if (!IsAttached())
2865     return;
2866 
2867   // Notify RenderFrame observers.
2868   WebLocalFrameClient* client = Client()->GetWebFrame()->Client();
2869   if (client)
2870     client->OnStopLoading();
2871 }
2872 
Collapse(bool collapsed)2873 void LocalFrame::Collapse(bool collapsed) {
2874   FrameOwner* owner = Owner();
2875   To<HTMLFrameOwnerElement>(owner)->SetCollapsed(collapsed);
2876 }
2877 
EnableViewSourceMode()2878 void LocalFrame::EnableViewSourceMode() {
2879   DCHECK(!Tree().Parent());
2880   SetInViewSourceMode(true);
2881 }
2882 
Focus()2883 void LocalFrame::Focus() {
2884   FocusImpl();
2885 }
2886 
ClearFocusedElement()2887 void LocalFrame::ClearFocusedElement() {
2888   Document* document = GetDocument();
2889   Element* old_focused_element = document->FocusedElement();
2890   document->ClearFocusedElement();
2891   if (!old_focused_element)
2892     return;
2893 
2894   // If a text field has focus, we need to make sure the selection controller
2895   // knows to remove selection from it. Otherwise, the text field is still
2896   // processing keyboard events even though focus has been moved to the page and
2897   // keystrokes get eaten as a result.
2898   document->UpdateStyleAndLayoutTree();
2899   if (HasEditableStyle(*old_focused_element) ||
2900       old_focused_element->IsTextControl())
2901     Selection().Clear();
2902 }
2903 
GetResourceSnapshotForWebBundle(mojo::PendingReceiver<data_decoder::mojom::blink::ResourceSnapshotForWebBundle> receiver)2904 void LocalFrame::GetResourceSnapshotForWebBundle(
2905     mojo::PendingReceiver<
2906         data_decoder::mojom::blink::ResourceSnapshotForWebBundle> receiver) {
2907   Deque<SerializedResource> resources;
2908 
2909   HeapHashSet<WeakMember<const Element>> shadow_template_elements;
2910   WebBundleGenerationDelegate web_delegate;
2911   FrameSerializerDelegateImpl core_delegate(web_delegate,
2912                                             shadow_template_elements);
2913   FrameSerializer serializer(resources, core_delegate);
2914   serializer.SerializeFrame(*this);
2915 
2916   mojo::MakeSelfOwnedReceiver(
2917       std::make_unique<ResourceSnapshotForWebBundleImpl>(std::move(resources)),
2918       std::move(receiver));
2919 }
2920 
CopyImageAtViewportPoint(const IntPoint & viewport_point)2921 void LocalFrame::CopyImageAtViewportPoint(const IntPoint& viewport_point) {
2922   HitTestResult result = HitTestResultForVisualViewportPos(viewport_point);
2923   if (!IsA<HTMLCanvasElement>(result.InnerNodeOrImageMapImage()) &&
2924       result.AbsoluteImageURL().IsEmpty()) {
2925     // There isn't actually an image at these coordinates.  Might be because
2926     // the window scrolled while the context menu was open or because the page
2927     // changed itself between when we thought there was an image here and when
2928     // we actually tried to retrieve the image.
2929     //
2930     // FIXME: implement a cache of the most recent HitTestResult to avoid having
2931     //        to do two hit tests.
2932     return;
2933   }
2934 
2935   // TODO(editing-dev): The use of UpdateStyleAndLayout
2936   // needs to be audited.  See http://crbug.com/590369 for more details.
2937   GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
2938 
2939   GetEditor().CopyImage(result);
2940 }
2941 
CopyImageAt(const gfx::Point & window_point)2942 void LocalFrame::CopyImageAt(const gfx::Point& window_point) {
2943   gfx::Point viewport_position =
2944       GetWidgetForLocalRoot()->DIPsToRoundedBlinkSpace(window_point);
2945   CopyImageAtViewportPoint(IntPoint(viewport_position));
2946 }
2947 
SaveImageAt(const gfx::Point & window_point)2948 void LocalFrame::SaveImageAt(const gfx::Point& window_point) {
2949   gfx::Point viewport_position =
2950       GetWidgetForLocalRoot()->DIPsToRoundedBlinkSpace(window_point);
2951   IntPoint location(viewport_position);
2952   Node* node =
2953       HitTestResultForVisualViewportPos(location).InnerNodeOrImageMapImage();
2954   if (!node || !(IsA<HTMLCanvasElement>(*node) || IsA<HTMLImageElement>(*node)))
2955     return;
2956 
2957   String url = To<Element>(*node).ImageSourceURL();
2958   if (!KURL(NullURL(), url).ProtocolIsData())
2959     return;
2960 
2961   auto params = mojom::blink::DownloadURLParams::New();
2962   params->data_url_blob = DataURLToBlob(url);
2963   GetLocalFrameHostRemote().DownloadURL(std::move(params));
2964 }
2965 
ReportBlinkFeatureUsage(const Vector<mojom::blink::WebFeature> & features)2966 void LocalFrame::ReportBlinkFeatureUsage(
2967     const Vector<mojom::blink::WebFeature>& features) {
2968   DCHECK(!features.IsEmpty());
2969 
2970   // Assimilate all features used/performed by the browser into UseCounter.
2971   auto* document = GetDocument();
2972   DCHECK(document);
2973   for (const auto& feature : features)
2974     document->CountUse(feature);
2975 }
2976 
RenderFallbackContent()2977 void LocalFrame::RenderFallbackContent() {
2978   // TODO(ekaramad): If the owner renders its own content, then the current
2979   // ContentFrame() should detach (see https://crbug.com/850223).
2980   auto* owner = DeprecatedLocalOwner();
2981   DCHECK(IsA<HTMLObjectElement>(owner));
2982   owner->RenderFallbackContent(this);
2983 }
2984 
BeforeUnload(bool is_reload,BeforeUnloadCallback callback)2985 void LocalFrame::BeforeUnload(bool is_reload, BeforeUnloadCallback callback) {
2986   base::TimeTicks before_unload_start_time = base::TimeTicks::Now();
2987 
2988   // This will execute the BeforeUnload event in this frame and all of its
2989   // local descendant frames, including children of remote frames.  The browser
2990   // process will send separate IPCs to dispatch beforeunload in any
2991   // out-of-process child frames.
2992   bool proceed = Loader().ShouldClose(is_reload);
2993 
2994   DCHECK(!callback.is_null());
2995   base::TimeTicks before_unload_end_time = base::TimeTicks::Now();
2996   std::move(callback).Run(proceed, before_unload_start_time,
2997                           before_unload_end_time);
2998 }
2999 
DispatchBeforeUnload(bool is_reload,BeforeUnloadCallback callback)3000 void LocalFrame::DispatchBeforeUnload(bool is_reload,
3001                                       BeforeUnloadCallback callback) {
3002   BeforeUnload(is_reload, std::move(callback));
3003 }
3004 
MediaPlayerActionAtViewportPoint(const IntPoint & viewport_position,const blink::mojom::blink::MediaPlayerActionType type,bool enable)3005 void LocalFrame::MediaPlayerActionAtViewportPoint(
3006     const IntPoint& viewport_position,
3007     const blink::mojom::blink::MediaPlayerActionType type,
3008     bool enable) {
3009   HitTestResult result = HitTestResultForVisualViewportPos(viewport_position);
3010   Node* node = result.InnerNode();
3011   if (!IsA<HTMLVideoElement>(*node) && !IsA<HTMLAudioElement>(*node))
3012     return;
3013 
3014   auto* media_element = To<HTMLMediaElement>(node);
3015   switch (type) {
3016     case blink::mojom::blink::MediaPlayerActionType::kPlay:
3017       if (enable)
3018         media_element->Play();
3019       else
3020         media_element->pause();
3021       break;
3022     case blink::mojom::blink::MediaPlayerActionType::kMute:
3023       media_element->setMuted(enable);
3024       break;
3025     case blink::mojom::blink::MediaPlayerActionType::kLoop:
3026       media_element->SetLoop(enable);
3027       break;
3028     case blink::mojom::blink::MediaPlayerActionType::kControls:
3029       media_element->SetBooleanAttribute(html_names::kControlsAttr, enable);
3030       break;
3031     case blink::mojom::blink::MediaPlayerActionType::kPictureInPicture:
3032       DCHECK(IsA<HTMLVideoElement>(media_element));
3033       if (enable) {
3034         PictureInPictureController::From(node->GetDocument())
3035             .EnterPictureInPicture(To<HTMLVideoElement>(media_element),
3036                                    nullptr /* promise */,
3037                                    nullptr /* options */);
3038       } else {
3039         PictureInPictureController::From(node->GetDocument())
3040             .ExitPictureInPicture(To<HTMLVideoElement>(media_element), nullptr);
3041       }
3042 
3043       break;
3044   }
3045 }
3046 
DownloadURL(const ResourceRequest & request,network::mojom::blink::RedirectMode cross_origin_redirect_behavior)3047 void LocalFrame::DownloadURL(
3048     const ResourceRequest& request,
3049     network::mojom::blink::RedirectMode cross_origin_redirect_behavior) {
3050   mojo::PendingRemote<mojom::blink::BlobURLToken> blob_url_token;
3051   if (request.Url().ProtocolIs("blob")) {
3052     DomWindow()->GetPublicURLManager().Resolve(
3053         request.Url(), blob_url_token.InitWithNewPipeAndPassReceiver());
3054   }
3055 
3056   DownloadURL(request, cross_origin_redirect_behavior,
3057               std::move(blob_url_token));
3058 }
3059 
DownloadURL(const ResourceRequest & request,network::mojom::blink::RedirectMode cross_origin_redirect_behavior,mojo::PendingRemote<mojom::blink::BlobURLToken> blob_url_token)3060 void LocalFrame::DownloadURL(
3061     const ResourceRequest& request,
3062     network::mojom::blink::RedirectMode cross_origin_redirect_behavior,
3063     mojo::PendingRemote<mojom::blink::BlobURLToken> blob_url_token) {
3064   if (ShouldThrottleDownload())
3065     return;
3066 
3067   auto params = mojom::blink::DownloadURLParams::New();
3068   const KURL& url = request.Url();
3069   // Pass data URL through blob.
3070   if (url.ProtocolIs("data")) {
3071     params->url = KURL();
3072     params->data_url_blob = DataURLToBlob(url.GetString());
3073   } else {
3074     params->url = url;
3075   }
3076 
3077   params->referrer = mojom::blink::Referrer::New();
3078   params->referrer->url = KURL(request.ReferrerString());
3079   params->referrer->policy = request.GetReferrerPolicy();
3080   params->initiator_origin = request.RequestorOrigin();
3081   if (request.GetSuggestedFilename().has_value())
3082     params->suggested_name = *request.GetSuggestedFilename();
3083   params->cross_origin_redirects = cross_origin_redirect_behavior;
3084   params->blob_url_token = std::move(blob_url_token);
3085 
3086   GetLocalFrameHostRemote().DownloadURL(std::move(params));
3087 }
3088 
MediaPlayerActionAt(const gfx::Point & window_point,blink::mojom::blink::MediaPlayerActionPtr action)3089 void LocalFrame::MediaPlayerActionAt(
3090     const gfx::Point& window_point,
3091     blink::mojom::blink::MediaPlayerActionPtr action) {
3092   gfx::Point viewport_position =
3093       GetWidgetForLocalRoot()->DIPsToRoundedBlinkSpace(window_point);
3094   IntPoint location(viewport_position);
3095 
3096   MediaPlayerActionAtViewportPoint(location, action->type, action->enable);
3097 }
3098 
AdvanceFocusInFrame(mojom::blink::FocusType focus_type,const base::Optional<base::UnguessableToken> & source_frame_token)3099 void LocalFrame::AdvanceFocusInFrame(
3100     mojom::blink::FocusType focus_type,
3101     const base::Optional<base::UnguessableToken>& source_frame_token) {
3102   RemoteFrame* source_frame = SourceFrameForOptionalToken(source_frame_token);
3103   if (!source_frame) {
3104     SetInitialFocus(focus_type == mojom::blink::FocusType::kBackward);
3105     return;
3106   }
3107 
3108   GetPage()->GetFocusController().AdvanceFocusAcrossFrames(focus_type,
3109                                                            source_frame, this);
3110 }
3111 
AdvanceFocusInForm(mojom::blink::FocusType focus_type)3112 void LocalFrame::AdvanceFocusInForm(mojom::blink::FocusType focus_type) {
3113   auto* focused_frame = GetPage()->GetFocusController().FocusedFrame();
3114   if (focused_frame != this)
3115     return;
3116 
3117   DCHECK(GetDocument());
3118   Element* element = GetDocument()->FocusedElement();
3119   if (!element)
3120     return;
3121 
3122   Element* next_element =
3123       GetPage()->GetFocusController().NextFocusableElementInForm(element,
3124                                                                  focus_type);
3125   if (!next_element)
3126     return;
3127 
3128   next_element->scrollIntoViewIfNeeded(true /*centerIfNeeded*/);
3129   next_element->focus();
3130 }
3131 
ReportContentSecurityPolicyViolation(network::mojom::blink::CSPViolationPtr violation)3132 void LocalFrame::ReportContentSecurityPolicyViolation(
3133     network::mojom::blink::CSPViolationPtr violation) {
3134   auto source_location = std::make_unique<SourceLocation>(
3135       violation->source_location->url, violation->source_location->line,
3136       violation->source_location->column, nullptr);
3137 
3138   console_->AddMessage(MakeGarbageCollected<ConsoleMessage>(
3139       mojom::ConsoleMessageSource::kSecurity,
3140       mojom::ConsoleMessageLevel::kError, violation->console_message,
3141       source_location->Clone()));
3142 
3143   auto directive_type =
3144       ContentSecurityPolicy::GetDirectiveType(violation->effective_directive);
3145   LocalFrame* context_frame =
3146       directive_type == ContentSecurityPolicy::DirectiveType::kFrameAncestors
3147           ? this
3148           : nullptr;
3149 
3150   DomWindow()->GetContentSecurityPolicy()->ReportViolation(
3151       violation->directive, directive_type, violation->console_message,
3152       violation->blocked_url, violation->report_endpoints,
3153       violation->use_reporting_api, violation->header, violation->type,
3154       ContentSecurityPolicy::ContentSecurityPolicyViolationType::kURLViolation,
3155       std::move(source_location), context_frame,
3156       violation->after_redirect ? RedirectStatus::kFollowedRedirect
3157                                 : RedirectStatus::kNoRedirect,
3158       nullptr /* Element */);
3159 }
3160 
DidUpdateFramePolicy(const FramePolicy & frame_policy)3161 void LocalFrame::DidUpdateFramePolicy(const FramePolicy& frame_policy) {
3162   // At the moment, this is only used to replicate sandbox flags and container
3163   // policy for frames with a remote owner.
3164   SECURITY_CHECK(IsA<RemoteFrameOwner>(Owner()));
3165   To<RemoteFrameOwner>(Owner())->SetFramePolicy(frame_policy);
3166 }
3167 
OnScreensChange()3168 void LocalFrame::OnScreensChange() {
3169   if (RuntimeEnabledFeatures::WindowPlacementEnabled(DomWindow())) {
3170     // Allow fullscreen requests shortly after user-generated screens changes.
3171     transient_allow_fullscreen_.Activate();
3172     DomWindow()->DispatchEvent(
3173         *Event::Create(event_type_names::kScreenschange));
3174   }
3175 }
3176 
PostMessageEvent(const base::Optional<base::UnguessableToken> & source_frame_token,const String & source_origin,const String & target_origin,BlinkTransferableMessage message)3177 void LocalFrame::PostMessageEvent(
3178     const base::Optional<base::UnguessableToken>& source_frame_token,
3179     const String& source_origin,
3180     const String& target_origin,
3181     BlinkTransferableMessage message) {
3182   RemoteFrame* source_frame = SourceFrameForOptionalToken(source_frame_token);
3183 
3184   // We must pass in the target_origin to do the security check on this side,
3185   // since it may have changed since the original postMessage call was made.
3186   scoped_refptr<SecurityOrigin> target_security_origin;
3187   if (!target_origin.IsEmpty()) {
3188     target_security_origin = SecurityOrigin::CreateFromString(target_origin);
3189   }
3190 
3191   // Preparation of the MessageEvent.
3192   MessageEvent* message_event = MessageEvent::Create();
3193   DOMWindow* window = nullptr;
3194   if (source_frame)
3195     window = source_frame->DomWindow();
3196   MessagePortArray* ports = nullptr;
3197   if (GetDocument()) {
3198     ports = MessagePort::EntanglePorts(*GetDocument()->GetExecutionContext(),
3199                                        std::move(message.ports));
3200   }
3201   UserActivation* user_activation = nullptr;
3202   if (message.user_activation) {
3203     user_activation = MakeGarbageCollected<UserActivation>(
3204         message.user_activation->has_been_active,
3205         message.user_activation->was_active);
3206   }
3207   message_event->initMessageEvent(
3208       "message", false, false, std::move(message.message), source_origin,
3209       "" /*lastEventId*/, window, ports, user_activation);
3210 
3211   // If the agent cluster id had a value it means this was locked when it
3212   // was serialized.
3213   if (message.locked_agent_cluster_id)
3214     message_event->LockToAgentCluster();
3215 
3216   // Finally dispatch the message to the DOM Window.
3217   DomWindow()->DispatchMessageEventWithOriginCheck(
3218       target_security_origin.get(), message_event,
3219       std::make_unique<SourceLocation>(String(), 0, 0, nullptr),
3220       message.locked_agent_cluster_id ? message.locked_agent_cluster_id.value()
3221                                       : base::UnguessableToken());
3222 }
3223 
BindReportingObserver(mojo::PendingReceiver<mojom::blink::ReportingObserver> receiver)3224 void LocalFrame::BindReportingObserver(
3225     mojo::PendingReceiver<mojom::blink::ReportingObserver> receiver) {
3226   ReportingContext::From(DomWindow())->Bind(std::move(receiver));
3227 }
3228 
UpdateOpener(const base::Optional<base::UnguessableToken> & opener_frame_token)3229 void LocalFrame::UpdateOpener(
3230     const base::Optional<base::UnguessableToken>& opener_frame_token) {
3231   if (auto* web_frame = WebFrame::FromFrame(this)) {
3232     Frame* opener_frame = nullptr;
3233     if (opener_frame_token)
3234       opener_frame = Frame::ResolveFrame(opener_frame_token.value());
3235     SetOpenerDoNotNotify(opener_frame);
3236   }
3237 }
3238 
GetSavableResourceLinks(GetSavableResourceLinksCallback callback)3239 void LocalFrame::GetSavableResourceLinks(
3240     GetSavableResourceLinksCallback callback) {
3241   Vector<KURL> resources_list;
3242   Vector<mojom::blink::SavableSubframePtr> subframes;
3243   SavableResources::Result result(&resources_list, &subframes);
3244 
3245   if (!SavableResources::GetSavableResourceLinksForFrame(this, &result)) {
3246     std::move(callback).Run(nullptr);
3247     return;
3248   }
3249 
3250   auto referrer = mojom::blink::Referrer::New(GetDocument()->Url(),
3251                                               DomWindow()->GetReferrerPolicy());
3252 
3253   auto reply = mojom::blink::GetSavableResourceLinksReply::New();
3254   reply->resources_list = std::move(resources_list);
3255   reply->referrer = std::move(referrer);
3256   reply->subframes = std::move(subframes);
3257 
3258   std::move(callback).Run(std::move(reply));
3259 }
3260 
MixedContentFound(const KURL & main_resource_url,const KURL & mixed_content_url,mojom::blink::RequestContextType request_context,bool was_allowed,const KURL & url_before_redirects,bool had_redirect,network::mojom::blink::SourceLocationPtr source_location)3261 void LocalFrame::MixedContentFound(
3262     const KURL& main_resource_url,
3263     const KURL& mixed_content_url,
3264     mojom::blink::RequestContextType request_context,
3265     bool was_allowed,
3266     const KURL& url_before_redirects,
3267     bool had_redirect,
3268     network::mojom::blink::SourceLocationPtr source_location) {
3269   std::unique_ptr<SourceLocation> source;
3270   if (source_location) {
3271     source = std::make_unique<SourceLocation>(source_location->url,
3272                                               source_location->line,
3273                                               source_location->column, nullptr);
3274   }
3275   MixedContentChecker::MixedContentFound(
3276       this, main_resource_url, mixed_content_url, request_context, was_allowed,
3277       url_before_redirects, had_redirect, std::move(source));
3278 }
3279 
ShouldThrottleDownload()3280 bool LocalFrame::ShouldThrottleDownload() {
3281   const auto now = base::TimeTicks::Now();
3282   if (num_burst_download_requests_ == 0) {
3283     burst_download_start_time_ = now;
3284   } else if (num_burst_download_requests_ >= kBurstDownloadLimit) {
3285     static constexpr auto kBurstDownloadLimitResetInterval =
3286         base::TimeDelta::FromSeconds(1);
3287     if (now - burst_download_start_time_ > kBurstDownloadLimitResetInterval) {
3288       num_burst_download_requests_ = 1;
3289       burst_download_start_time_ = now;
3290       return false;
3291     }
3292     return true;
3293   }
3294 
3295   num_burst_download_requests_++;
3296   return false;
3297 }
3298 
3299 #if defined(OS_MAC)
GetTextInputHost()3300 mojom::blink::TextInputHost& LocalFrame::GetTextInputHost() {
3301   DCHECK(text_input_host_.is_bound());
3302   return *text_input_host_.get();
3303 }
3304 #endif
3305 
BindToReceiver(blink::LocalFrame * frame,mojo::PendingAssociatedReceiver<mojom::blink::LocalFrame> receiver)3306 void LocalFrame::BindToReceiver(
3307     blink::LocalFrame* frame,
3308     mojo::PendingAssociatedReceiver<mojom::blink::LocalFrame> receiver) {
3309   DCHECK(frame);
3310   if (frame->IsDetached())
3311     return;
3312 
3313   frame->receiver_.Bind(
3314       std::move(receiver),
3315       frame->GetTaskRunner(blink::TaskType::kInternalDefault));
3316   frame->receiver_.SetFilter(std::make_unique<ActiveURLMessageFilter>(frame));
3317 }
3318 
BindToMainFrameReceiver(blink::LocalFrame * frame,mojo::PendingAssociatedReceiver<mojom::blink::LocalMainFrame> receiver)3319 void LocalFrame::BindToMainFrameReceiver(
3320     blink::LocalFrame* frame,
3321     mojo::PendingAssociatedReceiver<mojom::blink::LocalMainFrame> receiver) {
3322   DCHECK(frame);
3323   if (frame->IsDetached())
3324     return;
3325 
3326   frame->main_frame_receiver_.Bind(
3327       std::move(receiver),
3328       frame->GetTaskRunner(blink::TaskType::kInternalDefault));
3329   frame->main_frame_receiver_.SetFilter(
3330       std::make_unique<ActiveURLMessageFilter>(frame));
3331 }
3332 
BindToHighPriorityReceiver(mojo::PendingReceiver<mojom::blink::HighPriorityLocalFrame> receiver)3333 void LocalFrame::BindToHighPriorityReceiver(
3334     mojo::PendingReceiver<mojom::blink::HighPriorityLocalFrame> receiver) {
3335   if (IsDetached())
3336     return;
3337 
3338   high_priority_frame_receiver_.Bind(
3339       std::move(receiver),
3340       GetTaskRunner(blink::TaskType::kInternalHighPriorityLocalFrame));
3341   high_priority_frame_receiver_.SetFilter(
3342       std::make_unique<ActiveURLMessageFilter>(this));
3343 }
3344 
BindTextFragmentSelectorProducer(mojo::PendingReceiver<mojom::blink::TextFragmentSelectorProducer> receiver)3345 void LocalFrame::BindTextFragmentSelectorProducer(
3346     mojo::PendingReceiver<mojom::blink::TextFragmentSelectorProducer>
3347         receiver) {
3348   if (IsDetached() || !text_fragment_selector_generator_)
3349     return;
3350 
3351   text_fragment_selector_generator_->BindTextFragmentSelectorProducer(
3352       std::move(receiver));
3353 }
3354 
GetSpellChecker() const3355 SpellChecker& LocalFrame::GetSpellChecker() const {
3356   DCHECK(DomWindow());
3357   return DomWindow()->GetSpellChecker();
3358 }
3359 
GetInputMethodController() const3360 InputMethodController& LocalFrame::GetInputMethodController() const {
3361   DCHECK(DomWindow());
3362   return DomWindow()->GetInputMethodController();
3363 }
3364 
GetTextSuggestionController() const3365 TextSuggestionController& LocalFrame::GetTextSuggestionController() const {
3366   DCHECK(DomWindow());
3367   return DomWindow()->GetTextSuggestionController();
3368 }
3369 
3370 }  // namespace blink
3371