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