1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Dirk Mueller (mueller@kde.org)
5  *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
6  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All
7  * rights reserved.
8  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
9  * (http://www.torchmobile.com/)
10  * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved.
11  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
12  * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved.
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public License
25  * along with this library; see the file COPYING.LIB.  If not, write to
26  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29 
30 #include "third_party/blink/renderer/core/dom/document.h"
31 
32 #include <memory>
33 #include <utility>
34 
35 #include "base/auto_reset.h"
36 #include "base/macros.h"
37 #include "base/optional.h"
38 #include "base/time/time.h"
39 #include "cc/input/overscroll_behavior.h"
40 #include "cc/input/scroll_snap_data.h"
41 #include "components/performance_manager/public/mojom/coordination_unit.mojom-blink.h"
42 #include "mojo/public/cpp/bindings/pending_remote.h"
43 #include "mojo/public/cpp/bindings/remote.h"
44 #include "mojo/public/mojom/base/text_direction.mojom-blink.h"
45 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
46 #include "services/metrics/public/cpp/mojo_ukm_recorder.h"
47 #include "services/metrics/public/cpp/ukm_builders.h"
48 #include "services/metrics/public/cpp/ukm_source_id.h"
49 #include "services/metrics/public/mojom/ukm_interface.mojom-blink.h"
50 #include "services/network/public/mojom/ip_address_space.mojom-blink.h"
51 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
52 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
53 #include "third_party/blink/public/common/feature_policy/document_policy_features.h"
54 #include "third_party/blink/public/common/features.h"
55 #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
56 #include "third_party/blink/public/mojom/feature_policy/policy_disposition.mojom-blink.h"
57 #include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
58 #include "third_party/blink/public/mojom/insecure_input/insecure_input_service.mojom-blink.h"
59 #include "third_party/blink/public/mojom/ukm/ukm.mojom-blink.h"
60 #include "third_party/blink/public/platform/platform.h"
61 #include "third_party/blink/public/platform/task_type.h"
62 #include "third_party/blink/public/platform/web_content_settings_client.h"
63 #include "third_party/blink/public/platform/web_theme_engine.h"
64 #include "third_party/blink/renderer/bindings/core/v8/html_script_element_or_svg_script_element.h"
65 #include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h"
66 #include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
67 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
68 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
69 #include "third_party/blink/renderer/bindings/core/v8/source_location.h"
70 #include "third_party/blink/renderer/bindings/core/v8/string_or_element_creation_options.h"
71 #include "third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.h"
72 #include "third_party/blink/renderer/bindings/core/v8/v8_element_creation_options.h"
73 #include "third_party/blink/renderer/bindings/core/v8/v8_element_registration_options.h"
74 #include "third_party/blink/renderer/bindings/core/v8/window_proxy.h"
75 #include "third_party/blink/renderer/core/accessibility/ax_context.h"
76 #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
77 #include "third_party/blink/renderer/core/animation/document_animations.h"
78 #include "third_party/blink/renderer/core/animation/document_timeline.h"
79 #include "third_party/blink/renderer/core/animation/pending_animations.h"
80 #include "third_party/blink/renderer/core/animation/worklet_animation_controller.h"
81 #include "third_party/blink/renderer/core/aom/computed_accessible_node.h"
82 #include "third_party/blink/renderer/core/css/css_font_selector.h"
83 #include "third_party/blink/renderer/core/css/css_property_value_set.h"
84 #include "third_party/blink/renderer/core/css/css_style_declaration.h"
85 #include "third_party/blink/renderer/core/css/css_style_sheet.h"
86 #include "third_party/blink/renderer/core/css/cssom/computed_style_property_map.h"
87 #include "third_party/blink/renderer/core/css/font_face_set_document.h"
88 #include "third_party/blink/renderer/core/css/invalidation/style_invalidator.h"
89 #include "third_party/blink/renderer/core/css/media_query_matcher.h"
90 #include "third_party/blink/renderer/core/css/parser/css_parser.h"
91 #include "third_party/blink/renderer/core/css/properties/css_property.h"
92 #include "third_party/blink/renderer/core/css/property_registry.h"
93 #include "third_party/blink/renderer/core/css/resolver/font_builder.h"
94 #include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
95 #include "third_party/blink/renderer/core/css/resolver/style_resolver_stats.h"
96 #include "third_party/blink/renderer/core/css/selector_query.h"
97 #include "third_party/blink/renderer/core/css/style_change_reason.h"
98 #include "third_party/blink/renderer/core/css/style_engine.h"
99 #include "third_party/blink/renderer/core/css/style_sheet_contents.h"
100 #include "third_party/blink/renderer/core/css/style_sheet_list.h"
101 #include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
102 #include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
103 #include "third_party/blink/renderer/core/dom/attr.h"
104 #include "third_party/blink/renderer/core/dom/beforeunload_event_listener.h"
105 #include "third_party/blink/renderer/core/dom/cdata_section.h"
106 #include "third_party/blink/renderer/core/dom/comment.h"
107 #include "third_party/blink/renderer/core/dom/context_features.h"
108 #include "third_party/blink/renderer/core/dom/document_fragment.h"
109 #include "third_party/blink/renderer/core/dom/document_init.h"
110 #include "third_party/blink/renderer/core/dom/document_parser_timing.h"
111 #include "third_party/blink/renderer/core/dom/document_type.h"
112 #include "third_party/blink/renderer/core/dom/dom_implementation.h"
113 #include "third_party/blink/renderer/core/dom/element.h"
114 #include "third_party/blink/renderer/core/dom/element_data_cache.h"
115 #include "third_party/blink/renderer/core/dom/element_traversal.h"
116 #include "third_party/blink/renderer/core/dom/events/event.h"
117 #include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
118 #include "third_party/blink/renderer/core/dom/events/event_listener.h"
119 #include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
120 #include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
121 #include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
122 #include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
123 #include "third_party/blink/renderer/core/dom/live_node_list.h"
124 #include "third_party/blink/renderer/core/dom/mutation_observer.h"
125 #include "third_party/blink/renderer/core/dom/node_child_removal_tracker.h"
126 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
127 #include "third_party/blink/renderer/core/dom/node_iterator.h"
128 #include "third_party/blink/renderer/core/dom/node_lists_node_data.h"
129 #include "third_party/blink/renderer/core/dom/node_rare_data.h"
130 #include "third_party/blink/renderer/core/dom/node_traversal.h"
131 #include "third_party/blink/renderer/core/dom/node_with_index.h"
132 #include "third_party/blink/renderer/core/dom/processing_instruction.h"
133 #include "third_party/blink/renderer/core/dom/scripted_animation_controller.h"
134 #include "third_party/blink/renderer/core/dom/shadow_root.h"
135 #include "third_party/blink/renderer/core/dom/slot_assignment.h"
136 #include "third_party/blink/renderer/core/dom/slot_assignment_engine.h"
137 #include "third_party/blink/renderer/core/dom/slot_assignment_recalc_forbidden_scope.h"
138 #include "third_party/blink/renderer/core/dom/static_node_list.h"
139 #include "third_party/blink/renderer/core/dom/transform_source.h"
140 #include "third_party/blink/renderer/core/dom/tree_walker.h"
141 #include "third_party/blink/renderer/core/dom/visited_link_state.h"
142 #include "third_party/blink/renderer/core/dom/whitespace_attacher.h"
143 #include "third_party/blink/renderer/core/dom/xml_document.h"
144 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
145 #include "third_party/blink/renderer/core/editing/frame_selection.h"
146 #include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
147 #include "third_party/blink/renderer/core/editing/serializers/serialization.h"
148 #include "third_party/blink/renderer/core/events/before_unload_event.h"
149 #include "third_party/blink/renderer/core/events/event_factory.h"
150 #include "third_party/blink/renderer/core/events/hash_change_event.h"
151 #include "third_party/blink/renderer/core/events/overscroll_event.h"
152 #include "third_party/blink/renderer/core/events/page_transition_event.h"
153 #include "third_party/blink/renderer/core/events/visual_viewport_resize_event.h"
154 #include "third_party/blink/renderer/core/events/visual_viewport_scroll_event.h"
155 #include "third_party/blink/renderer/core/execution_context/agent_metrics_collector.h"
156 #include "third_party/blink/renderer/core/execution_context/security_context_init.h"
157 #include "third_party/blink/renderer/core/execution_context/window_agent.h"
158 #include "third_party/blink/renderer/core/execution_context/window_agent_factory.h"
159 #include "third_party/blink/renderer/core/feature_policy/dom_document_policy.h"
160 #include "third_party/blink/renderer/core/feature_policy/feature_policy_parser.h"
161 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
162 #include "third_party/blink/renderer/core/frame/csp/navigation_initiator_impl.h"
163 #include "third_party/blink/renderer/core/frame/document_policy_violation_report_body.h"
164 #include "third_party/blink/renderer/core/frame/dom_timer.h"
165 #include "third_party/blink/renderer/core/frame/dom_visual_viewport.h"
166 #include "third_party/blink/renderer/core/frame/event_handler_registry.h"
167 #include "third_party/blink/renderer/core/frame/feature_policy_violation_report_body.h"
168 #include "third_party/blink/renderer/core/frame/frame_console.h"
169 #include "third_party/blink/renderer/core/frame/history.h"
170 #include "third_party/blink/renderer/core/frame/intervention.h"
171 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
172 #include "third_party/blink/renderer/core/frame/local_frame.h"
173 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
174 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
175 #include "third_party/blink/renderer/core/frame/performance_monitor.h"
176 #include "third_party/blink/renderer/core/frame/report.h"
177 #include "third_party/blink/renderer/core/frame/reporting_context.h"
178 #include "third_party/blink/renderer/core/frame/settings.h"
179 #include "third_party/blink/renderer/core/frame/viewport_data.h"
180 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
181 #include "third_party/blink/renderer/core/html/anchor_element_metrics.h"
182 #include "third_party/blink/renderer/core/html/canvas/canvas_font_cache.h"
183 #include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
184 #include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
185 #include "third_party/blink/renderer/core/html/custom/custom_element.h"
186 #include "third_party/blink/renderer/core/html/custom/custom_element_definition.h"
187 #include "third_party/blink/renderer/core/html/custom/custom_element_descriptor.h"
188 #include "third_party/blink/renderer/core/html/custom/custom_element_registry.h"
189 #include "third_party/blink/renderer/core/html/custom/v0_custom_element_microtask_run_queue.h"
190 #include "third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.h"
191 #include "third_party/blink/renderer/core/html/document_all_name_collection.h"
192 #include "third_party/blink/renderer/core/html/document_name_collection.h"
193 #include "third_party/blink/renderer/core/html/forms/form_controller.h"
194 #include "third_party/blink/renderer/core/html/forms/html_form_element.h"
195 #include "third_party/blink/renderer/core/html/forms/html_input_element.h"
196 #include "third_party/blink/renderer/core/html/html_all_collection.h"
197 #include "third_party/blink/renderer/core/html/html_anchor_element.h"
198 #include "third_party/blink/renderer/core/html/html_base_element.h"
199 #include "third_party/blink/renderer/core/html/html_body_element.h"
200 #include "third_party/blink/renderer/core/html/html_collection.h"
201 #include "third_party/blink/renderer/core/html/html_dialog_element.h"
202 #include "third_party/blink/renderer/core/html/html_document.h"
203 #include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
204 #include "third_party/blink/renderer/core/html/html_head_element.h"
205 #include "third_party/blink/renderer/core/html/html_html_element.h"
206 #include "third_party/blink/renderer/core/html/html_link_element.h"
207 #include "third_party/blink/renderer/core/html/html_meta_element.h"
208 #include "third_party/blink/renderer/core/html/html_object_element.h"
209 #include "third_party/blink/renderer/core/html/html_plugin_element.h"
210 #include "third_party/blink/renderer/core/html/html_script_element.h"
211 #include "third_party/blink/renderer/core/html/html_title_element.h"
212 #include "third_party/blink/renderer/core/html/html_unknown_element.h"
213 #include "third_party/blink/renderer/core/html/imports/html_import_loader.h"
214 #include "third_party/blink/renderer/core/html/imports/html_imports_controller.h"
215 #include "third_party/blink/renderer/core/html/lazy_load_image_observer.h"
216 #include "third_party/blink/renderer/core/html/parser/html_document_parser.h"
217 #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
218 #include "third_party/blink/renderer/core/html/parser/nesting_level_incrementer.h"
219 #include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
220 #include "third_party/blink/renderer/core/html/plugin_document.h"
221 #include "third_party/blink/renderer/core/html/portal/document_portals.h"
222 #include "third_party/blink/renderer/core/html/portal/portal_contents.h"
223 #include "third_party/blink/renderer/core/html/window_name_collection.h"
224 #include "third_party/blink/renderer/core/html_element_factory.h"
225 #include "third_party/blink/renderer/core/html_element_type_helpers.h"
226 #include "third_party/blink/renderer/core/html_names.h"
227 #include "third_party/blink/renderer/core/input/event_handler.h"
228 #include "third_party/blink/renderer/core/input/touch_list.h"
229 #include "third_party/blink/renderer/core/inspector/console_message.h"
230 #include "third_party/blink/renderer/core/inspector/inspector_issue.h"
231 #include "third_party/blink/renderer/core/inspector/inspector_issue_storage.h"
232 #include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
233 #include "third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h"
234 #include "third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h"
235 #include "third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h"
236 #include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
237 #include "third_party/blink/renderer/core/layout/hit_test_canvas_result.h"
238 #include "third_party/blink/renderer/core/layout/hit_test_result.h"
239 #include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
240 #include "third_party/blink/renderer/core/layout/layout_view.h"
241 #include "third_party/blink/renderer/core/layout/text_autosizer.h"
242 #include "third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.h"
243 #include "third_party/blink/renderer/core/loader/cookie_jar.h"
244 #include "third_party/blink/renderer/core/loader/document_loader.h"
245 #include "third_party/blink/renderer/core/loader/frame_fetch_context.h"
246 #include "third_party/blink/renderer/core/loader/frame_loader.h"
247 #include "third_party/blink/renderer/core/loader/http_refresh_scheduler.h"
248 #include "third_party/blink/renderer/core/loader/idleness_detector.h"
249 #include "third_party/blink/renderer/core/loader/interactive_detector.h"
250 #include "third_party/blink/renderer/core/loader/prerenderer_client.h"
251 #include "third_party/blink/renderer/core/loader/progress_tracker.h"
252 #include "third_party/blink/renderer/core/loader/text_resource_decoder_builder.h"
253 #include "third_party/blink/renderer/core/mathml/mathml_element.h"
254 #include "third_party/blink/renderer/core/mathml/mathml_row_element.h"
255 #include "third_party/blink/renderer/core/mathml_element_factory.h"
256 #include "third_party/blink/renderer/core/mathml_names.h"
257 #include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
258 #include "third_party/blink/renderer/core/page/chrome_client.h"
259 #include "third_party/blink/renderer/core/page/event_with_hit_test_results.h"
260 #include "third_party/blink/renderer/core/page/focus_controller.h"
261 #include "third_party/blink/renderer/core/page/frame_tree.h"
262 #include "third_party/blink/renderer/core/page/page.h"
263 #include "third_party/blink/renderer/core/page/plugin_script_forbidden_scope.h"
264 #include "third_party/blink/renderer/core/page/pointer_lock_controller.h"
265 #include "third_party/blink/renderer/core/page/scrolling/overscroll_controller.h"
266 #include "third_party/blink/renderer/core/page/scrolling/root_scroller_controller.h"
267 #include "third_party/blink/renderer/core/page/scrolling/scroll_state_callback.h"
268 #include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
269 #include "third_party/blink/renderer/core/page/scrolling/snap_coordinator.h"
270 #include "third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h"
271 #include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h"
272 #include "third_party/blink/renderer/core/page/spatial_navigation_controller.h"
273 #include "third_party/blink/renderer/core/page/validation_message_client.h"
274 #include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
275 #include "third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h"
276 #include "third_party/blink/renderer/core/paint/paint_layer.h"
277 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
278 #include "third_party/blink/renderer/core/probe/core_probes.h"
279 #include "third_party/blink/renderer/core/resize_observer/resize_observer_controller.h"
280 #include "third_party/blink/renderer/core/script/script_runner.h"
281 #include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
282 #include "third_party/blink/renderer/core/svg/svg_document_extensions.h"
283 #include "third_party/blink/renderer/core/svg/svg_script_element.h"
284 #include "third_party/blink/renderer/core/svg/svg_title_element.h"
285 #include "third_party/blink/renderer/core/svg/svg_unknown_element.h"
286 #include "third_party/blink/renderer/core/svg/svg_use_element.h"
287 #include "third_party/blink/renderer/core/svg_element_factory.h"
288 #include "third_party/blink/renderer/core/svg_names.h"
289 #include "third_party/blink/renderer/core/trustedtypes/trusted_html.h"
290 #include "third_party/blink/renderer/core/xml/parser/xml_document_parser.h"
291 #include "third_party/blink/renderer/core/xml_names.h"
292 #include "third_party/blink/renderer/core/xmlhttprequest/main_thread_disallow_synchronous_xhr_scope.h"
293 #include "third_party/blink/renderer/core/xmlns_names.h"
294 #include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
295 #include "third_party/blink/renderer/platform/bindings/exception_messages.h"
296 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
297 #include "third_party/blink/renderer/platform/bindings/microtask.h"
298 #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
299 #include "third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h"
300 #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
301 #include "third_party/blink/renderer/platform/fonts/font_matching_metrics.h"
302 #include "third_party/blink/renderer/platform/geometry/length_functions.h"
303 #include "third_party/blink/renderer/platform/heap/heap.h"
304 #include "third_party/blink/renderer/platform/instrumentation/histogram.h"
305 #include "third_party/blink/renderer/platform/instrumentation/instance_counters.h"
306 #include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h"
307 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
308 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
309 #include "third_party/blink/renderer/platform/language.h"
310 #include "third_party/blink/renderer/platform/loader/fetch/null_resource_fetcher_properties.h"
311 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
312 #include "third_party/blink/renderer/platform/network/content_security_policy_parsers.h"
313 #include "third_party/blink/renderer/platform/network/http_parsers.h"
314 #include "third_party/blink/renderer/platform/network/network_state_notifier.h"
315 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
316 #include "third_party/blink/renderer/platform/scheduler/public/event_loop.h"
317 #include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h"
318 #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
319 #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
320 #include "third_party/blink/renderer/platform/text/platform_locale.h"
321 #include "third_party/blink/renderer/platform/web_test_support.h"
322 #include "third_party/blink/renderer/platform/weborigin/origin_access_entry.h"
323 #include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
324 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
325 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
326 #include "third_party/blink/renderer/platform/wtf/functional.h"
327 #include "third_party/blink/renderer/platform/wtf/hash_functions.h"
328 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
329 #include "third_party/blink/renderer/platform/wtf/text/character_names.h"
330 #include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
331 #include "third_party/blink/renderer/platform/wtf/text/text_encoding_registry.h"
332 
333 #ifndef NDEBUG
334 using WeakDocumentSet = blink::HeapHashSet<blink::WeakMember<blink::Document>>;
335 static WeakDocumentSet& liveDocumentSet();
336 #endif
337 
338 namespace blink {
339 
340 namespace {
341 
342 // Returns true if any of <object> ancestors don't start loading or are loading
343 // plugins/frames/images. If there are no <object> ancestors, this function
344 // returns false.
IsInIndeterminateObjectAncestor(const Element * element)345 bool IsInIndeterminateObjectAncestor(const Element* element) {
346   if (!element->isConnected())
347     return false;
348   for (; element; element = element->ParentOrShadowHostElement()) {
349     if (const auto* object = DynamicTo<HTMLObjectElement>(element)) {
350       if (!object->DidFinishLoading())
351         return true;
352     }
353   }
354   return false;
355 }
356 
357 }  // namespace
358 
359 class DocumentOutliveTimeReporter : public BlinkGCObserver {
360  public:
DocumentOutliveTimeReporter(Document * document)361   explicit DocumentOutliveTimeReporter(Document* document)
362       : BlinkGCObserver(ThreadState::Current()), document_(document) {}
363 
~DocumentOutliveTimeReporter()364   ~DocumentOutliveTimeReporter() override {
365     // As not all documents are destroyed before the process dies, this might
366     // miss some long-lived documents or leaked documents.
367     UMA_HISTOGRAM_EXACT_LINEAR(
368         "Document.OutliveTimeAfterShutdown.DestroyedBeforeProcessDies",
369         GetOutliveTimeCount() + 1, 101);
370   }
371 
OnCompleteSweepDone()372   void OnCompleteSweepDone() override {
373     enum GCCount {
374       kGCCount5,
375       kGCCount10,
376       kGCCountMax,
377     };
378 
379     // There are some cases that a document can live after shutting down because
380     // the document can still be referenced (e.g. a document opened via
381     // window.open can be referenced by the opener even after shutting down). To
382     // avoid such cases as much as possible, outlive time count is started after
383     // all DomWrapper of the document have disappeared.
384     if (!gc_age_when_document_detached_) {
385       if (document_->domWindow() &&
386           DOMWrapperWorld::HasWrapperInAnyWorldInMainThread(
387               document_->domWindow())) {
388         return;
389       }
390       gc_age_when_document_detached_ = ThreadState::Current()->GcAge();
391     }
392 
393     int outlive_time_count = GetOutliveTimeCount();
394     if (outlive_time_count == 5 || outlive_time_count == 10) {
395       const char* kUMAString = "Document.OutliveTimeAfterShutdown.GCCount";
396 
397       if (outlive_time_count == 5)
398         UMA_HISTOGRAM_ENUMERATION(kUMAString, kGCCount5, kGCCountMax);
399       else if (outlive_time_count == 10)
400         UMA_HISTOGRAM_ENUMERATION(kUMAString, kGCCount10, kGCCountMax);
401       else
402         NOTREACHED();
403     }
404 
405     if (outlive_time_count == 5 || outlive_time_count == 10 ||
406         outlive_time_count == 20 || outlive_time_count == 50) {
407       document_->RecordUkmOutliveTimeAfterShutdown(outlive_time_count);
408     }
409   }
410 
411  private:
GetOutliveTimeCount() const412   int GetOutliveTimeCount() const {
413     if (!gc_age_when_document_detached_)
414       return 0;
415     return ThreadState::Current()->GcAge() - gc_age_when_document_detached_;
416   }
417 
418   WeakPersistent<Document> document_;
419   int gc_age_when_document_detached_ = 0;
420 };
421 
422 static const unsigned kCMaxWriteRecursionDepth = 21;
423 
424 // This amount of time must have elapsed before we will even consider scheduling
425 // a layout without a delay.
426 // FIXME: For faster machines this value can really be lowered to 200.  250 is
427 // adequate, but a little high for dual G5s. :)
428 static const base::TimeDelta kCLayoutScheduleThreshold =
429     base::TimeDelta::FromMilliseconds(250);
430 
431 // DOM Level 2 says (letters added):
432 //
433 // a) Name start characters must have one of the categories Ll, Lu, Lo, Lt, Nl.
434 // b) Name characters other than Name-start characters must have one of the
435 //    categories Mc, Me, Mn, Lm, or Nd.
436 // c) Characters in the compatibility area (i.e. with character code greater
437 //    than #xF900 and less than #xFFFE) are not allowed in XML names.
438 // d) Characters which have a font or compatibility decomposition (i.e. those
439 //    with a "compatibility formatting tag" in field 5 of the database -- marked
440 //    by field 5 beginning with a "<") are not allowed.
441 // e) The following characters are treated as name-start characters rather than
442 //    name characters, because the property file classifies them as Alphabetic:
443 //    [#x02BB-#x02C1], #x0559, #x06E5, #x06E6.
444 // f) Characters #x20DD-#x20E0 are excluded (in accordance with Unicode, section
445 //    5.14).
446 // g) Character #x00B7 is classified as an extender, because the property list
447 //    so identifies it.
448 // h) Character #x0387 is added as a name character, because #x00B7 is its
449 //    canonical equivalent.
450 // i) Characters ':' and '_' are allowed as name-start characters.
451 // j) Characters '-' and '.' are allowed as name characters.
452 //
453 // It also contains complete tables. If we decide it's better, we could include
454 // those instead of the following code.
455 
IsValidNameStart(UChar32 c)456 static inline bool IsValidNameStart(UChar32 c) {
457   // rule (e) above
458   if ((c >= 0x02BB && c <= 0x02C1) || c == 0x559 || c == 0x6E5 || c == 0x6E6)
459     return true;
460 
461   // rule (i) above
462   if (c == ':' || c == '_')
463     return true;
464 
465   // rules (a) and (f) above
466   const uint32_t kNameStartMask =
467       WTF::unicode::kLetter_Lowercase | WTF::unicode::kLetter_Uppercase |
468       WTF::unicode::kLetter_Other | WTF::unicode::kLetter_Titlecase |
469       WTF::unicode::kNumber_Letter;
470   if (!(WTF::unicode::Category(c) & kNameStartMask))
471     return false;
472 
473   // rule (c) above
474   if (c >= 0xF900 && c < 0xFFFE)
475     return false;
476 
477   // rule (d) above
478   WTF::unicode::CharDecompositionType decomp_type =
479       WTF::unicode::DecompositionType(c);
480   if (decomp_type == WTF::unicode::kDecompositionFont ||
481       decomp_type == WTF::unicode::kDecompositionCompat)
482     return false;
483 
484   return true;
485 }
486 
IsValidNamePart(UChar32 c)487 static inline bool IsValidNamePart(UChar32 c) {
488   // rules (a), (e), and (i) above
489   if (IsValidNameStart(c))
490     return true;
491 
492   // rules (g) and (h) above
493   if (c == 0x00B7 || c == 0x0387)
494     return true;
495 
496   // rule (j) above
497   if (c == '-' || c == '.')
498     return true;
499 
500   // rules (b) and (f) above
501   const uint32_t kOtherNamePartMask =
502       WTF::unicode::kMark_NonSpacing | WTF::unicode::kMark_Enclosing |
503       WTF::unicode::kMark_SpacingCombining | WTF::unicode::kLetter_Modifier |
504       WTF::unicode::kNumber_DecimalDigit;
505   if (!(WTF::unicode::Category(c) & kOtherNamePartMask))
506     return false;
507 
508   // rule (c) above
509   if (c >= 0xF900 && c < 0xFFFE)
510     return false;
511 
512   // rule (d) above
513   WTF::unicode::CharDecompositionType decomp_type =
514       WTF::unicode::DecompositionType(c);
515   if (decomp_type == WTF::unicode::kDecompositionFont ||
516       decomp_type == WTF::unicode::kDecompositionCompat)
517     return false;
518 
519   return true;
520 }
521 
522 // Tests whether |name| is something the HTML parser would accept as a
523 // tag name.
524 template <typename CharType>
IsValidElementNamePerHTMLParser(const CharType * characters,unsigned length)525 static inline bool IsValidElementNamePerHTMLParser(const CharType* characters,
526                                                    unsigned length) {
527   CharType c = characters[0] | 0x20;
528   if (!('a' <= c && c <= 'z'))
529     return false;
530 
531   for (unsigned i = 1; i < length; ++i) {
532     c = characters[i];
533     if (c == '\t' || c == '\n' || c == '\f' || c == '\r' || c == ' ' ||
534         c == '/' || c == '>')
535       return false;
536   }
537 
538   return true;
539 }
540 
IsValidElementNamePerHTMLParser(const String & name)541 static bool IsValidElementNamePerHTMLParser(const String& name) {
542   unsigned length = name.length();
543   if (!length)
544     return false;
545 
546   if (name.Is8Bit()) {
547     const LChar* characters = name.Characters8();
548     return IsValidElementNamePerHTMLParser(characters, length);
549   }
550   const UChar* characters = name.Characters16();
551   return IsValidElementNamePerHTMLParser(characters, length);
552 }
553 
554 // Tests whether |name| is a valid name per DOM spec. Also checks
555 // whether the HTML parser would accept this element name and counts
556 // cases of mismatches.
IsValidElementName(Document * document,const String & name)557 static bool IsValidElementName(Document* document, const String& name) {
558   bool is_valid_dom_name = Document::IsValidName(name);
559   bool is_valid_html_name = IsValidElementNamePerHTMLParser(name);
560   if (UNLIKELY(is_valid_html_name != is_valid_dom_name)) {
561     // This is inaccurate because it will not report activity in
562     // detached documents. However retrieving the frame from the
563     // bindings is too slow.
564     UseCounter::Count(document,
565                       is_valid_dom_name
566                           ? WebFeature::kElementNameDOMValidHTMLParserInvalid
567                           : WebFeature::kElementNameDOMInvalidHTMLParserValid);
568   }
569   return is_valid_dom_name;
570 }
571 
AcceptsEditingFocus(const Element & element)572 static bool AcceptsEditingFocus(const Element& element) {
573   DCHECK(HasEditableStyle(element));
574 
575   return element.GetDocument().GetFrame() && RootEditableElement(element);
576 }
577 
578 uint64_t Document::global_tree_version_ = 0;
579 
580 static bool g_threaded_parsing_enabled_for_testing = true;
581 
582 class Document::NetworkStateObserver final
583     : public GarbageCollected<Document::NetworkStateObserver>,
584       public NetworkStateNotifier::NetworkStateObserver,
585       public ExecutionContextLifecycleObserver {
586   USING_GARBAGE_COLLECTED_MIXIN(Document::NetworkStateObserver);
587 
588  public:
NetworkStateObserver(ExecutionContext * context)589   explicit NetworkStateObserver(ExecutionContext* context)
590       : ExecutionContextLifecycleObserver(context) {
591     online_observer_handle_ = GetNetworkStateNotifier().AddOnLineObserver(
592         this, GetExecutionContext()->GetTaskRunner(TaskType::kNetworking));
593   }
594 
OnLineStateChange(bool on_line)595   void OnLineStateChange(bool on_line) override {
596     AtomicString event_name =
597         on_line ? event_type_names::kOnline : event_type_names::kOffline;
598     auto* window = To<LocalDOMWindow>(GetExecutionContext());
599     window->DispatchEvent(*Event::Create(event_name));
600     probe::NetworkStateChanged(window->GetFrame(), on_line);
601   }
602 
ContextDestroyed()603   void ContextDestroyed() override {
604     UnregisterAsObserver(GetExecutionContext());
605   }
606 
UnregisterAsObserver(ExecutionContext * context)607   void UnregisterAsObserver(ExecutionContext* context) {
608     DCHECK(context);
609     online_observer_handle_ = nullptr;
610   }
611 
Trace(Visitor * visitor)612   void Trace(Visitor* visitor) override {
613     ExecutionContextLifecycleObserver::Trace(visitor);
614   }
615 
616  private:
617   std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle>
618       online_observer_handle_;
619 };
620 
GetExplicitlySetAttrElementsMap(Element * element)621 ExplicitlySetAttrElementsMap* Document::GetExplicitlySetAttrElementsMap(
622     Element* element) {
623   DCHECK(element);
624   DCHECK(element->GetDocument() == this);
625   auto add_result =
626       element_explicitly_set_attr_elements_map_.insert(element, nullptr);
627   if (add_result.is_new_entry) {
628     add_result.stored_value->value =
629         MakeGarbageCollected<ExplicitlySetAttrElementsMap>();
630   }
631   return add_result.stored_value->value;
632 }
633 
Create(Document & document)634 Document* Document::Create(Document& document) {
635   Document* new_document =
636       MakeGarbageCollected<Document>(DocumentInit::Create()
637                                          .WithContextDocument(&document)
638                                          .WithURL(BlankURL())
639                                          .WithOwnerDocument(&document));
640   new_document->SetContextFeatures(document.GetContextFeatures());
641   return new_document;
642 }
643 
Document()644 Document::Document() : Document(DocumentInit::Create()) {}
645 
Document(const DocumentInit & initializer,DocumentClassFlags document_classes)646 Document::Document(const DocumentInit& initializer,
647                    DocumentClassFlags document_classes)
648     : Document(initializer,
649                SecurityContextInit(initializer),
650                document_classes) {}
651 
Document(const DocumentInit & initializer,const SecurityContextInit & security_initializer,DocumentClassFlags document_classes)652 Document::Document(const DocumentInit& initializer,
653                    const SecurityContextInit& security_initializer,
654                    DocumentClassFlags document_classes)
655     : ContainerNode(nullptr, kCreateDocument),
656       TreeScope(*this),
657       evaluate_media_queries_on_style_recalc_(false),
658       pending_sheet_layout_(kNoLayoutWithPendingSheets),
659       window_agent_factory_(initializer.GetWindowAgentFactory()),
660       frame_(initializer.GetFrame()),
661       // TODO(dcheng): Why does this need both a LocalFrame and LocalDOMWindow
662       // pointer?
663       dom_window_(frame_ ? frame_->DomWindow() : nullptr),
664       imports_controller_(initializer.ImportsController()),
665       security_context_(security_initializer, SecurityContext::kLocal),
666       use_counter_during_construction_(initializer.GetUseCounter()),
667       context_document_(initializer.ContextDocument()),
668       context_features_(ContextFeatures::DefaultSwitch()),
669       http_refresh_scheduler_(MakeGarbageCollected<HttpRefreshScheduler>(this)),
670       well_formed_(false),
671       printing_(kNotPrinting),
672       is_painting_preview_(false),
673       compatibility_mode_(kNoQuirksMode),
674       compatibility_mode_locked_(false),
675       last_focus_type_(mojom::blink::FocusType::kNone),
676       had_keyboard_event_(false),
677       clear_focused_element_timer_(
678           GetTaskRunner(TaskType::kInternalUserInteraction),
679           this,
680           &Document::ClearFocusedElementTimerFired),
681       dom_tree_version_(++global_tree_version_),
682       style_version_(0),
683       listener_types_(0),
684       mutation_observer_types_(0),
685       visited_link_state_(MakeGarbageCollected<VisitedLinkState>(*this)),
686       visually_ordered_(false),
687       // https://html.spec.whatwg.org/multipage/dom.html#current-document-readiness
688       // says the ready state starts as 'loading' if there's an associated
689       // parser and 'complete' otherwise. We don't know whether there's an
690       // associated parser here (we create the parser in ImplicitOpen). But
691       // waiting to set the ready state to 'loading' in ImplicitOpen fires a
692       // readystatechange event, which can be observed in the case where we
693       // reuse a window. If there's a window being reused, then there must be
694       // a frame, and if there's a frame, there must be an associated parser, so
695       // setting based on frame_ here is sufficient to ensure that the quirk of
696       // when we set the ready state is not web-observable.
697       ready_state_(frame_ ? kLoading : kComplete),
698       parsing_state_(kFinishedParsing),
699       contains_plugins_(false),
700       ignore_destructive_write_count_(0),
701       throw_on_dynamic_markup_insertion_count_(0),
702       ignore_opens_during_unload_count_(0),
703       markers_(MakeGarbageCollected<DocumentMarkerController>(*this)),
704       css_target_(nullptr),
705       was_discarded_(false),
706       load_event_progress_(kLoadEventCompleted),
707       is_freezing_in_progress_(false),
708       script_runner_(MakeGarbageCollected<ScriptRunner>(this)),
709       xml_version_("1.0"),
710       xml_standalone_(kStandaloneUnspecified),
711       has_xml_declaration_(0),
712       design_mode_(false),
713       is_running_exec_command_(false),
714       has_annotated_regions_(false),
715       annotated_regions_dirty_(false),
716       document_classes_(document_classes),
717       is_view_source_(false),
718       saw_elements_in_known_namespaces_(false),
719       is_srcdoc_document_(initializer.IsSrcdocDocument()),
720       is_mobile_document_(false),
721       layout_view_(nullptr),
722       has_fullscreen_supplement_(false),
723       load_event_delay_count_(0),
724       // We already intentionally fire load event asynchronously and here we use
725       // kDOMManipulation to ensure that we run onload() in order with other
726       // callbacks (e.g. onloadstart()) per the spec.
727       // See: https://html.spec.whatwg.org/#delay-the-load-event
728       load_event_delay_timer_(GetTaskRunner(TaskType::kDOMManipulation),
729                               this,
730                               &Document::LoadEventDelayTimerFired),
731       plugin_loading_timer_(GetTaskRunner(TaskType::kInternalLoading),
732                             this,
733                             &Document::PluginLoadingTimerFired),
734       document_timing_(*this),
735       write_recursion_is_too_deep_(false),
736       write_recursion_depth_(0),
737       scripted_animation_controller_(
738           MakeGarbageCollected<ScriptedAnimationController>(domWindow())),
739       current_frame_is_throttled_(false),
740       registration_context_(initializer.RegistrationContext(this)),
741       element_data_cache_clear_timer_(
742           GetTaskRunner(TaskType::kInternalUserInteraction),
743           this,
744           &Document::ElementDataCacheClearTimerFired),
745       document_animations_(MakeGarbageCollected<DocumentAnimations>(this)),
746       timeline_(MakeGarbageCollected<DocumentTimeline>(this)),
747       pending_animations_(MakeGarbageCollected<PendingAnimations>(*this)),
748       worklet_animation_controller_(
749           MakeGarbageCollected<WorkletAnimationController>(this)),
750       template_document_host_(nullptr),
751       did_associate_form_controls_timer_(
752           GetTaskRunner(TaskType::kInternalLoading),
753           this,
754           &Document::DidAssociateFormControlsTimerFired),
755       has_viewport_units_(false),
756       parser_sync_policy_(kAllowAsynchronousParsing),
757       node_count_(0),
758       logged_field_edit_(false),
759       ukm_source_id_(ukm::UkmRecorder::GetNewSourceID()),
760       needs_to_record_ukm_outlive_time_(false),
761       viewport_data_(MakeGarbageCollected<ViewportData>(*this)),
762       is_for_external_handler_(initializer.IsForExternalHandler()),
763       isolated_world_csp_map_(
764           MakeGarbageCollected<
765               HeapHashMap<int, Member<ContentSecurityPolicy>>>()),
766       permission_service_(GetExecutionContext()),
767       font_preload_manager_(*this) {
768   security_initializer.ApplyPendingDataToDocument(*this);
769   GetOriginTrialContext()->BindExecutionContext(GetExecutionContext());
770 
771   if (frame_) {
772     pending_fp_headers_ = security_initializer.FeaturePolicyHeader();
773     pending_dp_headers_ = initializer.GetDocumentPolicy().feature_state;
774   }
775 
776   if (frame_) {
777     DCHECK(frame_->GetPage());
778     ProvideContextFeaturesToDocumentFrom(*this, *frame_->GetPage());
779     fetcher_ = FrameFetchContext::CreateFetcherForCommittedDocument(
780         *frame_->Loader().GetDocumentLoader(), *this);
781     // TODO(dcheng): Why does this need to check that DOMWindow is non-null?
782     CustomElementRegistry* registry =
783         frame_->DomWindow() ? frame_->DomWindow()->MaybeCustomElements()
784                             : nullptr;
785     if (registry && registration_context_)
786       registry->Entangle(registration_context_);
787     cookie_jar_ = MakeGarbageCollected<CookieJar>(this);
788   } else {
789     // We disable fetches for frame-less Documents, including HTML-imported
790     // Documents (if kHtmlImportsRequestInitiatorLock is enabled). Subresources
791     // of HTML-imported Documents are fetched via the context document's
792     // ResourceFetcher. See https://crbug.com/961614 for details.
793     auto& properties =
794         *MakeGarbageCollected<DetachableResourceFetcherProperties>(
795             *MakeGarbageCollected<NullResourceFetcherProperties>());
796     fetcher_ = MakeGarbageCollected<ResourceFetcher>(ResourceFetcherInit(
797         properties, &FetchContext::NullInstance(),
798         GetTaskRunner(TaskType::kNetworking), nullptr /* loader_factory */));
799 
800     if (imports_controller_) {
801       // We don't expect the fetcher to be used, so count such unexpected use.
802       fetcher_->SetShouldLogRequestAsInvalidInImportedDocument();
803     }
804   }
805   DCHECK(fetcher_);
806 
807   root_scroller_controller_ =
808       MakeGarbageCollected<RootScrollerController>(*this);
809 
810   // We depend on the url getting immediately set in subframes, but we
811   // also depend on the url NOT getting immediately set in opened windows.
812   // See fast/dom/early-frame-url.html
813   // and fast/dom/location-new-window-no-crash.html, respectively.
814   // FIXME: Can/should we unify this behavior?
815   if (initializer.ShouldSetURL()) {
816     SetURL(initializer.Url());
817   } else {
818     // Even if this document has no URL, we need to initialize base URL with
819     // fallback base URL.
820     UpdateBaseURL();
821   }
822 
823   if (initializer.GetWebBundleClaimedUrl().IsValid()) {
824     web_bundle_claimed_url_ = initializer.GetWebBundleClaimedUrl();
825     SetBaseURLOverride(initializer.GetWebBundleClaimedUrl());
826   }
827 
828   InitSecurityContext(initializer);
829   PoliciesInitialized(initializer);
830   InitDNSPrefetch();
831 
832   InstanceCounters::IncrementCounter(InstanceCounters::kDocumentCounter);
833 
834   lifecycle_.AdvanceTo(DocumentLifecycle::kInactive);
835 
836   UpdateForcedColors();
837 
838   // Since CSSFontSelector requires Document::fetcher_ and StyleEngine owns
839   // CSSFontSelector, need to initialize |style_engine_| after initializing
840   // |fetcher_|.
841   style_engine_ = MakeGarbageCollected<StyleEngine>(*this);
842 
843   // The parent's parser should be suspended together with all the other
844   // objects, else this new Document would have a new ExecutionContext which
845   // suspended state would not match the one from the parent, and could start
846   // loading resources ignoring the defersLoading flag.
847   DCHECK(!ParentDocument() || !ParentDocument()->IsContextPaused());
848 
849 #ifndef NDEBUG
850   liveDocumentSet().insert(this);
851 #endif
852 
853   if (frame_ && frame_->GetPage()->GetAgentMetricsCollector())
854     frame_->GetPage()->GetAgentMetricsCollector()->DidAttachDocument(*this);
855 
856   // We will use Loader() as UseCounter after initialization.
857   use_counter_during_construction_ = nullptr;
858 }
859 
~Document()860 Document::~Document() {
861   DCHECK(!GetLayoutView());
862   DCHECK(!ParentTreeScope());
863   // If a top document with a cache, verify that it was comprehensively
864   // cleared during detach.
865   DCHECK(!ax_object_cache_);
866 
867   InstanceCounters::DecrementCounter(InstanceCounters::kDocumentCounter);
868 }
869 
CreateRangeAdjustedToTreeScope(const TreeScope & tree_scope,const Position & position)870 Range* Document::CreateRangeAdjustedToTreeScope(const TreeScope& tree_scope,
871                                                 const Position& position) {
872   DCHECK(position.IsNotNull());
873   // Note: Since |Position::ComputeContainerNode()| returns |nullptr| if
874   // |position| is |BeforeAnchor| or |AfterAnchor|.
875   Node* const anchor_node = position.AnchorNode();
876   if (anchor_node->GetTreeScope() == tree_scope) {
877     return MakeGarbageCollected<Range>(tree_scope.GetDocument(), position,
878                                        position);
879   }
880   Node* const shadow_host = tree_scope.AncestorInThisScope(anchor_node);
881   return MakeGarbageCollected<Range>(tree_scope.GetDocument(),
882                                      Position::BeforeNode(*shadow_host),
883                                      Position::BeforeNode(*shadow_host));
884 }
885 
GetSelectorQueryCache()886 SelectorQueryCache& Document::GetSelectorQueryCache() {
887   if (!selector_query_cache_)
888     selector_query_cache_ = std::make_unique<SelectorQueryCache>();
889   return *selector_query_cache_;
890 }
891 
GetMediaQueryMatcher()892 MediaQueryMatcher& Document::GetMediaQueryMatcher() {
893   if (!media_query_matcher_)
894     media_query_matcher_ = MakeGarbageCollected<MediaQueryMatcher>(*this);
895   return *media_query_matcher_;
896 }
897 
MediaQueryAffectingValueChanged(MediaValueChange change)898 void Document::MediaQueryAffectingValueChanged(MediaValueChange change) {
899   GetStyleEngine().MediaQueryAffectingValueChanged(change);
900   if (NeedsLayoutTreeUpdate())
901     evaluate_media_queries_on_style_recalc_ = true;
902   else
903     EvaluateMediaQueryList();
904   probe::MediaQueryResultChanged(this);
905 }
906 
SetCompatibilityMode(CompatibilityMode mode)907 void Document::SetCompatibilityMode(CompatibilityMode mode) {
908   if (compatibility_mode_locked_ || mode == compatibility_mode_)
909     return;
910 
911   if (compatibility_mode_ == kQuirksMode)
912     UseCounter::Count(*this, WebFeature::kQuirksModeDocument);
913   else if (compatibility_mode_ == kLimitedQuirksMode)
914     UseCounter::Count(*this, WebFeature::kLimitedQuirksModeDocument);
915 
916   compatibility_mode_ = mode;
917   GetSelectorQueryCache().Invalidate();
918 }
919 
compatMode() const920 String Document::compatMode() const {
921   return InQuirksMode() ? "BackCompat" : "CSS1Compat";
922 }
923 
SetDoctype(DocumentType * doc_type)924 void Document::SetDoctype(DocumentType* doc_type) {
925   // This should never be called more than once.
926   DCHECK(!doc_type_ || !doc_type);
927   doc_type_ = doc_type;
928   if (doc_type_) {
929     AdoptIfNeeded(*doc_type_);
930     if (doc_type_->publicId().StartsWithIgnoringASCIICase(
931             "-//wapforum//dtd xhtml mobile 1.")) {
932       is_mobile_document_ = true;
933       style_engine_->ViewportRulesChanged();
934     }
935   }
936 }
937 
implementation()938 DOMImplementation& Document::implementation() {
939   if (!implementation_)
940     implementation_ = MakeGarbageCollected<DOMImplementation>(*this);
941   return *implementation_;
942 }
943 
location() const944 Location* Document::location() const {
945   if (!GetFrame())
946     return nullptr;
947 
948   return domWindow()->location();
949 }
950 
GetContentSecurityPolicyForWorld()951 ContentSecurityPolicy* Document::GetContentSecurityPolicyForWorld() {
952   v8::Isolate* isolate = GetIsolate();
953   if (!isolate)
954     return GetContentSecurityPolicy();
955   v8::HandleScope handle_scope(isolate);
956   v8::Local<v8::Context> v8_context = isolate->GetCurrentContext();
957 
958   // This can be called before we enter v8, hence the context might be empty,
959   // which implies we are not in an isolated world.
960   if (v8_context.IsEmpty())
961     return GetContentSecurityPolicy();
962 
963   DOMWrapperWorld& world = DOMWrapperWorld::Current(isolate);
964   if (!world.IsIsolatedWorld())
965     return GetContentSecurityPolicy();
966 
967   int32_t world_id = world.GetWorldId();
968   auto it = isolated_world_csp_map_->find(world_id);
969   if (it != isolated_world_csp_map_->end())
970     return it->value;
971 
972   ContentSecurityPolicy* policy =
973       IsolatedWorldCSP::Get().CreateIsolatedWorldCSP(*this, world_id);
974   if (!policy)
975     return GetContentSecurityPolicy();
976 
977   isolated_world_csp_map_->insert(world_id, policy);
978   return policy;
979 }
980 
981 // static
From(ExecutionContext & context)982 Document& Document::From(ExecutionContext& context) {
983   SECURITY_DCHECK(context.IsDocument());
984   return *static_cast<LocalDOMWindow&>(context).document();
985 }
986 
987 // static
From(const ExecutionContext & context)988 const Document& Document::From(const ExecutionContext& context) {
989   SECURITY_DCHECK(context.IsDocument());
990   return *static_cast<const LocalDOMWindow&>(context).document();
991 }
992 
ToExecutionContext()993 ExecutionContext* Document::ToExecutionContext() {
994   return GetExecutionContext();
995 }
996 
ToExecutionContext() const997 const ExecutionContext* Document::ToExecutionContext() const {
998   return GetExecutionContext();
999 }
1000 
FeatureEnabled(OriginTrialFeature feature) const1001 bool Document::FeatureEnabled(OriginTrialFeature feature) const {
1002   return GetOriginTrialContext()->IsFeatureEnabled(feature);
1003 }
1004 
CountFeaturePolicyUsage(mojom::WebFeature feature)1005 void Document::CountFeaturePolicyUsage(mojom::WebFeature feature) {
1006   UseCounter::Count(*this, feature);
1007 }
1008 
FeaturePolicyFeatureObserved(mojom::blink::FeaturePolicyFeature feature)1009 bool Document::FeaturePolicyFeatureObserved(
1010     mojom::blink::FeaturePolicyFeature feature) {
1011   wtf_size_t feature_index = static_cast<wtf_size_t>(feature);
1012   if (parsed_feature_policies_.size() == 0) {
1013     parsed_feature_policies_.resize(
1014         static_cast<wtf_size_t>(mojom::blink::FeaturePolicyFeature::kMaxValue) +
1015         1);
1016   } else if (parsed_feature_policies_[feature_index]) {
1017     return true;
1018   }
1019   parsed_feature_policies_[feature_index] = true;
1020   return false;
1021 }
1022 
GetSecurityOrigin() const1023 const SecurityOrigin* Document::GetSecurityOrigin() const {
1024   return GetSecurityContext().GetSecurityOrigin();
1025 }
1026 
GetMutableSecurityOrigin()1027 SecurityOrigin* Document::GetMutableSecurityOrigin() {
1028   return GetSecurityContext().GetMutableSecurityOrigin();
1029 }
1030 
GetContentSecurityPolicy() const1031 ContentSecurityPolicy* Document::GetContentSecurityPolicy() const {
1032   return GetSecurityContext().GetContentSecurityPolicy();
1033 }
1034 
GetSandboxFlags() const1035 mojom::blink::WebSandboxFlags Document::GetSandboxFlags() const {
1036   return GetSecurityContext().GetSandboxFlags();
1037 }
1038 
IsSandboxed(mojom::blink::WebSandboxFlags mask) const1039 bool Document::IsSandboxed(mojom::blink::WebSandboxFlags mask) const {
1040   return GetSecurityContext().IsSandboxed(mask);
1041 }
1042 
GetPublicURLManager()1043 PublicURLManager& Document::GetPublicURLManager() {
1044   DCHECK(GetExecutionContext());
1045   return GetExecutionContext()->GetPublicURLManager();
1046 }
1047 
IsContextPaused() const1048 bool Document::IsContextPaused() const {
1049   return GetExecutionContext() ? GetExecutionContext()->IsContextPaused()
1050                                : false;
1051 }
1052 
IsContextDestroyed() const1053 bool Document::IsContextDestroyed() const {
1054   return GetExecutionContext() ? GetExecutionContext()->IsContextDestroyed()
1055                                : true;
1056 }
1057 
GetContentSecurityPolicyDelegate()1058 ContentSecurityPolicyDelegate& Document::GetContentSecurityPolicyDelegate() {
1059   return GetExecutionContext()->GetContentSecurityPolicyDelegate();
1060 }
1061 
GetSecureContextMode() const1062 SecureContextMode Document::GetSecureContextMode() const {
1063   return GetSecurityContext().GetSecureContextMode();
1064 }
1065 
IsSecureContext() const1066 bool Document::IsSecureContext() const {
1067   return GetExecutionContext()->IsSecureContext();
1068 }
1069 
IsSecureContext(String & error_message) const1070 bool Document::IsSecureContext(String& error_message) const {
1071   return GetExecutionContext()->IsSecureContext(error_message);
1072 }
1073 
SetReferrerPolicy(network::mojom::ReferrerPolicy policy)1074 void Document::SetReferrerPolicy(network::mojom::ReferrerPolicy policy) {
1075   GetExecutionContext()->SetReferrerPolicy(policy);
1076 }
1077 
GetIsolate() const1078 v8::Isolate* Document::GetIsolate() const {
1079   return GetExecutionContext() ? GetExecutionContext()->GetIsolate() : nullptr;
1080 }
1081 
GetAgent() const1082 Agent* Document::GetAgent() const {
1083   return GetSecurityContext().GetAgent();
1084 }
1085 
GetOriginTrialContext() const1086 OriginTrialContext* Document::GetOriginTrialContext() const {
1087   return MasterDocument().GetSecurityContext().GetOriginTrialContext();
1088 }
1089 
SetSecureContextModeForTesting(SecureContextMode mode)1090 void Document::SetSecureContextModeForTesting(SecureContextMode mode) {
1091   GetSecurityContext().SetSecureContextModeForTesting(mode);
1092 }
1093 
IsFeatureEnabled(mojom::blink::FeaturePolicyFeature feature,ReportOptions report_on_failure,const String & message,const String & source_file) const1094 bool Document::IsFeatureEnabled(mojom::blink::FeaturePolicyFeature feature,
1095                                 ReportOptions report_on_failure,
1096                                 const String& message,
1097                                 const String& source_file) const {
1098   return GetExecutionContext() &&
1099          GetExecutionContext()->IsFeatureEnabled(feature, report_on_failure,
1100                                                  message, source_file);
1101 }
1102 
IsFeatureEnabled(mojom::blink::FeaturePolicyFeature feature,PolicyValue threshold_value,ReportOptions report_on_failure,const String & message,const String & source_file) const1103 bool Document::IsFeatureEnabled(mojom::blink::FeaturePolicyFeature feature,
1104                                 PolicyValue threshold_value,
1105                                 ReportOptions report_on_failure,
1106                                 const String& message,
1107                                 const String& source_file) const {
1108   return GetExecutionContext() &&
1109          GetExecutionContext()->IsFeatureEnabled(
1110              feature, threshold_value, report_on_failure, message, source_file);
1111 }
1112 
IsFeatureEnabled(mojom::blink::DocumentPolicyFeature feature,ReportOptions report_option,const String & message,const String & source_file) const1113 bool Document::IsFeatureEnabled(mojom::blink::DocumentPolicyFeature feature,
1114                                 ReportOptions report_option,
1115                                 const String& message,
1116                                 const String& source_file) const {
1117   return GetExecutionContext() &&
1118          GetExecutionContext()->IsFeatureEnabled(feature, report_option,
1119                                                  message, source_file);
1120 }
1121 
IsFeatureEnabled(mojom::blink::DocumentPolicyFeature feature,PolicyValue threshold_value,ReportOptions report_option,const String & message,const String & source_file) const1122 bool Document::IsFeatureEnabled(mojom::blink::DocumentPolicyFeature feature,
1123                                 PolicyValue threshold_value,
1124                                 ReportOptions report_option,
1125                                 const String& message,
1126                                 const String& source_file) const {
1127   return GetExecutionContext() &&
1128          GetExecutionContext()->IsFeatureEnabled(
1129              feature, threshold_value, report_option, message, source_file);
1130 }
1131 
addressSpaceForBindings() const1132 String Document::addressSpaceForBindings() const {
1133   return GetExecutionContext()->addressSpaceForBindings();
1134 }
1135 
ChildrenChanged(const ChildrenChange & change)1136 void Document::ChildrenChanged(const ChildrenChange& change) {
1137   ContainerNode::ChildrenChanged(change);
1138   document_element_ = ElementTraversal::FirstWithin(*this);
1139 
1140   // For non-HTML documents the willInsertBody notification won't happen
1141   // so we resume as soon as we have a document element. Even for XHTML
1142   // documents there may never be a <body> (since the parser won't always
1143   // insert one), so we resume here too. That does mean XHTML documents make
1144   // frames when there's only a <head>, but such documents are pretty rare.
1145   if (document_element_ && !IsA<HTMLDocument>(this))
1146     BeginLifecycleUpdatesIfRenderingReady();
1147 }
1148 
setRootScroller(Element * new_scroller,ExceptionState &)1149 void Document::setRootScroller(Element* new_scroller, ExceptionState&) {
1150   root_scroller_controller_->Set(new_scroller);
1151 }
1152 
rootScroller() const1153 Element* Document::rootScroller() const {
1154   return root_scroller_controller_->Get();
1155 }
1156 
IsInMainFrame() const1157 bool Document::IsInMainFrame() const {
1158   return GetFrame() && GetFrame()->IsMainFrame();
1159 }
1160 
ConvertLocalName(const AtomicString & name)1161 AtomicString Document::ConvertLocalName(const AtomicString& name) {
1162   return IsA<HTMLDocument>(this) ? name.LowerASCII() : name;
1163 }
1164 
1165 // Just creates an element with specified qualified name without any
1166 // custom element processing.
1167 // This is a common code for step 5.2 and 7.2 of "create an element"
1168 // <https://dom.spec.whatwg.org/#concept-create-element>
1169 // Functions other than this one should not use HTMLElementFactory and
1170 // SVGElementFactory because they don't support prefixes correctly.
CreateRawElement(const QualifiedName & qname,CreateElementFlags flags)1171 Element* Document::CreateRawElement(const QualifiedName& qname,
1172                                     CreateElementFlags flags) {
1173   Element* element = nullptr;
1174   if (qname.NamespaceURI() == html_names::xhtmlNamespaceURI) {
1175     // https://html.spec.whatwg.org/C/#elements-in-the-dom:element-interface
1176     element = HTMLElementFactory::Create(qname.LocalName(), *this, flags);
1177     if (!element) {
1178       // 6. If name is a valid custom element name, then return
1179       // HTMLElement.
1180       // 7. Return HTMLUnknownElement.
1181       if (CustomElement::IsValidName(qname.LocalName()))
1182         element = MakeGarbageCollected<HTMLElement>(qname, *this);
1183       else
1184         element = MakeGarbageCollected<HTMLUnknownElement>(qname, *this);
1185     }
1186     saw_elements_in_known_namespaces_ = true;
1187   } else if (qname.NamespaceURI() == svg_names::kNamespaceURI) {
1188     element = SVGElementFactory::Create(qname.LocalName(), *this, flags);
1189     if (!element)
1190       element = MakeGarbageCollected<SVGUnknownElement>(qname, *this);
1191     saw_elements_in_known_namespaces_ = true;
1192   } else if (RuntimeEnabledFeatures::MathMLCoreEnabled() &&
1193              qname.NamespaceURI() == mathml_names::kNamespaceURI) {
1194     element = MathMLElementFactory::Create(qname.LocalName(), *this, flags);
1195     // An unknown MathML element is treated like an <mrow> element.
1196     // TODO(crbug.com/1021837): Determine if we need to introduce a
1197     // MathMLUnknownElement IDL.
1198     if (!element)
1199       element = MakeGarbageCollected<MathMLRowElement>(qname, *this);
1200     saw_elements_in_known_namespaces_ = true;
1201   } else {
1202     element = MakeGarbageCollected<Element>(qname, this);
1203   }
1204 
1205   if (element->prefix() != qname.Prefix())
1206     element->SetTagNameForCreateElementNS(qname);
1207   DCHECK(qname == element->TagQName());
1208 
1209   return element;
1210 }
1211 
1212 // https://dom.spec.whatwg.org/#dom-document-createelement
CreateElementForBinding(const AtomicString & name,ExceptionState & exception_state)1213 Element* Document::CreateElementForBinding(const AtomicString& name,
1214                                            ExceptionState& exception_state) {
1215   if (!IsValidElementName(this, name)) {
1216     exception_state.ThrowDOMException(
1217         DOMExceptionCode::kInvalidCharacterError,
1218         "The tag name provided ('" + name + "') is not a valid name.");
1219     return nullptr;
1220   }
1221 
1222   if (IsXHTMLDocument() || IsA<HTMLDocument>(this)) {
1223     // 2. If the context object is an HTML document, let localName be
1224     // converted to ASCII lowercase.
1225     AtomicString local_name = ConvertLocalName(name);
1226     if (CustomElement::ShouldCreateCustomElement(local_name)) {
1227       return CustomElement::CreateCustomElement(
1228           *this,
1229           QualifiedName(g_null_atom, local_name, html_names::xhtmlNamespaceURI),
1230           CreateElementFlags::ByCreateElement());
1231     }
1232     if (auto* element = HTMLElementFactory::Create(
1233             local_name, *this, CreateElementFlags::ByCreateElement()))
1234       return element;
1235     QualifiedName q_name(g_null_atom, local_name,
1236                          html_names::xhtmlNamespaceURI);
1237     if (RegistrationContext() && V0CustomElement::IsValidName(local_name))
1238       return RegistrationContext()->CreateCustomTagElement(*this, q_name);
1239     return MakeGarbageCollected<HTMLUnknownElement>(q_name, *this);
1240   }
1241   return MakeGarbageCollected<Element>(
1242       QualifiedName(g_null_atom, name, g_null_atom), this);
1243 }
1244 
GetTypeExtension(Document * document,const StringOrElementCreationOptions & string_or_options)1245 AtomicString GetTypeExtension(
1246     Document* document,
1247     const StringOrElementCreationOptions& string_or_options) {
1248   if (string_or_options.IsNull())
1249     return AtomicString();
1250 
1251   if (string_or_options.IsString()) {
1252     UseCounter::Count(document,
1253                       WebFeature::kDocumentCreateElement2ndArgStringHandling);
1254     return AtomicString(string_or_options.GetAsString());
1255   }
1256 
1257   if (string_or_options.IsElementCreationOptions()) {
1258     const ElementCreationOptions& options =
1259         *string_or_options.GetAsElementCreationOptions();
1260     if (options.hasIs())
1261       return AtomicString(options.is());
1262   }
1263 
1264   return AtomicString();
1265 }
1266 
1267 // https://dom.spec.whatwg.org/#dom-document-createelement
CreateElementForBinding(const AtomicString & local_name,const StringOrElementCreationOptions & string_or_options,ExceptionState & exception_state)1268 Element* Document::CreateElementForBinding(
1269     const AtomicString& local_name,
1270     const StringOrElementCreationOptions& string_or_options,
1271     ExceptionState& exception_state) {
1272   if (string_or_options.IsNull()) {
1273     return CreateElementForBinding(local_name, exception_state);
1274   }
1275 
1276   // 1. If localName does not match Name production, throw InvalidCharacterError
1277   if (!IsValidElementName(this, local_name)) {
1278     exception_state.ThrowDOMException(
1279         DOMExceptionCode::kInvalidCharacterError,
1280         "The tag name provided ('" + local_name + "') is not a valid name.");
1281     return nullptr;
1282   }
1283 
1284   // 2. localName converted to ASCII lowercase
1285   const AtomicString& converted_local_name = ConvertLocalName(local_name);
1286   QualifiedName q_name(g_null_atom, converted_local_name,
1287                        IsXHTMLDocument() || IsA<HTMLDocument>(this)
1288                            ? html_names::xhtmlNamespaceURI
1289                            : g_null_atom);
1290 
1291   bool is_v1 =
1292       string_or_options.IsElementCreationOptions() || !RegistrationContext();
1293   // V0 is only allowed with the flag.
1294   DCHECK(is_v1 || RuntimeEnabledFeatures::CustomElementsV0Enabled(this));
1295   bool create_v1_builtin = string_or_options.IsElementCreationOptions();
1296   bool should_create_builtin =
1297       create_v1_builtin || string_or_options.IsString();
1298 
1299   // 3.
1300   const AtomicString& is = GetTypeExtension(this, string_or_options);
1301 
1302   // 5. Let element be the result of creating an element given ...
1303   Element* element =
1304       CreateElement(q_name,
1305                     is_v1 ? CreateElementFlags::ByCreateElementV1()
1306                           : CreateElementFlags::ByCreateElementV0(),
1307                     should_create_builtin ? is : g_null_atom);
1308 
1309   // 8. If 'is' is non-null, set 'is' attribute
1310   if (!is_v1 && !is.IsEmpty())
1311     element->setAttribute(html_names::kIsAttr, is);
1312 
1313   return element;
1314 }
1315 
CreateQualifiedName(const AtomicString & namespace_uri,const AtomicString & qualified_name,ExceptionState & exception_state)1316 static inline QualifiedName CreateQualifiedName(
1317     const AtomicString& namespace_uri,
1318     const AtomicString& qualified_name,
1319     ExceptionState& exception_state) {
1320   AtomicString prefix, local_name;
1321   if (!Document::ParseQualifiedName(qualified_name, prefix, local_name,
1322                                     exception_state))
1323     return QualifiedName::Null();
1324 
1325   QualifiedName q_name(prefix, local_name, namespace_uri);
1326   if (!Document::HasValidNamespaceForElements(q_name)) {
1327     exception_state.ThrowDOMException(
1328         DOMExceptionCode::kNamespaceError,
1329         "The namespace URI provided ('" + namespace_uri +
1330             "') is not valid for the qualified name provided ('" +
1331             qualified_name + "').");
1332     return QualifiedName::Null();
1333   }
1334 
1335   return q_name;
1336 }
1337 
createElementNS(const AtomicString & namespace_uri,const AtomicString & qualified_name,ExceptionState & exception_state)1338 Element* Document::createElementNS(const AtomicString& namespace_uri,
1339                                    const AtomicString& qualified_name,
1340                                    ExceptionState& exception_state) {
1341   QualifiedName q_name(
1342       CreateQualifiedName(namespace_uri, qualified_name, exception_state));
1343   if (q_name == QualifiedName::Null())
1344     return nullptr;
1345 
1346   CreateElementFlags flags = CreateElementFlags::ByCreateElement();
1347   if (CustomElement::ShouldCreateCustomElement(q_name))
1348     return CustomElement::CreateCustomElement(*this, q_name, flags);
1349   if (RegistrationContext() && V0CustomElement::IsValidName(q_name.LocalName()))
1350     return RegistrationContext()->CreateCustomTagElement(*this, q_name);
1351   return CreateRawElement(q_name, flags);
1352 }
1353 
1354 // https://dom.spec.whatwg.org/#internal-createelementns-steps
createElementNS(const AtomicString & namespace_uri,const AtomicString & qualified_name,const StringOrElementCreationOptions & string_or_options,ExceptionState & exception_state)1355 Element* Document::createElementNS(
1356     const AtomicString& namespace_uri,
1357     const AtomicString& qualified_name,
1358     const StringOrElementCreationOptions& string_or_options,
1359     ExceptionState& exception_state) {
1360   if (string_or_options.IsNull())
1361     return createElementNS(namespace_uri, qualified_name, exception_state);
1362 
1363   // 1. Validate and extract
1364   QualifiedName q_name(
1365       CreateQualifiedName(namespace_uri, qualified_name, exception_state));
1366   if (q_name == QualifiedName::Null())
1367     return nullptr;
1368 
1369   bool is_v1 =
1370       string_or_options.IsElementCreationOptions() || !RegistrationContext();
1371   // V0 is only allowed with the flag.
1372   DCHECK(is_v1 || RuntimeEnabledFeatures::CustomElementsV0Enabled(this));
1373   bool create_v1_builtin = string_or_options.IsElementCreationOptions();
1374   bool should_create_builtin =
1375       create_v1_builtin || string_or_options.IsString();
1376 
1377   // 2.
1378   const AtomicString& is = GetTypeExtension(this, string_or_options);
1379 
1380   if (!IsValidElementName(this, qualified_name)) {
1381     exception_state.ThrowDOMException(DOMExceptionCode::kInvalidCharacterError,
1382                                       "The tag name provided ('" +
1383                                           qualified_name +
1384                                           "') is not a valid name.");
1385     return nullptr;
1386   }
1387 
1388   // 3. Let element be the result of creating an element
1389   Element* element =
1390       CreateElement(q_name,
1391                     is_v1 ? CreateElementFlags::ByCreateElementV1()
1392                           : CreateElementFlags::ByCreateElementV0(),
1393                     should_create_builtin ? is : g_null_atom);
1394 
1395   // 4. If 'is' is non-null, set 'is' attribute
1396   if (!is_v1 && !is.IsEmpty())
1397     element->setAttribute(html_names::kIsAttr, is);
1398 
1399   return element;
1400 }
1401 
1402 // Entry point of "create an element".
1403 // https://dom.spec.whatwg.org/#concept-create-element
CreateElement(const QualifiedName & q_name,const CreateElementFlags flags,const AtomicString & is)1404 Element* Document::CreateElement(const QualifiedName& q_name,
1405                                  const CreateElementFlags flags,
1406                                  const AtomicString& is) {
1407   CustomElementDefinition* definition = nullptr;
1408   if (flags.IsCustomElementsV1() &&
1409       q_name.NamespaceURI() == html_names::xhtmlNamespaceURI) {
1410     const CustomElementDescriptor desc(is.IsNull() ? q_name.LocalName() : is,
1411                                        q_name.LocalName());
1412     if (CustomElementRegistry* registry = CustomElement::Registry(*this))
1413       definition = registry->DefinitionFor(desc);
1414   }
1415 
1416   if (definition)
1417     return definition->CreateElement(*this, q_name, flags);
1418 
1419   return CustomElement::CreateUncustomizedOrUndefinedElement(*this, q_name,
1420                                                              flags, is);
1421 }
1422 
registerElement(ScriptState * script_state,const AtomicString & name,const ElementRegistrationOptions * options,ExceptionState & exception_state)1423 ScriptValue Document::registerElement(ScriptState* script_state,
1424                                       const AtomicString& name,
1425                                       const ElementRegistrationOptions* options,
1426                                       ExceptionState& exception_state) {
1427   if (!RegistrationContext()) {
1428     exception_state.ThrowDOMException(
1429         DOMExceptionCode::kNotSupportedError,
1430         "No element registration context is available.");
1431     return ScriptValue();
1432   }
1433 
1434   // Polymer V1 uses Custom Elements V0. <dom-module> is defined in its base
1435   // library and is a strong signal that this is a Polymer V1.
1436   // This counter is used to research how much users are affected once Custom
1437   // Element V0 is deprecated.
1438   if (name == "dom-module")
1439     UseCounter::Count(*this, WebFeature::kPolymerV1Detected);
1440 
1441   V0CustomElementConstructorBuilder constructor_builder(script_state, options);
1442   RegistrationContext()->RegisterElement(this, &constructor_builder, name,
1443                                          exception_state);
1444   if (exception_state.HadException())
1445     return ScriptValue();
1446   return constructor_builder.BindingsReturnValue();
1447 }
1448 
RegistrationContext() const1449 V0CustomElementRegistrationContext* Document::RegistrationContext() const {
1450   if (RuntimeEnabledFeatures::CustomElementsV0Enabled(this))
1451     return registration_context_.Get();
1452   return nullptr;
1453 }
1454 
CustomElementMicrotaskRunQueue()1455 V0CustomElementMicrotaskRunQueue* Document::CustomElementMicrotaskRunQueue() {
1456   if (!custom_element_microtask_run_queue_) {
1457     custom_element_microtask_run_queue_ =
1458         MakeGarbageCollected<V0CustomElementMicrotaskRunQueue>();
1459   }
1460   return custom_element_microtask_run_queue_.Get();
1461 }
1462 
ClearImportsController()1463 void Document::ClearImportsController() {
1464   fetcher_->ClearContext();
1465   imports_controller_ = nullptr;
1466 }
1467 
EnsureImportsController()1468 HTMLImportsController* Document::EnsureImportsController() {
1469   if (!imports_controller_) {
1470     DCHECK(frame_);
1471     imports_controller_ = MakeGarbageCollected<HTMLImportsController>(*this);
1472   }
1473 
1474   return imports_controller_;
1475 }
1476 
ImportLoader() const1477 HTMLImportLoader* Document::ImportLoader() const {
1478   if (!imports_controller_)
1479     return nullptr;
1480   return imports_controller_->LoaderFor(*this);
1481 }
1482 
IsHTMLImport() const1483 bool Document::IsHTMLImport() const {
1484   return imports_controller_ && imports_controller_->Master() != this;
1485 }
1486 
MasterDocument() const1487 Document& Document::MasterDocument() const {
1488   if (!imports_controller_)
1489     return *const_cast<Document*>(this);
1490 
1491   Document* master = imports_controller_->Master();
1492   DCHECK(master);
1493   return *master;
1494 }
1495 
HaveImportsLoaded() const1496 bool Document::HaveImportsLoaded() const {
1497   if (!imports_controller_)
1498     return true;
1499   return !imports_controller_->ShouldBlockScriptExecution(*this);
1500 }
1501 
ExecutingWindow() const1502 LocalDOMWindow* Document::ExecutingWindow() const {
1503   if (LocalDOMWindow* owning_window = domWindow())
1504     return owning_window;
1505   if (HTMLImportsController* import = ImportsController())
1506     return import->Master()->domWindow();
1507   return nullptr;
1508 }
1509 
ExecutingFrame()1510 LocalFrame* Document::ExecutingFrame() {
1511   LocalDOMWindow* window = ExecutingWindow();
1512   if (!window)
1513     return nullptr;
1514   return window->GetFrame();
1515 }
1516 
createDocumentFragment()1517 DocumentFragment* Document::createDocumentFragment() {
1518   return DocumentFragment::Create(*this);
1519 }
1520 
createTextNode(const String & data)1521 Text* Document::createTextNode(const String& data) {
1522   return Text::Create(*this, data);
1523 }
1524 
createComment(const String & data)1525 Comment* Document::createComment(const String& data) {
1526   return Comment::Create(*this, data);
1527 }
1528 
createCDATASection(const String & data,ExceptionState & exception_state)1529 CDATASection* Document::createCDATASection(const String& data,
1530                                            ExceptionState& exception_state) {
1531   if (IsA<HTMLDocument>(this)) {
1532     exception_state.ThrowDOMException(
1533         DOMExceptionCode::kNotSupportedError,
1534         "This operation is not supported for HTML documents.");
1535     return nullptr;
1536   }
1537   if (data.Contains("]]>")) {
1538     exception_state.ThrowDOMException(DOMExceptionCode::kInvalidCharacterError,
1539                                       "String cannot contain ']]>' since that "
1540                                       "is the end delimiter of a CData "
1541                                       "section.");
1542     return nullptr;
1543   }
1544   return CDATASection::Create(*this, data);
1545 }
1546 
createProcessingInstruction(const String & target,const String & data,ExceptionState & exception_state)1547 ProcessingInstruction* Document::createProcessingInstruction(
1548     const String& target,
1549     const String& data,
1550     ExceptionState& exception_state) {
1551   if (!IsValidName(target)) {
1552     exception_state.ThrowDOMException(
1553         DOMExceptionCode::kInvalidCharacterError,
1554         "The target provided ('" + target + "') is not a valid name.");
1555     return nullptr;
1556   }
1557   if (data.Contains("?>")) {
1558     exception_state.ThrowDOMException(
1559         DOMExceptionCode::kInvalidCharacterError,
1560         "The data provided ('" + data + "') contains '?>'.");
1561     return nullptr;
1562   }
1563   if (IsA<HTMLDocument>(this)) {
1564     UseCounter::Count(*this,
1565                       WebFeature::kHTMLDocumentCreateProcessingInstruction);
1566   }
1567   return MakeGarbageCollected<ProcessingInstruction>(*this, target, data);
1568 }
1569 
CreateEditingTextNode(const String & text)1570 Text* Document::CreateEditingTextNode(const String& text) {
1571   return Text::CreateEditingText(*this, text);
1572 }
1573 
importNode(Node * imported_node,bool deep,ExceptionState & exception_state)1574 Node* Document::importNode(Node* imported_node,
1575                            bool deep,
1576                            ExceptionState& exception_state) {
1577   // https://dom.spec.whatwg.org/#dom-document-importnode
1578 
1579   // 1. If node is a document or shadow root, then throw a "NotSupportedError"
1580   // DOMException.
1581   if (imported_node->IsDocumentNode()) {
1582     exception_state.ThrowDOMException(
1583         DOMExceptionCode::kNotSupportedError,
1584         "The node provided is a document, which may not be imported.");
1585     return nullptr;
1586   }
1587   if (imported_node->IsShadowRoot()) {
1588     // ShadowRoot nodes should not be explicitly importable.  Either they are
1589     // imported along with their host node, or created implicitly.
1590     exception_state.ThrowDOMException(
1591         DOMExceptionCode::kNotSupportedError,
1592         "The node provided is a shadow root, which may not be imported.");
1593     return nullptr;
1594   }
1595 
1596   // 2. Return a clone of node, with context object and the clone children flag
1597   // set if deep is true.
1598   return imported_node->Clone(
1599       *this, deep ? CloneChildrenFlag::kClone : CloneChildrenFlag::kSkip);
1600 }
1601 
adoptNode(Node * source,ExceptionState & exception_state)1602 Node* Document::adoptNode(Node* source, ExceptionState& exception_state) {
1603   EventQueueScope scope;
1604 
1605   switch (source->getNodeType()) {
1606     case kDocumentNode:
1607       exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
1608                                         "The node provided is of type '" +
1609                                             source->nodeName() +
1610                                             "', which may not be adopted.");
1611       return nullptr;
1612     case kAttributeNode: {
1613       auto* attr = To<Attr>(source);
1614       if (Element* owner_element = attr->ownerElement())
1615         owner_element->removeAttributeNode(attr, exception_state);
1616       break;
1617     }
1618     default:
1619       if (source->IsShadowRoot()) {
1620         // ShadowRoot cannot disconnect itself from the host node.
1621         exception_state.ThrowDOMException(
1622             DOMExceptionCode::kHierarchyRequestError,
1623             "The node provided is a shadow root, which may not be adopted.");
1624         return nullptr;
1625       }
1626 
1627       if (auto* frame_owner_element =
1628               DynamicTo<HTMLFrameOwnerElement>(source)) {
1629         if (GetFrame() && GetFrame()->Tree().IsDescendantOf(
1630                               frame_owner_element->ContentFrame())) {
1631           exception_state.ThrowDOMException(
1632               DOMExceptionCode::kHierarchyRequestError,
1633               "The node provided is a frame which contains this document.");
1634           return nullptr;
1635         }
1636       }
1637       if (source->parentNode()) {
1638         source->parentNode()->RemoveChild(source, exception_state);
1639         if (exception_state.HadException())
1640           return nullptr;
1641         // The above removeChild() can execute arbitrary JavaScript code.
1642         if (source->parentNode()) {
1643           AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
1644               mojom::ConsoleMessageSource::kJavaScript,
1645               mojom::ConsoleMessageLevel::kWarning,
1646               ExceptionMessages::FailedToExecute("adoptNode", "Document",
1647                                                  "Unable to remove the "
1648                                                  "specified node from the "
1649                                                  "original parent.")));
1650           return nullptr;
1651         }
1652       }
1653   }
1654 
1655   AdoptIfNeeded(*source);
1656 
1657   return source;
1658 }
1659 
HasValidNamespaceForElements(const QualifiedName & q_name)1660 bool Document::HasValidNamespaceForElements(const QualifiedName& q_name) {
1661   // These checks are from DOM Core Level 2, createElementNS
1662   // http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-DocCrElNS
1663   // createElementNS(null, "html:div")
1664   if (!q_name.Prefix().IsEmpty() && q_name.NamespaceURI().IsNull())
1665     return false;
1666   // createElementNS("http://www.example.com", "xml:lang")
1667   if (q_name.Prefix() == g_xml_atom &&
1668       q_name.NamespaceURI() != xml_names::kNamespaceURI)
1669     return false;
1670 
1671   // Required by DOM Level 3 Core and unspecified by DOM Level 2 Core:
1672   // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-DocCrElNS
1673   // createElementNS("http://www.w3.org/2000/xmlns/", "foo:bar"),
1674   // createElementNS(null, "xmlns:bar"), createElementNS(null, "xmlns")
1675   if (q_name.Prefix() == g_xmlns_atom ||
1676       (q_name.Prefix().IsEmpty() && q_name.LocalName() == g_xmlns_atom))
1677     return q_name.NamespaceURI() == xmlns_names::kNamespaceURI;
1678   return q_name.NamespaceURI() != xmlns_names::kNamespaceURI;
1679 }
1680 
HasValidNamespaceForAttributes(const QualifiedName & q_name)1681 bool Document::HasValidNamespaceForAttributes(const QualifiedName& q_name) {
1682   return HasValidNamespaceForElements(q_name);
1683 }
1684 
readyState() const1685 String Document::readyState() const {
1686   DEFINE_STATIC_LOCAL(const String, loading, ("loading"));
1687   DEFINE_STATIC_LOCAL(const String, interactive, ("interactive"));
1688   DEFINE_STATIC_LOCAL(const String, complete, ("complete"));
1689 
1690   switch (ready_state_) {
1691     case kLoading:
1692       return loading;
1693     case kInteractive:
1694       return interactive;
1695     case kComplete:
1696       return complete;
1697   }
1698 
1699   NOTREACHED();
1700   return String();
1701 }
1702 
SetReadyState(DocumentReadyState ready_state)1703 void Document::SetReadyState(DocumentReadyState ready_state) {
1704   if (ready_state == ready_state_)
1705     return;
1706 
1707   switch (ready_state) {
1708     case kLoading:
1709       if (document_timing_.DomLoading().is_null()) {
1710         document_timing_.MarkDomLoading();
1711       }
1712       break;
1713     case kInteractive:
1714       if (document_timing_.DomInteractive().is_null())
1715         document_timing_.MarkDomInteractive();
1716       break;
1717     case kComplete:
1718       if (document_timing_.DomComplete().is_null())
1719         document_timing_.MarkDomComplete();
1720       break;
1721   }
1722 
1723   ready_state_ = ready_state;
1724   DispatchEvent(*Event::Create(event_type_names::kReadystatechange));
1725 }
1726 
IsLoadCompleted() const1727 bool Document::IsLoadCompleted() const {
1728   return ready_state_ == kComplete;
1729 }
1730 
EncodingName() const1731 AtomicString Document::EncodingName() const {
1732   // TextEncoding::name() returns a char*, no need to allocate a new
1733   // String for it each time.
1734   // FIXME: We should fix TextEncoding to speak AtomicString anyway.
1735   return AtomicString(Encoding().GetName());
1736 }
1737 
SetContentLanguage(const AtomicString & language)1738 void Document::SetContentLanguage(const AtomicString& language) {
1739   if (content_language_ == language)
1740     return;
1741   content_language_ = language;
1742 
1743   // Document's style depends on the content language.
1744   GetStyleEngine().MarkViewportStyleDirty();
1745   GetStyleEngine().MarkAllElementsForStyleRecalc(
1746       StyleChangeReasonForTracing::Create(style_change_reason::kLanguage));
1747 }
1748 
setXMLVersion(const String & version,ExceptionState & exception_state)1749 void Document::setXMLVersion(const String& version,
1750                              ExceptionState& exception_state) {
1751   if (!XMLDocumentParser::SupportsXMLVersion(version)) {
1752     exception_state.ThrowDOMException(
1753         DOMExceptionCode::kNotSupportedError,
1754         "This document does not support the XML version '" + version + "'.");
1755     return;
1756   }
1757 
1758   xml_version_ = version;
1759 }
1760 
setXMLStandalone(bool standalone,ExceptionState & exception_state)1761 void Document::setXMLStandalone(bool standalone,
1762                                 ExceptionState& exception_state) {
1763   xml_standalone_ = standalone ? kStandalone : kNotStandalone;
1764 }
1765 
SetContent(const String & content)1766 void Document::SetContent(const String& content) {
1767   // Only set the content of the document if it is ready to be set. This method
1768   // could be called at any time.
1769   if (ScriptableDocumentParser* parser = GetScriptableDocumentParser()) {
1770     if (parser->IsParsing() && parser->IsExecutingScript())
1771       return;
1772   }
1773   if (ignore_opens_during_unload_count_)
1774     return;
1775 
1776   open();
1777   parser_->Append(content);
1778   close();
1779 }
1780 
SuggestedMIMEType() const1781 String Document::SuggestedMIMEType() const {
1782   if (IsA<XMLDocument>(this)) {
1783     if (IsXHTMLDocument())
1784       return "application/xhtml+xml";
1785     if (IsSVGDocument())
1786       return "image/svg+xml";
1787     return "application/xml";
1788   }
1789   if (xmlStandalone())
1790     return "text/xml";
1791   if (IsA<HTMLDocument>(this))
1792     return "text/html";
1793 
1794   if (DocumentLoader* document_loader = Loader())
1795     return document_loader->MimeType();
1796   return String();
1797 }
1798 
SetMimeType(const AtomicString & mime_type)1799 void Document::SetMimeType(const AtomicString& mime_type) {
1800   mime_type_ = mime_type;
1801 }
1802 
contentType() const1803 AtomicString Document::contentType() const {
1804   if (!mime_type_.IsEmpty())
1805     return mime_type_;
1806 
1807   if (DocumentLoader* document_loader = Loader())
1808     return document_loader->MimeType();
1809 
1810   String mime_type = SuggestedMIMEType();
1811   if (!mime_type.IsEmpty())
1812     return AtomicString(mime_type);
1813 
1814   return AtomicString("application/xml");
1815 }
1816 
ElementFromPoint(double x,double y) const1817 Element* Document::ElementFromPoint(double x, double y) const {
1818   if (!GetLayoutView())
1819     return nullptr;
1820 
1821   return TreeScope::ElementFromPoint(x, y);
1822 }
1823 
ElementsFromPoint(double x,double y) const1824 HeapVector<Member<Element>> Document::ElementsFromPoint(double x,
1825                                                         double y) const {
1826   if (!GetLayoutView())
1827     return HeapVector<Member<Element>>();
1828   return TreeScope::ElementsFromPoint(x, y);
1829 }
1830 
caretRangeFromPoint(int x,int y)1831 Range* Document::caretRangeFromPoint(int x, int y) {
1832   if (!GetLayoutView())
1833     return nullptr;
1834 
1835   HitTestResult result = HitTestInDocument(this, x, y);
1836   PositionWithAffinity position_with_affinity = result.GetPosition();
1837   if (position_with_affinity.IsNull())
1838     return nullptr;
1839 
1840   Position range_compliant_position =
1841       position_with_affinity.GetPosition().ParentAnchoredEquivalent();
1842   return CreateRangeAdjustedToTreeScope(*this, range_compliant_position);
1843 }
1844 
scrollingElement()1845 Element* Document::scrollingElement() {
1846   if (RuntimeEnabledFeatures::ScrollTopLeftInteropEnabled() && InQuirksMode())
1847     UpdateStyleAndLayoutTree();
1848   return ScrollingElementNoLayout();
1849 }
1850 
ScrollingElementNoLayout()1851 Element* Document::ScrollingElementNoLayout() {
1852   if (RuntimeEnabledFeatures::ScrollTopLeftInteropEnabled()) {
1853     if (InQuirksMode()) {
1854       DCHECK(!IsActive() ||
1855              lifecycle_.GetState() >= DocumentLifecycle::kStyleClean);
1856       HTMLBodyElement* body = FirstBodyElement();
1857       if (body && body->GetLayoutObject() &&
1858           body->GetLayoutObject()->HasOverflowClip())
1859         return nullptr;
1860 
1861       return body;
1862     }
1863 
1864     return documentElement();
1865   }
1866 
1867   return body();
1868 }
1869 
1870 /*
1871  * Performs three operations:
1872  *  1. Convert control characters to spaces
1873  *  2. Trim leading and trailing spaces
1874  *  3. Collapse internal whitespace.
1875  */
1876 template <typename CharacterType>
CanonicalizedTitle(Document * document,const String & title)1877 static inline String CanonicalizedTitle(Document* document,
1878                                         const String& title) {
1879   unsigned length = title.length();
1880   unsigned builder_index = 0;
1881   const CharacterType* characters = title.GetCharacters<CharacterType>();
1882 
1883   StringBuffer<CharacterType> buffer(length);
1884 
1885   // Replace control characters with spaces and collapse whitespace.
1886   bool pending_whitespace = false;
1887   for (unsigned i = 0; i < length; ++i) {
1888     UChar32 c = characters[i];
1889     if ((c <= WTF::unicode::kSpaceCharacter &&
1890          c != WTF::unicode::kLineTabulationCharacter) ||
1891         c == WTF::unicode::kDeleteCharacter) {
1892       if (builder_index != 0)
1893         pending_whitespace = true;
1894     } else {
1895       if (pending_whitespace) {
1896         buffer[builder_index++] = ' ';
1897         pending_whitespace = false;
1898       }
1899       buffer[builder_index++] = c;
1900     }
1901   }
1902   buffer.Shrink(builder_index);
1903 
1904   return String::Adopt(buffer);
1905 }
1906 
UpdateTitle(const String & title)1907 void Document::UpdateTitle(const String& title) {
1908   if (raw_title_ == title)
1909     return;
1910 
1911   raw_title_ = title;
1912 
1913   String old_title = title_;
1914   if (raw_title_.IsEmpty())
1915     title_ = String();
1916   else if (raw_title_.Is8Bit())
1917     title_ = CanonicalizedTitle<LChar>(this, raw_title_);
1918   else
1919     title_ = CanonicalizedTitle<UChar>(this, raw_title_);
1920 
1921   if (!frame_ || old_title == title_)
1922     return;
1923   DispatchDidReceiveTitle();
1924 
1925   if (AXObjectCache* cache = ExistingAXObjectCache())
1926     cache->DocumentTitleChanged();
1927 }
1928 
DispatchDidReceiveTitle()1929 void Document::DispatchDidReceiveTitle() {
1930   if (GetFrame() && !GetFrame()->Tree().Parent()) {
1931     String shortened_title = title_.Substring(0, mojom::blink::kMaxTitleChars);
1932     GetFrame()->GetLocalFrameHostRemote().UpdateTitle(
1933         shortened_title, mojo_base::mojom::blink::TextDirection::LEFT_TO_RIGHT);
1934   }
1935   frame_->Client()->DispatchDidReceiveTitle(title_);
1936 }
1937 
setTitle(const String & title)1938 void Document::setTitle(const String& title) {
1939   // Title set by JavaScript -- overrides any title elements.
1940   Element* element = documentElement();
1941   if (IsA<SVGSVGElement>(element)) {
1942     if (!title_element_) {
1943       title_element_ = MakeGarbageCollected<SVGTitleElement>(*this);
1944       element->InsertBefore(title_element_.Get(), element->firstChild());
1945     }
1946     if (auto* svg_title = DynamicTo<SVGTitleElement>(title_element_.Get()))
1947       svg_title->SetText(title);
1948   } else if (element && element->IsHTMLElement()) {
1949     if (!title_element_) {
1950       HTMLElement* head_element = head();
1951       if (!head_element)
1952         return;
1953       title_element_ = MakeGarbageCollected<HTMLTitleElement>(*this);
1954       head_element->AppendChild(title_element_.Get());
1955     }
1956     if (auto* html_title = DynamicTo<HTMLTitleElement>(title_element_.Get()))
1957       html_title->setText(title);
1958   }
1959 }
1960 
SetTitleElement(Element * title_element)1961 void Document::SetTitleElement(Element* title_element) {
1962   // If the root element is an svg element in the SVG namespace, then let value
1963   // be the child text content of the first title element in the SVG namespace
1964   // that is a child of the root element.
1965   if (IsA<SVGSVGElement>(documentElement())) {
1966     title_element_ = Traversal<SVGTitleElement>::FirstChild(*documentElement());
1967   } else {
1968     if (title_element_ && title_element_ != title_element)
1969       title_element_ = Traversal<HTMLTitleElement>::FirstWithin(*this);
1970     else
1971       title_element_ = title_element;
1972 
1973     // If the root element isn't an svg element in the SVG namespace and the
1974     // title element is in the SVG namespace, it is ignored.
1975     if (IsA<SVGTitleElement>(*title_element_)) {
1976       title_element_ = nullptr;
1977       return;
1978     }
1979   }
1980 
1981   if (auto* html_title = DynamicTo<HTMLTitleElement>(title_element_.Get()))
1982     UpdateTitle(html_title->text());
1983   else if (auto* svg_title = DynamicTo<SVGTitleElement>(title_element_.Get()))
1984     UpdateTitle(svg_title->textContent());
1985 }
1986 
RemoveTitle(Element * title_element)1987 void Document::RemoveTitle(Element* title_element) {
1988   if (title_element_ != title_element)
1989     return;
1990 
1991   title_element_ = nullptr;
1992 
1993   // Update title based on first title element in the document, if one exists.
1994   if (IsA<HTMLDocument>(this) || IsXHTMLDocument()) {
1995     if (HTMLTitleElement* title =
1996             Traversal<HTMLTitleElement>::FirstWithin(*this))
1997       SetTitleElement(title);
1998   } else if (IsSVGDocument()) {
1999     if (SVGTitleElement* title = Traversal<SVGTitleElement>::FirstWithin(*this))
2000       SetTitleElement(title);
2001   }
2002 
2003   if (!title_element_)
2004     UpdateTitle(String());
2005 }
2006 
dir()2007 const AtomicString& Document::dir() {
2008   Element* root_element = documentElement();
2009   if (auto* html = DynamicTo<HTMLHtmlElement>(root_element))
2010     return html->dir();
2011   return g_null_atom;
2012 }
2013 
setDir(const AtomicString & value)2014 void Document::setDir(const AtomicString& value) {
2015   Element* root_element = documentElement();
2016   if (auto* html = DynamicTo<HTMLHtmlElement>(root_element))
2017     html->setDir(value);
2018 }
2019 
IsPageVisible() const2020 bool Document::IsPageVisible() const {
2021   // The visibility of the document is inherited from the visibility of the
2022   // page. If there is no page associated with the document, we will assume
2023   // that the page is hidden, as specified by the spec:
2024   // https://w3c.github.io/page-visibility/#hidden-attribute
2025   if (!frame_ || !frame_->GetPage())
2026     return false;
2027   // While visibilitychange is being dispatched during unloading it is
2028   // expected that the visibility is hidden regardless of the page's
2029   // visibility.
2030   if (load_event_progress_ >= kUnloadVisibilityChangeInProgress)
2031     return false;
2032   return frame_->GetPage()->IsPageVisible();
2033 }
2034 
IsPrefetchOnly() const2035 bool Document::IsPrefetchOnly() const {
2036   if (!frame_ || !frame_->GetPage())
2037     return false;
2038 
2039   PrerendererClient* prerenderer_client =
2040       PrerendererClient::From(frame_->GetPage());
2041   return prerenderer_client && prerenderer_client->IsPrefetchOnly();
2042 }
2043 
visibilityState() const2044 String Document::visibilityState() const {
2045   return PageHiddenStateString(hidden());
2046 }
2047 
hidden() const2048 bool Document::hidden() const {
2049   return !IsPageVisible();
2050 }
2051 
wasDiscarded() const2052 bool Document::wasDiscarded() const {
2053   return was_discarded_;
2054 }
2055 
SetWasDiscarded(bool was_discarded)2056 void Document::SetWasDiscarded(bool was_discarded) {
2057   was_discarded_ = was_discarded;
2058 }
2059 
DidChangeVisibilityState()2060 void Document::DidChangeVisibilityState() {
2061   DispatchEvent(*Event::CreateBubble(event_type_names::kVisibilitychange));
2062   // Also send out the deprecated version until it can be removed.
2063   DispatchEvent(
2064       *Event::CreateBubble(event_type_names::kWebkitvisibilitychange));
2065 
2066   if (IsPageVisible())
2067     Timeline().SetAllCompositorPending();
2068 
2069   if (hidden() && canvas_font_cache_)
2070     canvas_font_cache_->PruneAll();
2071 
2072   InteractiveDetector* interactive_detector = InteractiveDetector::From(*this);
2073   if (interactive_detector) {
2074     interactive_detector->OnPageHiddenChanged(hidden());
2075   }
2076 }
2077 
nodeName() const2078 String Document::nodeName() const {
2079   return "#document";
2080 }
2081 
getNodeType() const2082 Node::NodeType Document::getNodeType() const {
2083   return kDocumentNode;
2084 }
2085 
GetFormController()2086 FormController& Document::GetFormController() {
2087   if (!form_controller_) {
2088     form_controller_ = MakeGarbageCollected<FormController>(*this);
2089     HistoryItem* history_item = Loader() ? Loader()->GetHistoryItem() : nullptr;
2090     if (history_item)
2091       history_item->SetDocumentState(form_controller_->ControlStates());
2092   }
2093   return *form_controller_;
2094 }
2095 
GetDocumentState() const2096 DocumentState* Document::GetDocumentState() const {
2097   if (!form_controller_)
2098     return nullptr;
2099   return form_controller_->ControlStates();
2100 }
2101 
SetStateForNewControls(const Vector<String> & state_vector)2102 void Document::SetStateForNewControls(const Vector<String>& state_vector) {
2103   if (!state_vector.size() && !form_controller_)
2104     return;
2105   GetFormController().SetStateForNewControls(state_vector);
2106 }
2107 
View() const2108 LocalFrameView* Document::View() const {
2109   return frame_ ? frame_->View() : nullptr;
2110 }
2111 
GetPage() const2112 Page* Document::GetPage() const {
2113   return frame_ ? frame_->GetPage() : nullptr;
2114 }
2115 
GetFrameOfMasterDocument() const2116 LocalFrame* Document::GetFrameOfMasterDocument() const {
2117   if (frame_)
2118     return frame_;
2119   if (imports_controller_)
2120     return imports_controller_->Master()->GetFrame();
2121   return nullptr;
2122 }
2123 
GetSettings() const2124 Settings* Document::GetSettings() const {
2125   return frame_ ? frame_->GetSettings() : nullptr;
2126 }
2127 
createRange()2128 Range* Document::createRange() {
2129   return Range::Create(*this);
2130 }
2131 
createNodeIterator(Node * root,unsigned what_to_show,V8NodeFilter * filter)2132 NodeIterator* Document::createNodeIterator(Node* root,
2133                                            unsigned what_to_show,
2134                                            V8NodeFilter* filter) {
2135   DCHECK(root);
2136   return MakeGarbageCollected<NodeIterator>(root, what_to_show, filter);
2137 }
2138 
createTreeWalker(Node * root,unsigned what_to_show,V8NodeFilter * filter)2139 TreeWalker* Document::createTreeWalker(Node* root,
2140                                        unsigned what_to_show,
2141                                        V8NodeFilter* filter) {
2142   DCHECK(root);
2143   return MakeGarbageCollected<TreeWalker>(root, what_to_show, filter);
2144 }
2145 
NeedsLayoutTreeUpdate() const2146 bool Document::NeedsLayoutTreeUpdate() const {
2147   if (!IsActive() || !View())
2148     return false;
2149   if (NeedsFullLayoutTreeUpdate())
2150     return true;
2151   if (style_engine_->NeedsStyleRecalc())
2152     return true;
2153   if (style_engine_->NeedsStyleInvalidation())
2154     return true;
2155   if (GetLayoutView() && GetLayoutView()->WasNotifiedOfSubtreeChange())
2156     return true;
2157   if (style_engine_->NeedsLayoutTreeRebuild()) {
2158     // TODO(futhark): there a couple of places where call back into the top
2159     // frame while recursively doing a lifecycle update. One of them are for the
2160     // RootScrollerController. These should probably be post layout tasks and
2161     // make this test unnecessary since the layout tree rebuild dirtiness is
2162     // internal to StyleEngine::UpdateStyleAndLayoutTree().
2163     DCHECK(InStyleRecalc());
2164     return true;
2165   }
2166   return false;
2167 }
2168 
NeedsFullLayoutTreeUpdate() const2169 bool Document::NeedsFullLayoutTreeUpdate() const {
2170   // This method returns true if we cannot decide which specific elements need
2171   // to have its style or layout tree updated on the next lifecycle update. If
2172   // this method returns false, we typically use that to walk up the ancestor
2173   // chain to decide if we can let getComputedStyle() use the current
2174   // ComputedStyle without doing the lifecycle update (implemented in
2175   // Document::NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked()).
2176   if (!IsActive() || !View())
2177     return false;
2178   if (style_engine_->NeedsFullStyleUpdate())
2179     return true;
2180   if (!use_elements_needing_update_.IsEmpty())
2181     return true;
2182   // We have scheduled an invalidation set on the document node which means any
2183   // element may need a style recalc.
2184   if (NeedsStyleInvalidation())
2185     return true;
2186   if (IsSlotAssignmentOrLegacyDistributionDirty())
2187     return true;
2188   if (document_animations_->NeedsAnimationTimingUpdate())
2189     return true;
2190   return false;
2191 }
2192 
ShouldScheduleLayoutTreeUpdate() const2193 bool Document::ShouldScheduleLayoutTreeUpdate() const {
2194   if (!IsActive())
2195     return false;
2196   if (InStyleRecalc())
2197     return false;
2198   // InPreLayout will recalc style itself. There's no reason to schedule another
2199   // recalc.
2200   if (lifecycle_.GetState() == DocumentLifecycle::kInPreLayout)
2201     return false;
2202   if (!ShouldScheduleLayout())
2203     return false;
2204   return true;
2205 }
2206 
ScheduleLayoutTreeUpdate()2207 void Document::ScheduleLayoutTreeUpdate() {
2208   DCHECK(!HasPendingVisualUpdate());
2209   DCHECK(ShouldScheduleLayoutTreeUpdate());
2210   DCHECK(NeedsLayoutTreeUpdate());
2211 
2212   if (!View()->CanThrottleRendering())
2213     GetPage()->Animator().ScheduleVisualUpdate(GetFrame());
2214 
2215   // FrameSelection caches visual selection information, which must be
2216   // invalidated on dirty layout tree.
2217   GetFrame()->Selection().MarkCacheDirty();
2218 
2219   lifecycle_.EnsureStateAtMost(DocumentLifecycle::kVisualUpdatePending);
2220 
2221   TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
2222                        "ScheduleStyleRecalculation", TRACE_EVENT_SCOPE_THREAD,
2223                        "data",
2224                        inspector_recalculate_styles_event::Data(GetFrame()));
2225   ++style_version_;
2226 }
2227 
HasPendingForcedStyleRecalc() const2228 bool Document::HasPendingForcedStyleRecalc() const {
2229   return HasPendingVisualUpdate() && !InStyleRecalc() &&
2230          GetStyleChangeType() == kSubtreeStyleChange;
2231 }
2232 
UpdateStyleInvalidationIfNeeded()2233 void Document::UpdateStyleInvalidationIfNeeded() {
2234   DCHECK(IsActive());
2235   ScriptForbiddenScope forbid_script;
2236 
2237   if (!GetStyleEngine().NeedsStyleInvalidation())
2238     return;
2239   TRACE_EVENT0("blink", "Document::updateStyleInvalidationIfNeeded");
2240   SCOPED_BLINK_UMA_HISTOGRAM_TIMER_HIGHRES("Style.InvalidationTime");
2241   GetStyleEngine().InvalidateStyle();
2242 }
2243 
SetupFontBuilder(ComputedStyle & document_style)2244 void Document::SetupFontBuilder(ComputedStyle& document_style) {
2245   FontBuilder font_builder(this);
2246   font_builder.CreateFontForDocument(document_style);
2247 }
2248 
2249 #define PROPAGATE_FROM(source, getter, setter, initial) \
2250   PROPAGATE_VALUE(source ? source->getter() : initial, getter, setter);
2251 
2252 #define PROPAGATE_VALUE(value, getter, setter)     \
2253   if ((new_viewport_style->getter()) != (value)) { \
2254     new_viewport_style->setter(value);             \
2255     changed = true;                                \
2256   }
2257 
PropagateScrollSnapStyleToViewport(Document & document,const ComputedStyle * document_element_style,scoped_refptr<ComputedStyle> new_viewport_style)2258 bool PropagateScrollSnapStyleToViewport(
2259     Document& document,
2260     const ComputedStyle* document_element_style,
2261     scoped_refptr<ComputedStyle> new_viewport_style) {
2262   bool changed = false;
2263   // We only propagate the properties related to snap container since viewport
2264   // defining element cannot be a snap area.
2265   PROPAGATE_FROM(document_element_style, GetScrollSnapType, SetScrollSnapType,
2266                  cc::ScrollSnapType());
2267   PROPAGATE_FROM(document_element_style, ScrollPaddingTop, SetScrollPaddingTop,
2268                  Length());
2269   PROPAGATE_FROM(document_element_style, ScrollPaddingRight,
2270                  SetScrollPaddingRight, Length());
2271   PROPAGATE_FROM(document_element_style, ScrollPaddingBottom,
2272                  SetScrollPaddingBottom, Length());
2273   PROPAGATE_FROM(document_element_style, ScrollPaddingLeft,
2274                  SetScrollPaddingLeft, Length());
2275 
2276   if (changed) {
2277     document.GetSnapCoordinator().SnapContainerDidChange(
2278         *document.GetLayoutView());
2279   }
2280 
2281   return changed;
2282 }
2283 
PropagateStyleToViewport()2284 void Document::PropagateStyleToViewport() {
2285   DCHECK(InStyleRecalc());
2286   HTMLElement* body = this->body();
2287   Element* document_element = this->documentElement();
2288 
2289   const ComputedStyle* document_element_style =
2290       document_element && documentElement()->GetLayoutObject()
2291           ? documentElement()->GetComputedStyle()
2292           : nullptr;
2293   const ComputedStyle* body_style =
2294       body && body->GetLayoutObject() ? body->GetComputedStyle() : nullptr;
2295 
2296   const ComputedStyle& viewport_style = GetLayoutView()->StyleRef();
2297   scoped_refptr<ComputedStyle> new_viewport_style =
2298       ComputedStyle::Clone(viewport_style);
2299   bool changed = false;
2300   bool update_scrollbar_style = false;
2301 
2302   // Writing mode and direction
2303   {
2304     const ComputedStyle* direction_style =
2305         body_style ? body_style : document_element_style;
2306     PROPAGATE_FROM(direction_style, GetWritingMode, SetWritingMode,
2307                    WritingMode::kHorizontalTb);
2308     PROPAGATE_FROM(direction_style, Direction, SetDirection,
2309                    TextDirection::kLtr);
2310   }
2311 
2312   // Background
2313   {
2314     const ComputedStyle* background_style = document_element_style;
2315     // http://www.w3.org/TR/css3-background/#body-background
2316     // <html> root element with no background steals background from its first
2317     // <body> child.
2318     // Also see LayoutBoxModelObject::BackgroundTransfersToView()
2319     if (body_style && IsA<HTMLHtmlElement>(documentElement()) &&
2320         IsA<HTMLBodyElement>(body) && !background_style->HasBackground()) {
2321       background_style = body_style;
2322     }
2323 
2324     Color background_color = Color::kTransparent;
2325     FillLayer background_layers(EFillLayerType::kBackground, true);
2326     EImageRendering image_rendering = EImageRendering::kAuto;
2327 
2328     if (background_style) {
2329       background_color = background_style->VisitedDependentColor(
2330           GetCSSPropertyBackgroundColor());
2331       background_layers = background_style->BackgroundLayers();
2332       for (auto* current_layer = &background_layers; current_layer;
2333            current_layer = current_layer->Next()) {
2334         // http://www.w3.org/TR/css3-background/#root-background
2335         // The root element background always have painting area of the whole
2336         // canvas.
2337         current_layer->SetClip(EFillBox::kBorder);
2338 
2339         // The root element doesn't scroll. It always propagates its layout
2340         // overflow to the viewport. Positioning background against either box
2341         // is equivalent to positioning against the scrolled box of the
2342         // viewport.
2343         if (current_layer->Attachment() == EFillAttachment::kScroll)
2344           current_layer->SetAttachment(EFillAttachment::kLocal);
2345       }
2346       image_rendering = background_style->ImageRendering();
2347     }
2348 
2349     if (viewport_style.VisitedDependentColor(GetCSSPropertyBackgroundColor()) !=
2350             background_color ||
2351         viewport_style.BackgroundLayers() != background_layers ||
2352         viewport_style.ImageRendering() != image_rendering) {
2353       changed = true;
2354       new_viewport_style->SetBackgroundColor(background_color);
2355       new_viewport_style->AccessBackgroundLayers() = background_layers;
2356       new_viewport_style->SetImageRendering(image_rendering);
2357     }
2358   }
2359 
2360   // Overflow
2361   {
2362     const ComputedStyle* overflow_style = nullptr;
2363     if (Element* viewport_element = ViewportDefiningElement()) {
2364       if (viewport_element == body) {
2365         overflow_style = body_style;
2366       } else {
2367         DCHECK_EQ(viewport_element, documentElement());
2368         overflow_style = document_element_style;
2369 
2370         // The body element has its own scrolling box, independent from the
2371         // viewport.  This is a bit of a weird edge case in the CSS spec that we
2372         // might want to try to eliminate some day (eg. for ScrollTopLeftInterop
2373         // - see http://crbug.com/157855).
2374         if (body_style && !body_style->IsOverflowVisible()) {
2375           UseCounter::Count(*this,
2376                             WebFeature::kBodyScrollsInAdditionToViewport);
2377         }
2378       }
2379     }
2380 
2381     // TODO(954423, 952711): overscroll-behavior (and most likely
2382     // overflow-anchor) should be propagated from the document element and not
2383     // the viewport defining element.
2384     PROPAGATE_FROM(overflow_style, OverscrollBehaviorX, SetOverscrollBehaviorX,
2385                    EOverscrollBehavior::kAuto);
2386     PROPAGATE_FROM(overflow_style, OverscrollBehaviorY, SetOverscrollBehaviorY,
2387                    EOverscrollBehavior::kAuto);
2388 
2389     // Counts any time scroll snapping and scroll padding break if we change its
2390     // viewport propagation logic. Scroll snapping only breaks if body has
2391     // non-none snap type that is different from the document one.
2392     // TODO(952711): Remove once propagation logic change is complete.
2393     if (document_element_style && body_style) {
2394       bool snap_type_is_different =
2395           !body_style->GetScrollSnapType().is_none &&
2396           (body_style->GetScrollSnapType() !=
2397            document_element_style->GetScrollSnapType());
2398       bool scroll_padding_is_different =
2399           body_style->ScrollPaddingTop() !=
2400               document_element_style->ScrollPaddingTop() ||
2401           body_style->ScrollPaddingBottom() !=
2402               document_element_style->ScrollPaddingBottom() ||
2403           body_style->ScrollPaddingLeft() !=
2404               document_element_style->ScrollPaddingLeft() ||
2405           body_style->ScrollPaddingRight() !=
2406               document_element_style->ScrollPaddingRight();
2407 
2408       if (snap_type_is_different) {
2409         UseCounter::Count(*this, WebFeature::kScrollSnapOnViewportBreaks);
2410       }
2411       if (scroll_padding_is_different) {
2412         UseCounter::Count(*this, WebFeature::kScrollPaddingOnViewportBreaks);
2413       }
2414     }
2415 
2416     EOverflow overflow_x = EOverflow::kAuto;
2417     EOverflow overflow_y = EOverflow::kAuto;
2418     EOverflowAnchor overflow_anchor = EOverflowAnchor::kAuto;
2419 
2420     if (overflow_style) {
2421       overflow_x = overflow_style->OverflowX();
2422       overflow_y = overflow_style->OverflowY();
2423       overflow_anchor = overflow_style->OverflowAnchor();
2424       // Visible overflow on the viewport is meaningless, and the spec says to
2425       // treat it as 'auto':
2426       if (overflow_x == EOverflow::kVisible)
2427         overflow_x = EOverflow::kAuto;
2428       if (overflow_y == EOverflow::kVisible)
2429         overflow_y = EOverflow::kAuto;
2430       if (overflow_anchor == EOverflowAnchor::kVisible)
2431         overflow_anchor = EOverflowAnchor::kAuto;
2432 
2433       if (IsInMainFrame()) {
2434         using OverscrollBehaviorType =
2435             cc::OverscrollBehavior::OverscrollBehaviorType;
2436         GetPage()->GetChromeClient().SetOverscrollBehavior(
2437             *GetFrame(),
2438             cc::OverscrollBehavior(static_cast<OverscrollBehaviorType>(
2439                                        overflow_style->OverscrollBehaviorX()),
2440                                    static_cast<OverscrollBehaviorType>(
2441                                        overflow_style->OverscrollBehaviorY())));
2442       }
2443 
2444       if (overflow_style->HasPseudoElementStyle(kPseudoIdScrollbar))
2445         update_scrollbar_style = true;
2446     }
2447 
2448     PROPAGATE_VALUE(overflow_x, OverflowX, SetOverflowX)
2449     PROPAGATE_VALUE(overflow_y, OverflowY, SetOverflowY)
2450     PROPAGATE_VALUE(overflow_anchor, OverflowAnchor, SetOverflowAnchor);
2451   }
2452 
2453   // Misc
2454   {
2455     PROPAGATE_FROM(document_element_style, GetEffectiveTouchAction,
2456                    SetEffectiveTouchAction, TouchAction::kAuto);
2457     PROPAGATE_FROM(document_element_style, GetScrollBehavior, SetScrollBehavior,
2458                    mojom::blink::ScrollBehavior::kAuto);
2459     PROPAGATE_FROM(document_element_style, DarkColorScheme, SetDarkColorScheme,
2460                    false);
2461   }
2462 
2463   changed |= PropagateScrollSnapStyleToViewport(*this, document_element_style,
2464                                                 new_viewport_style);
2465 
2466   if (changed) {
2467     new_viewport_style->UpdateFontOrientation();
2468     GetLayoutView()->SetStyle(new_viewport_style);
2469     SetupFontBuilder(*new_viewport_style);
2470   }
2471 
2472   if (changed || update_scrollbar_style) {
2473     if (PaintLayerScrollableArea* scrollable_area =
2474             GetLayoutView()->GetScrollableArea()) {
2475       if (scrollable_area->HorizontalScrollbar() &&
2476           scrollable_area->HorizontalScrollbar()->IsCustomScrollbar())
2477         scrollable_area->HorizontalScrollbar()->StyleChanged();
2478       if (scrollable_area->VerticalScrollbar() &&
2479           scrollable_area->VerticalScrollbar()->IsCustomScrollbar())
2480         scrollable_area->VerticalScrollbar()->StyleChanged();
2481     }
2482   }
2483 }
2484 #undef PROPAGATE_VALUE
2485 #undef PROPAGATE_FROM
2486 
2487 #if DCHECK_IS_ON()
AssertNodeClean(const Node & node)2488 static void AssertNodeClean(const Node& node) {
2489   DCHECK(!node.NeedsStyleRecalc());
2490   DCHECK(!node.ChildNeedsStyleRecalc());
2491   DCHECK(!node.NeedsReattachLayoutTree());
2492   DCHECK(!node.ChildNeedsReattachLayoutTree());
2493   DCHECK(!node.ChildNeedsDistributionRecalc());
2494   DCHECK(!node.NeedsStyleInvalidation());
2495   DCHECK(!node.ChildNeedsStyleInvalidation());
2496   DCHECK(!node.GetForceReattachLayoutTree());
2497 }
2498 
AssertLayoutTreeUpdatedForPseudoElements(const Element & element)2499 static void AssertLayoutTreeUpdatedForPseudoElements(const Element& element) {
2500   WTF::Vector<PseudoId> pseudo_ids = {kPseudoIdFirstLetter, kPseudoIdBefore,
2501                                       kPseudoIdAfter, kPseudoIdMarker,
2502                                       kPseudoIdBackdrop};
2503   for (auto pseudo_id : pseudo_ids) {
2504     if (auto* pseudo_element = element.GetPseudoElement(pseudo_id))
2505       AssertNodeClean(*pseudo_element);
2506   }
2507 }
2508 
AssertLayoutTreeUpdated(Node & root)2509 static void AssertLayoutTreeUpdated(Node& root) {
2510   Node* node = &root;
2511   while (node) {
2512     if (auto* element = DynamicTo<Element>(node)) {
2513       if (RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() &&
2514           element->StyleRecalcBlockedByDisplayLock(
2515               DisplayLockLifecycleTarget::kChildren)) {
2516         node = FlatTreeTraversal::NextSkippingChildren(*node);
2517         continue;
2518       }
2519       // Check pseudo elements.
2520       AssertLayoutTreeUpdatedForPseudoElements(*element);
2521     }
2522 
2523     AssertNodeClean(*node);
2524 
2525     // Make sure there is no node which has a LayoutObject, but doesn't have a
2526     // parent in a flat tree. If there is such a node, we forgot to detach the
2527     // node. DocumentNode is only an exception.
2528     DCHECK((node->IsDocumentNode() || !node->GetLayoutObject() ||
2529             FlatTreeTraversal::Parent(*node)))
2530         << *node;
2531 
2532     node = FlatTreeTraversal::Next(*node);
2533   }
2534 }
2535 #endif
2536 
UpdateStyleAndLayoutTree()2537 void Document::UpdateStyleAndLayoutTree() {
2538   DCHECK(IsMainThread());
2539   if (Lifecycle().LifecyclePostponed())
2540     return;
2541 
2542   HTMLFrameOwnerElement::PluginDisposeSuspendScope suspend_plugin_dispose;
2543   ScriptForbiddenScope forbid_script;
2544 
2545   if (HTMLFrameOwnerElement* owner = LocalOwner()) {
2546     owner->GetDocument().UpdateStyleAndLayoutTree();
2547   }
2548 
2549   if (!View() || !IsActive())
2550     return;
2551 
2552   if (View()->ShouldThrottleRendering())
2553     return;
2554 
2555   // RecalcSlotAssignments should be done before checking
2556   // NeedsLayoutTreeUpdate().
2557   GetSlotAssignmentEngine().RecalcSlotAssignments();
2558 
2559   // We can call FlatTreeTraversal::AssertFlatTreeNodeDataUpdated just after
2560   // calling RecalcSlotAssignments(), however, it would be better to call it at
2561   // least after InStyleRecalc() check below in order to avoid superfluous
2562   // check, which would be the cause of web tests timeout when dcheck is on.
2563 
2564   SlotAssignmentRecalcForbiddenScope forbid_slot_recalc(*this);
2565 
2566   if (!NeedsLayoutTreeUpdate()) {
2567     if (Lifecycle().GetState() < DocumentLifecycle::kStyleClean) {
2568       // needsLayoutTreeUpdate may change to false without any actual layout
2569       // tree update.  For example, needsAnimationTimingUpdate may change to
2570       // false when time elapses.  Advance lifecycle to StyleClean because style
2571       // is actually clean now.
2572       Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc);
2573       Lifecycle().AdvanceTo(DocumentLifecycle::kStyleClean);
2574     }
2575     return;
2576   }
2577 
2578   if (InStyleRecalc())
2579     return;
2580 
2581 #if DCHECK_IS_ON()
2582   int assigned_nodes_in_slot_count = 0;
2583   int nodes_which_have_assigned_slot_count = 0;
2584   FlatTreeTraversal::AssertFlatTreeNodeDataUpdated(
2585       *this, assigned_nodes_in_slot_count,
2586       nodes_which_have_assigned_slot_count);
2587   DCHECK_EQ(assigned_nodes_in_slot_count, nodes_which_have_assigned_slot_count);
2588 #endif
2589 
2590   // Entering here from inside layout, paint etc. would be catastrophic since
2591   // recalcStyle can tear down the layout tree or (unfortunately) run
2592   // script. Kill the whole layoutObject if someone managed to get into here in
2593   // states not allowing tree mutations.
2594   CHECK(Lifecycle().StateAllowsTreeMutations());
2595 
2596   TRACE_EVENT_BEGIN1("blink,devtools.timeline", "UpdateLayoutTree", "beginData",
2597                      inspector_recalculate_styles_event::Data(GetFrame()));
2598 
2599   unsigned start_element_count = GetStyleEngine().StyleForElementCount();
2600 
2601   probe::RecalculateStyle recalculate_style_scope(this);
2602 
2603   document_animations_->UpdateAnimationTimingIfNeeded();
2604   EvaluateMediaQueryListIfNeeded();
2605   UpdateUseShadowTreesIfNeeded();
2606 
2607   UpdateDistributionForLegacyDistributedNodes();
2608 
2609   UpdateActiveStyle();
2610   InvalidateStyleAndLayoutForFontUpdates();
2611   UpdateStyleInvalidationIfNeeded();
2612   UpdateStyle();
2613 
2614   NotifyLayoutTreeOfSubtreeChanges();
2615 
2616   if (focused_element_ && !focused_element_->IsFocusable())
2617     ClearFocusedElementSoon();
2618   GetLayoutView()->ClearHitTestCache();
2619 
2620   DCHECK(!document_animations_->NeedsAnimationTimingUpdate());
2621 
2622   unsigned element_count =
2623       GetStyleEngine().StyleForElementCount() - start_element_count;
2624 
2625   TRACE_EVENT_END1("blink,devtools.timeline", "UpdateLayoutTree",
2626                    "elementCount", element_count);
2627 
2628 #if DCHECK_IS_ON()
2629   AssertLayoutTreeUpdated(*this);
2630 #endif
2631 }
2632 
UpdateActiveStyle()2633 void Document::UpdateActiveStyle() {
2634   DCHECK(IsActive());
2635   DCHECK(IsMainThread());
2636   TRACE_EVENT0("blink", "Document::updateActiveStyle");
2637   GetStyleEngine().UpdateActiveStyle();
2638 }
2639 
InvalidateStyleAndLayoutForFontUpdates()2640 void Document::InvalidateStyleAndLayoutForFontUpdates() {
2641   DCHECK(IsActive());
2642   DCHECK(IsMainThread());
2643   GetStyleEngine().InvalidateStyleAndLayoutForFontUpdates();
2644 }
2645 
UpdateStyle()2646 void Document::UpdateStyle() {
2647   DCHECK(!View()->ShouldThrottleRendering());
2648   TRACE_EVENT_BEGIN0("blink,blink_style", "Document::updateStyle");
2649   RUNTIME_CALL_TIMER_SCOPE(V8PerIsolateData::MainThreadIsolate(),
2650                            RuntimeCallStats::CounterId::kUpdateStyle);
2651 
2652   unsigned initial_element_count = GetStyleEngine().StyleForElementCount();
2653 
2654   lifecycle_.AdvanceTo(DocumentLifecycle::kInStyleRecalc);
2655 
2656   // SetNeedsStyleRecalc should only happen on Element and Text nodes.
2657   DCHECK(!NeedsStyleRecalc());
2658 
2659   StyleResolver& resolver = EnsureStyleResolver();
2660   bool should_record_stats;
2661   TRACE_EVENT_CATEGORY_GROUP_ENABLED("blink,blink_style", &should_record_stats);
2662   GetStyleEngine().SetStatsEnabled(should_record_stats);
2663 
2664   GetStyleEngine().UpdateStyleAndLayoutTree();
2665 
2666   ClearChildNeedsStyleRecalc();
2667 
2668   PropagateStyleToViewport();
2669 
2670   View()->UpdateCountersAfterStyleChange();
2671   GetLayoutView()->RecalcLayoutOverflow();
2672 
2673   DCHECK(!NeedsStyleRecalc());
2674   DCHECK(!ChildNeedsStyleRecalc());
2675   DCHECK(!NeedsReattachLayoutTree());
2676   DCHECK(!ChildNeedsReattachLayoutTree());
2677   DCHECK(InStyleRecalc());
2678   DCHECK_EQ(GetStyleResolver(), &resolver);
2679   lifecycle_.AdvanceTo(DocumentLifecycle::kStyleClean);
2680   if (should_record_stats) {
2681     TRACE_EVENT_END2(
2682         "blink,blink_style", "Document::updateStyle", "resolverAccessCount",
2683         GetStyleEngine().StyleForElementCount() - initial_element_count,
2684         "counters", GetStyleEngine().Stats()->ToTracedValue());
2685   } else {
2686     TRACE_EVENT_END1(
2687         "blink,blink_style", "Document::updateStyle", "resolverAccessCount",
2688         GetStyleEngine().StyleForElementCount() - initial_element_count);
2689   }
2690 }
2691 
NotifyLayoutTreeOfSubtreeChanges()2692 void Document::NotifyLayoutTreeOfSubtreeChanges() {
2693   if (!GetLayoutView()->WasNotifiedOfSubtreeChange())
2694     return;
2695 
2696   lifecycle_.AdvanceTo(DocumentLifecycle::kInLayoutSubtreeChange);
2697 
2698   GetLayoutView()->HandleSubtreeModifications();
2699   DCHECK(!GetLayoutView()->WasNotifiedOfSubtreeChange());
2700 
2701   lifecycle_.AdvanceTo(DocumentLifecycle::kLayoutSubtreeChangeClean);
2702 }
2703 
NeedsLayoutTreeUpdateForNode(const Node & node,bool ignore_adjacent_style) const2704 bool Document::NeedsLayoutTreeUpdateForNode(const Node& node,
2705                                             bool ignore_adjacent_style) const {
2706   // TODO(rakina): Switch some callers that may need to call
2707   // NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked instead of this.
2708   if (DisplayLockUtilities::NearestLockedExclusiveAncestor(node)) {
2709     // |node| is in a locked-subtree, so we don't need to update it.
2710     return false;
2711   }
2712   return NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked(
2713       node, ignore_adjacent_style);
2714 }
2715 
NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked(const Node & node,bool ignore_adjacent_style) const2716 bool Document::NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked(
2717     const Node& node,
2718     bool ignore_adjacent_style) const {
2719   if (!node.CanParticipateInFlatTree())
2720     return false;
2721   if (locked_display_lock_count_ == 0 && !NeedsLayoutTreeUpdate())
2722     return false;
2723   if (!node.isConnected())
2724     return false;
2725 
2726   if (NeedsFullLayoutTreeUpdate() || node.NeedsStyleRecalc() ||
2727       node.NeedsStyleInvalidation())
2728     return true;
2729   for (const ContainerNode* ancestor = LayoutTreeBuilderTraversal::Parent(node);
2730        ancestor; ancestor = LayoutTreeBuilderTraversal::Parent(*ancestor)) {
2731     if (ShadowRoot* root = ancestor->GetShadowRoot()) {
2732       if (root->NeedsStyleRecalc() || root->NeedsStyleInvalidation() ||
2733           root->NeedsAdjacentStyleRecalc()) {
2734         return true;
2735       }
2736     }
2737     if (ancestor->NeedsStyleRecalc() || ancestor->NeedsStyleInvalidation() ||
2738         (ancestor->NeedsAdjacentStyleRecalc() && !ignore_adjacent_style)) {
2739       return true;
2740     }
2741     auto* element = DynamicTo<Element>(ancestor);
2742     if (!element)
2743       continue;
2744     if (auto* context = element->GetDisplayLockContext()) {
2745       // Even if the ancestor is style-clean, we might've previously
2746       // blocked a style traversal going to the ancestor or its descendants.
2747       if (context->StyleTraversalWasBlocked()) {
2748         DCHECK(context->IsLocked());
2749         return true;
2750       }
2751     }
2752   }
2753   return false;
2754 }
2755 
UpdateStyleAndLayoutTreeForNode(const Node * node)2756 void Document::UpdateStyleAndLayoutTreeForNode(const Node* node) {
2757   DCHECK(node);
2758   if (!node->InActiveDocument()) {
2759     // If |node| is not in the active document, we can't update its style or
2760     // layout tree.
2761     DCHECK_EQ(node->ownerDocument(), this);
2762     return;
2763   }
2764   DCHECK(!InStyleRecalc())
2765       << "UpdateStyleAndLayoutTreeForNode called from within style recalc";
2766   if (!NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked(*node))
2767     return;
2768 
2769   DisplayLockUtilities::ScopedChainForcedUpdate scoped_update_forced(node);
2770   UpdateStyleAndLayoutTree();
2771 }
2772 
UpdateStyleAndLayoutTreeForSubtree(const Node * node)2773 void Document::UpdateStyleAndLayoutTreeForSubtree(const Node* node) {
2774   DCHECK(node);
2775   if (!node->InActiveDocument()) {
2776     DCHECK_EQ(node->ownerDocument(), this);
2777     return;
2778   }
2779   DCHECK(!InStyleRecalc())
2780       << "UpdateStyleAndLayoutTreeForSubtree called from within style recalc";
2781 
2782   if (NeedsLayoutTreeUpdateForNodeIncludingDisplayLocked(*node) ||
2783       node->ChildNeedsStyleRecalc() || node->ChildNeedsStyleInvalidation()) {
2784     DisplayLockUtilities::ScopedChainForcedUpdate scoped_update_forced(node);
2785     UpdateStyleAndLayoutTree();
2786   }
2787 }
2788 
UpdateStyleAndLayoutForNode(const Node * node,DocumentUpdateReason reason)2789 void Document::UpdateStyleAndLayoutForNode(const Node* node,
2790                                            DocumentUpdateReason reason) {
2791   DCHECK(node);
2792   if (!node->InActiveDocument())
2793     return;
2794 
2795   DisplayLockUtilities::ScopedChainForcedUpdate scoped_update_forced(node);
2796   UpdateStyleAndLayout(reason);
2797 }
2798 
ApplyScrollRestorationLogic()2799 void Document::ApplyScrollRestorationLogic() {
2800   // This function in not re-entrant. However, the places that invoke this are
2801   // re-entrant. Specifically, UpdateStyleAndLayout() calls this, which in turn
2802   // can do a find-in-page for the scroll-to-text feature, which can cause
2803   // UpdateStyleAndLayout to happen with subtree-visibility, which gets back here
2804   // and recurses indefinitely. As a result, we ensure to early out from this
2805   // function if are currently in process of restoring scroll.
2806   if (applying_scroll_restoration_logic_)
2807     return;
2808   base::AutoReset<bool> applying_scroll_restoration_logic_scope(
2809       &applying_scroll_restoration_logic_, true);
2810 
2811   // If we're restoring a scroll position from history, that takes precedence
2812   // over scrolling to the anchor in the URL.
2813   View()->InvokeFragmentAnchor();
2814 
2815   auto& frame_loader = GetFrame()->Loader();
2816   auto* document_loader = frame_loader.GetDocumentLoader();
2817   if (!document_loader)
2818     return;
2819   if (frame_->IsLoading() &&
2820       !FrameLoader::NeedsHistoryItemRestore(document_loader->LoadType()))
2821     return;
2822 
2823   auto* history_item = document_loader->GetHistoryItem();
2824 
2825   if (!history_item || !history_item->GetViewState())
2826     return;
2827 
2828   if (!View()->GetScrollableArea()->HasPendingHistoryRestoreScrollOffset())
2829     return;
2830 
2831   bool should_restore_scroll =
2832       history_item->ScrollRestorationType() != kScrollRestorationManual;
2833   auto& scroll_offset = history_item->GetViewState()->scroll_offset_;
2834 
2835   // This tries to balance:
2836   // 1. restoring as soon as possible.
2837   // 2. not overriding user scroll (TODO(majidvp): also respect user scale).
2838   // 3. detecting clamping to avoid repeatedly popping the scroll position
2839   // down
2840   //    as the page height increases.
2841   // 4. ignoring clamp detection if scroll state is not being restored, if
2842   // load
2843   //    is complete, or if the navigation is same-document (as the new page
2844   //    may be smaller than the previous page).
2845   bool can_restore_without_clamping =
2846       View()->LayoutViewport()->ClampScrollOffset(scroll_offset) ==
2847       scroll_offset;
2848 
2849   bool can_restore_without_annoying_user =
2850       !document_loader->GetInitialScrollState().was_scrolled_by_user &&
2851       (can_restore_without_clamping || !frame_->IsLoading() ||
2852        !should_restore_scroll);
2853   if (!can_restore_without_annoying_user)
2854     return;
2855 
2856   // Apply scroll restoration to the LayoutView's scroller. Note that we do
2857   // *not* apply it to the RootFrameViewport's LayoutViewport, because that
2858   // may be for child frame's implicit root scroller, which is not the right
2859   // one to apply to because scroll restoration does not affect implicit root
2860   // scrollers.
2861   auto* layout_scroller = View()->LayoutViewport();
2862   layout_scroller->ApplyPendingHistoryRestoreScrollOffset();
2863 
2864   // Also apply restoration to the visual viewport of the root frame, if needed.
2865   auto* root_frame_scroller = View()->GetScrollableArea();
2866   if (root_frame_scroller != layout_scroller)
2867     root_frame_scroller->ApplyPendingHistoryRestoreScrollOffset();
2868 
2869   document_loader->GetInitialScrollState().did_restore_from_history = true;
2870 }
2871 
MarkHasFindInPageRequest()2872 void Document::MarkHasFindInPageRequest() {
2873   // Note that although find-in-page requests happen in non-main frames, we only
2874   // record the main frame results (per UKM policy). Additionally, we only
2875   // record the event once.
2876   if (had_find_in_page_request_ || !IsInMainFrame())
2877     return;
2878 
2879   auto* recorder = UkmRecorder();
2880   DCHECK(recorder);
2881   DCHECK(UkmSourceID() != ukm::kInvalidSourceId);
2882   ukm::builders::Blink_FindInPage(UkmSourceID())
2883       .SetDidSearch(true)
2884       .Record(recorder);
2885   had_find_in_page_request_ = true;
2886 }
2887 
MarkHasFindInPageSubtreeVisibilityActiveMatch()2888 void Document::MarkHasFindInPageSubtreeVisibilityActiveMatch() {
2889   // Note that although find-in-page in subtree-visibility requests happen in
2890   // non-main frames, we only record the main frame results (per UKM policy).
2891   // Additionally, we only record the event once.
2892   if (had_find_in_page_render_subtree_active_match_ || !IsInMainFrame())
2893     return;
2894 
2895   auto* recorder = UkmRecorder();
2896   DCHECK(recorder);
2897   DCHECK(UkmSourceID() != ukm::kInvalidSourceId);
2898   // TODO(vmpstr): Rename UKM values if possible.
2899   ukm::builders::Blink_FindInPage(UkmSourceID())
2900       .SetDidHaveRenderSubtreeMatch(true)
2901       .Record(recorder);
2902   had_find_in_page_render_subtree_active_match_ = true;
2903 }
2904 
UpdateStyleAndLayout(DocumentUpdateReason reason)2905 void Document::UpdateStyleAndLayout(DocumentUpdateReason reason) {
2906   DCHECK(IsMainThread());
2907   LocalFrameView* frame_view = View();
2908 
2909   if (reason != DocumentUpdateReason::kBeginMainFrame && frame_view)
2910     frame_view->WillStartForcedLayout();
2911 
2912   HTMLFrameOwnerElement::PluginDisposeSuspendScope suspend_plugin_dispose;
2913   ScriptForbiddenScope forbid_script;
2914 
2915   DCHECK(!frame_view || !frame_view->IsInPerformLayout())
2916       << "View layout should not be re-entrant";
2917 
2918   if (HTMLFrameOwnerElement* owner = LocalOwner())
2919     owner->GetDocument().UpdateStyleAndLayout(reason);
2920 
2921   UpdateStyleAndLayoutTree();
2922 
2923   if (!IsActive()) {
2924     if (reason != DocumentUpdateReason::kBeginMainFrame && frame_view)
2925       frame_view->DidFinishForcedLayout(reason);
2926     return;
2927   }
2928 
2929   if (frame_view && frame_view->NeedsLayout())
2930     frame_view->UpdateLayout();
2931 
2932   if (Lifecycle().GetState() < DocumentLifecycle::kLayoutClean)
2933     Lifecycle().AdvanceTo(DocumentLifecycle::kLayoutClean);
2934 
2935   ApplyScrollRestorationLogic();
2936 
2937   if (LocalFrameView* frame_view_anchored = View())
2938     frame_view_anchored->PerformScrollAnchoringAdjustments();
2939   PerformScrollSnappingTasks();
2940 
2941   if (reason != DocumentUpdateReason::kBeginMainFrame && frame_view)
2942     frame_view->DidFinishForcedLayout(reason);
2943 
2944   if (update_focus_appearance_after_layout_)
2945     UpdateFocusAppearance();
2946 }
2947 
LayoutUpdated()2948 void Document::LayoutUpdated() {
2949   DCHECK(GetFrame());
2950   DCHECK(View());
2951 
2952   // Plugins can run script inside layout which can detach the page.
2953   // TODO(dcheng): Does it make sense to do any of this work if detached?
2954   if (GetFrame()) {
2955     if (GetFrame()->IsMainFrame())
2956       GetFrame()->GetPage()->GetChromeClient().MainFrameLayoutUpdated();
2957 
2958     // We do attach here, during lifecycle update, because until then we
2959     // don't have a good place that has access to its local root's FrameWidget.
2960     // TODO(dcheng): If we create FrameWidget before Frame then we could move
2961     // this to Document::Initialize().
2962     AttachCompositorTimeline(Timeline().CompositorTimeline());
2963   }
2964 
2965   Markers().InvalidateRectsForAllTextMatchMarkers();
2966 }
2967 
AttachCompositorTimeline(CompositorAnimationTimeline * timeline) const2968 void Document::AttachCompositorTimeline(
2969     CompositorAnimationTimeline* timeline) const {
2970   if (!Platform::Current()->IsThreadedAnimationEnabled() ||
2971       !GetSettings()->GetAcceleratedCompositingEnabled())
2972     return;
2973 
2974   if (timeline->GetAnimationTimeline()->IsScrollTimeline() &&
2975       timeline->GetAnimationTimeline()->animation_host())
2976     return;
2977 
2978   GetPage()->GetChromeClient().AttachCompositorAnimationTimeline(timeline,
2979                                                                  GetFrame());
2980 }
2981 
DetachCompositorTimeline(CompositorAnimationTimeline * timeline) const2982 void Document::DetachCompositorTimeline(
2983     CompositorAnimationTimeline* timeline) const {
2984   if (!Platform::Current()->IsThreadedAnimationEnabled() ||
2985       !GetSettings()->GetAcceleratedCompositingEnabled())
2986     return;
2987 
2988   // This requires detaching all animations from timeline first before detaching
2989   // timeline.
2990   if (timeline->GetAnimationTimeline()->IsScrollTimeline() &&
2991       timeline->GetAnimationTimeline()->HasAnimation())
2992     return;
2993 
2994   GetPage()->GetChromeClient().DetachCompositorAnimationTimeline(timeline,
2995                                                                  GetFrame());
2996 }
2997 
ClearFocusedElementSoon()2998 void Document::ClearFocusedElementSoon() {
2999   if (!clear_focused_element_timer_.IsActive())
3000     clear_focused_element_timer_.StartOneShot(base::TimeDelta(), FROM_HERE);
3001 }
3002 
ClearFocusedElementTimerFired(TimerBase *)3003 void Document::ClearFocusedElementTimerFired(TimerBase*) {
3004   UpdateStyleAndLayoutTree();
3005 
3006   if (focused_element_ && !focused_element_->IsFocusable())
3007     focused_element_->blur();
3008 }
3009 
StyleForPage(int page_index)3010 scoped_refptr<const ComputedStyle> Document::StyleForPage(int page_index) {
3011   UpdateDistributionForUnknownReasons();
3012   return EnsureStyleResolver().StyleForPage(page_index);
3013 }
3014 
EnsurePaintLocationDataValidForNode(const Node * node,DocumentUpdateReason reason)3015 void Document::EnsurePaintLocationDataValidForNode(
3016     const Node* node,
3017     DocumentUpdateReason reason) {
3018   DCHECK(node);
3019   if (!node->InActiveDocument())
3020     return;
3021 
3022   DisplayLockUtilities::ScopedChainForcedUpdate scoped_update_forced(node);
3023 
3024   // For all nodes we must have up-to-date style and have performed layout to do
3025   // any location-based calculation.
3026   UpdateStyleAndLayout(reason);
3027 
3028   // The location of elements that are position: sticky is not known until
3029   // compositing inputs are cleaned. Therefore, for any elements that are either
3030   // sticky or are in a sticky sub-tree (e.g. are affected by a sticky element),
3031   // we need to also clean compositing inputs.
3032   if (View() && node->GetLayoutObject() &&
3033       node->GetLayoutObject()->StyleRef().SubtreeIsSticky()) {
3034     bool success = false;
3035     if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
3036       // In CAP, compositing inputs are cleaned as part of PrePaint.
3037       success = View()->UpdateAllLifecyclePhasesExceptPaint(reason);
3038     } else {
3039       success = View()->UpdateLifecycleToCompositingInputsClean(reason);
3040     }
3041     // The lifecycle update should always succeed, because forced lifecycles
3042     // from script are never throttled.
3043     DCHECK(success);
3044   }
3045 }
3046 
IsPageBoxVisible(int page_index)3047 bool Document::IsPageBoxVisible(int page_index) {
3048   return StyleForPage(page_index)->Visibility() !=
3049          EVisibility::kHidden;  // display property doesn't apply to @page.
3050 }
3051 
PageSizeAndMarginsInPixels(int page_index,DoubleSize & page_size,int & margin_top,int & margin_right,int & margin_bottom,int & margin_left)3052 void Document::PageSizeAndMarginsInPixels(int page_index,
3053                                           DoubleSize& page_size,
3054                                           int& margin_top,
3055                                           int& margin_right,
3056                                           int& margin_bottom,
3057                                           int& margin_left) {
3058   scoped_refptr<const ComputedStyle> style = StyleForPage(page_index);
3059 
3060   double width = page_size.Width();
3061   double height = page_size.Height();
3062   switch (style->GetPageSizeType()) {
3063     case PageSizeType::kAuto:
3064       break;
3065     case PageSizeType::kLandscape:
3066       if (width < height)
3067         std::swap(width, height);
3068       break;
3069     case PageSizeType::kPortrait:
3070       if (width > height)
3071         std::swap(width, height);
3072       break;
3073     case PageSizeType::kFixed: {
3074       FloatSize size = style->PageSize();
3075       width = size.Width();
3076       height = size.Height();
3077       break;
3078     }
3079     default:
3080       NOTREACHED();
3081   }
3082   page_size = DoubleSize(width, height);
3083 
3084   // The percentage is calculated with respect to the width even for margin top
3085   // and bottom.
3086   // http://www.w3.org/TR/CSS2/box.html#margin-properties
3087   margin_top = style->MarginTop().IsAuto()
3088                    ? margin_top
3089                    : IntValueForLength(style->MarginTop(), width);
3090   margin_right = style->MarginRight().IsAuto()
3091                      ? margin_right
3092                      : IntValueForLength(style->MarginRight(), width);
3093   margin_bottom = style->MarginBottom().IsAuto()
3094                       ? margin_bottom
3095                       : IntValueForLength(style->MarginBottom(), width);
3096   margin_left = style->MarginLeft().IsAuto()
3097                     ? margin_left
3098                     : IntValueForLength(style->MarginLeft(), width);
3099 }
3100 
SetIsViewSource(bool is_view_source)3101 void Document::SetIsViewSource(bool is_view_source) {
3102   is_view_source_ = is_view_source;
3103   if (!is_view_source_)
3104     return;
3105 }
3106 
SetIsXrOverlay(bool val,Element * overlay_element)3107 void Document::SetIsXrOverlay(bool val, Element* overlay_element) {
3108   if (!documentElement())
3109     return;
3110 
3111   if (val == is_xr_overlay_)
3112     return;
3113 
3114   is_xr_overlay_ = val;
3115 
3116   // On navigation, the layout view may be invalid, skip style changes.
3117   if (!GetLayoutView())
3118     return;
3119 
3120   if (val) {
3121     // The UA style sheet for the :xr-overlay pseudoclass uses lazy loading.
3122     // If we get here, we need to ensure that it's present.
3123     GetStyleEngine().EnsureUAStyleForXrOverlay();
3124   }
3125 
3126   if (overlay_element) {
3127     // Now that the custom style sheet is loaded, update the pseudostyle for
3128     // the overlay element.
3129     overlay_element->PseudoStateChanged(CSSSelector::kPseudoXrOverlay);
3130   }
3131 
3132   // The DOM overlay may change the effective root element. Need to update
3133   // compositing inputs to avoid a mismatch in CompositingRequirementsUpdater.
3134   GetLayoutView()->Layer()->SetNeedsCompositingInputsUpdate();
3135 
3136   // Ensure that the graphics layer tree gets fully rebuilt on changes,
3137   // similar to HTMLVideoElement::DidEnterFullscreen(). This may not be
3138   // strictly necessary if the compositing changes are based on visibility
3139   // settings, but helps ensure consistency in case it's changed to
3140   // detaching layers or re-rooting the graphics layer tree.
3141   if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
3142     auto* compositor = GetLayoutView()->Compositor();
3143     compositor->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
3144   }
3145 }
3146 
ScheduleUseShadowTreeUpdate(SVGUseElement & element)3147 void Document::ScheduleUseShadowTreeUpdate(SVGUseElement& element) {
3148   use_elements_needing_update_.insert(&element);
3149   ScheduleLayoutTreeUpdateIfNeeded();
3150 }
3151 
UnscheduleUseShadowTreeUpdate(SVGUseElement & element)3152 void Document::UnscheduleUseShadowTreeUpdate(SVGUseElement& element) {
3153   use_elements_needing_update_.erase(&element);
3154 }
3155 
UpdateUseShadowTreesIfNeeded()3156 void Document::UpdateUseShadowTreesIfNeeded() {
3157   ScriptForbiddenScope forbid_script;
3158 
3159   // Breadth-first search since nested use elements add to the queue.
3160   while (!use_elements_needing_update_.IsEmpty()) {
3161     HeapHashSet<Member<SVGUseElement>> elements;
3162     use_elements_needing_update_.swap(elements);
3163     for (SVGUseElement* element : elements)
3164       element->BuildPendingResource();
3165   }
3166 }
3167 
GetStyleResolver() const3168 StyleResolver* Document::GetStyleResolver() const {
3169   return style_engine_->Resolver();
3170 }
3171 
EnsureStyleResolver() const3172 StyleResolver& Document::EnsureStyleResolver() const {
3173   return style_engine_->EnsureResolver();
3174 }
3175 
Initialize()3176 void Document::Initialize() {
3177   DCHECK_EQ(lifecycle_.GetState(), DocumentLifecycle::kInactive);
3178   DCHECK(!ax_object_cache_ || this != &AXObjectCacheOwner());
3179 
3180   layout_view_ = new LayoutView(this);
3181   SetLayoutObject(layout_view_);
3182 
3183   layout_view_->SetStyle(StyleResolver::StyleForViewport(*this));
3184 
3185   AttachContext context;
3186   AttachLayoutTree(context);
3187 
3188   // The TextAutosizer can't update layout view info while the Document is
3189   // detached, so update now in case anything changed.
3190   if (TextAutosizer* autosizer = GetTextAutosizer())
3191     autosizer->UpdatePageInfo();
3192 
3193   frame_->DidAttachDocument();
3194   lifecycle_.AdvanceTo(DocumentLifecycle::kStyleClean);
3195 
3196   if (View())
3197     View()->DidAttachDocument();
3198 
3199   // Observer(s) should not be initialized until the document is initialized /
3200   // attached to a frame. Otherwise
3201   // ExecutionContextLifecycleObserver::contextDestroyed wouldn't be fired.
3202   network_state_observer_ =
3203       MakeGarbageCollected<NetworkStateObserver>(GetExecutionContext());
3204 
3205   // Check for frame_ so we only attach documents with its own scheduler.
3206   if (frame_)
3207     GetAgent()->AttachDocument(this);
3208 }
3209 
Shutdown()3210 void Document::Shutdown() {
3211   TRACE_EVENT0("blink", "Document::shutdown");
3212   CHECK(!frame_ || frame_->Tree().ChildCount() == 0);
3213   if (!IsActive())
3214     return;
3215 
3216   // An active Document must have an associated frame.
3217   CHECK(frame_);
3218 
3219   // Frame navigation can cause a new Document to be attached. Don't allow that,
3220   // since that will cause a situation where LocalFrame still has a Document
3221   // attached after this finishes!  Normally, it shouldn't actually be possible
3222   // to trigger navigation here.  However, plugins (see below) can cause lots of
3223   // crazy things to happen, since plugin detach involves nested run loops.
3224   FrameNavigationDisabler navigation_disabler(*frame_);
3225   // Defer plugin dispose to avoid plugins trying to run script inside
3226   // ScriptForbiddenScope, which will crash the renderer after
3227   // https://crrev.com/200984
3228   // TODO(dcheng): This is a temporary workaround, Document::Shutdown() should
3229   // not be running script at all.
3230   HTMLFrameOwnerElement::PluginDisposeSuspendScope suspend_plugin_dispose;
3231   // Don't allow script to run in the middle of DetachLayoutTree() because a
3232   // detaching Document is not in a consistent state.
3233   ScriptForbiddenScope forbid_script;
3234 
3235   lifecycle_.AdvanceTo(DocumentLifecycle::kStopping);
3236 
3237   // Do not add code before this without a documented reason. A postcondition of
3238   // Shutdown() is that |frame_| must not have an attached Document. Allowing
3239   // script execution when the Document is shutting down can make it easy to
3240   // accidentally violate this condition, and the ordering of the scopers above
3241   // is subtle due to legacy interactions with plugins.
3242 
3243   if (num_canvases_ > 0)
3244     UMA_HISTOGRAM_COUNTS_100("Blink.Canvas.NumCanvasesPerPage", num_canvases_);
3245 
3246   GetFontMatchingMetrics()->PublishUkmMetrics();
3247 
3248   GetViewportData().Shutdown();
3249 
3250   View()->Dispose();
3251   // TODO(crbug.com/729196): Trace why LocalFrameView::DetachFromLayout crashes.
3252   CHECK(!View()->IsAttached());
3253 
3254   // If the EmbeddedContentView of the document's frame owner doesn't match
3255   // view() then LocalFrameView::Dispose() didn't clear the owner's
3256   // EmbeddedContentView. If we don't clear it here, it may be clobbered later
3257   // in LocalFrame::CreateView(). See also https://crbug.com/673170 and the
3258   // comment in LocalFrameView::Dispose().
3259   HTMLFrameOwnerElement* owner_element = frame_->DeprecatedLocalOwner();
3260 
3261   // In the case of a provisional frame, skip clearing the EmbeddedContentView.
3262   // A provisional frame is not fully attached to the DOM yet and clearing the
3263   // EmbeddedContentView here could clear a not-yet-swapped-out frame
3264   // (https://crbug.com/807772).
3265   if (owner_element && !frame_->IsProvisional())
3266     owner_element->SetEmbeddedContentView(nullptr);
3267 
3268   markers_->PrepareForDestruction();
3269 
3270   GetPage()->DocumentDetached(this);
3271 
3272   probe::DocumentDetached(this);
3273 
3274   scripted_idle_task_controller_.Clear();
3275 
3276   if (SvgExtensions())
3277     AccessSVGExtensions().PauseAnimations();
3278 
3279   CancelPendingJavaScriptUrls();
3280   http_refresh_scheduler_->Cancel();
3281   GetFrame()->CancelFormSubmission();
3282 
3283   DetachCompositorTimeline(Timeline().CompositorTimeline());
3284 
3285   if (frame_->IsLocalRoot())
3286     GetPage()->GetChromeClient().AttachRootLayer(nullptr, frame_.Get());
3287   if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
3288     layout_view_->CleanUpCompositor();
3289 
3290   if (RegistrationContext())
3291     RegistrationContext()->DocumentWasDetached();
3292 
3293   MutationObserver::CleanSlotChangeList(*this);
3294 
3295   hover_element_ = nullptr;
3296   active_element_ = nullptr;
3297   autofocus_candidates_.clear();
3298 
3299   if (focused_element_.Get()) {
3300     Element* old_focused_element = focused_element_;
3301     focused_element_ = nullptr;
3302     NotifyFocusedElementChanged(old_focused_element, nullptr);
3303   }
3304   sequential_focus_navigation_starting_point_ = nullptr;
3305 
3306   if (this == &AXObjectCacheOwner()) {
3307     ax_contexts_.clear();
3308     ClearAXObjectCache();
3309   }
3310   computed_node_mapping_.clear();
3311 
3312   layout_view_ = nullptr;
3313   DetachLayoutTree();
3314   // TODO(crbug.com/729196): Trace why LocalFrameView::DetachFromLayout crashes.
3315   CHECK(!View()->IsAttached());
3316 
3317   if (this != &AXObjectCacheOwner()) {
3318     if (AXObjectCache* cache = ExistingAXObjectCache()) {
3319       // Documents that are not a root document use the AXObjectCache in
3320       // their root document. Node::removedFrom is called after the
3321       // document has been detached so it can't find the root document.
3322       // We do the removals here instead.
3323       for (Node& node : NodeTraversal::DescendantsOf(*this)) {
3324         cache->Remove(&node);
3325       }
3326     }
3327   }
3328 
3329   GetStyleEngine().DidDetach();
3330 
3331   frame_->GetEventHandlerRegistry().DocumentDetached(*this);
3332 
3333   // Signal destruction to mutation observers.
3334   synchronous_mutation_observer_list_.ForEachObserver(
3335       [](SynchronousMutationObserver* observer) {
3336         observer->ContextDestroyed();
3337         observer->ObserverListWillBeCleared();
3338       });
3339   synchronous_mutation_observer_list_.Clear();
3340 
3341   cookie_jar_ = nullptr;  // Not accessible after navigated away.
3342   fetcher_->ClearContext();
3343   // If this document is the master for an HTMLImportsController, sever that
3344   // relationship. This ensures that we don't leave import loads in flight,
3345   // thinking they should have access to a valid frame when they don't.
3346   if (imports_controller_) {
3347     imports_controller_->Dispose();
3348     ClearImportsController();
3349   }
3350 
3351   if (media_query_matcher_)
3352     media_query_matcher_->DocumentDetached();
3353 
3354   lifecycle_.AdvanceTo(DocumentLifecycle::kStopped);
3355   // TODO(crbug.com/729196): Trace why LocalFrameView::DetachFromLayout crashes.
3356   CHECK(!View()->IsAttached());
3357 
3358   // Check for frame_ so we only detach documents with its own scheduler.
3359   // TODO(bokan): Can this happen? |frame_| is dereferenced above and CHECKed
3360   // at top.
3361   if (frame_)
3362     GetAgent()->DetachDocument(this);
3363 
3364   // TODO(crbug.com/729196): Trace why LocalFrameView::DetachFromLayout crashes.
3365   CHECK(!View()->IsAttached());
3366 
3367   needs_to_record_ukm_outlive_time_ = IsInMainFrame();
3368   if (needs_to_record_ukm_outlive_time_) {
3369     // Ensure |ukm_recorder_| and |ukm_source_id_|.
3370     UkmRecorder();
3371   }
3372 
3373   mime_handler_view_before_unload_event_listener_ = nullptr;
3374 
3375   resource_coordinator_.reset();
3376 
3377   // This is required, as our LocalFrame might delete itself as soon as it
3378   // detaches us. However, this violates Node::detachLayoutTree() semantics, as
3379   // it's never possible to re-attach. Eventually Document::detachLayoutTree()
3380   // should be renamed, or this setting of the frame to 0 could be made
3381   // explicit in each of the callers of Document::detachLayoutTree().
3382   frame_ = nullptr;
3383 
3384   document_outlive_time_reporter_ =
3385       std::make_unique<DocumentOutliveTimeReporter>(this);
3386 }
3387 
RemoveAllEventListeners()3388 void Document::RemoveAllEventListeners() {
3389   ContainerNode::RemoveAllEventListeners();
3390 
3391   if (LocalDOMWindow* dom_window = domWindow())
3392     dom_window->RemoveAllEventListeners();
3393 }
3394 
AXObjectCacheOwner() const3395 Document& Document::AXObjectCacheOwner() const {
3396   // Every document has its own axObjectCache if accessibility is enabled,
3397   // except for page popups, which share the axObjectCache of their owner.
3398   Document* doc = const_cast<Document*>(this);
3399   if (doc->GetFrame() && doc->GetFrame()->PagePopupOwner()) {
3400     DCHECK(!doc->ax_object_cache_);
3401     return doc->GetFrame()
3402         ->PagePopupOwner()
3403         ->GetDocument()
3404         .AXObjectCacheOwner();
3405   }
3406   return *doc;
3407 }
3408 
AddAXContext(AXContext * context)3409 void Document::AddAXContext(AXContext* context) {
3410   // The only case when |&cache_owner| is not |this| is when this is a
3411   // pop-up. We want pop-ups to share the AXObjectCache of their parent
3412   // document. However, there's no valid reason to explicitly create an
3413   // AXContext for a pop-up document, so check to make sure we're not
3414   // trying to do that here.
3415   DCHECK_EQ(&AXObjectCacheOwner(), this);
3416 
3417   // If the document has already been detached, do not make a new AXObjectCache.
3418   if (!GetLayoutView())
3419     return;
3420 
3421   ax_contexts_.push_back(context);
3422   if (ax_contexts_.size() != 1)
3423     return;
3424 
3425   if (!ax_object_cache_)
3426     ax_object_cache_ = AXObjectCache::Create(*this);
3427 }
3428 
RemoveAXContext(AXContext * context)3429 void Document::RemoveAXContext(AXContext* context) {
3430   auto** iter =
3431       std::find_if(ax_contexts_.begin(), ax_contexts_.end(),
3432                    [&context](const auto& item) { return item == context; });
3433   if (iter != ax_contexts_.end())
3434     ax_contexts_.erase(iter);
3435   if (ax_contexts_.size() == 0)
3436     ClearAXObjectCache();
3437 }
3438 
ClearAXObjectCache()3439 void Document::ClearAXObjectCache() {
3440   DCHECK_EQ(&AXObjectCacheOwner(), this);
3441 
3442   // Clear the cache member variable before calling delete because attempts
3443   // are made to access it during destruction.
3444   if (ax_object_cache_)
3445     ax_object_cache_->Dispose();
3446   ax_object_cache_.Clear();
3447 
3448   // If there's at least one AXContext in scope and there's still a LayoutView
3449   // around, recreate an empty AXObjectCache.
3450   //
3451   // TODO(dmazzoni): right now ClearAXObjectCache() is being used as a way
3452   // to invalidate / reset the AXObjectCache while keeping it around. We
3453   // should rewrite that as a method on AXObjectCache rather than destroying
3454   // and recreating it here.
3455   if (ax_contexts_.size() > 0 && GetLayoutView())
3456     ax_object_cache_ = AXObjectCache::Create(*this);
3457 }
3458 
ExistingAXObjectCache() const3459 AXObjectCache* Document::ExistingAXObjectCache() const {
3460   auto& cache_owner = AXObjectCacheOwner();
3461 
3462   // If the LayoutView is gone then we are in the process of destruction.
3463   // This method will be called before frame_ = nullptr.
3464   if (!cache_owner.GetLayoutView())
3465     return nullptr;
3466 
3467   return cache_owner.ax_object_cache_.Get();
3468 }
3469 
GetCanvasFontCache()3470 CanvasFontCache* Document::GetCanvasFontCache() {
3471   if (!canvas_font_cache_)
3472     canvas_font_cache_ = MakeGarbageCollected<CanvasFontCache>(*this);
3473 
3474   return canvas_font_cache_.Get();
3475 }
3476 
CreateParser()3477 DocumentParser* Document::CreateParser() {
3478   if (auto* html_document = DynamicTo<HTMLDocument>(this)) {
3479     return MakeGarbageCollected<HTMLDocumentParser>(*html_document,
3480                                                     parser_sync_policy_);
3481   }
3482   // FIXME: this should probably pass the frame instead
3483   return MakeGarbageCollected<XMLDocumentParser>(*this, View());
3484 }
3485 
IsFrameSet() const3486 bool Document::IsFrameSet() const {
3487   if (!IsA<HTMLDocument>(this))
3488     return false;
3489   return IsA<HTMLFrameSetElement>(body());
3490 }
3491 
GetScriptableDocumentParser() const3492 ScriptableDocumentParser* Document::GetScriptableDocumentParser() const {
3493   return Parser() ? Parser()->AsScriptableDocumentParser() : nullptr;
3494 }
3495 
DisplayNoneChangedForFrame()3496 void Document::DisplayNoneChangedForFrame() {
3497   if (!documentElement())
3498     return;
3499   // LayoutView()::CanHaveChildren(), hence the existence of style and
3500   // layout tree, depends on the owner being display:none or not. Trigger
3501   // detaching or attaching the style/layout-tree as a result of that
3502   // changing.
3503   documentElement()->SetNeedsStyleRecalc(
3504       kLocalStyleChange,
3505       StyleChangeReasonForTracing::Create(style_change_reason::kFrame));
3506 }
3507 
SetPrinting(PrintingState state)3508 void Document::SetPrinting(PrintingState state) {
3509   bool was_printing = Printing();
3510   printing_ = state;
3511   bool is_printing = Printing();
3512 
3513   if ((was_printing != is_printing) && documentElement() && GetFrame() &&
3514       !GetFrame()->IsMainFrame() && GetFrame()->Owner() &&
3515       GetFrame()->Owner()->IsDisplayNone()) {
3516     // In non-printing mode we do not generate style or layout objects for
3517     // display:none iframes, yet we do when printing (see
3518     // LayoutView::CanHaveChildren). Trigger a style recalc on the root element
3519     // to create a layout tree for printing.
3520     DisplayNoneChangedForFrame();
3521   }
3522 }
3523 
SetIsPaintingPreview(bool is_painting_preview)3524 void Document::SetIsPaintingPreview(bool is_painting_preview) {
3525   is_painting_preview_ = is_painting_preview;
3526 }
3527 
3528 // https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#document-open-steps
open(Document * entered_document,ExceptionState & exception_state)3529 void Document::open(Document* entered_document,
3530                     ExceptionState& exception_state) {
3531   if (ImportLoader()) {
3532     exception_state.ThrowDOMException(
3533         DOMExceptionCode::kInvalidStateError,
3534         "Imported document doesn't support open().");
3535     return;
3536   }
3537 
3538   // If |document| is an XML document, then throw an "InvalidStateError"
3539   // DOMException exception.
3540   if (!IsA<HTMLDocument>(this)) {
3541     exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
3542                                       "Only HTML documents support open().");
3543     return;
3544   }
3545 
3546   // If |document|'s throw-on-dynamic-markup-insertion counter is greater than
3547   // 0, then throw an "InvalidStateError" DOMException.
3548   if (throw_on_dynamic_markup_insertion_count_) {
3549     exception_state.ThrowDOMException(
3550         DOMExceptionCode::kInvalidStateError,
3551         "Custom Element constructor should not use open().");
3552     return;
3553   }
3554 
3555   if (!AllowedToUseDynamicMarkUpInsertion("open", exception_state))
3556     return;
3557 
3558   // If |document|'s origin is not same origin to the origin of the responsible
3559   // document specified by the entry settings object, then throw a
3560   // "SecurityError" DOMException.
3561   if (entered_document && !GetSecurityOrigin()->IsSameOriginWith(
3562                               entered_document->GetSecurityOrigin())) {
3563     exception_state.ThrowSecurityError(
3564         "Can only call open() on same-origin documents.");
3565     return;
3566   }
3567 
3568   // If |document| has an active parser whose script nesting level is greater
3569   // than 0, then return |document|.
3570   if (ScriptableDocumentParser* parser = GetScriptableDocumentParser()) {
3571     if (parser->IsParsing() && parser->IsExecutingScript())
3572       return;
3573   }
3574 
3575   // Similarly, if |document|'s ignore-opens-during-unload counter is greater
3576   // than 0, then return |document|.
3577   if (ignore_opens_during_unload_count_)
3578     return;
3579 
3580   // If |document|'s active parser was aborted is true, then return |document|.
3581   if (ignore_opens_and_writes_for_abort_)
3582     return;
3583 
3584   // Change |document|'s URL to the URL of the responsible document specified
3585   // by the entry settings object.
3586   if (entered_document && this != entered_document) {
3587     auto* csp = MakeGarbageCollected<ContentSecurityPolicy>();
3588     csp->CopyStateFrom(entered_document->GetContentSecurityPolicy());
3589     // We inherit the sandbox flags of the entered document, so mask on
3590     // the ones contained in the CSP.
3591     GetSecurityContext().ApplySandboxFlags(csp->GetSandboxMask());
3592     InitContentSecurityPolicy(csp);
3593     // Clear the hash fragment from the inherited URL to prevent a
3594     // scroll-into-view for any document.open()'d frame.
3595     KURL new_url = entered_document->Url();
3596     new_url.SetFragmentIdentifier(String());
3597     SetURL(new_url);
3598     if (Loader())
3599       Loader()->UpdateUrlForDocumentOpen(new_url);
3600 
3601     GetSecurityContext().SetSecurityOrigin(
3602         entered_document->GetMutableSecurityOrigin());
3603     SetReferrerPolicy(entered_document->GetReferrerPolicy());
3604     SetCookieURL(entered_document->CookieURL());
3605   }
3606 
3607   open();
3608 }
3609 
3610 // https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#document-open-steps
open()3611 void Document::open() {
3612   DCHECK(!ImportLoader());
3613   DCHECK(!ignore_opens_during_unload_count_);
3614   if (ScriptableDocumentParser* parser = GetScriptableDocumentParser())
3615     DCHECK(!parser->IsParsing() || !parser->IsExecutingScript());
3616 
3617   // If |document| has a browsing context and there is an existing attempt to
3618   // navigate |document|'s browsing context, then stop document loading given
3619   // |document|.
3620   //
3621   // As noted in the spec and https://github.com/whatwg/html/issues/3975, we
3622   // want to treat ongoing navigation and queued navigation the same way.
3623   // However, we don't want to consider navigations scheduled too much into the
3624   // future through Refresh headers or a <meta> refresh pragma to be a current
3625   // navigation. Thus, we cut it off with
3626   // IsHttpRefreshScheduledWithin(base::TimeDelta()).
3627   //
3628   // This also prevents window.open(url) -- eg window.open("about:blank") --
3629   // from blowing away results from a subsequent window.document.open /
3630   // window.document.write call.
3631   if (frame_ && (frame_->Loader().HasProvisionalNavigation() ||
3632                  IsHttpRefreshScheduledWithin(base::TimeDelta()))) {
3633     frame_->Loader().StopAllLoaders();
3634     // Navigations handled by the client should also be cancelled.
3635     if (frame_ && frame_->Client())
3636       frame_->Client()->AbortClientNavigation();
3637   }
3638   CancelPendingJavaScriptUrls();
3639 
3640   // TODO(crbug.com/1085514): Consider making HasProvisionalNavigation() return
3641   // true when form submission task is active, in which case we can delete this
3642   // redundant attempt to cancel it.
3643   if (GetFrame())
3644     GetFrame()->CancelFormSubmission();
3645 
3646   // For each shadow-including inclusive descendant |node| of |document|, erase
3647   // all event listeners and handlers given |node|.
3648   //
3649   // Erase all event listeners and handlers given |window|.
3650   //
3651   // NB: Document::RemoveAllEventListeners() (called by
3652   // RemoveAllEventListenersRecursively()) erases event listeners from the
3653   // Window object as well.
3654   RemoveAllEventListenersRecursively();
3655 
3656   ResetTreeScope();
3657   if (frame_)
3658     frame_->Selection().Clear();
3659 
3660   // Create a new HTML parser and associate it with |document|.
3661   //
3662   // Set the current document readiness of |document| to "loading".
3663   ImplicitOpen(kForceSynchronousParsing);
3664 
3665   // This is a script-created parser.
3666   if (ScriptableDocumentParser* parser = GetScriptableDocumentParser())
3667     parser->SetWasCreatedByScript(true);
3668 
3669   if (frame_)
3670     frame_->Loader().DidExplicitOpen();
3671 }
3672 
DetachParser()3673 void Document::DetachParser() {
3674   if (!parser_)
3675     return;
3676   parser_->Detach();
3677   parser_.Clear();
3678   DocumentParserTiming::From(*this).MarkParserDetached();
3679 }
3680 
CancelParsing()3681 void Document::CancelParsing() {
3682   // There appears to be an unspecced assumption that a document.open()
3683   // or document.write() immediately after a navigation start won't cancel
3684   // the navigation. Firefox avoids cancelling the navigation by ignoring an
3685   // open() or write() after an active parser is aborted. See
3686   // https://github.com/whatwg/html/issues/4723 for discussion about
3687   // standardizing this behavior.
3688   if (parser_ && parser_->IsParsing())
3689     ignore_opens_and_writes_for_abort_ = true;
3690   DetachParser();
3691   SetParsingState(kFinishedParsing);
3692   SetReadyState(kComplete);
3693   if (!LoadEventFinished())
3694     load_event_progress_ = kLoadEventCompleted;
3695   CancelPendingJavaScriptUrls();
3696   http_refresh_scheduler_->Cancel();
3697 }
3698 
OpenForNavigation(ParserSynchronizationPolicy parser_sync_policy,const AtomicString & mime_type,const AtomicString & encoding)3699 DocumentParser* Document::OpenForNavigation(
3700     ParserSynchronizationPolicy parser_sync_policy,
3701     const AtomicString& mime_type,
3702     const AtomicString& encoding) {
3703   DocumentParser* parser = ImplicitOpen(parser_sync_policy);
3704   if (parser->NeedsDecoder())
3705     parser->SetDecoder(BuildTextResourceDecoderFor(this, mime_type, encoding));
3706   return parser;
3707 }
3708 
ImplicitOpen(ParserSynchronizationPolicy parser_sync_policy)3709 DocumentParser* Document::ImplicitOpen(
3710     ParserSynchronizationPolicy parser_sync_policy) {
3711   RemoveChildren();
3712   DCHECK(!focused_element_);
3713 
3714   SetCompatibilityMode(kNoQuirksMode);
3715 
3716   if (!ThreadedParsingEnabledForTesting()) {
3717     parser_sync_policy = kForceSynchronousParsing;
3718   } else if (parser_sync_policy == kAllowAsynchronousParsing &&
3719              IsPrefetchOnly()) {
3720     // Prefetch must be synchronous.
3721     parser_sync_policy = kForceSynchronousParsing;
3722   }
3723 
3724   DetachParser();
3725   parser_sync_policy_ = parser_sync_policy;
3726   parser_ = CreateParser();
3727   DocumentParserTiming::From(*this).MarkParserStart();
3728   SetParsingState(kParsing);
3729   SetReadyState(kLoading);
3730   if (load_event_progress_ != kLoadEventInProgress &&
3731       PageDismissalEventBeingDispatched() == kNoDismissal) {
3732     load_event_progress_ = kLoadEventNotRun;
3733   }
3734 
3735   return parser_;
3736 }
3737 
body() const3738 HTMLElement* Document::body() const {
3739   if (!IsA<HTMLHtmlElement>(documentElement()))
3740     return nullptr;
3741 
3742   for (HTMLElement* child =
3743            Traversal<HTMLElement>::FirstChild(*documentElement());
3744        child; child = Traversal<HTMLElement>::NextSibling(*child)) {
3745     if (IsA<HTMLFrameSetElement>(*child) || IsA<HTMLBodyElement>(*child))
3746       return child;
3747   }
3748 
3749   return nullptr;
3750 }
3751 
FirstBodyElement() const3752 HTMLBodyElement* Document::FirstBodyElement() const {
3753   if (!IsA<HTMLHtmlElement>(documentElement()))
3754     return nullptr;
3755 
3756   for (HTMLElement* child =
3757            Traversal<HTMLElement>::FirstChild(*documentElement());
3758        child; child = Traversal<HTMLElement>::NextSibling(*child)) {
3759     if (auto* body = DynamicTo<HTMLBodyElement>(*child))
3760       return body;
3761   }
3762 
3763   return nullptr;
3764 }
3765 
setBody(HTMLElement * prp_new_body,ExceptionState & exception_state)3766 void Document::setBody(HTMLElement* prp_new_body,
3767                        ExceptionState& exception_state) {
3768   HTMLElement* new_body = prp_new_body;
3769 
3770   if (!new_body) {
3771     exception_state.ThrowDOMException(
3772         DOMExceptionCode::kHierarchyRequestError,
3773         ExceptionMessages::ArgumentNullOrIncorrectType(1, "HTMLElement"));
3774     return;
3775   }
3776   if (!documentElement()) {
3777     exception_state.ThrowDOMException(DOMExceptionCode::kHierarchyRequestError,
3778                                       "No document element exists.");
3779     return;
3780   }
3781 
3782   if (!IsA<HTMLBodyElement>(*new_body) &&
3783       !IsA<HTMLFrameSetElement>(*new_body)) {
3784     exception_state.ThrowDOMException(
3785         DOMExceptionCode::kHierarchyRequestError,
3786         "The new body element is of type '" + new_body->tagName() +
3787             "'. It must be either a 'BODY' or 'FRAMESET' element.");
3788     return;
3789   }
3790 
3791   HTMLElement* old_body = body();
3792   if (old_body == new_body)
3793     return;
3794 
3795   if (old_body)
3796     documentElement()->ReplaceChild(new_body, old_body, exception_state);
3797   else
3798     documentElement()->AppendChild(new_body, exception_state);
3799 }
3800 
WillInsertBody()3801 void Document::WillInsertBody() {
3802   if (Loader())
3803     fetcher_->LoosenLoadThrottlingPolicy();
3804 
3805   // If we get to the <body> try to resume commits since we should have content
3806   // to paint now.
3807   // TODO(esprehn): Is this really optimal? We might start producing frames
3808   // for very little content, should we wait for some heuristic like
3809   // isVisuallyNonEmpty() ?
3810   BeginLifecycleUpdatesIfRenderingReady();
3811 }
3812 
head() const3813 HTMLHeadElement* Document::head() const {
3814   Node* de = documentElement();
3815   if (!de)
3816     return nullptr;
3817 
3818   return Traversal<HTMLHeadElement>::FirstChild(*de);
3819 }
3820 
ViewportDefiningElement() const3821 Element* Document::ViewportDefiningElement() const {
3822   // If a BODY element sets non-visible overflow, it is to be propagated to the
3823   // viewport, as long as the following conditions are all met:
3824   // (1) The root element is HTML.
3825   // (2) It is the primary BODY element (we only assert for this, expecting
3826   //     callers to behave).
3827   // (3) The root element has visible overflow.
3828   // Otherwise it's the root element's properties that are to be propagated.
3829   Element* root_element = documentElement();
3830   Element* body_element = body();
3831   if (!root_element)
3832     return nullptr;
3833   const ComputedStyle* root_style = root_element->GetComputedStyle();
3834   if (!root_style || root_style->IsEnsuredInDisplayNone())
3835     return nullptr;
3836   if (body_element && root_style->IsOverflowVisible() &&
3837       IsA<HTMLHtmlElement>(root_element))
3838     return body_element;
3839   return root_element;
3840 }
3841 
open(v8::Isolate * isolate,const AtomicString & type,const AtomicString & replace,ExceptionState & exception_state)3842 Document* Document::open(v8::Isolate* isolate,
3843                          const AtomicString& type,
3844                          const AtomicString& replace,
3845                          ExceptionState& exception_state) {
3846   if (replace == "replace") {
3847     CountUse(WebFeature::kDocumentOpenTwoArgsWithReplace);
3848   }
3849   open(EnteredDOMWindow(isolate)->document(), exception_state);
3850   return this;
3851 }
3852 
open(v8::Isolate * isolate,const String & url_string,const AtomicString & name,const AtomicString & features,ExceptionState & exception_state)3853 DOMWindow* Document::open(v8::Isolate* isolate,
3854                           const String& url_string,
3855                           const AtomicString& name,
3856                           const AtomicString& features,
3857                           ExceptionState& exception_state) {
3858   if (!domWindow()) {
3859     exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
3860                                       "The document has no window associated.");
3861     return nullptr;
3862   }
3863 
3864   return domWindow()->open(isolate, url_string, name, features,
3865                            exception_state);
3866 }
3867 
3868 // https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#dom-document-close
close(ExceptionState & exception_state)3869 void Document::close(ExceptionState& exception_state) {
3870   if (ImportLoader()) {
3871     exception_state.ThrowDOMException(
3872         DOMExceptionCode::kInvalidStateError,
3873         "Imported document doesn't support close().");
3874     return;
3875   }
3876 
3877   // If the Document object is an XML document, then throw an
3878   // "InvalidStateError" DOMException.
3879   if (!IsA<HTMLDocument>(this)) {
3880     exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
3881                                       "Only HTML documents support close().");
3882     return;
3883   }
3884 
3885   // If the Document object's throw-on-dynamic-markup-insertion counter is
3886   // greater than zero, then throw an "InvalidStateError" DOMException.
3887   if (throw_on_dynamic_markup_insertion_count_) {
3888     exception_state.ThrowDOMException(
3889         DOMExceptionCode::kInvalidStateError,
3890         "Custom Element constructor should not use close().");
3891     return;
3892   }
3893 
3894   if (!AllowedToUseDynamicMarkUpInsertion("close", exception_state))
3895     return;
3896 
3897   close();
3898 }
3899 
3900 // https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#dom-document-close
close()3901 void Document::close() {
3902   // If there is no script-created parser associated with the document, then
3903   // return.
3904   if (!GetScriptableDocumentParser() ||
3905       !GetScriptableDocumentParser()->WasCreatedByScript() ||
3906       !GetScriptableDocumentParser()->IsParsing())
3907     return;
3908 
3909   // Insert an explicit "EOF" character at the end of the parser's input
3910   // stream.
3911   parser_->Finish();
3912 
3913   // TODO(timothygu): We should follow the specification more closely.
3914   if (!parser_ || !parser_->IsParsing())
3915     SetReadyState(kComplete);
3916   CheckCompleted();
3917 }
3918 
ImplicitClose()3919 void Document::ImplicitClose() {
3920   DCHECK(!InStyleRecalc());
3921 
3922   load_event_progress_ = kLoadEventInProgress;
3923 
3924   // We have to clear the parser, in case someone document.write()s from the
3925   // onLoad event handler, as in Radar 3206524.
3926   DetachParser();
3927 
3928   // JS running below could remove the frame or destroy the LayoutView so we
3929   // call those two functions repeatedly and don't save them on the stack.
3930 
3931   // To align the HTML load event and the SVGLoad event for the outermost <svg>
3932   // element, fire it from here, instead of doing it from
3933   // SVGElement::finishedParsingChildren.
3934   if (SvgExtensions())
3935     AccessSVGExtensions().DispatchSVGLoadEventToOutermostSVGElements();
3936 
3937   if (domWindow())
3938     domWindow()->DocumentWasClosed();
3939 
3940   if (GetFrame() && GetFrame()->IsMainFrame())
3941     GetFrame()->GetLocalFrameHostRemote().DocumentOnLoadCompleted();
3942 
3943   if (GetFrame()) {
3944     GetFrame()->Client()->DispatchDidHandleOnloadEvents();
3945     Loader()->GetApplicationCacheHost()->StopDeferringEvents();
3946   }
3947 
3948   if (!GetFrame()) {
3949     load_event_progress_ = kLoadEventCompleted;
3950     return;
3951   }
3952 
3953   if (GetFrame()->Loader().HasProvisionalNavigation() &&
3954       start_time_.Elapsed() < kCLayoutScheduleThreshold) {
3955     // Just bail out. Before or during the onload we were shifted to another
3956     // page.  The old i-Bench suite does this. When this happens don't bother
3957     // painting or laying out.
3958     load_event_progress_ = kLoadEventCompleted;
3959     return;
3960   }
3961 
3962   // We used to force a synchronous display and flush here.  This really isn't
3963   // necessary and can in fact be actively harmful if pages are loading at a
3964   // rate of > 60fps
3965   // (if your platform is syncing flushes and limiting them to 60fps).
3966   if (!LocalOwner() || (LocalOwner()->GetLayoutObject() &&
3967                         !LocalOwner()->GetLayoutObject()->NeedsLayout())) {
3968     UpdateStyleAndLayoutTree();
3969 
3970     // Always do a layout after loading if needed.
3971     if (View() && GetLayoutView() &&
3972         (!GetLayoutView()->FirstChild() || GetLayoutView()->NeedsLayout()))
3973       View()->UpdateLayout();
3974   }
3975 
3976   load_event_progress_ = kLoadEventCompleted;
3977 
3978   if (GetFrame() && GetLayoutView()) {
3979     if (AXObjectCache* cache = ExistingAXObjectCache()) {
3980       if (this == &AXObjectCacheOwner())
3981         cache->HandleLoadComplete(this);
3982       else
3983         cache->HandleLayoutComplete(this);
3984     }
3985   }
3986 
3987   if (SvgExtensions())
3988     AccessSVGExtensions().StartAnimations();
3989 }
3990 
AllDescendantsAreComplete(Document * document)3991 static bool AllDescendantsAreComplete(Document* document) {
3992   Frame* frame = document->GetFrame();
3993   if (!frame)
3994     return true;
3995   for (Frame* child = frame->Tree().FirstChild(); child;
3996        child = child->Tree().TraverseNext(frame)) {
3997     if (child->IsLoading())
3998       return false;
3999   }
4000   for (PortalContents* portal : DocumentPortals::From(*document).GetPortals()) {
4001     auto* frame = portal->GetFrame();
4002     if (frame && frame->IsLoading())
4003       return false;
4004   }
4005   return true;
4006 }
4007 
ShouldComplete()4008 bool Document::ShouldComplete() {
4009   return parsing_state_ == kFinishedParsing && HaveImportsLoaded() &&
4010          !fetcher_->BlockingRequestCount() && !IsDelayingLoadEvent() &&
4011          !javascript_url_task_handle_.IsActive() &&
4012          load_event_progress_ != kLoadEventInProgress &&
4013          AllDescendantsAreComplete(this) && !Fetcher()->IsInRequestResource();
4014 }
4015 
Abort()4016 void Document::Abort() {
4017   CancelParsing();
4018   CheckCompletedInternal();
4019 }
4020 
CheckCompleted()4021 void Document::CheckCompleted() {
4022   if (CheckCompletedInternal()) {
4023     frame_->Loader().DidFinishNavigation(
4024         FrameLoader::NavigationFinishState::kSuccess);
4025   }
4026 }
4027 
CheckCompletedInternal()4028 bool Document::CheckCompletedInternal() {
4029   if (!ShouldComplete())
4030     return false;
4031 
4032   if (frame_ && !UnloadStarted()) {
4033     frame_->Client()->RunScriptsAtDocumentIdle();
4034 
4035     // Injected scripts may have disconnected this frame.
4036     if (!frame_)
4037       return false;
4038 
4039     // Check again, because runScriptsAtDocumentIdle() may have delayed the load
4040     // event.
4041     if (!ShouldComplete())
4042       return false;
4043   }
4044 
4045   // OK, completed. Fire load completion events as needed.
4046   SetReadyState(kComplete);
4047   if (LoadEventStillNeeded())
4048     ImplicitClose();
4049 
4050   // The readystatechanged or load event may have disconnected this frame.
4051   if (!frame_ || !frame_->IsAttached())
4052     return false;
4053   http_refresh_scheduler_->MaybeStartTimer();
4054   View()->HandleLoadCompleted();
4055   // The document itself is complete, but if a child frame was restarted due to
4056   // an event, this document is still considered to be in progress.
4057   if (!AllDescendantsAreComplete(this))
4058     return false;
4059 
4060   // No need to repeat if we've already notified this load as finished.
4061   if (!Loader()->SentDidFinishLoad()) {
4062     if (frame_->IsMainFrame())
4063       GetViewportData().GetViewportDescription().ReportMobilePageStats(frame_);
4064     Loader()->SetSentDidFinishLoad();
4065     frame_->Client()->DispatchDidFinishLoad();
4066     frame_->GetLocalFrameHostRemote().DidFinishLoad(Loader()->Url());
4067     if (!frame_)
4068       return false;
4069 
4070     // Send the source ID of the document to the browser.
4071     if (frame_->Client()->GetRemoteNavigationAssociatedInterfaces()) {
4072       mojo::AssociatedRemote<mojom::blink::UkmSourceIdFrameHost> ukm_binding;
4073       frame_->Client()->GetRemoteNavigationAssociatedInterfaces()->GetInterface(
4074           &ukm_binding);
4075       DCHECK(ukm_binding.is_bound());
4076       ukm_binding->SetDocumentSourceId(ukm_source_id_);
4077     }
4078 
4079     frame_->GetFrameScheduler()->RegisterStickyFeature(
4080         SchedulingPolicy::Feature::kDocumentLoaded,
4081         {SchedulingPolicy::RecordMetricsForBackForwardCache()});
4082 
4083     AnchorElementMetrics::NotifyOnLoad(*this);
4084 
4085     // If this is a document associated with a resource loading hints based
4086     // preview, then record the resource loading hints UKM now that the load is
4087     // finished.
4088     PreviewsResourceLoadingHints* hints =
4089         Loader()->GetPreviewsResourceLoadingHints();
4090     if (hints) {
4091       hints->RecordUKM(UkmRecorder());
4092     }
4093   }
4094 
4095   if (auto* view = View()) {
4096     if (view->GetFragmentAnchor()) {
4097       // Schedule an animation frame to process fragment anchors. The frame
4098       // can't be scheduled when the fragment anchor is set because, per spec,
4099       // we must wait for the document to be loaded before invoking fragment
4100       // anchors.
4101       View()->ScheduleAnimation();
4102     }
4103   }
4104 
4105   return true;
4106 }
4107 
DispatchBeforeUnloadEvent(ChromeClient * chrome_client,bool is_reload,bool & did_allow_navigation)4108 bool Document::DispatchBeforeUnloadEvent(ChromeClient* chrome_client,
4109                                          bool is_reload,
4110                                          bool& did_allow_navigation) {
4111   if (!dom_window_)
4112     return true;
4113 
4114   if (!body())
4115     return true;
4116 
4117   if (ProcessingBeforeUnload())
4118     return false;
4119 
4120   MainThreadDisallowSynchronousXHRScope disallow_synchronous_xhr;
4121   auto& before_unload_event = *MakeGarbageCollected<BeforeUnloadEvent>();
4122   before_unload_event.initEvent(event_type_names::kBeforeunload, false, true);
4123   load_event_progress_ = kBeforeUnloadEventInProgress;
4124   const base::TimeTicks beforeunload_event_start = base::TimeTicks::Now();
4125   dom_window_->DispatchEvent(before_unload_event, this);
4126   const base::TimeTicks beforeunload_event_end = base::TimeTicks::Now();
4127   load_event_progress_ = kBeforeUnloadEventCompleted;
4128   DEFINE_STATIC_LOCAL(
4129       CustomCountHistogram, beforeunload_histogram,
4130       ("DocumentEventTiming.BeforeUnloadDuration", 0, 10000000, 50));
4131   beforeunload_histogram.CountMicroseconds(beforeunload_event_end -
4132                                            beforeunload_event_start);
4133   if (!before_unload_event.defaultPrevented())
4134     DefaultEventHandler(before_unload_event);
4135 
4136   enum BeforeUnloadDialogHistogramEnum {
4137     kNoDialogNoText,
4138     kNoDialogNoUserGesture,
4139     kNoDialogMultipleConfirmationForNavigation,
4140     kShowDialog,
4141     kNoDialogAutoCancelTrue,
4142     kDialogEnumMax
4143   };
4144   DEFINE_STATIC_LOCAL(EnumerationHistogram, beforeunload_dialog_histogram,
4145                       ("Document.BeforeUnloadDialog", kDialogEnumMax));
4146   if (before_unload_event.returnValue().IsNull()) {
4147     beforeunload_dialog_histogram.Count(kNoDialogNoText);
4148   }
4149   if (!GetFrame() || before_unload_event.returnValue().IsNull())
4150     return true;
4151 
4152   if (!GetFrame()->HasStickyUserActivation()) {
4153     beforeunload_dialog_histogram.Count(kNoDialogNoUserGesture);
4154     String message =
4155         "Blocked attempt to show a 'beforeunload' confirmation panel for a "
4156         "frame that never had a user gesture since its load. "
4157         "https://www.chromestatus.com/feature/5082396709879808";
4158     Intervention::GenerateReport(frame_, "BeforeUnloadNoGesture", message);
4159     return true;
4160   }
4161 
4162   if (did_allow_navigation) {
4163     beforeunload_dialog_histogram.Count(
4164         kNoDialogMultipleConfirmationForNavigation);
4165     String message =
4166         "Blocked attempt to show multiple 'beforeunload' confirmation panels "
4167         "for a single navigation.";
4168     Intervention::GenerateReport(frame_, "BeforeUnloadMultiple", message);
4169     return true;
4170   }
4171 
4172   // If |chrome_client| is null simply indicate that the navigation should
4173   // not proceed.
4174   if (!chrome_client) {
4175     beforeunload_dialog_histogram.Count(kNoDialogAutoCancelTrue);
4176     did_allow_navigation = false;
4177     return false;
4178   }
4179 
4180   String text = before_unload_event.returnValue();
4181   beforeunload_dialog_histogram.Count(
4182       BeforeUnloadDialogHistogramEnum::kShowDialog);
4183   const base::TimeTicks beforeunload_confirmpanel_start =
4184       base::TimeTicks::Now();
4185   did_allow_navigation =
4186       chrome_client->OpenBeforeUnloadConfirmPanel(text, frame_, is_reload);
4187   const base::TimeTicks beforeunload_confirmpanel_end = base::TimeTicks::Now();
4188   if (did_allow_navigation) {
4189     // Only record when a navigation occurs, since we want to understand
4190     // the impact of the before unload dialog on overall input to navigation.
4191     UMA_HISTOGRAM_MEDIUM_TIMES(
4192         "DocumentEventTiming.BeforeUnloadDialogDuration.ByNavigation",
4193         beforeunload_confirmpanel_end - beforeunload_confirmpanel_start);
4194     return true;
4195   }
4196 
4197   return false;
4198 }
4199 
DispatchUnloadEvents(SecurityOrigin * committing_origin,base::Optional<Document::UnloadEventTiming> * unload_timing)4200 void Document::DispatchUnloadEvents(
4201     SecurityOrigin* committing_origin,
4202     base::Optional<Document::UnloadEventTiming>* unload_timing) {
4203   PluginScriptForbiddenScope forbid_plugin_destructor_scripting;
4204   MainThreadDisallowSynchronousXHRScope disallow_synchronous_xhr;
4205   if (parser_)
4206     parser_->StopParsing();
4207 
4208   if (load_event_progress_ == kLoadEventNotRun)
4209     return;
4210 
4211   if (load_event_progress_ <= kUnloadEventInProgress) {
4212     Element* current_focused_element = FocusedElement();
4213     if (auto* input = DynamicTo<HTMLInputElement>(current_focused_element))
4214       input->EndEditing();
4215     if (load_event_progress_ < kPageHideInProgress) {
4216       load_event_progress_ = kPageHideInProgress;
4217       if (LocalDOMWindow* window = domWindow()) {
4218         const base::TimeTicks pagehide_event_start = base::TimeTicks::Now();
4219         window->DispatchEvent(
4220             *PageTransitionEvent::Create(event_type_names::kPagehide, false),
4221             this);
4222         const base::TimeTicks pagehide_event_end = base::TimeTicks::Now();
4223         DEFINE_STATIC_LOCAL(
4224             CustomCountHistogram, pagehide_histogram,
4225             ("DocumentEventTiming.PageHideDuration", 0, 10000000, 50));
4226         pagehide_histogram.CountMicroseconds(pagehide_event_end -
4227                                              pagehide_event_start);
4228       }
4229       if (!frame_)
4230         return;
4231 
4232       // This must be queried before |load_event_progress_| is changed to
4233       // kUnloadVisibilityChangeInProgress because that would change the result.
4234       bool page_visible = IsPageVisible();
4235       load_event_progress_ = kUnloadVisibilityChangeInProgress;
4236       if (page_visible) {
4237         // Dispatch visibilitychange event, but don't bother doing
4238         // other notifications as we're about to be unloaded.
4239         const base::TimeTicks pagevisibility_hidden_event_start =
4240             base::TimeTicks::Now();
4241         DispatchEvent(
4242             *Event::CreateBubble(event_type_names::kVisibilitychange));
4243         const base::TimeTicks pagevisibility_hidden_event_end =
4244             base::TimeTicks::Now();
4245         DEFINE_STATIC_LOCAL(CustomCountHistogram, pagevisibility_histogram,
4246                             ("DocumentEventTiming.PageVibilityHiddenDuration",
4247                              0, 10000000, 50));
4248         pagevisibility_histogram.CountMicroseconds(
4249             pagevisibility_hidden_event_end -
4250             pagevisibility_hidden_event_start);
4251         DispatchEvent(
4252             *Event::CreateBubble(event_type_names::kWebkitvisibilitychange));
4253       }
4254       if (!frame_)
4255         return;
4256 
4257       frame_->Loader().SaveScrollAnchor();
4258 
4259       load_event_progress_ = kUnloadEventInProgress;
4260       Event& unload_event = *Event::Create(event_type_names::kUnload);
4261       const base::TimeTicks unload_event_start = base::TimeTicks::Now();
4262       frame_->DomWindow()->DispatchEvent(unload_event, this);
4263       const base::TimeTicks unload_event_end = base::TimeTicks::Now();
4264 
4265       if (unload_timing) {
4266         // Record unload event timing when navigating cross-document.
4267         DEFINE_STATIC_LOCAL(
4268             CustomCountHistogram, unload_histogram,
4269             ("DocumentEventTiming.UnloadDuration", 0, 10000000, 50));
4270         unload_histogram.CountMicroseconds(unload_event_end -
4271                                            unload_event_start);
4272 
4273         // Fill in the unload timing if the new document origin has access to
4274         // them.
4275         if (committing_origin->CanRequest(Url())) {
4276           auto& timing = unload_timing->emplace();
4277           timing.unload_event_start = unload_event_start;
4278           timing.unload_event_end = unload_event_end;
4279         }
4280       }
4281     }
4282     load_event_progress_ = kUnloadEventHandled;
4283   }
4284 }
4285 
DispatchFreezeEvent()4286 void Document::DispatchFreezeEvent() {
4287   const base::TimeTicks freeze_event_start = base::TimeTicks::Now();
4288   SetFreezingInProgress(true);
4289   DispatchEvent(*Event::Create(event_type_names::kFreeze));
4290   SetFreezingInProgress(false);
4291   const base::TimeTicks freeze_event_end = base::TimeTicks::Now();
4292   DEFINE_STATIC_LOCAL(CustomCountHistogram, freeze_histogram,
4293                       ("DocumentEventTiming.FreezeDuration", 0, 10000000, 50));
4294   freeze_histogram.CountMicroseconds(freeze_event_end - freeze_event_start);
4295   UseCounter::Count(*this, WebFeature::kPageLifeCycleFreeze);
4296 }
4297 
PageDismissalEventBeingDispatched() const4298 Document::PageDismissalType Document::PageDismissalEventBeingDispatched()
4299     const {
4300   switch (load_event_progress_) {
4301     case kBeforeUnloadEventInProgress:
4302       return kBeforeUnloadDismissal;
4303     case kPageHideInProgress:
4304       return kPageHideDismissal;
4305     case kUnloadVisibilityChangeInProgress:
4306       return kUnloadVisibilityChangeDismissal;
4307     case kUnloadEventInProgress:
4308       return kUnloadDismissal;
4309 
4310     case kLoadEventNotRun:
4311     case kLoadEventInProgress:
4312     case kLoadEventCompleted:
4313     case kBeforeUnloadEventCompleted:
4314     case kUnloadEventHandled:
4315       return kNoDismissal;
4316   }
4317   NOTREACHED();
4318   return kNoDismissal;
4319 }
4320 
SetParsingState(ParsingState parsing_state)4321 void Document::SetParsingState(ParsingState parsing_state) {
4322   ParsingState previous_state = parsing_state_;
4323   parsing_state_ = parsing_state;
4324 
4325   if (Parsing() && !element_data_cache_)
4326     element_data_cache_ = MakeGarbageCollected<ElementDataCache>();
4327   if (previous_state != kFinishedParsing &&
4328       parsing_state_ == kFinishedParsing) {
4329     if (form_controller_ && form_controller_->HasControlStates())
4330       form_controller_->ScheduleRestore();
4331   }
4332 }
4333 
ShouldScheduleLayout() const4334 bool Document::ShouldScheduleLayout() const {
4335   // This function will only be called when LocalFrameView thinks a layout is
4336   // needed. This enforces a couple extra rules.
4337   //
4338   //    (a) Only schedule a layout once the stylesheets are loaded.
4339   //    (b) Only schedule layout once we have a body element.
4340   if (!IsActive())
4341     return false;
4342 
4343   if (HaveRenderBlockingResourcesLoaded() && body())
4344     return true;
4345 
4346   if (documentElement() && !IsA<HTMLHtmlElement>(documentElement()))
4347     return true;
4348 
4349   return false;
4350 }
4351 
write(const String & text,Document * entered_document,ExceptionState & exception_state)4352 void Document::write(const String& text,
4353                      Document* entered_document,
4354                      ExceptionState& exception_state) {
4355   if (ImportLoader()) {
4356     exception_state.ThrowDOMException(
4357         DOMExceptionCode::kInvalidStateError,
4358         "Imported document doesn't support write().");
4359     return;
4360   }
4361 
4362   if (!IsA<HTMLDocument>(this)) {
4363     exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
4364                                       "Only HTML documents support write().");
4365     return;
4366   }
4367 
4368   if (throw_on_dynamic_markup_insertion_count_) {
4369     exception_state.ThrowDOMException(
4370         DOMExceptionCode::kInvalidStateError,
4371         "Custom Element constructor should not use write().");
4372     return;
4373   }
4374 
4375   if (entered_document && !GetSecurityOrigin()->IsSameOriginWith(
4376                               entered_document->GetSecurityOrigin())) {
4377     exception_state.ThrowSecurityError(
4378         "Can only call write() on same-origin documents.");
4379     return;
4380   }
4381 
4382   if (ignore_opens_and_writes_for_abort_)
4383     return;
4384 
4385   NestingLevelIncrementer nesting_level_incrementer(write_recursion_depth_);
4386 
4387   write_recursion_is_too_deep_ =
4388       (write_recursion_depth_ > 1) && write_recursion_is_too_deep_;
4389   write_recursion_is_too_deep_ =
4390       (write_recursion_depth_ > kCMaxWriteRecursionDepth) ||
4391       write_recursion_is_too_deep_;
4392 
4393   if (write_recursion_is_too_deep_)
4394     return;
4395 
4396   bool has_insertion_point = parser_ && parser_->HasInsertionPoint();
4397 
4398   if (!has_insertion_point) {
4399     if (ignore_destructive_write_count_) {
4400       AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
4401           mojom::ConsoleMessageSource::kJavaScript,
4402           mojom::ConsoleMessageLevel::kWarning,
4403           ExceptionMessages::FailedToExecute(
4404               "write", "Document",
4405               "It isn't possible to write into a document "
4406               "from an asynchronously-loaded external "
4407               "script unless it is explicitly opened.")));
4408       return;
4409     }
4410     if (ignore_opens_during_unload_count_)
4411       return;
4412 
4413     open(entered_document, ASSERT_NO_EXCEPTION);
4414   }
4415 
4416   DCHECK(parser_);
4417   PerformanceMonitor::ReportGenericViolation(
4418       domWindow(), PerformanceMonitor::kDiscouragedAPIUse,
4419       "Avoid using document.write(). "
4420       "https://developers.google.com/web/updates/2016/08/"
4421       "removing-document-write",
4422       base::TimeDelta(), nullptr);
4423   probe::BreakableLocation(domWindow(), "Document.write");
4424   parser_->insert(text);
4425 }
4426 
writeln(const String & text,Document * entered_document,ExceptionState & exception_state)4427 void Document::writeln(const String& text,
4428                        Document* entered_document,
4429                        ExceptionState& exception_state) {
4430   write(text, entered_document, exception_state);
4431   if (exception_state.HadException())
4432     return;
4433   write("\n", entered_document);
4434 }
4435 
write(v8::Isolate * isolate,const Vector<String> & text,ExceptionState & exception_state)4436 void Document::write(v8::Isolate* isolate,
4437                      const Vector<String>& text,
4438                      ExceptionState& exception_state) {
4439   if (!AllowedToUseDynamicMarkUpInsertion("write", exception_state))
4440     return;
4441 
4442   StringBuilder builder;
4443   for (const String& string : text)
4444     builder.Append(string);
4445   String string =
4446       TrustedTypesCheckForHTML(builder.ToString(), this, exception_state);
4447   if (exception_state.HadException())
4448     return;
4449 
4450   write(string, EnteredDOMWindow(isolate)->document(), exception_state);
4451 }
4452 
writeln(v8::Isolate * isolate,const Vector<String> & text,ExceptionState & exception_state)4453 void Document::writeln(v8::Isolate* isolate,
4454                        const Vector<String>& text,
4455                        ExceptionState& exception_state) {
4456   if (!AllowedToUseDynamicMarkUpInsertion("writeln", exception_state))
4457     return;
4458 
4459   StringBuilder builder;
4460   for (const String& string : text)
4461     builder.Append(string);
4462   String string =
4463       TrustedTypesCheckForHTML(builder.ToString(), this, exception_state);
4464   if (exception_state.HadException())
4465     return;
4466 
4467   writeln(string, EnteredDOMWindow(isolate)->document(), exception_state);
4468 }
4469 
IsTrustedTypesEnabledForDoc() const4470 bool Document::IsTrustedTypesEnabledForDoc() const {
4471   return GetExecutionContext()->RequireTrustedTypes();
4472 }
4473 
write(v8::Isolate * isolate,TrustedHTML * text,ExceptionState & exception_state)4474 void Document::write(v8::Isolate* isolate,
4475                      TrustedHTML* text,
4476                      ExceptionState& exception_state) {
4477   DCHECK(RuntimeEnabledFeatures::TrustedDOMTypesEnabled(this));
4478   write(text->toString(), EnteredDOMWindow(isolate)->document(),
4479         exception_state);
4480 }
4481 
writeln(v8::Isolate * isolate,TrustedHTML * text,ExceptionState & exception_state)4482 void Document::writeln(v8::Isolate* isolate,
4483                        TrustedHTML* text,
4484                        ExceptionState& exception_state) {
4485   DCHECK(RuntimeEnabledFeatures::TrustedDOMTypesEnabled(this));
4486   writeln(text->toString(), EnteredDOMWindow(isolate)->document(),
4487           exception_state);
4488 }
4489 
urlForBinding() const4490 KURL Document::urlForBinding() const {
4491   if (WebBundleClaimedUrl().IsValid()) {
4492     return WebBundleClaimedUrl();
4493   }
4494   if (!Url().IsNull()) {
4495     return Url();
4496   }
4497   return BlankURL();
4498 }
4499 
SetURL(const KURL & url)4500 void Document::SetURL(const KURL& url) {
4501   KURL new_url = url.IsEmpty() ? BlankURL() : url;
4502   if (new_url == url_)
4503     return;
4504 
4505   // Count non-targetText occurrences of :~: in the url fragment to make sure
4506   // the delimiter is web-compatible. This can be removed once the feature
4507   // ships.
4508   wtf_size_t delim_pos = new_url.FragmentIdentifier().Find(":~:");
4509   if (delim_pos != kNotFound) {
4510     const wtf_size_t one_past_delim = delim_pos + 3;
4511     if (new_url.FragmentIdentifier().Find(kTextFragmentIdentifierPrefix,
4512                                           one_past_delim) != one_past_delim) {
4513       // We can't use count here because the DocumentLoader hasn't yet been
4514       // created. It'll be use counted with other delimiters in
4515       // FragmentAnchor::TryCreate.
4516       use_count_fragment_directive_ = true;
4517     }
4518   }
4519 
4520   // If text fragment identifiers are enabled, we strip the fragment directive
4521   // from the URL fragment.
4522   // E.g. "#id:~:text=a" --> "#id"
4523   if (RuntimeEnabledFeatures::TextFragmentIdentifiersEnabled(this)) {
4524     String fragment = new_url.FragmentIdentifier();
4525     wtf_size_t start_pos = fragment.Find(kFragmentDirectivePrefix);
4526     if (start_pos != kNotFound) {
4527       fragment_directive_ =
4528           fragment.Substring(start_pos + kFragmentDirectivePrefixStringLength);
4529 
4530       if (start_pos == 0)
4531         new_url.RemoveFragmentIdentifier();
4532       else
4533         new_url.SetFragmentIdentifier(fragment.Substring(0, start_pos));
4534     }
4535   }
4536 
4537   url_ = new_url;
4538   access_entry_from_url_ = nullptr;
4539   UpdateBaseURL();
4540   GetContextFeatures().UrlDidChange(this);
4541 
4542   // TODO(crbug/795354): Move handling of URL recording out of the renderer.
4543   // URL must only be recorded from the main frame.
4544   if (ukm_recorder_ && IsInMainFrame())
4545     ukm_recorder_->UpdateSourceURL(ukm_source_id_, url_);
4546 
4547   if (frame_) {
4548     if (FrameScheduler* frame_scheduler = frame_->GetFrameScheduler())
4549       frame_scheduler->TraceUrlChange(url_.GetString());
4550   }
4551 }
4552 
ValidBaseElementURL() const4553 KURL Document::ValidBaseElementURL() const {
4554   if (base_element_url_.IsValid())
4555     return base_element_url_;
4556 
4557   return KURL();
4558 }
4559 
UpdateBaseURL()4560 void Document::UpdateBaseURL() {
4561   KURL old_base_url = base_url_;
4562   // DOM 3 Core: When the Document supports the feature "HTML" [DOM Level 2
4563   // HTML], the base URI is computed using first the value of the href attribute
4564   // of the HTML BASE element if any, and the value of the documentURI attribute
4565   // from the Document interface otherwise (which we store, preparsed, in
4566   // |url_|).
4567   if (!base_element_url_.IsEmpty())
4568     base_url_ = base_element_url_;
4569   else if (!base_url_override_.IsEmpty())
4570     base_url_ = base_url_override_;
4571   else
4572     base_url_ = FallbackBaseURL();
4573 
4574   GetSelectorQueryCache().Invalidate();
4575 
4576   if (!base_url_.IsValid())
4577     base_url_ = KURL();
4578 
4579   if (elem_sheet_) {
4580     // Element sheet is silly. It never contains anything.
4581     DCHECK(!elem_sheet_->Contents()->RuleCount());
4582     elem_sheet_ = CSSStyleSheet::CreateInline(*this, base_url_);
4583   }
4584 
4585   if (!EqualIgnoringFragmentIdentifier(old_base_url, base_url_)) {
4586     // Base URL change changes any relative visited links.
4587     // FIXME: There are other URLs in the tree that would need to be
4588     // re-evaluated on dynamic base URL change. Style should be invalidated too.
4589     for (HTMLAnchorElement& anchor :
4590          Traversal<HTMLAnchorElement>::StartsAfter(*this))
4591       anchor.InvalidateCachedVisitedLinkHash();
4592   }
4593 }
4594 
FallbackBaseURL() const4595 KURL Document::FallbackBaseURL() const {
4596   if (IsSrcdocDocument()) {
4597     // TODO(tkent): Referring to ParentDocument() is not correct.  See
4598     // crbug.com/751329.
4599     if (Document* parent = ParentDocument())
4600       return parent->BaseURL();
4601   } else if (urlForBinding().IsAboutBlankURL()) {
4602     if (context_document_)
4603       return context_document_->BaseURL();
4604     // TODO(tkent): Referring to ParentDocument() is not correct.  See
4605     // crbug.com/751329.
4606     if (Document* parent = ParentDocument())
4607       return parent->BaseURL();
4608   }
4609   return urlForBinding();
4610 }
4611 
BaseURL() const4612 const KURL& Document::BaseURL() const {
4613   if (!base_url_.IsNull())
4614     return base_url_;
4615   return BlankURL();
4616 }
4617 
SetBaseURLOverride(const KURL & url)4618 void Document::SetBaseURLOverride(const KURL& url) {
4619   base_url_override_ = url;
4620   UpdateBaseURL();
4621 }
4622 
ProcessBaseElement()4623 void Document::ProcessBaseElement() {
4624   UseCounter::Count(*this, WebFeature::kBaseElement);
4625 
4626   // Find the first href attribute in a base element and the first target
4627   // attribute in a base element.
4628   const AtomicString* href = nullptr;
4629   const AtomicString* target = nullptr;
4630   for (HTMLBaseElement* base = Traversal<HTMLBaseElement>::FirstWithin(*this);
4631        base && (!href || !target);
4632        base = Traversal<HTMLBaseElement>::Next(*base)) {
4633     if (!href) {
4634       const AtomicString& value = base->FastGetAttribute(html_names::kHrefAttr);
4635       if (!value.IsNull())
4636         href = &value;
4637     }
4638     if (!target) {
4639       const AtomicString& value =
4640           base->FastGetAttribute(html_names::kTargetAttr);
4641       if (!value.IsNull())
4642         target = &value;
4643     }
4644     if (GetContentSecurityPolicy()->IsActive()) {
4645       UseCounter::Count(*this,
4646                         WebFeature::kContentSecurityPolicyWithBaseElement);
4647     }
4648   }
4649 
4650   // FIXME: Since this doesn't share code with completeURL it may not handle
4651   // encodings correctly.
4652   KURL base_element_url;
4653   if (href) {
4654     String stripped_href = StripLeadingAndTrailingHTMLSpaces(*href);
4655     if (!stripped_href.IsEmpty())
4656       base_element_url = KURL(FallbackBaseURL(), stripped_href);
4657   }
4658 
4659   if (!base_element_url.IsEmpty()) {
4660     if (base_element_url.ProtocolIsData() ||
4661         base_element_url.ProtocolIsJavaScript()) {
4662       UseCounter::Count(*this, WebFeature::kBaseWithDataHref);
4663       AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
4664           mojom::ConsoleMessageSource::kSecurity,
4665           mojom::ConsoleMessageLevel::kError,
4666           "'" + base_element_url.Protocol() +
4667               "' URLs may not be used as base URLs for a document."));
4668     }
4669     if (!GetSecurityOrigin()->CanRequest(base_element_url))
4670       UseCounter::Count(*this, WebFeature::kBaseWithCrossOriginHref);
4671   }
4672 
4673   if (base_element_url != base_element_url_ &&
4674       !base_element_url.ProtocolIsData() &&
4675       !base_element_url.ProtocolIsJavaScript() &&
4676       GetContentSecurityPolicy()->AllowBaseURI(base_element_url)) {
4677     base_element_url_ = base_element_url;
4678     UpdateBaseURL();
4679   }
4680 
4681   if (target) {
4682     if (target->Contains('\n') || target->Contains('\r'))
4683       UseCounter::Count(*this, WebFeature::kBaseWithNewlinesInTarget);
4684     if (target->Contains('<'))
4685       UseCounter::Count(*this, WebFeature::kBaseWithOpenBracketInTarget);
4686     base_target_ = *target;
4687   } else {
4688     base_target_ = g_null_atom;
4689   }
4690 }
4691 
UserAgent() const4692 String Document::UserAgent() const {
4693   return GetFrame() ? GetFrame()->Loader().UserAgent() : String();
4694 }
4695 
DidLoadAllImports()4696 void Document::DidLoadAllImports() {
4697   if (!HaveScriptBlockingStylesheetsLoaded())
4698     return;
4699   DidLoadAllScriptBlockingResources();
4700 }
4701 
DidAddPendingParserBlockingStylesheet()4702 void Document::DidAddPendingParserBlockingStylesheet() {
4703   if (ScriptableDocumentParser* parser = GetScriptableDocumentParser())
4704     parser->DidAddPendingParserBlockingStylesheet();
4705 }
4706 
DidRemoveAllPendingStylesheets()4707 void Document::DidRemoveAllPendingStylesheets() {
4708   // Only imports on master documents can trigger rendering.
4709   if (HTMLImportLoader* import = ImportLoader())
4710     import->DidRemoveAllPendingStylesheets();
4711   if (!HaveImportsLoaded())
4712     return;
4713   DidLoadAllScriptBlockingResources();
4714 }
4715 
DidLoadAllPendingParserBlockingStylesheets()4716 void Document::DidLoadAllPendingParserBlockingStylesheets() {
4717   if (ScriptableDocumentParser* parser = GetScriptableDocumentParser())
4718     parser->DidLoadAllPendingParserBlockingStylesheets();
4719 }
4720 
DidLoadAllScriptBlockingResources()4721 void Document::DidLoadAllScriptBlockingResources() {
4722   // Use wrapWeakPersistent because the task should not keep this Document alive
4723   // just for executing scripts.
4724   execute_scripts_waiting_for_resources_task_handle_ = PostCancellableTask(
4725       *GetTaskRunner(TaskType::kNetworking), FROM_HERE,
4726       WTF::Bind(&Document::ExecuteScriptsWaitingForResources,
4727                 WrapWeakPersistent(this)));
4728 
4729   if (IsA<HTMLDocument>(this) && body()) {
4730     // For HTML if we have no more stylesheets to load and we're past the body
4731     // tag, we should have something to paint so resume.
4732     BeginLifecycleUpdatesIfRenderingReady();
4733   } else if (!IsA<HTMLDocument>(this) && documentElement()) {
4734     // For non-HTML there is no body so resume as soon as the sheets are loaded.
4735     BeginLifecycleUpdatesIfRenderingReady();
4736   }
4737 }
4738 
ExecuteScriptsWaitingForResources()4739 void Document::ExecuteScriptsWaitingForResources() {
4740   if (!IsScriptExecutionReady())
4741     return;
4742   if (ScriptableDocumentParser* parser = GetScriptableDocumentParser())
4743     parser->ExecuteScriptsWaitingForResources();
4744 }
4745 
ElementSheet()4746 CSSStyleSheet& Document::ElementSheet() {
4747   if (!elem_sheet_)
4748     elem_sheet_ = CSSStyleSheet::CreateInline(*this, base_url_);
4749   return *elem_sheet_;
4750 }
4751 
MaybeHandleHttpRefresh(const String & content,HttpRefreshType http_refresh_type)4752 void Document::MaybeHandleHttpRefresh(const String& content,
4753                                       HttpRefreshType http_refresh_type) {
4754   if (is_view_source_ || !frame_)
4755     return;
4756 
4757   base::TimeDelta delay;
4758   String refresh_url_string;
4759   if (!ParseHTTPRefresh(content,
4760                         http_refresh_type == kHttpRefreshFromMetaTag
4761                             ? IsHTMLSpace<UChar>
4762                             : nullptr,
4763                         delay, refresh_url_string))
4764     return;
4765   KURL refresh_url =
4766       refresh_url_string.IsEmpty() ? Url() : CompleteURL(refresh_url_string);
4767 
4768   if (refresh_url.ProtocolIsJavaScript()) {
4769     String message =
4770         "Refused to refresh " + url_.ElidedString() + " to a javascript: URL";
4771     AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
4772         mojom::ConsoleMessageSource::kSecurity,
4773         mojom::ConsoleMessageLevel::kError, message));
4774     return;
4775   }
4776 
4777   if (http_refresh_type == kHttpRefreshFromMetaTag &&
4778       IsSandboxed(mojom::blink::WebSandboxFlags::kAutomaticFeatures)) {
4779     String message =
4780         "Refused to execute the redirect specified via '<meta "
4781         "http-equiv='refresh' content='...'>'. The document is sandboxed, and "
4782         "the 'allow-scripts' keyword is not set.";
4783     AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
4784         mojom::ConsoleMessageSource::kSecurity,
4785         mojom::ConsoleMessageLevel::kError, message));
4786     return;
4787   }
4788   if (http_refresh_type == kHttpRefreshFromHeader) {
4789     UseCounter::Count(this, WebFeature::kRefreshHeader);
4790   }
4791   http_refresh_scheduler_->Schedule(delay, refresh_url, http_refresh_type);
4792 }
4793 
IsHttpRefreshScheduledWithin(base::TimeDelta interval)4794 bool Document::IsHttpRefreshScheduledWithin(base::TimeDelta interval) {
4795   return http_refresh_scheduler_->IsScheduledWithin(interval);
4796 }
4797 
4798 // https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer
OutgoingReferrer() const4799 String Document::OutgoingReferrer() const {
4800   // Step 3.1: "If environment's global object is a Window object, then"
4801 
4802   // Step 3.1.1: "Let document be the associated Document of environment's
4803   // global object."
4804   const Document* referrer_document = this;
4805 
4806   // Step 3.1.2: "If document's origin is an opaque origin, return no referrer."
4807   if (GetSecurityOrigin()->IsOpaque())
4808     return String();
4809 
4810   // Step 3.1.3: "While document is an iframe srcdoc document, let document be
4811   // document's browsing context's browsing context container's node document."
4812   if (LocalFrame* frame = frame_) {
4813     while (frame->GetDocument()->IsSrcdocDocument()) {
4814       // Srcdoc documents must be local within the containing frame.
4815       frame = To<LocalFrame>(frame->Tree().Parent());
4816       // Srcdoc documents cannot be top-level documents, by definition,
4817       // because they need to be contained in iframes with the srcdoc.
4818       DCHECK(frame);
4819     }
4820     referrer_document = frame->GetDocument();
4821   }
4822 
4823   // Step: 3.1.4: "Let referrerSource be document's URL."
4824   return referrer_document->url_.StrippedForUseAsReferrer();
4825 }
4826 
GetReferrerPolicy() const4827 network::mojom::ReferrerPolicy Document::GetReferrerPolicy() const {
4828   return GetExecutionContext() ? GetExecutionContext()->GetReferrerPolicy()
4829                                : network::mojom::ReferrerPolicy::kDefault;
4830 }
4831 
PerformMouseEventHitTest(const HitTestRequest & request,const PhysicalOffset & document_point,const WebMouseEvent & event)4832 MouseEventWithHitTestResults Document::PerformMouseEventHitTest(
4833     const HitTestRequest& request,
4834     const PhysicalOffset& document_point,
4835     const WebMouseEvent& event) {
4836   DCHECK(!GetLayoutView() || IsA<LayoutView>(GetLayoutView()));
4837 
4838   // LayoutView::hitTest causes a layout, and we don't want to hit that until
4839   // the first layout because until then, there is nothing shown on the screen -
4840   // the user can't have intentionally clicked on something belonging to this
4841   // page.  Furthermore, mousemove events before the first layout should not
4842   // lead to a premature layout() happening, which could show a flash of white.
4843   // See also the similar code in EventHandler::hitTestResultAtPoint.
4844   if (!GetLayoutView() || !View() || !View()->DidFirstLayout()) {
4845     HitTestLocation location((PhysicalOffset()));
4846     return MouseEventWithHitTestResults(event, location,
4847                                         HitTestResult(request, location));
4848   }
4849 
4850   HitTestLocation location(document_point);
4851   HitTestResult result(request, location);
4852   GetLayoutView()->HitTest(location, result);
4853 
4854   if (!request.ReadOnly()) {
4855     UpdateHoverActiveState(request.Active(), !request.Move(),
4856                            result.InnerElement());
4857   }
4858 
4859   if (auto* canvas = DynamicTo<HTMLCanvasElement>(result.InnerNode())) {
4860     HitTestCanvasResult* hit_test_canvas_result =
4861         canvas->GetControlAndIdIfHitRegionExists(
4862             result.PointInInnerNodeFrame());
4863     if (hit_test_canvas_result->GetControl()) {
4864       result.SetInnerNode(hit_test_canvas_result->GetControl());
4865     }
4866     result.SetCanvasRegionId(hit_test_canvas_result->GetId());
4867   }
4868 
4869   return MouseEventWithHitTestResults(event, location, result);
4870 }
4871 
4872 // DOM Section 1.1.1
ChildTypeAllowed(NodeType type) const4873 bool Document::ChildTypeAllowed(NodeType type) const {
4874   switch (type) {
4875     case kAttributeNode:
4876     case kCdataSectionNode:
4877     case kDocumentFragmentNode:
4878     case kDocumentNode:
4879     case kTextNode:
4880       return false;
4881     case kCommentNode:
4882     case kProcessingInstructionNode:
4883       return true;
4884     case kDocumentTypeNode:
4885     case kElementNode:
4886       // Documents may contain no more than one of each of these.
4887       // (One Element and one DocumentType.)
4888       for (Node& c : NodeTraversal::ChildrenOf(*this)) {
4889         if (c.getNodeType() == type)
4890           return false;
4891       }
4892       return true;
4893   }
4894   return false;
4895 }
4896 
4897 // This is an implementation of step 6 of
4898 // https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
4899 // and https://dom.spec.whatwg.org/#concept-node-replace .
4900 //
4901 // 6. If parent is a document, and any of the statements below, switched on
4902 // node, are true, throw a HierarchyRequestError.
4903 //  -> DocumentFragment node
4904 //     If node has more than one element child or has a Text node child.
4905 //     Otherwise, if node has one element child and either parent has an element
4906 //     child, child is a doctype, or child is not null and a doctype is
4907 //     following child.
4908 //  -> element
4909 //     parent has an element child, child is a doctype, or child is not null and
4910 //     a doctype is following child.
4911 //  -> doctype
4912 //     parent has a doctype child, child is non-null and an element is preceding
4913 //     child, or child is null and parent has an element child.
4914 //
4915 // 6. If parent is a document, and any of the statements below, switched on
4916 // node, are true, throw a HierarchyRequestError.
4917 //  -> DocumentFragment node
4918 //     If node has more than one element child or has a Text node child.
4919 //     Otherwise, if node has one element child and either parent has an element
4920 //     child that is not child or a doctype is following child.
4921 //  -> element
4922 //     parent has an element child that is not child or a doctype is following
4923 //     child.
4924 //  -> doctype
4925 //     parent has a doctype child that is not child, or an element is preceding
4926 //     child.
CanAcceptChild(const Node & new_child,const Node * next,const Node * old_child,ExceptionState & exception_state) const4927 bool Document::CanAcceptChild(const Node& new_child,
4928                               const Node* next,
4929                               const Node* old_child,
4930                               ExceptionState& exception_state) const {
4931   DCHECK(!(next && old_child));
4932   if (old_child && old_child->getNodeType() == new_child.getNodeType())
4933     return true;
4934 
4935   int num_doctypes = 0;
4936   int num_elements = 0;
4937   bool has_doctype_after_reference_node = false;
4938   bool has_element_after_reference_node = false;
4939 
4940   // First, check how many doctypes and elements we have, not counting
4941   // the child we're about to remove.
4942   bool saw_reference_node = false;
4943   for (Node& child : NodeTraversal::ChildrenOf(*this)) {
4944     if (old_child && *old_child == child) {
4945       saw_reference_node = true;
4946       continue;
4947     }
4948     if (&child == next)
4949       saw_reference_node = true;
4950 
4951     switch (child.getNodeType()) {
4952       case kDocumentTypeNode:
4953         num_doctypes++;
4954         has_doctype_after_reference_node = saw_reference_node;
4955         break;
4956       case kElementNode:
4957         num_elements++;
4958         has_element_after_reference_node = saw_reference_node;
4959         break;
4960       default:
4961         break;
4962     }
4963   }
4964 
4965   // Then, see how many doctypes and elements might be added by the new child.
4966   if (auto* new_child_fragment = DynamicTo<DocumentFragment>(new_child)) {
4967     for (Node& child : NodeTraversal::ChildrenOf(*new_child_fragment)) {
4968       switch (child.getNodeType()) {
4969         case kAttributeNode:
4970         case kCdataSectionNode:
4971         case kDocumentFragmentNode:
4972         case kDocumentNode:
4973         case kTextNode:
4974           exception_state.ThrowDOMException(
4975               DOMExceptionCode::kHierarchyRequestError,
4976               "Nodes of type '" + new_child.nodeName() +
4977                   "' may not be inserted inside nodes of type '#document'.");
4978           return false;
4979         case kCommentNode:
4980         case kProcessingInstructionNode:
4981           break;
4982         case kDocumentTypeNode:
4983           num_doctypes++;
4984           break;
4985         case kElementNode:
4986           num_elements++;
4987           if (has_doctype_after_reference_node) {
4988             exception_state.ThrowDOMException(
4989                 DOMExceptionCode::kHierarchyRequestError,
4990                 "Can't insert an element before a doctype.");
4991             return false;
4992           }
4993           break;
4994       }
4995     }
4996   } else {
4997     switch (new_child.getNodeType()) {
4998       case kAttributeNode:
4999       case kCdataSectionNode:
5000       case kDocumentFragmentNode:
5001       case kDocumentNode:
5002       case kTextNode:
5003         exception_state.ThrowDOMException(
5004             DOMExceptionCode::kHierarchyRequestError,
5005             "Nodes of type '" + new_child.nodeName() +
5006                 "' may not be inserted inside nodes of type '#document'.");
5007         return false;
5008       case kCommentNode:
5009       case kProcessingInstructionNode:
5010         return true;
5011       case kDocumentTypeNode:
5012         num_doctypes++;
5013         if (num_elements > 0 && !has_element_after_reference_node) {
5014           exception_state.ThrowDOMException(
5015               DOMExceptionCode::kHierarchyRequestError,
5016               "Can't insert a doctype before the root element.");
5017           return false;
5018         }
5019         break;
5020       case kElementNode:
5021         num_elements++;
5022         if (has_doctype_after_reference_node) {
5023           exception_state.ThrowDOMException(
5024               DOMExceptionCode::kHierarchyRequestError,
5025               "Can't insert an element before a doctype.");
5026           return false;
5027         }
5028         break;
5029     }
5030   }
5031 
5032   if (num_elements > 1 || num_doctypes > 1) {
5033     exception_state.ThrowDOMException(
5034         DOMExceptionCode::kHierarchyRequestError,
5035         String::Format("Only one %s on document allowed.",
5036                        num_elements > 1 ? "element" : "doctype"));
5037     return false;
5038   }
5039 
5040   return true;
5041 }
5042 
Clone(Document & factory,CloneChildrenFlag flag) const5043 Node* Document::Clone(Document& factory, CloneChildrenFlag flag) const {
5044   DCHECK_EQ(this, &factory)
5045       << "Document::Clone() doesn't support importNode mode.";
5046   Document* clone = CloneDocumentWithoutChildren();
5047   clone->CloneDataFromDocument(*this);
5048   if (flag == CloneChildrenFlag::kClone)
5049     clone->CloneChildNodesFrom(*this);
5050   return clone;
5051 }
5052 
CloneDocumentWithoutChildren() const5053 Document* Document::CloneDocumentWithoutChildren() const {
5054   DocumentInit init = DocumentInit::Create()
5055                           .WithContextDocument(ContextDocument())
5056                           .WithOwnerDocument(const_cast<Document*>(this))
5057                           .WithURL(Url());
5058   if (IsA<XMLDocument>(this)) {
5059     if (IsXHTMLDocument())
5060       return XMLDocument::CreateXHTML(
5061           init.WithRegistrationContext(RegistrationContext()));
5062     return MakeGarbageCollected<XMLDocument>(init);
5063   }
5064   return MakeGarbageCollected<Document>(init);
5065 }
5066 
CloneDataFromDocument(const Document & other)5067 void Document::CloneDataFromDocument(const Document& other) {
5068   SetCompatibilityMode(other.GetCompatibilityMode());
5069   SetEncodingData(other.encoding_data_);
5070   SetContextFeatures(other.GetContextFeatures());
5071   SetMimeType(other.contentType());
5072 }
5073 
StyleSheets()5074 StyleSheetList& Document::StyleSheets() {
5075   if (!style_sheet_list_)
5076     style_sheet_list_ = MakeGarbageCollected<StyleSheetList>(this);
5077   return *style_sheet_list_;
5078 }
5079 
EvaluateMediaQueryListIfNeeded()5080 void Document::EvaluateMediaQueryListIfNeeded() {
5081   if (!evaluate_media_queries_on_style_recalc_)
5082     return;
5083   EvaluateMediaQueryList();
5084   evaluate_media_queries_on_style_recalc_ = false;
5085 }
5086 
EvaluateMediaQueryList()5087 void Document::EvaluateMediaQueryList() {
5088   if (media_query_matcher_)
5089     media_query_matcher_->MediaFeaturesChanged();
5090 }
5091 
SetResizedForViewportUnits()5092 void Document::SetResizedForViewportUnits() {
5093   if (media_query_matcher_)
5094     media_query_matcher_->ViewportChanged();
5095   if (!HasViewportUnits())
5096     return;
5097   EnsureStyleResolver().SetResizedForViewportUnits();
5098   SetNeedsStyleRecalcForViewportUnits();
5099 }
5100 
ClearResizedForViewportUnits()5101 void Document::ClearResizedForViewportUnits() {
5102   EnsureStyleResolver().ClearResizedForViewportUnits();
5103 }
5104 
SetHoverElement(Element * new_hover_element)5105 void Document::SetHoverElement(Element* new_hover_element) {
5106   hover_element_ = new_hover_element;
5107 }
5108 
SetActiveElement(Element * new_active_element)5109 void Document::SetActiveElement(Element* new_active_element) {
5110   if (!new_active_element) {
5111     active_element_.Clear();
5112     return;
5113   }
5114 
5115   active_element_ = new_active_element;
5116 }
5117 
RemoveFocusedElementOfSubtree(Node & node,bool among_children_only)5118 void Document::RemoveFocusedElementOfSubtree(Node& node,
5119                                              bool among_children_only) {
5120   if (!focused_element_)
5121     return;
5122 
5123   // We can't be focused if we're not in the document.
5124   if (!node.isConnected())
5125     return;
5126   bool contains = node.IsShadowIncludingInclusiveAncestorOf(*focused_element_);
5127   if (contains && (focused_element_ != &node || !among_children_only))
5128     ClearFocusedElement();
5129 }
5130 
SkipDisplayNoneAncestors(Element * element)5131 static Element* SkipDisplayNoneAncestors(Element* element) {
5132   for (; element; element = FlatTreeTraversal::ParentElement(*element)) {
5133     if (element->GetLayoutObject() || element->HasDisplayContentsStyle())
5134       return element;
5135   }
5136   return nullptr;
5137 }
5138 
SkipDisplayNoneAncestorsOrReturnNullIfFlatTreeIsDirty(Element & element)5139 static Element* SkipDisplayNoneAncestorsOrReturnNullIfFlatTreeIsDirty(
5140     Element& element) {
5141   if (element.GetDocument().IsSlotAssignmentOrLegacyDistributionDirty()) {
5142     // We shouldn't use FlatTreeTraversal during detach if slot assignment is
5143     // dirty because it might trigger assignment recalc. The hover and active
5144     // elements are then set to null. The hover element is updated on the next
5145     // lifecycle update instead.
5146     //
5147     // TODO(crbug.com/939769): The active element is not updated on the next
5148     // lifecycle update, and is generally not correctly updated on re-slotting.
5149     return nullptr;
5150   }
5151   return SkipDisplayNoneAncestors(&element);
5152 }
5153 
HoveredElementDetached(Element & element)5154 void Document::HoveredElementDetached(Element& element) {
5155   if (!hover_element_)
5156     return;
5157   if (element != hover_element_)
5158     return;
5159   hover_element_ =
5160       SkipDisplayNoneAncestorsOrReturnNullIfFlatTreeIsDirty(element);
5161 
5162   // If the mouse cursor is not visible, do not clear existing
5163   // hover effects on the ancestors of |element| and do not invoke
5164   // new hover effects on any other element.
5165   if (!GetPage()->IsCursorVisible())
5166     return;
5167 
5168   if (GetFrame())
5169     GetFrame()->GetEventHandler().ScheduleHoverStateUpdate();
5170 }
5171 
ActiveChainNodeDetached(Element & element)5172 void Document::ActiveChainNodeDetached(Element& element) {
5173   if (active_element_ && element == active_element_) {
5174     active_element_ =
5175         SkipDisplayNoneAncestorsOrReturnNullIfFlatTreeIsDirty(element);
5176   }
5177 }
5178 
AnnotatedRegions() const5179 const Vector<AnnotatedRegionValue>& Document::AnnotatedRegions() const {
5180   return annotated_regions_;
5181 }
5182 
SetAnnotatedRegions(const Vector<AnnotatedRegionValue> & regions)5183 void Document::SetAnnotatedRegions(
5184     const Vector<AnnotatedRegionValue>& regions) {
5185   annotated_regions_ = regions;
5186   SetAnnotatedRegionsDirty(false);
5187 }
5188 
SetLastFocusType(mojom::blink::FocusType last_focus_type)5189 void Document::SetLastFocusType(mojom::blink::FocusType last_focus_type) {
5190   last_focus_type_ = last_focus_type;
5191 }
5192 
SetFocusedElement(Element * new_focused_element,const FocusParams & params)5193 bool Document::SetFocusedElement(Element* new_focused_element,
5194                                  const FocusParams& params) {
5195   DCHECK(!lifecycle_.InDetach());
5196 
5197   clear_focused_element_timer_.Stop();
5198 
5199   // Make sure new_focused_element is actually in this document.
5200   if (new_focused_element) {
5201     if (new_focused_element->GetDocument() != this)
5202       return true;
5203 
5204     if (NodeChildRemovalTracker::IsBeingRemoved(*new_focused_element))
5205       return true;
5206   }
5207 
5208   if (focused_element_ == new_focused_element)
5209     return true;
5210 
5211   bool focus_change_blocked = false;
5212   Element* old_focused_element = focused_element_;
5213   focused_element_ = nullptr;
5214 
5215   UpdateDistributionForFlatTreeTraversal();
5216   Node* ancestor = (old_focused_element && old_focused_element->isConnected() &&
5217                     new_focused_element)
5218                        ? FlatTreeTraversal::CommonAncestor(*old_focused_element,
5219                                                            *new_focused_element)
5220                        : nullptr;
5221 
5222   // Remove focus from the existing focus node (if any)
5223   if (old_focused_element) {
5224     old_focused_element->SetFocused(false, params.type);
5225     old_focused_element->SetHasFocusWithinUpToAncestor(false, ancestor);
5226 
5227     DisplayLockUtilities::ElementLostFocus(old_focused_element);
5228 
5229     // Dispatch the blur event and let the node do any other blur related
5230     // activities (important for text fields)
5231     // If page lost focus, blur event will have already been dispatched
5232     if (GetPage() && (GetPage()->GetFocusController().IsFocused())) {
5233       old_focused_element->DispatchBlurEvent(new_focused_element, params.type,
5234                                              params.source_capabilities);
5235       if (focused_element_) {
5236         // handler shifted focus
5237         focus_change_blocked = true;
5238         new_focused_element = nullptr;
5239       }
5240 
5241       // 'focusout' is a DOM level 3 name for the bubbling blur event.
5242       old_focused_element->DispatchFocusOutEvent(event_type_names::kFocusout,
5243                                                  new_focused_element,
5244                                                  params.source_capabilities);
5245       // 'DOMFocusOut' is a DOM level 2 name for compatibility.
5246       // FIXME: We should remove firing DOMFocusOutEvent event when we are sure
5247       // no content depends on it, probably when <rdar://problem/8503958> is
5248       // resolved.
5249       old_focused_element->DispatchFocusOutEvent(event_type_names::kDOMFocusOut,
5250                                                  new_focused_element,
5251                                                  params.source_capabilities);
5252 
5253       if (focused_element_) {
5254         // handler shifted focus
5255         focus_change_blocked = true;
5256         new_focused_element = nullptr;
5257       }
5258     }
5259   }
5260 
5261   if (new_focused_element)
5262     UpdateStyleAndLayoutTreeForNode(new_focused_element);
5263   if (new_focused_element && new_focused_element->IsFocusable()) {
5264     if (IsRootEditableElement(*new_focused_element) &&
5265         !AcceptsEditingFocus(*new_focused_element)) {
5266       // delegate blocks focus change
5267       UpdateStyleAndLayoutTree();
5268       if (LocalFrame* frame = GetFrame())
5269         frame->Selection().DidChangeFocus();
5270       return false;
5271     }
5272     // Set focus on the new node
5273     focused_element_ = new_focused_element;
5274     SetSequentialFocusNavigationStartingPoint(focused_element_.Get());
5275 
5276     // Keep track of last focus from user interaction, ignoring focus from code.
5277     if (params.type != mojom::blink::FocusType::kNone)
5278       last_focus_type_ = params.type;
5279 
5280     focused_element_->SetFocused(true, params.type);
5281     focused_element_->SetHasFocusWithinUpToAncestor(true, ancestor);
5282     DisplayLockUtilities::ElementGainedFocus(focused_element_.Get());
5283 
5284     // Element::setFocused for frames can dispatch events.
5285     if (focused_element_ != new_focused_element) {
5286       UpdateStyleAndLayoutTree();
5287       if (LocalFrame* frame = GetFrame())
5288         frame->Selection().DidChangeFocus();
5289       return false;
5290     }
5291     CancelFocusAppearanceUpdate();
5292     EnsurePaintLocationDataValidForNode(focused_element_,
5293                                         DocumentUpdateReason::kFocus);
5294     focused_element_->UpdateFocusAppearanceWithOptions(
5295         params.selection_behavior, params.options);
5296 
5297     // Dispatch the focus event and let the node do any other focus related
5298     // activities (important for text fields)
5299     // If page lost focus, event will be dispatched on page focus, don't
5300     // duplicate
5301     if (GetPage() && (GetPage()->GetFocusController().IsFocused())) {
5302       focused_element_->DispatchFocusEvent(old_focused_element, params.type,
5303                                            params.source_capabilities);
5304 
5305       if (focused_element_ != new_focused_element) {
5306         // handler shifted focus
5307         UpdateStyleAndLayoutTree();
5308         if (LocalFrame* frame = GetFrame())
5309           frame->Selection().DidChangeFocus();
5310         return false;
5311       }
5312       // DOM level 3 bubbling focus event.
5313       focused_element_->DispatchFocusInEvent(event_type_names::kFocusin,
5314                                              old_focused_element, params.type,
5315                                              params.source_capabilities);
5316 
5317       if (focused_element_ != new_focused_element) {
5318         // handler shifted focus
5319         UpdateStyleAndLayoutTree();
5320         if (LocalFrame* frame = GetFrame())
5321           frame->Selection().DidChangeFocus();
5322         return false;
5323       }
5324 
5325       // For DOM level 2 compatibility.
5326       // FIXME: We should remove firing DOMFocusInEvent event when we are sure
5327       // no content depends on it, probably when <rdar://problem/8503958> is m.
5328       focused_element_->DispatchFocusInEvent(event_type_names::kDOMFocusIn,
5329                                              old_focused_element, params.type,
5330                                              params.source_capabilities);
5331 
5332       if (focused_element_ != new_focused_element) {
5333         // handler shifted focus
5334         UpdateStyleAndLayoutTree();
5335         if (LocalFrame* frame = GetFrame())
5336           frame->Selection().DidChangeFocus();
5337         return false;
5338       }
5339     }
5340   }
5341 
5342   if (!focus_change_blocked)
5343     NotifyFocusedElementChanged(old_focused_element, focused_element_.Get());
5344 
5345   UpdateStyleAndLayoutTree();
5346   if (LocalFrame* frame = GetFrame())
5347     frame->Selection().DidChangeFocus();
5348   return !focus_change_blocked;
5349 }
5350 
ClearFocusedElement()5351 void Document::ClearFocusedElement() {
5352   SetFocusedElement(nullptr,
5353                     FocusParams(SelectionBehaviorOnFocus::kNone,
5354                                 mojom::blink::FocusType::kNone, nullptr));
5355 }
5356 
NotifyFocusedElementChanged(Element * old_focused_element,Element * new_focused_element)5357 void Document::NotifyFocusedElementChanged(Element* old_focused_element,
5358                                            Element* new_focused_element) {
5359   // |old_focused_element| may not belong to this document by invoking
5360   // adoptNode in event handlers during moving the focus to the new element.
5361   DCHECK(!new_focused_element || new_focused_element->GetDocument() == this);
5362 
5363   if (AXObjectCache* cache = ExistingAXObjectCache()) {
5364     cache->HandleFocusedUIElementChanged(old_focused_element,
5365                                          new_focused_element);
5366   }
5367 
5368   if (GetPage()) {
5369     GetPage()->GetValidationMessageClient().DidChangeFocusTo(
5370         new_focused_element);
5371 
5372     bool is_editable = false;
5373     gfx::Rect element_bounds;
5374     if (new_focused_element) {
5375       IntRect rect = new_focused_element->BoundsInViewport();
5376       View()->FrameToScreen(rect);
5377       is_editable = IsEditableElement(*new_focused_element);
5378       element_bounds = gfx::Rect(rect);
5379     }
5380 
5381     GetFrame()->GetLocalFrameHostRemote().FocusedElementChanged(is_editable,
5382                                                                 element_bounds);
5383 
5384     Document* old_document =
5385         old_focused_element ? &old_focused_element->GetDocument() : nullptr;
5386     if (old_document && old_document != this && old_document->GetFrame())
5387       old_document->GetFrame()->Client()->FocusedElementChanged(nullptr);
5388 
5389     GetFrame()->Client()->FocusedElementChanged(new_focused_element);
5390 
5391     GetPage()->GetChromeClient().SetKeyboardFocusURL(new_focused_element);
5392 
5393     if (GetSettings()->GetSpatialNavigationEnabled())
5394       GetPage()->GetSpatialNavigationController().FocusedNodeChanged(this);
5395   }
5396 }
5397 
SetSequentialFocusNavigationStartingPoint(Node * node)5398 void Document::SetSequentialFocusNavigationStartingPoint(Node* node) {
5399   if (!frame_)
5400     return;
5401   if (!node) {
5402     sequential_focus_navigation_starting_point_ = nullptr;
5403     return;
5404   }
5405   DCHECK_EQ(node->GetDocument(), this);
5406   if (!sequential_focus_navigation_starting_point_)
5407     sequential_focus_navigation_starting_point_ = Range::Create(*this);
5408   sequential_focus_navigation_starting_point_->selectNodeContents(
5409       node, ASSERT_NO_EXCEPTION);
5410 }
5411 
SequentialFocusNavigationStartingPoint(mojom::blink::FocusType type) const5412 Element* Document::SequentialFocusNavigationStartingPoint(
5413     mojom::blink::FocusType type) const {
5414   if (focused_element_)
5415     return focused_element_.Get();
5416   if (!sequential_focus_navigation_starting_point_)
5417     return nullptr;
5418   DCHECK(sequential_focus_navigation_starting_point_->IsConnected());
5419   if (!sequential_focus_navigation_starting_point_->collapsed()) {
5420     Node* node = sequential_focus_navigation_starting_point_->startContainer();
5421     DCHECK_EQ(node,
5422               sequential_focus_navigation_starting_point_->endContainer());
5423     if (auto* element = DynamicTo<Element>(node))
5424       return element;
5425     if (Element* neighbor_element = type == mojom::blink::FocusType::kForward
5426                                         ? ElementTraversal::Previous(*node)
5427                                         : ElementTraversal::Next(*node))
5428       return neighbor_element;
5429     return node->ParentOrShadowHostElement();
5430   }
5431 
5432   // Range::selectNodeContents didn't select contents because the element had
5433   // no children.
5434   auto* element = DynamicTo<Element>(
5435       sequential_focus_navigation_starting_point_->startContainer());
5436   if (element && !element->hasChildren() &&
5437       sequential_focus_navigation_starting_point_->startOffset() == 0)
5438     return element;
5439 
5440   // A node selected by Range::selectNodeContents was removed from the
5441   // document tree.
5442   if (Node* next_node =
5443           sequential_focus_navigation_starting_point_->FirstNode()) {
5444     if (next_node->IsShadowRoot())
5445       return next_node->OwnerShadowHost();
5446     // TODO(tkent): Using FlatTreeTraversal is inconsistent with
5447     // FocusController. Ideally we should find backward/forward focusable
5448     // elements before the starting point is disconnected. crbug.com/606582
5449     if (type == mojom::blink::FocusType::kForward) {
5450       Node* previous = FlatTreeTraversal::Previous(*next_node);
5451       for (; previous; previous = FlatTreeTraversal::Previous(*previous)) {
5452         if (auto* element = DynamicTo<Element>(previous))
5453           return element;
5454       }
5455     }
5456     for (Node* next = next_node; next; next = FlatTreeTraversal::Next(*next)) {
5457       if (auto* element = DynamicTo<Element>(next))
5458         return element;
5459     }
5460   }
5461   return nullptr;
5462 }
5463 
SetCSSTarget(Element * new_target)5464 void Document::SetCSSTarget(Element* new_target) {
5465   if (css_target_)
5466     css_target_->PseudoStateChanged(CSSSelector::kPseudoTarget);
5467   css_target_ = new_target;
5468   if (css_target_)
5469     css_target_->PseudoStateChanged(CSSSelector::kPseudoTarget);
5470 }
5471 
RegisterNodeList(const LiveNodeListBase * list)5472 void Document::RegisterNodeList(const LiveNodeListBase* list) {
5473   node_lists_.Add(list, list->InvalidationType());
5474   if (list->IsRootedAtTreeScope())
5475     lists_invalidated_at_document_.insert(list);
5476 }
5477 
UnregisterNodeList(const LiveNodeListBase * list)5478 void Document::UnregisterNodeList(const LiveNodeListBase* list) {
5479   node_lists_.Remove(list, list->InvalidationType());
5480   if (list->IsRootedAtTreeScope()) {
5481     DCHECK(lists_invalidated_at_document_.Contains(list));
5482     lists_invalidated_at_document_.erase(list);
5483   }
5484 }
5485 
RegisterNodeListWithIdNameCache(const LiveNodeListBase * list)5486 void Document::RegisterNodeListWithIdNameCache(const LiveNodeListBase* list) {
5487   node_lists_.Add(list, kInvalidateOnIdNameAttrChange);
5488 }
5489 
UnregisterNodeListWithIdNameCache(const LiveNodeListBase * list)5490 void Document::UnregisterNodeListWithIdNameCache(const LiveNodeListBase* list) {
5491   node_lists_.Remove(list, kInvalidateOnIdNameAttrChange);
5492 }
5493 
AttachNodeIterator(NodeIterator * ni)5494 void Document::AttachNodeIterator(NodeIterator* ni) {
5495   node_iterators_.insert(ni);
5496 }
5497 
DetachNodeIterator(NodeIterator * ni)5498 void Document::DetachNodeIterator(NodeIterator* ni) {
5499   // The node iterator can be detached without having been attached if its root
5500   // node didn't have a document when the iterator was created, but has it now.
5501   node_iterators_.erase(ni);
5502 }
5503 
MoveNodeIteratorsToNewDocument(Node & node,Document & new_document)5504 void Document::MoveNodeIteratorsToNewDocument(Node& node,
5505                                               Document& new_document) {
5506   HeapHashSet<WeakMember<NodeIterator>> node_iterators_list = node_iterators_;
5507   for (NodeIterator* ni : node_iterators_list) {
5508     if (ni->root() == node) {
5509       DetachNodeIterator(ni);
5510       new_document.AttachNodeIterator(ni);
5511     }
5512   }
5513 }
5514 
DidMoveTreeToNewDocument(const Node & root)5515 void Document::DidMoveTreeToNewDocument(const Node& root) {
5516   DCHECK_NE(root.GetDocument(), this);
5517   if (!ranges_.IsEmpty()) {
5518     AttachedRangeSet ranges = ranges_;
5519     for (Range* range : ranges)
5520       range->UpdateOwnerDocumentIfNeeded();
5521   }
5522   synchronous_mutation_observer_list_.ForEachObserver(
5523       [&](SynchronousMutationObserver* observer) {
5524         observer->DidMoveTreeToNewDocument(root);
5525       });
5526 }
5527 
NodeChildrenWillBeRemoved(ContainerNode & container)5528 void Document::NodeChildrenWillBeRemoved(ContainerNode& container) {
5529   EventDispatchForbiddenScope assert_no_event_dispatch;
5530   for (Range* range : ranges_) {
5531     range->NodeChildrenWillBeRemoved(container);
5532     if (range == sequential_focus_navigation_starting_point_)
5533       range->FixupRemovedChildrenAcrossShadowBoundary(container);
5534   }
5535 
5536   for (NodeIterator* ni : node_iterators_) {
5537     for (Node& n : NodeTraversal::ChildrenOf(container))
5538       ni->NodeWillBeRemoved(n);
5539   }
5540 
5541   synchronous_mutation_observer_list_.ForEachObserver(
5542       [&](SynchronousMutationObserver* observer) {
5543         observer->NodeChildrenWillBeRemoved(container);
5544       });
5545 
5546   if (ContainsV1ShadowTree()) {
5547     for (Node& n : NodeTraversal::ChildrenOf(container))
5548       n.CheckSlotChangeBeforeRemoved();
5549   }
5550 }
5551 
NodeWillBeRemoved(Node & n)5552 void Document::NodeWillBeRemoved(Node& n) {
5553   for (NodeIterator* ni : node_iterators_)
5554     ni->NodeWillBeRemoved(n);
5555 
5556   for (Range* range : ranges_) {
5557     range->NodeWillBeRemoved(n);
5558     if (range == sequential_focus_navigation_starting_point_)
5559       range->FixupRemovedNodeAcrossShadowBoundary(n);
5560   }
5561 
5562   synchronous_mutation_observer_list_.ForEachObserver(
5563       [&](SynchronousMutationObserver* observer) {
5564         observer->NodeWillBeRemoved(n);
5565       });
5566 
5567   if (ContainsV1ShadowTree())
5568     n.CheckSlotChangeBeforeRemoved();
5569 
5570   if (n.InActiveDocument())
5571     GetStyleEngine().NodeWillBeRemoved(n);
5572 }
5573 
NotifyUpdateCharacterData(CharacterData * character_data,unsigned offset,unsigned old_length,unsigned new_length)5574 void Document::NotifyUpdateCharacterData(CharacterData* character_data,
5575                                          unsigned offset,
5576                                          unsigned old_length,
5577                                          unsigned new_length) {
5578   synchronous_mutation_observer_list_.ForEachObserver(
5579       [&](SynchronousMutationObserver* observer) {
5580         observer->DidUpdateCharacterData(character_data, offset, old_length,
5581                                          new_length);
5582       });
5583 }
5584 
NotifyChangeChildren(const ContainerNode & container)5585 void Document::NotifyChangeChildren(const ContainerNode& container) {
5586   synchronous_mutation_observer_list_.ForEachObserver(
5587       [&](SynchronousMutationObserver* observer) {
5588         observer->DidChangeChildren(container);
5589       });
5590 }
5591 
DidInsertText(const CharacterData & text,unsigned offset,unsigned length)5592 void Document::DidInsertText(const CharacterData& text,
5593                              unsigned offset,
5594                              unsigned length) {
5595   for (Range* range : ranges_)
5596     range->DidInsertText(text, offset, length);
5597 }
5598 
DidRemoveText(const CharacterData & text,unsigned offset,unsigned length)5599 void Document::DidRemoveText(const CharacterData& text,
5600                              unsigned offset,
5601                              unsigned length) {
5602   for (Range* range : ranges_)
5603     range->DidRemoveText(text, offset, length);
5604 }
5605 
DidMergeTextNodes(const Text & merged_node,const Text & node_to_be_removed,unsigned old_length)5606 void Document::DidMergeTextNodes(const Text& merged_node,
5607                                  const Text& node_to_be_removed,
5608                                  unsigned old_length) {
5609   NodeWithIndex node_to_be_removed_with_index(
5610       const_cast<Text&>(node_to_be_removed));
5611   if (!ranges_.IsEmpty()) {
5612     for (Range* range : ranges_)
5613       range->DidMergeTextNodes(node_to_be_removed_with_index, old_length);
5614   }
5615 
5616   synchronous_mutation_observer_list_.ForEachObserver(
5617       [&](SynchronousMutationObserver* observer) {
5618         observer->DidMergeTextNodes(merged_node, node_to_be_removed_with_index,
5619                                     old_length);
5620       });
5621 
5622   // FIXME: This should update markers for spelling and grammar checking.
5623 }
5624 
DidSplitTextNode(const Text & old_node)5625 void Document::DidSplitTextNode(const Text& old_node) {
5626   for (Range* range : ranges_)
5627     range->DidSplitTextNode(old_node);
5628 
5629   synchronous_mutation_observer_list_.ForEachObserver(
5630       [&](SynchronousMutationObserver* observer) {
5631         observer->DidSplitTextNode(old_node);
5632       });
5633 
5634   // FIXME: This should update markers for spelling and grammar checking.
5635 }
5636 
SetWindowAttributeEventListener(const AtomicString & event_type,EventListener * listener)5637 void Document::SetWindowAttributeEventListener(const AtomicString& event_type,
5638                                                EventListener* listener) {
5639   LocalDOMWindow* dom_window = domWindow();
5640   if (!dom_window)
5641     return;
5642   dom_window->SetAttributeEventListener(event_type, listener);
5643 }
5644 
GetWindowAttributeEventListener(const AtomicString & event_type)5645 EventListener* Document::GetWindowAttributeEventListener(
5646     const AtomicString& event_type) {
5647   LocalDOMWindow* dom_window = domWindow();
5648   if (!dom_window)
5649     return nullptr;
5650   return dom_window->GetAttributeEventListener(event_type);
5651 }
5652 
EnqueueDisplayLockActivationTask(base::OnceClosure task)5653 void Document::EnqueueDisplayLockActivationTask(base::OnceClosure task) {
5654   scripted_animation_controller_->EnqueueTask(std::move(task));
5655 }
5656 
EnqueueAnimationFrameTask(base::OnceClosure task)5657 void Document::EnqueueAnimationFrameTask(base::OnceClosure task) {
5658   scripted_animation_controller_->EnqueueTask(std::move(task));
5659 }
5660 
EnqueueAnimationFrameEvent(Event * event)5661 void Document::EnqueueAnimationFrameEvent(Event* event) {
5662   scripted_animation_controller_->EnqueueEvent(event);
5663 }
5664 
EnqueueUniqueAnimationFrameEvent(Event * event)5665 void Document::EnqueueUniqueAnimationFrameEvent(Event* event) {
5666   scripted_animation_controller_->EnqueuePerFrameEvent(event);
5667 }
5668 
EnqueueScrollEventForNode(Node * target)5669 void Document::EnqueueScrollEventForNode(Node* target) {
5670   // Per the W3C CSSOM View Module only scroll events fired at the document
5671   // should bubble.
5672   overscroll_accumulated_delta_x_ = overscroll_accumulated_delta_y_ = 0;
5673   Event* scroll_event = target->IsDocumentNode()
5674                             ? Event::CreateBubble(event_type_names::kScroll)
5675                             : Event::Create(event_type_names::kScroll);
5676   scroll_event->SetTarget(target);
5677   scripted_animation_controller_->EnqueuePerFrameEvent(scroll_event);
5678 }
5679 
EnqueueScrollEndEventForNode(Node * target)5680 void Document::EnqueueScrollEndEventForNode(Node* target) {
5681   // Mimic bubbling behavior of scroll event for consistency.
5682   overscroll_accumulated_delta_x_ = overscroll_accumulated_delta_y_ = 0;
5683   Event* scroll_end_event =
5684       target->IsDocumentNode()
5685           ? Event::CreateBubble(event_type_names::kScrollend)
5686           : Event::Create(event_type_names::kScrollend);
5687   scroll_end_event->SetTarget(target);
5688   scripted_animation_controller_->EnqueuePerFrameEvent(scroll_end_event);
5689 }
5690 
EnqueueOverscrollEventForNode(Node * target,double delta_x,double delta_y)5691 void Document::EnqueueOverscrollEventForNode(Node* target,
5692                                              double delta_x,
5693                                              double delta_y) {
5694   // Mimic bubbling behavior of scroll event for consistency.
5695   overscroll_accumulated_delta_x_ += delta_x;
5696   overscroll_accumulated_delta_y_ += delta_y;
5697   bool bubbles = target->IsDocumentNode();
5698   Event* overscroll_event = OverscrollEvent::Create(
5699       event_type_names::kOverscroll, bubbles, overscroll_accumulated_delta_x_,
5700       overscroll_accumulated_delta_y_);
5701   overscroll_event->SetTarget(target);
5702   scripted_animation_controller_->EnqueuePerFrameEvent(overscroll_event);
5703 }
5704 
EnqueueResizeEvent()5705 void Document::EnqueueResizeEvent() {
5706   Event* event = Event::Create(event_type_names::kResize);
5707   event->SetTarget(domWindow());
5708   scripted_animation_controller_->EnqueuePerFrameEvent(event);
5709 }
5710 
EnqueueMediaQueryChangeListeners(HeapVector<Member<MediaQueryListListener>> & listeners)5711 void Document::EnqueueMediaQueryChangeListeners(
5712     HeapVector<Member<MediaQueryListListener>>& listeners) {
5713   scripted_animation_controller_->EnqueueMediaQueryChangeListeners(listeners);
5714 }
5715 
EnqueueVisualViewportScrollEvent()5716 void Document::EnqueueVisualViewportScrollEvent() {
5717   VisualViewportScrollEvent* event =
5718       MakeGarbageCollected<VisualViewportScrollEvent>();
5719   event->SetTarget(domWindow()->visualViewport());
5720   scripted_animation_controller_->EnqueuePerFrameEvent(event);
5721 }
5722 
EnqueueVisualViewportResizeEvent()5723 void Document::EnqueueVisualViewportResizeEvent() {
5724   VisualViewportResizeEvent* event =
5725       MakeGarbageCollected<VisualViewportResizeEvent>();
5726   event->SetTarget(domWindow()->visualViewport());
5727   scripted_animation_controller_->EnqueuePerFrameEvent(event);
5728 }
5729 
DispatchEventsForPrinting()5730 void Document::DispatchEventsForPrinting() {
5731   scripted_animation_controller_->DispatchEventsAndCallbacksForPrinting();
5732 }
5733 
EventFactories()5734 Document::EventFactorySet& Document::EventFactories() {
5735   DEFINE_STATIC_LOCAL(EventFactorySet, event_factory, ());
5736   return event_factory;
5737 }
5738 
AccessEntryFromURL()5739 const OriginAccessEntry& Document::AccessEntryFromURL() {
5740   if (!access_entry_from_url_) {
5741     access_entry_from_url_ = std::make_unique<OriginAccessEntry>(
5742         Url(), network::mojom::CorsDomainMatchMode::kAllowRegistrableDomains);
5743   }
5744   return *access_entry_from_url_;
5745 }
5746 
SendDidEditFieldInInsecureContext()5747 void Document::SendDidEditFieldInInsecureContext() {
5748   if (!GetFrame())
5749     return;
5750 
5751   mojo::Remote<mojom::blink::InsecureInputService> insecure_input_service;
5752   GetFrame()->GetBrowserInterfaceBroker().GetInterface(
5753       insecure_input_service.BindNewPipeAndPassReceiver());
5754 
5755   insecure_input_service->DidEditFieldInInsecureContext();
5756 }
5757 
RegisterEventFactory(std::unique_ptr<EventFactoryBase> event_factory)5758 void Document::RegisterEventFactory(
5759     std::unique_ptr<EventFactoryBase> event_factory) {
5760   DCHECK(!EventFactories().Contains(event_factory.get()));
5761   EventFactories().insert(std::move(event_factory));
5762 }
5763 
createEvent(ScriptState * script_state,const String & event_type,ExceptionState & exception_state)5764 Event* Document::createEvent(ScriptState* script_state,
5765                              const String& event_type,
5766                              ExceptionState& exception_state) {
5767   Event* event = nullptr;
5768   ExecutionContext* execution_context = ExecutionContext::From(script_state);
5769   for (const auto& factory : EventFactories()) {
5770     event = factory->Create(execution_context, event_type);
5771     if (event) {
5772       // createEvent for TouchEvent should throw DOM exception if touch event
5773       // feature detection is not enabled. See crbug.com/392584#c22
5774       if (EqualIgnoringASCIICase(event_type, "TouchEvent") &&
5775           !RuntimeEnabledFeatures::TouchEventFeatureDetectionEnabled(
5776               execution_context))
5777         break;
5778       return event;
5779     }
5780   }
5781   exception_state.ThrowDOMException(
5782       DOMExceptionCode::kNotSupportedError,
5783       "The provided event type ('" + event_type + "') is invalid.");
5784   return nullptr;
5785 }
5786 
AddMutationEventListenerTypeIfEnabled(ListenerType listener_type)5787 void Document::AddMutationEventListenerTypeIfEnabled(
5788     ListenerType listener_type) {
5789   if (ContextFeatures::MutationEventsEnabled(this))
5790     AddListenerType(listener_type);
5791 }
5792 
AddListenerTypeIfNeeded(const AtomicString & event_type,EventTarget & event_target)5793 void Document::AddListenerTypeIfNeeded(const AtomicString& event_type,
5794                                        EventTarget& event_target) {
5795   if (event_type == event_type_names::kDOMSubtreeModified) {
5796     UseCounter::Count(*this, WebFeature::kDOMSubtreeModifiedEvent);
5797     AddMutationEventListenerTypeIfEnabled(kDOMSubtreeModifiedListener);
5798   } else if (event_type == event_type_names::kDOMNodeInserted) {
5799     UseCounter::Count(*this, WebFeature::kDOMNodeInsertedEvent);
5800     AddMutationEventListenerTypeIfEnabled(kDOMNodeInsertedListener);
5801   } else if (event_type == event_type_names::kDOMNodeRemoved) {
5802     UseCounter::Count(*this, WebFeature::kDOMNodeRemovedEvent);
5803     AddMutationEventListenerTypeIfEnabled(kDOMNodeRemovedListener);
5804   } else if (event_type == event_type_names::kDOMNodeRemovedFromDocument) {
5805     UseCounter::Count(*this, WebFeature::kDOMNodeRemovedFromDocumentEvent);
5806     AddMutationEventListenerTypeIfEnabled(kDOMNodeRemovedFromDocumentListener);
5807   } else if (event_type == event_type_names::kDOMNodeInsertedIntoDocument) {
5808     UseCounter::Count(*this, WebFeature::kDOMNodeInsertedIntoDocumentEvent);
5809     AddMutationEventListenerTypeIfEnabled(kDOMNodeInsertedIntoDocumentListener);
5810   } else if (event_type == event_type_names::kDOMCharacterDataModified) {
5811     UseCounter::Count(*this, WebFeature::kDOMCharacterDataModifiedEvent);
5812     AddMutationEventListenerTypeIfEnabled(kDOMCharacterDataModifiedListener);
5813   } else if (event_type == event_type_names::kWebkitAnimationStart ||
5814              event_type == event_type_names::kAnimationstart) {
5815     AddListenerType(kAnimationStartListener);
5816   } else if (event_type == event_type_names::kWebkitAnimationEnd ||
5817              event_type == event_type_names::kAnimationend) {
5818     AddListenerType(kAnimationEndListener);
5819   } else if (event_type == event_type_names::kWebkitAnimationIteration ||
5820              event_type == event_type_names::kAnimationiteration) {
5821     AddListenerType(kAnimationIterationListener);
5822     if (View()) {
5823       // Need to re-evaluate time-to-effect-change for any running animations.
5824       View()->ScheduleAnimation();
5825     }
5826   } else if (event_type == event_type_names::kAnimationcancel) {
5827     AddListenerType(kAnimationCancelListener);
5828   } else if (event_type == event_type_names::kTransitioncancel) {
5829     AddListenerType(kTransitionCancelListener);
5830   } else if (event_type == event_type_names::kTransitionrun) {
5831     AddListenerType(kTransitionRunListener);
5832   } else if (event_type == event_type_names::kTransitionstart) {
5833     AddListenerType(kTransitionStartListener);
5834   } else if (event_type == event_type_names::kWebkitTransitionEnd ||
5835              event_type == event_type_names::kTransitionend) {
5836     AddListenerType(kTransitionEndListener);
5837   } else if (event_type == event_type_names::kScroll) {
5838     AddListenerType(kScrollListener);
5839   } else if (event_type == event_type_names::kLoad) {
5840     if (Node* node = event_target.ToNode()) {
5841       if (IsA<HTMLStyleElement>(*node)) {
5842         AddListenerType(kLoadListenerAtCapturePhaseOrAtStyleElement);
5843         return;
5844       }
5845     }
5846     if (event_target.HasCapturingEventListeners(event_type))
5847       AddListenerType(kLoadListenerAtCapturePhaseOrAtStyleElement);
5848   }
5849 }
5850 
LocalOwner() const5851 HTMLFrameOwnerElement* Document::LocalOwner() const {
5852   if (!GetFrame())
5853     return nullptr;
5854   // FIXME: This probably breaks the attempts to layout after a load is finished
5855   // in implicitClose(), and probably tons of other things...
5856   return GetFrame()->DeprecatedLocalOwner();
5857 }
5858 
WillChangeFrameOwnerProperties(int margin_width,int margin_height,mojom::blink::ScrollbarMode scrollbar_mode,bool is_display_none)5859 void Document::WillChangeFrameOwnerProperties(
5860     int margin_width,
5861     int margin_height,
5862     mojom::blink::ScrollbarMode scrollbar_mode,
5863     bool is_display_none) {
5864   DCHECK(GetFrame() && GetFrame()->Owner());
5865   FrameOwner* owner = GetFrame()->Owner();
5866 
5867   if (is_display_none != owner->IsDisplayNone())
5868     DisplayNoneChangedForFrame();
5869 
5870   // body() may become null as a result of modification event listeners, so we
5871   // check before each call.
5872   if (margin_width != owner->MarginWidth()) {
5873     if (auto* body_element = body()) {
5874       body_element->SetIntegralAttribute(html_names::kMarginwidthAttr,
5875                                          margin_width);
5876     }
5877   }
5878   if (margin_height != owner->MarginHeight()) {
5879     if (auto* body_element = body()) {
5880       body_element->SetIntegralAttribute(html_names::kMarginheightAttr,
5881                                          margin_height);
5882     }
5883   }
5884   if (scrollbar_mode != owner->ScrollbarMode() && View()) {
5885     View()->SetCanHaveScrollbars(scrollbar_mode !=
5886                                  mojom::blink::ScrollbarMode::kAlwaysOff);
5887     View()->SetNeedsLayout();
5888   }
5889 }
5890 
cookie(ExceptionState & exception_state) const5891 String Document::cookie(ExceptionState& exception_state) const {
5892   if (GetSettings() && !GetSettings()->GetCookieEnabled())
5893     return String();
5894 
5895   CountUse(WebFeature::kCookieGet);
5896 
5897   if (!GetSecurityOrigin()->CanAccessCookies()) {
5898     if (IsSandboxed(mojom::blink::WebSandboxFlags::kOrigin))
5899       exception_state.ThrowSecurityError(
5900           "The document is sandboxed and lacks the 'allow-same-origin' flag.");
5901     else if (Url().ProtocolIsData())
5902       exception_state.ThrowSecurityError(
5903           "Cookies are disabled inside 'data:' URLs.");
5904     else
5905       exception_state.ThrowSecurityError("Access is denied for this document.");
5906     return String();
5907   } else if (GetSecurityOrigin()->IsLocal()) {
5908     CountUse(WebFeature::kFileAccessedCookies);
5909   }
5910 
5911   if (!cookie_jar_)
5912     return String();
5913 
5914   return cookie_jar_->Cookies();
5915 }
5916 
setCookie(const String & value,ExceptionState & exception_state)5917 void Document::setCookie(const String& value, ExceptionState& exception_state) {
5918   if (GetSettings() && !GetSettings()->GetCookieEnabled())
5919     return;
5920 
5921   UseCounter::Count(*this, WebFeature::kCookieSet);
5922 
5923   if (!GetSecurityOrigin()->CanAccessCookies()) {
5924     if (IsSandboxed(mojom::blink::WebSandboxFlags::kOrigin))
5925       exception_state.ThrowSecurityError(
5926           "The document is sandboxed and lacks the 'allow-same-origin' flag.");
5927     else if (Url().ProtocolIsData())
5928       exception_state.ThrowSecurityError(
5929           "Cookies are disabled inside 'data:' URLs.");
5930     else
5931       exception_state.ThrowSecurityError("Access is denied for this document.");
5932     return;
5933   } else if (GetSecurityOrigin()->IsLocal()) {
5934     UseCounter::Count(*this, WebFeature::kFileAccessedCookies);
5935   }
5936 
5937   if (!cookie_jar_)
5938     return;
5939 
5940   cookie_jar_->SetCookie(value);
5941 }
5942 
CookiesEnabled() const5943 bool Document::CookiesEnabled() const {
5944   // Compatible behavior in contexts that don't have cookie access.
5945   if (!GetSecurityOrigin()->CanAccessCookies())
5946     return true;
5947 
5948   if (!cookie_jar_)
5949     return false;
5950 
5951   return cookie_jar_->CookiesEnabled();
5952 }
5953 
referrer() const5954 const AtomicString& Document::referrer() const {
5955   if (Loader())
5956     return Loader()->GetReferrer().referrer;
5957   return g_null_atom;
5958 }
5959 
domain() const5960 String Document::domain() const {
5961   return GetSecurityOrigin()->Domain();
5962 }
5963 
setDomain(const String & raw_domain,ExceptionState & exception_state)5964 void Document::setDomain(const String& raw_domain,
5965                          ExceptionState& exception_state) {
5966   UseCounter::Count(*this, WebFeature::kDocumentSetDomain);
5967 
5968   const String feature_policy_error =
5969       "Setting `document.domain` is disabled by Feature Policy.";
5970   if (!IsFeatureEnabled(mojom::blink::FeaturePolicyFeature::kDocumentDomain,
5971                         ReportOptions::kReportOnFailure,
5972                         feature_policy_error)) {
5973     exception_state.ThrowSecurityError(feature_policy_error);
5974     return;
5975   }
5976 
5977   if (!frame_) {
5978     exception_state.ThrowSecurityError(
5979         "A browsing context is required to set a domain.");
5980     return;
5981   }
5982 
5983   if (IsSandboxed(mojom::blink::WebSandboxFlags::kDocumentDomain)) {
5984     exception_state.ThrowSecurityError(
5985         "Assignment is forbidden for sandboxed iframes.");
5986     return;
5987   }
5988 
5989   if (SchemeRegistry::IsDomainRelaxationForbiddenForURLScheme(
5990           GetSecurityOrigin()->Protocol())) {
5991     exception_state.ThrowSecurityError("Assignment is forbidden for the '" +
5992                                        GetSecurityOrigin()->Protocol() +
5993                                        "' scheme.");
5994     return;
5995   }
5996 
5997   bool success = false;
5998   String new_domain = SecurityOrigin::CanonicalizeHost(raw_domain, &success);
5999   if (!success) {
6000     exception_state.ThrowSecurityError("'" + raw_domain +
6001                                        "' could not be parsed properly.");
6002     return;
6003   }
6004 
6005   if (new_domain.IsEmpty()) {
6006     exception_state.ThrowSecurityError("'" + new_domain +
6007                                        "' is an empty domain.");
6008     return;
6009   }
6010 
6011   scoped_refptr<SecurityOrigin> new_origin =
6012       GetSecurityOrigin()->IsolatedCopy();
6013   new_origin->SetDomainFromDOM(new_domain);
6014   OriginAccessEntry access_entry(
6015       *new_origin, network::mojom::CorsDomainMatchMode::kAllowSubdomains);
6016   network::cors::OriginAccessEntry::MatchResult result =
6017       access_entry.MatchesOrigin(*GetSecurityOrigin());
6018   if (result == network::cors::OriginAccessEntry::kDoesNotMatchOrigin) {
6019     exception_state.ThrowSecurityError(
6020         "'" + new_domain + "' is not a suffix of '" + domain() + "'.");
6021     return;
6022   }
6023 
6024   if (result ==
6025       network::cors::OriginAccessEntry::kMatchesOriginButIsPublicSuffix) {
6026     exception_state.ThrowSecurityError("'" + new_domain +
6027                                        "' is a top-level domain.");
6028     return;
6029   }
6030 
6031   if (frame_) {
6032     UseCounter::Count(*this,
6033                       GetSecurityOrigin()->Port() == 0
6034                           ? WebFeature::kDocumentDomainSetWithDefaultPort
6035                           : WebFeature::kDocumentDomainSetWithNonDefaultPort);
6036     bool was_cross_origin_to_main_frame = frame_->IsCrossOriginToMainFrame();
6037     bool was_cross_origin_to_parent_frame =
6038         frame_->IsCrossOriginToParentFrame();
6039     GetMutableSecurityOrigin()->SetDomainFromDOM(new_domain);
6040     bool is_cross_origin_to_main_frame = frame_->IsCrossOriginToMainFrame();
6041     if (FrameScheduler* frame_scheduler = frame_->GetFrameScheduler())
6042       frame_scheduler->SetCrossOriginToMainFrame(is_cross_origin_to_main_frame);
6043     if (View() &&
6044         (was_cross_origin_to_main_frame != is_cross_origin_to_main_frame)) {
6045       View()->CrossOriginToMainFrameChanged();
6046     }
6047     if (frame_->IsMainFrame()) {
6048       // Notify descendants if their cross-origin-to-main-frame status changed.
6049       // TODO(pdr): This will notify even if |Frame::IsCrossOriginToMainFrame|
6050       // is the same. Track whether each child was cross-origin to main before
6051       // and after changing the domain, and only notify the changed ones.
6052       for (Frame* child = frame_->Tree().FirstChild(); child;
6053            child = child->Tree().TraverseNext(frame_)) {
6054         auto* child_local_frame = DynamicTo<LocalFrame>(child);
6055         if (child_local_frame && child_local_frame->View())
6056           child_local_frame->View()->CrossOriginToMainFrameChanged();
6057       }
6058     }
6059 
6060     if (View() && was_cross_origin_to_parent_frame !=
6061                       frame_->IsCrossOriginToParentFrame()) {
6062       View()->CrossOriginToParentFrameChanged();
6063     }
6064     // Notify all child frames if their cross-origin-to-parent status changed.
6065     // TODO(pdr): This will notify even if |Frame::IsCrossOriginToParentFrame|
6066     // is the same. Track whether each child was cross-origin-to-parent before
6067     // and after changing the domain, and only notify the changed ones.
6068     for (Frame* child = frame_->Tree().FirstChild(); child;
6069          child = child->Tree().NextSibling()) {
6070       auto* child_local_frame = DynamicTo<LocalFrame>(child);
6071       if (child_local_frame && child_local_frame->View())
6072         child_local_frame->View()->CrossOriginToParentFrameChanged();
6073     }
6074 
6075     frame_->GetScriptController().UpdateSecurityOrigin(GetSecurityOrigin());
6076   }
6077 }
6078 
6079 // https://html.spec.whatwg.org/C#dom-document-lastmodified
lastModified() const6080 String Document::lastModified() const {
6081   base::Time::Exploded exploded;
6082   bool found_date = false;
6083   AtomicString http_last_modified = override_last_modified_;
6084   if (http_last_modified.IsEmpty() && frame_) {
6085     if (DocumentLoader* document_loader = Loader()) {
6086       http_last_modified = document_loader->GetResponse().HttpHeaderField(
6087           http_names::kLastModified);
6088     }
6089   }
6090   if (!http_last_modified.IsEmpty()) {
6091     base::Optional<base::Time> date_value = ParseDate(http_last_modified);
6092     if (date_value) {
6093       date_value.value().LocalExplode(&exploded);
6094       found_date = true;
6095     }
6096   }
6097   // FIXME: If this document came from the file system, the HTML5
6098   // specificiation tells us to read the last modification date from the file
6099   // system.
6100   if (!found_date) {
6101     base::Time::Now().LocalExplode(&exploded);
6102   }
6103   return String::Format("%02d/%02d/%04d %02d:%02d:%02d", exploded.month,
6104                         exploded.day_of_month, exploded.year, exploded.hour,
6105                         exploded.minute, exploded.second);
6106 }
6107 
SetFindInPageRoot(Element * find_in_page_root)6108 void Document::SetFindInPageRoot(Element* find_in_page_root) {
6109   DCHECK(RuntimeEnabledFeatures::InvisibleDOMEnabled());
6110   DCHECK(!find_in_page_root || !find_in_page_root_);
6111   find_in_page_root_ = find_in_page_root;
6112 }
6113 
TopFrameOrigin() const6114 scoped_refptr<const SecurityOrigin> Document::TopFrameOrigin() const {
6115   if (!GetFrame())
6116     return scoped_refptr<const SecurityOrigin>();
6117 
6118   return GetFrame()->Tree().Top().GetSecurityContext()->GetSecurityOrigin();
6119 }
6120 
SiteForCookies() const6121 net::SiteForCookies Document::SiteForCookies() const {
6122   // TODO(mkwst): This doesn't properly handle HTML Import documents.
6123 
6124   // If this is an imported document, grab its master document's first-party:
6125   if (IsHTMLImport())
6126     return ImportsController()->Master()->SiteForCookies();
6127 
6128   if (!GetFrame())
6129     return net::SiteForCookies();
6130 
6131   Frame& top = GetFrame()->Tree().Top();
6132   const SecurityOrigin* origin = top.GetSecurityContext()->GetSecurityOrigin();
6133   // TODO(yhirano): Ideally |origin| should not be null here.
6134   if (!origin)
6135     return net::SiteForCookies();
6136 
6137   net::SiteForCookies candidate =
6138       net::SiteForCookies::FromOrigin(origin->ToUrlOrigin());
6139 
6140   if (SchemeRegistry::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
6141           origin->Protocol())) {
6142     return candidate;
6143   }
6144 
6145   const Frame* current_frame = GetFrame();
6146   while (current_frame) {
6147     const SecurityOrigin* cur_security_origin =
6148         current_frame->GetSecurityContext()->GetSecurityOrigin();
6149     if (!candidate.IsEquivalent(net::SiteForCookies::FromOrigin(
6150             cur_security_origin->ToUrlOrigin()))) {
6151       return net::SiteForCookies();
6152     }
6153     current_frame = current_frame->Tree().Parent();
6154   }
6155 
6156   return candidate;
6157 }
6158 
GetPermissionService(ExecutionContext * execution_context)6159 mojom::blink::PermissionService* Document::GetPermissionService(
6160     ExecutionContext* execution_context) {
6161   if (!permission_service_.is_bound()) {
6162     execution_context->GetBrowserInterfaceBroker().GetInterface(
6163         permission_service_.BindNewPipeAndPassReceiver(
6164             execution_context->GetTaskRunner(TaskType::kPermission)));
6165     permission_service_.set_disconnect_handler(WTF::Bind(
6166         &Document::PermissionServiceConnectionError, WrapWeakPersistent(this)));
6167   }
6168   return permission_service_.get();
6169 }
6170 
PermissionServiceConnectionError()6171 void Document::PermissionServiceConnectionError() {
6172   permission_service_.reset();
6173 }
6174 
hasStorageAccess(ScriptState * script_state) const6175 ScriptPromise Document::hasStorageAccess(ScriptState* script_state) const {
6176   const bool has_access =
6177       TopFrameOrigin() &&
6178       GetSecurityOrigin()->IsSameOriginWith(TopFrameOrigin().get());
6179   ScriptPromiseResolver* resolver =
6180       MakeGarbageCollected<ScriptPromiseResolver>(script_state);
6181 
6182   // TODO (http://crbug.com/989663)
6183   // Hookup actual logic to Resolve/Reject this request properly.
6184   ScriptPromise promise = resolver->Promise();
6185   resolver->Resolve(has_access);
6186   return promise;
6187 }
6188 
requestStorageAccess(ScriptState * script_state)6189 ScriptPromise Document::requestStorageAccess(ScriptState* script_state) {
6190   DCHECK(frame_);
6191   ScriptPromiseResolver* resolver =
6192       MakeGarbageCollected<ScriptPromiseResolver>(script_state);
6193 
6194   // TODO (http://crbug.com/989663)
6195   // Hookup actual logic to Resolve/Reject this request properly.
6196 
6197   // Access the promise first to ensure it is created so that the proper state
6198   // can be changed when it is resolved or rejected.
6199   ScriptPromise promise = resolver->Promise();
6200 
6201   const bool has_user_gesture = LocalFrame::HasTransientUserActivation(frame_);
6202   if (has_user_gesture) {
6203     auto descriptor = mojom::blink::PermissionDescriptor::New();
6204     descriptor->name = mojom::blink::PermissionName::STORAGE_ACCESS;
6205     GetPermissionService(ExecutionContext::From(script_state))
6206         ->RequestPermission(
6207             std::move(descriptor), has_user_gesture,
6208             WTF::Bind(
6209                 [](ScriptPromiseResolver* resolver,
6210                    mojom::blink::PermissionStatus status) {
6211                   DCHECK(resolver);
6212                   (status == mojom::blink::PermissionStatus::GRANTED)
6213                       ? resolver->Resolve()
6214                       : resolver->Reject();
6215                 },
6216                 WrapPersistent(resolver)));
6217   } else {
6218     // Without a user gesture any request for storage access is immediately
6219     // denied.
6220     resolver->Reject();
6221   }
6222   return promise;
6223 }
6224 
IsValidNameNonASCII(const LChar * characters,unsigned length)6225 static bool IsValidNameNonASCII(const LChar* characters, unsigned length) {
6226   if (!IsValidNameStart(characters[0]))
6227     return false;
6228 
6229   for (unsigned i = 1; i < length; ++i) {
6230     if (!IsValidNamePart(characters[i]))
6231       return false;
6232   }
6233 
6234   return true;
6235 }
6236 
IsValidNameNonASCII(const UChar * characters,unsigned length)6237 static bool IsValidNameNonASCII(const UChar* characters, unsigned length) {
6238   for (unsigned i = 0; i < length;) {
6239     bool first = i == 0;
6240     UChar32 c;
6241     U16_NEXT(characters, i, length, c);  // Increments i.
6242     if (first ? !IsValidNameStart(c) : !IsValidNamePart(c))
6243       return false;
6244   }
6245 
6246   return true;
6247 }
6248 
6249 template <typename CharType>
IsValidNameASCII(const CharType * characters,unsigned length)6250 static inline bool IsValidNameASCII(const CharType* characters,
6251                                     unsigned length) {
6252   CharType c = characters[0];
6253   if (!(IsASCIIAlpha(c) || c == ':' || c == '_'))
6254     return false;
6255 
6256   for (unsigned i = 1; i < length; ++i) {
6257     c = characters[i];
6258     if (!(IsASCIIAlphanumeric(c) || c == ':' || c == '_' || c == '-' ||
6259           c == '.'))
6260       return false;
6261   }
6262 
6263   return true;
6264 }
6265 
IsValidName(const String & name)6266 bool Document::IsValidName(const String& name) {
6267   unsigned length = name.length();
6268   if (!length)
6269     return false;
6270 
6271   if (name.Is8Bit()) {
6272     const LChar* characters = name.Characters8();
6273 
6274     if (IsValidNameASCII(characters, length))
6275       return true;
6276 
6277     return IsValidNameNonASCII(characters, length);
6278   }
6279 
6280   const UChar* characters = name.Characters16();
6281 
6282   if (IsValidNameASCII(characters, length))
6283     return true;
6284 
6285   return IsValidNameNonASCII(characters, length);
6286 }
6287 
6288 enum QualifiedNameStatus {
6289   kQNValid,
6290   kQNMultipleColons,
6291   kQNInvalidStartChar,
6292   kQNInvalidChar,
6293   kQNEmptyPrefix,
6294   kQNEmptyLocalName
6295 };
6296 
6297 struct ParseQualifiedNameResult {
6298   QualifiedNameStatus status;
6299   UChar32 character;
6300   ParseQualifiedNameResult() = default;
ParseQualifiedNameResultblink::ParseQualifiedNameResult6301   explicit ParseQualifiedNameResult(QualifiedNameStatus status)
6302       : status(status) {}
ParseQualifiedNameResultblink::ParseQualifiedNameResult6303   ParseQualifiedNameResult(QualifiedNameStatus status, UChar32 character)
6304       : status(status), character(character) {}
6305 };
6306 
6307 template <typename CharType>
ParseQualifiedNameInternal(const AtomicString & qualified_name,const CharType * characters,unsigned length,AtomicString & prefix,AtomicString & local_name)6308 static ParseQualifiedNameResult ParseQualifiedNameInternal(
6309     const AtomicString& qualified_name,
6310     const CharType* characters,
6311     unsigned length,
6312     AtomicString& prefix,
6313     AtomicString& local_name) {
6314   bool name_start = true;
6315   bool saw_colon = false;
6316   unsigned colon_pos = 0;
6317 
6318   for (unsigned i = 0; i < length;) {
6319     UChar32 c;
6320     U16_NEXT(characters, i, length, c);
6321     if (c == ':') {
6322       if (saw_colon)
6323         return ParseQualifiedNameResult(kQNMultipleColons);
6324       name_start = true;
6325       saw_colon = true;
6326       colon_pos = i - 1;
6327     } else if (name_start) {
6328       if (!IsValidNameStart(c))
6329         return ParseQualifiedNameResult(kQNInvalidStartChar, c);
6330       name_start = false;
6331     } else {
6332       if (!IsValidNamePart(c))
6333         return ParseQualifiedNameResult(kQNInvalidChar, c);
6334     }
6335   }
6336 
6337   if (!saw_colon) {
6338     prefix = g_null_atom;
6339     local_name = qualified_name;
6340   } else {
6341     prefix = AtomicString(characters, colon_pos);
6342     if (prefix.IsEmpty())
6343       return ParseQualifiedNameResult(kQNEmptyPrefix);
6344     int prefix_start = colon_pos + 1;
6345     local_name = AtomicString(characters + prefix_start, length - prefix_start);
6346   }
6347 
6348   if (local_name.IsEmpty())
6349     return ParseQualifiedNameResult(kQNEmptyLocalName);
6350 
6351   return ParseQualifiedNameResult(kQNValid);
6352 }
6353 
ParseQualifiedName(const AtomicString & qualified_name,AtomicString & prefix,AtomicString & local_name,ExceptionState & exception_state)6354 bool Document::ParseQualifiedName(const AtomicString& qualified_name,
6355                                   AtomicString& prefix,
6356                                   AtomicString& local_name,
6357                                   ExceptionState& exception_state) {
6358   unsigned length = qualified_name.length();
6359 
6360   if (!length) {
6361     exception_state.ThrowDOMException(DOMExceptionCode::kInvalidCharacterError,
6362                                       "The qualified name provided is empty.");
6363     return false;
6364   }
6365 
6366   ParseQualifiedNameResult return_value;
6367   if (qualified_name.Is8Bit())
6368     return_value =
6369         ParseQualifiedNameInternal(qualified_name, qualified_name.Characters8(),
6370                                    length, prefix, local_name);
6371   else
6372     return_value = ParseQualifiedNameInternal(qualified_name,
6373                                               qualified_name.Characters16(),
6374                                               length, prefix, local_name);
6375   if (return_value.status == kQNValid)
6376     return true;
6377 
6378   StringBuilder message;
6379   message.Append("The qualified name provided ('");
6380   message.Append(qualified_name);
6381   message.Append("') ");
6382 
6383   if (return_value.status == kQNMultipleColons) {
6384     message.Append("contains multiple colons.");
6385   } else if (return_value.status == kQNInvalidStartChar) {
6386     message.Append("contains the invalid name-start character '");
6387     message.Append(return_value.character);
6388     message.Append("'.");
6389   } else if (return_value.status == kQNInvalidChar) {
6390     message.Append("contains the invalid character '");
6391     message.Append(return_value.character);
6392     message.Append("'.");
6393   } else if (return_value.status == kQNEmptyPrefix) {
6394     message.Append("has an empty namespace prefix.");
6395   } else {
6396     DCHECK_EQ(return_value.status, kQNEmptyLocalName);
6397     message.Append("has an empty local name.");
6398   }
6399 
6400   exception_state.ThrowDOMException(DOMExceptionCode::kInvalidCharacterError,
6401                                     message.ToString());
6402   return false;
6403 }
6404 
SetEncodingData(const DocumentEncodingData & new_data)6405 void Document::SetEncodingData(const DocumentEncodingData& new_data) {
6406   // It's possible for the encoding of the document to change while we're
6407   // decoding data. That can only occur while we're processing the <head>
6408   // portion of the document. There isn't much user-visible content in the
6409   // <head>, but there is the <title> element. This function detects that
6410   // situation and re-decodes the document's title so that the user doesn't see
6411   // an incorrectly decoded title in the title bar.
6412   if (title_element_ && Encoding() != new_data.Encoding() &&
6413       !ElementTraversal::FirstWithin(*title_element_) &&
6414       Encoding() == Latin1Encoding() &&
6415       title_element_->textContent().ContainsOnlyLatin1OrEmpty()) {
6416     std::string original_bytes = title_element_->textContent().Latin1();
6417     std::unique_ptr<TextCodec> codec = NewTextCodec(new_data.Encoding());
6418     String correctly_decoded_title =
6419         codec->Decode(original_bytes.c_str(),
6420                       static_cast<wtf_size_t>(original_bytes.length()),
6421                       WTF::FlushBehavior::kDataEOF);
6422     title_element_->setTextContent(correctly_decoded_title);
6423   }
6424 
6425   DCHECK(new_data.Encoding().IsValid());
6426   encoding_data_ = new_data;
6427 
6428   // FIXME: Should be removed as part of
6429   // https://code.google.com/p/chromium/issues/detail?id=319643
6430   bool should_use_visual_ordering =
6431       encoding_data_.Encoding().UsesVisualOrdering();
6432   if (should_use_visual_ordering != visually_ordered_) {
6433     visually_ordered_ = should_use_visual_ordering;
6434     GetStyleEngine().MarkViewportStyleDirty();
6435     GetStyleEngine().MarkAllElementsForStyleRecalc(
6436         StyleChangeReasonForTracing::Create(
6437             style_change_reason::kVisuallyOrdered));
6438   }
6439 }
6440 
CompleteURL(const String & url) const6441 KURL Document::CompleteURL(const String& url) const {
6442   return CompleteURLWithOverride(url, base_url_);
6443 }
6444 
CompleteURLWithOverride(const String & url,const KURL & base_url_override) const6445 KURL Document::CompleteURLWithOverride(const String& url,
6446                                        const KURL& base_url_override) const {
6447   DCHECK(base_url_override.IsEmpty() || base_url_override.IsValid());
6448 
6449   // Always return a null URL when passed a null string.
6450   // FIXME: Should we change the KURL constructor to have this behavior?
6451   // See also [CSS]StyleSheet::completeURL(const String&)
6452   if (url.IsNull())
6453     return KURL();
6454   if (!Encoding().IsValid())
6455     return KURL(base_url_override, url);
6456   return KURL(base_url_override, url, Encoding());
6457 }
6458 
6459 // static
ShouldInheritSecurityOriginFromOwner(const KURL & url)6460 bool Document::ShouldInheritSecurityOriginFromOwner(const KURL& url) {
6461   // https://html.spec.whatwg.org/C/#origin
6462   //
6463   // If a Document is the initial "about:blank" document The origin and
6464   // effective script origin of the Document are those it was assigned when its
6465   // browsing context was created.
6466   //
6467   // Note: We generalize this to all "blank" URLs and invalid URLs because we
6468   // treat all of these URLs as about:blank.
6469   return url.IsEmpty() || url.ProtocolIsAbout();
6470 }
6471 
OpenSearchDescriptionURL()6472 KURL Document::OpenSearchDescriptionURL() {
6473   static const char kOpenSearchMIMEType[] =
6474       "application/opensearchdescription+xml";
6475   static const char kOpenSearchRelation[] = "search";
6476 
6477   // FIXME: Why do only top-level frames have openSearchDescriptionURLs?
6478   if (!GetFrame() || GetFrame()->Tree().Parent())
6479     return KURL();
6480 
6481   // FIXME: Why do we need to wait for load completion?
6482   if (!LoadEventFinished())
6483     return KURL();
6484 
6485   if (!head())
6486     return KURL();
6487 
6488   for (HTMLLinkElement* link_element =
6489            Traversal<HTMLLinkElement>::FirstChild(*head());
6490        link_element;
6491        link_element = Traversal<HTMLLinkElement>::NextSibling(*link_element)) {
6492     if (!EqualIgnoringASCIICase(link_element->GetType(), kOpenSearchMIMEType) ||
6493         !EqualIgnoringASCIICase(link_element->Rel(), kOpenSearchRelation))
6494       continue;
6495     if (link_element->Href().IsEmpty())
6496       continue;
6497 
6498     // Count usage; perhaps we can lock this to secure contexts.
6499     WebFeature osd_disposition;
6500     scoped_refptr<const SecurityOrigin> target =
6501         SecurityOrigin::Create(link_element->Href());
6502     if (IsSecureContext()) {
6503       osd_disposition = target->IsPotentiallyTrustworthy()
6504                             ? WebFeature::kOpenSearchSecureOriginSecureTarget
6505                             : WebFeature::kOpenSearchSecureOriginInsecureTarget;
6506     } else {
6507       osd_disposition =
6508           target->IsPotentiallyTrustworthy()
6509               ? WebFeature::kOpenSearchInsecureOriginSecureTarget
6510               : WebFeature::kOpenSearchInsecureOriginInsecureTarget;
6511     }
6512     UseCounter::Count(*this, osd_disposition);
6513 
6514     return link_element->Href();
6515   }
6516 
6517   return KURL();
6518 }
6519 
currentScriptForBinding(HTMLScriptElementOrSVGScriptElement & script_element) const6520 void Document::currentScriptForBinding(
6521     HTMLScriptElementOrSVGScriptElement& script_element) const {
6522   if (!current_script_stack_.IsEmpty()) {
6523     if (ScriptElementBase* script_element_base = current_script_stack_.back())
6524       script_element_base->SetScriptElementForBinding(script_element);
6525   }
6526 }
6527 
PushCurrentScript(ScriptElementBase * new_current_script)6528 void Document::PushCurrentScript(ScriptElementBase* new_current_script) {
6529   current_script_stack_.push_back(new_current_script);
6530 }
6531 
PopCurrentScript(ScriptElementBase * script)6532 void Document::PopCurrentScript(ScriptElementBase* script) {
6533   DCHECK(!current_script_stack_.IsEmpty());
6534   DCHECK_EQ(current_script_stack_.back(), script);
6535   current_script_stack_.pop_back();
6536 }
6537 
SetTransformSource(std::unique_ptr<TransformSource> source)6538 void Document::SetTransformSource(std::unique_ptr<TransformSource> source) {
6539   transform_source_ = std::move(source);
6540 }
6541 
designMode() const6542 String Document::designMode() const {
6543   return InDesignMode() ? "on" : "off";
6544 }
6545 
setDesignMode(const String & value)6546 void Document::setDesignMode(const String& value) {
6547   bool new_value = design_mode_;
6548   if (EqualIgnoringASCIICase(value, "on")) {
6549     new_value = true;
6550     UseCounter::Count(*this, WebFeature::kDocumentDesignModeEnabeld);
6551   } else if (EqualIgnoringASCIICase(value, "off")) {
6552     new_value = false;
6553   }
6554   if (new_value == design_mode_)
6555     return;
6556   design_mode_ = new_value;
6557   GetStyleEngine().MarkViewportStyleDirty();
6558   GetStyleEngine().MarkAllElementsForStyleRecalc(
6559       StyleChangeReasonForTracing::Create(style_change_reason::kDesignMode));
6560 }
6561 
ParentDocument() const6562 Document* Document::ParentDocument() const {
6563   if (!frame_)
6564     return nullptr;
6565   auto* parent_local_frame = DynamicTo<LocalFrame>(frame_->Tree().Parent());
6566   if (!parent_local_frame)
6567     return nullptr;
6568   return parent_local_frame->GetDocument();
6569 }
6570 
TopDocument() const6571 Document& Document::TopDocument() const {
6572   // FIXME: Not clear what topDocument() should do in the OOPI case--should it
6573   // return the topmost available Document, or something else?
6574   Document* doc = const_cast<Document*>(this);
6575   for (HTMLFrameOwnerElement* element = doc->LocalOwner(); element;
6576        element = doc->LocalOwner())
6577     doc = &element->GetDocument();
6578 
6579   DCHECK(doc);
6580   return *doc;
6581 }
6582 
ContextDocument() const6583 Document* Document::ContextDocument() const {
6584   return context_document_ ? context_document_.Get()
6585                            : const_cast<Document*>(this);
6586 }
6587 
createAttribute(const AtomicString & name,ExceptionState & exception_state)6588 Attr* Document::createAttribute(const AtomicString& name,
6589                                 ExceptionState& exception_state) {
6590   if (!IsValidName(name)) {
6591     exception_state.ThrowDOMException(DOMExceptionCode::kInvalidCharacterError,
6592                                       "The localName provided ('" + name +
6593                                           "') contains an invalid character.");
6594     return nullptr;
6595   }
6596   return MakeGarbageCollected<Attr>(
6597       *this, QualifiedName(g_null_atom, ConvertLocalName(name), g_null_atom),
6598       g_empty_atom);
6599 }
6600 
createAttributeNS(const AtomicString & namespace_uri,const AtomicString & qualified_name,ExceptionState & exception_state)6601 Attr* Document::createAttributeNS(const AtomicString& namespace_uri,
6602                                   const AtomicString& qualified_name,
6603                                   ExceptionState& exception_state) {
6604   AtomicString prefix, local_name;
6605   if (!ParseQualifiedName(qualified_name, prefix, local_name, exception_state))
6606     return nullptr;
6607 
6608   QualifiedName q_name(prefix, local_name, namespace_uri);
6609 
6610   if (!HasValidNamespaceForAttributes(q_name)) {
6611     exception_state.ThrowDOMException(
6612         DOMExceptionCode::kNamespaceError,
6613         "The namespace URI provided ('" + namespace_uri +
6614             "') is not valid for the qualified name provided ('" +
6615             qualified_name + "').");
6616     return nullptr;
6617   }
6618 
6619   return MakeGarbageCollected<Attr>(*this, q_name, g_empty_atom);
6620 }
6621 
SvgExtensions()6622 const SVGDocumentExtensions* Document::SvgExtensions() {
6623   return svg_extensions_.Get();
6624 }
6625 
AccessSVGExtensions()6626 SVGDocumentExtensions& Document::AccessSVGExtensions() {
6627   if (!svg_extensions_)
6628     svg_extensions_ = MakeGarbageCollected<SVGDocumentExtensions>(this);
6629   return *svg_extensions_;
6630 }
6631 
HasSVGRootNode() const6632 bool Document::HasSVGRootNode() const {
6633   return IsA<SVGSVGElement>(documentElement());
6634 }
6635 
images()6636 HTMLCollection* Document::images() {
6637   return EnsureCachedCollection<HTMLCollection>(kDocImages);
6638 }
6639 
applets()6640 HTMLCollection* Document::applets() {
6641   return EnsureCachedCollection<HTMLCollection>(kDocApplets);
6642 }
6643 
embeds()6644 HTMLCollection* Document::embeds() {
6645   return EnsureCachedCollection<HTMLCollection>(kDocEmbeds);
6646 }
6647 
scripts()6648 HTMLCollection* Document::scripts() {
6649   return EnsureCachedCollection<HTMLCollection>(kDocScripts);
6650 }
6651 
links()6652 HTMLCollection* Document::links() {
6653   return EnsureCachedCollection<HTMLCollection>(kDocLinks);
6654 }
6655 
forms()6656 HTMLCollection* Document::forms() {
6657   return EnsureCachedCollection<HTMLCollection>(kDocForms);
6658 }
6659 
anchors()6660 HTMLCollection* Document::anchors() {
6661   return EnsureCachedCollection<HTMLCollection>(kDocAnchors);
6662 }
6663 
all()6664 HTMLAllCollection* Document::all() {
6665   return EnsureCachedCollection<HTMLAllCollection>(kDocAll);
6666 }
6667 
WindowNamedItems(const AtomicString & name)6668 HTMLCollection* Document::WindowNamedItems(const AtomicString& name) {
6669   return EnsureCachedCollection<WindowNameCollection>(kWindowNamedItems, name);
6670 }
6671 
DocumentNamedItems(const AtomicString & name)6672 DocumentNameCollection* Document::DocumentNamedItems(const AtomicString& name) {
6673   return EnsureCachedCollection<DocumentNameCollection>(kDocumentNamedItems,
6674                                                         name);
6675 }
6676 
DocumentAllNamedItems(const AtomicString & name)6677 HTMLCollection* Document::DocumentAllNamedItems(const AtomicString& name) {
6678   return EnsureCachedCollection<DocumentAllNameCollection>(
6679       kDocumentAllNamedItems, name);
6680 }
6681 
defaultView() const6682 DOMWindow* Document::defaultView() const {
6683   // The HTML spec requires to return null if the document is detached from the
6684   // DOM.  However, |dom_window_| is not cleared on the detachment.  So, we need
6685   // to check |frame_| to tell whether the document is attached or not.
6686   return frame_ ? dom_window_ : nullptr;
6687 }
6688 
6689 namespace {
6690 
6691 using performance_manager::mojom::InterventionPolicy;
6692 
6693 // A helper function to set the origin trial freeze policy of a document.
SetOriginTrialFreezePolicy(DocumentResourceCoordinator * document_resource_coordinator,ExecutionContext * context)6694 void SetOriginTrialFreezePolicy(
6695     DocumentResourceCoordinator* document_resource_coordinator,
6696     ExecutionContext* context) {
6697   // An explicit opt-out overrides an explicit opt-in if both are present.
6698   if (RuntimeEnabledFeatures::PageFreezeOptOutEnabled(context)) {
6699     document_resource_coordinator->SetOriginTrialFreezePolicy(
6700         InterventionPolicy::kOptOut);
6701     UseCounter::Count(context, WebFeature::kPageFreezeOptOut);
6702   } else if (RuntimeEnabledFeatures::PageFreezeOptInEnabled(context)) {
6703     document_resource_coordinator->SetOriginTrialFreezePolicy(
6704         InterventionPolicy::kOptIn);
6705     UseCounter::Count(context, WebFeature::kPageFreezeOptIn);
6706   }
6707 }
6708 
6709 }  // namespace
6710 
FinishedParsing()6711 void Document::FinishedParsing() {
6712   DCHECK(!GetScriptableDocumentParser() || !parser_->IsParsing());
6713   DCHECK(!GetScriptableDocumentParser() || ready_state_ != kLoading);
6714   SetParsingState(kInDOMContentLoaded);
6715   DocumentParserTiming::From(*this).MarkParserStop();
6716 
6717   // FIXME: DOMContentLoaded is dispatched synchronously, but this should be
6718   // dispatched in a queued task, see https://crbug.com/425790
6719   if (document_timing_.DomContentLoadedEventStart().is_null())
6720     document_timing_.MarkDomContentLoadedEventStart();
6721   DispatchEvent(*Event::CreateBubble(event_type_names::kDOMContentLoaded));
6722   if (document_timing_.DomContentLoadedEventEnd().is_null())
6723     document_timing_.MarkDomContentLoadedEventEnd();
6724   SetParsingState(kFinishedParsing);
6725 
6726   // Ensure Custom Element callbacks are drained before DOMContentLoaded.
6727   // FIXME: Remove this ad-hoc checkpoint when DOMContentLoaded is dispatched in
6728   // a queued task, which will do a checkpoint anyway. https://crbug.com/425790
6729   Microtask::PerformCheckpoint(V8PerIsolateData::MainThreadIsolate());
6730 
6731   ScriptableDocumentParser* parser = GetScriptableDocumentParser();
6732   well_formed_ = parser && parser->WellFormed();
6733 
6734   if (LocalFrame* frame = GetFrame()) {
6735     // Guarantee at least one call to the client specifying a title. (If
6736     // |title_| is not empty, then the title has already been dispatched.)
6737     if (title_.IsEmpty())
6738       DispatchDidReceiveTitle();
6739 
6740     // Don't update the layout tree if we haven't requested the main resource
6741     // yet to avoid adding extra latency. Note that the first layout tree update
6742     // can be expensive since it triggers the parsing of the default stylesheets
6743     // which are compiled-in.
6744     const bool main_resource_was_already_requested =
6745         frame->Loader().StateMachine()->CommittedFirstRealDocumentLoad();
6746 
6747     // FrameLoader::finishedParsing() might end up calling
6748     // Document::implicitClose() if all resource loads are
6749     // complete. HTMLObjectElements can start loading their resources from post
6750     // attach callbacks triggered by recalcStyle().  This means if we parse out
6751     // an <object> tag and then reach the end of the document without updating
6752     // styles, we might not have yet started the resource load and might fire
6753     // the window load event too early.  To avoid this we force the styles to be
6754     // up to date before calling FrameLoader::finishedParsing().  See
6755     // https://bugs.webkit.org/show_bug.cgi?id=36864 starting around comment 35.
6756     if (main_resource_was_already_requested)
6757       UpdateStyleAndLayoutTree();
6758 
6759     BeginLifecycleUpdatesIfRenderingReady();
6760 
6761     frame->Loader().FinishedParsing();
6762 
6763     TRACE_EVENT_INSTANT1("devtools.timeline", "MarkDOMContent",
6764                          TRACE_EVENT_SCOPE_THREAD, "data",
6765                          inspector_mark_load_event::Data(frame));
6766     probe::DomContentLoadedEventFired(frame);
6767     frame->GetIdlenessDetector()->DomContentLoadedEventFired();
6768 
6769     // Forward origin trial freeze policy to the corresponding frame object in
6770     // the resource coordinator.
6771     if (auto* document_resource_coordinator = GetResourceCoordinator())
6772       SetOriginTrialFreezePolicy(document_resource_coordinator, domWindow());
6773   }
6774 
6775   // Schedule dropping of the ElementDataCache. We keep it alive for a while
6776   // after parsing finishes so that dynamically inserted content can also
6777   // benefit from sharing optimizations.  Note that we don't refresh the timer
6778   // on cache access since that could lead to huge caches being kept alive
6779   // indefinitely by something innocuous like JS setting .innerHTML repeatedly
6780   // on a timer.
6781   element_data_cache_clear_timer_.StartOneShot(base::TimeDelta::FromSeconds(10),
6782                                                FROM_HERE);
6783 
6784   // Parser should have picked up all preloads by now
6785   fetcher_->ClearPreloads(ResourceFetcher::kClearSpeculativeMarkupPreloads);
6786 }
6787 
ElementDataCacheClearTimerFired(TimerBase *)6788 void Document::ElementDataCacheClearTimerFired(TimerBase*) {
6789   element_data_cache_.Clear();
6790 }
6791 
BeginLifecycleUpdatesIfRenderingReady()6792 void Document::BeginLifecycleUpdatesIfRenderingReady() {
6793   if (!IsActive())
6794     return;
6795   if (!HaveRenderBlockingResourcesLoaded())
6796     return;
6797   font_preload_manager_.WillBeginRendering();
6798   View()->BeginLifecycleUpdates();
6799 }
6800 
IconURLs(int icon_types_mask)6801 Vector<IconURL> Document::IconURLs(int icon_types_mask) {
6802   IconURL first_favicon;
6803   IconURL first_touch_icon;
6804   IconURL first_touch_precomposed_icon;
6805   Vector<IconURL> secondary_icons;
6806 
6807   using TraversalFunction = HTMLLinkElement* (*)(const Node&);
6808   TraversalFunction find_next_candidate =
6809       &Traversal<HTMLLinkElement>::NextSibling;
6810 
6811   HTMLLinkElement* first_element = nullptr;
6812   if (head()) {
6813     first_element = Traversal<HTMLLinkElement>::FirstChild(*head());
6814   } else if (IsSVGDocument() && IsA<SVGSVGElement>(documentElement())) {
6815     first_element = Traversal<HTMLLinkElement>::FirstWithin(*documentElement());
6816     find_next_candidate = &Traversal<HTMLLinkElement>::Next;
6817   }
6818 
6819   // Start from the first child node so that icons seen later take precedence as
6820   // required by the spec.
6821   for (HTMLLinkElement* link_element = first_element; link_element;
6822        link_element = find_next_candidate(*link_element)) {
6823     if (!((1 << static_cast<int>(link_element->GetIconType())) &
6824           icon_types_mask)) {
6825       continue;
6826     }
6827     if (link_element->Href().IsEmpty())
6828       continue;
6829 
6830     IconURL new_url(link_element->Href(), link_element->IconSizes(),
6831                     link_element->GetType(), link_element->GetIconType());
6832     if (link_element->GetIconType() ==
6833         mojom::blink::FaviconIconType::kFavicon) {
6834       if (first_favicon.icon_type_ != mojom::blink::FaviconIconType::kInvalid)
6835         secondary_icons.push_back(first_favicon);
6836       first_favicon = new_url;
6837     } else if (link_element->GetIconType() ==
6838                mojom::blink::FaviconIconType::kTouchIcon) {
6839       if (first_touch_icon.icon_type_ !=
6840           mojom::blink::FaviconIconType::kInvalid)
6841         secondary_icons.push_back(first_touch_icon);
6842       first_touch_icon = new_url;
6843     } else if (link_element->GetIconType() ==
6844                mojom::blink::FaviconIconType::kTouchPrecomposedIcon) {
6845       if (first_touch_precomposed_icon.icon_type_ !=
6846           mojom::blink::FaviconIconType::kInvalid)
6847         secondary_icons.push_back(first_touch_precomposed_icon);
6848       first_touch_precomposed_icon = new_url;
6849     } else {
6850       NOTREACHED();
6851     }
6852   }
6853 
6854   Vector<IconURL> icon_urls;
6855   if (first_favicon.icon_type_ != mojom::blink::FaviconIconType::kInvalid) {
6856     icon_urls.push_back(first_favicon);
6857   } else if (url_.ProtocolIsInHTTPFamily() &&
6858              icon_types_mask & 1 << static_cast<int>(
6859                                    mojom::blink::FaviconIconType::kFavicon)) {
6860     icon_urls.push_back(IconURL::DefaultFavicon(url_));
6861   }
6862 
6863   if (first_touch_icon.icon_type_ != mojom::blink::FaviconIconType::kInvalid)
6864     icon_urls.push_back(first_touch_icon);
6865   if (first_touch_precomposed_icon.icon_type_ !=
6866       mojom::blink::FaviconIconType::kInvalid)
6867     icon_urls.push_back(first_touch_precomposed_icon);
6868   for (int i = secondary_icons.size() - 1; i >= 0; --i)
6869     icon_urls.push_back(secondary_icons[i]);
6870   return icon_urls;
6871 }
6872 
ThemeColor() const6873 base::Optional<Color> Document::ThemeColor() const {
6874   auto* root_element = documentElement();
6875   if (!root_element)
6876     return base::nullopt;
6877   for (HTMLMetaElement& meta_element :
6878        Traversal<HTMLMetaElement>::DescendantsOf(*root_element)) {
6879     Color color;
6880     if (EqualIgnoringASCIICase(meta_element.GetName(), "theme-color") &&
6881         CSSParser::ParseColor(
6882             color, meta_element.Content().GetString().StripWhiteSpace(), true))
6883       return color;
6884   }
6885   return base::nullopt;
6886 }
6887 
ColorSchemeMetaChanged()6888 void Document::ColorSchemeMetaChanged() {
6889   if (!RuntimeEnabledFeatures::MetaColorSchemeEnabled())
6890     return;
6891 
6892   const CSSValue* color_scheme = nullptr;
6893   if (auto* head_element = head()) {
6894     for (HTMLMetaElement& meta_element :
6895          Traversal<HTMLMetaElement>::DescendantsOf(*head_element)) {
6896       if (EqualIgnoringASCIICase(meta_element.GetName(), "color-scheme")) {
6897         if ((color_scheme = CSSParser::ParseSingleValue(
6898                  CSSPropertyID::kColorScheme,
6899                  meta_element.Content().GetString().StripWhiteSpace(),
6900                  ElementSheet().Contents()->ParserContext()))) {
6901           break;
6902         }
6903       }
6904     }
6905   }
6906   GetStyleEngine().SetColorSchemeFromMeta(color_scheme);
6907 }
6908 
GetLinkElement(const Document * doc,bool (* match_fn)(HTMLLinkElement &))6909 static HTMLLinkElement* GetLinkElement(const Document* doc,
6910                                        bool (*match_fn)(HTMLLinkElement&)) {
6911   HTMLHeadElement* head = doc->head();
6912   if (!head)
6913     return nullptr;
6914 
6915   // The first matching link element is used. Others are ignored.
6916   for (HTMLLinkElement& link_element :
6917        Traversal<HTMLLinkElement>::ChildrenOf(*head)) {
6918     if (match_fn(link_element))
6919       return &link_element;
6920   }
6921   return nullptr;
6922 }
6923 
LinkManifest() const6924 HTMLLinkElement* Document::LinkManifest() const {
6925   return GetLinkElement(this, [](HTMLLinkElement& link_element) {
6926     return link_element.RelAttribute().IsManifest();
6927   });
6928 }
6929 
LinkCanonical() const6930 HTMLLinkElement* Document::LinkCanonical() const {
6931   return GetLinkElement(this, [](HTMLLinkElement& link_element) {
6932     return link_element.RelAttribute().IsCanonical();
6933   });
6934 }
6935 
PoliciesInitialized(const DocumentInit & document_initializer)6936 void Document::PoliciesInitialized(const DocumentInit& document_initializer) {
6937   // Processing of the feature policy header is done before the SecurityContext
6938   // is initialized. This method just records the usage.
6939   if (!document_initializer.FeaturePolicyHeader().IsEmpty())
6940     UseCounter::Count(*this, WebFeature::kFeaturePolicyHeader);
6941 
6942   // At this point, the document will not have been installed in the frame's
6943   // LocalDOMWindow, so we cannot call frame_->IsFeatureEnabled. This calls
6944   // SecurityContext::IsFeatureEnabled instead, which cannot report, but we
6945   // don't need reporting here in any case.
6946   is_vertical_scroll_enforced_ =
6947       frame_ && !frame_->IsMainFrame() &&
6948       RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled() &&
6949       !GetSecurityContext().GetFeaturePolicy()->IsFeatureEnabled(
6950           mojom::blink::FeaturePolicyFeature::kVerticalScroll);
6951 }
6952 
GetOwnerContainerPolicy() const6953 const ParsedFeaturePolicy Document::GetOwnerContainerPolicy() const {
6954   // If this frame is not the main frame, then get the container policy from its
6955   // owner.
6956   if (frame_ && frame_->Owner())
6957     return frame_->Owner()->GetFramePolicy().container_policy;
6958   return ParsedFeaturePolicy();
6959 }
6960 
GetParentFeaturePolicy() const6961 const FeaturePolicy* Document::GetParentFeaturePolicy() const {
6962   // If this frame is not the main frame, then get the feature policy from its
6963   // parent.
6964   if (frame_ && !frame_->IsMainFrame())
6965     return frame_->Tree().Parent()->GetSecurityContext()->GetFeaturePolicy();
6966   return nullptr;
6967 }
6968 
ApplyPendingFramePolicyHeaders()6969 void Document::ApplyPendingFramePolicyHeaders() {
6970   if (frame_) {
6971     frame_->Client()->DidSetFramePolicyHeaders(
6972         GetSandboxFlags(), pending_fp_headers_, pending_dp_headers_);
6973   }
6974   pending_fp_headers_.clear();
6975   pending_dp_headers_.clear();
6976 }
6977 
AllowedToUseDynamicMarkUpInsertion(const char * api_name,ExceptionState & exception_state)6978 bool Document::AllowedToUseDynamicMarkUpInsertion(
6979     const char* api_name,
6980     ExceptionState& exception_state) {
6981   if (!RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled()) {
6982     return true;
6983   }
6984   if (!frame_ ||
6985       IsFeatureEnabled(mojom::blink::FeaturePolicyFeature::kDocumentWrite,
6986                        ReportOptions::kReportOnFailure)) {
6987     return true;
6988   }
6989 
6990   // TODO(ekaramad): Throwing an exception seems an ideal resolution to mishaps
6991   // in using the API against the policy. But this cannot be applied to cross-
6992   // origin as there are security risks involved. We should perhaps unload the
6993   // whole frame instead of throwing.
6994   exception_state.ThrowDOMException(
6995       DOMExceptionCode::kNotAllowedError,
6996       String::Format(
6997           "The use of method '%s' has been blocked by feature policy. The "
6998           "feature "
6999           "'document-write' is disabled in this document.",
7000           api_name));
7001   return false;
7002 }
7003 
UkmRecorder()7004 ukm::UkmRecorder* Document::UkmRecorder() {
7005   if (ukm_recorder_)
7006     return ukm_recorder_.get();
7007 
7008   mojo::PendingRemote<ukm::mojom::UkmRecorderInterface> recorder;
7009   Platform::Current()->GetBrowserInterfaceBroker()->GetInterface(
7010       recorder.InitWithNewPipeAndPassReceiver());
7011   ukm_recorder_ = std::make_unique<ukm::MojoUkmRecorder>(std::move(recorder));
7012 
7013   // TODO(crbug/795354): Move handling of URL recording out of the renderer.
7014   // URL must only be recorded from the main frame.
7015   if (IsInMainFrame())
7016     ukm_recorder_->UpdateSourceURL(ukm_source_id_, url_);
7017   return ukm_recorder_.get();
7018 }
7019 
UkmSourceID() const7020 ukm::SourceId Document::UkmSourceID() const {
7021   return ukm_source_id_;
7022 }
7023 
GetFontMatchingMetrics()7024 FontMatchingMetrics* Document::GetFontMatchingMetrics() {
7025   if (font_matching_metrics_)
7026     return font_matching_metrics_.get();
7027   font_matching_metrics_ = std::make_unique<FontMatchingMetrics>(
7028       IsInMainFrame(), UkmRecorder(), UkmSourceID());
7029   return font_matching_metrics_.get();
7030 }
7031 
InitContentSecurityPolicy(ContentSecurityPolicy * csp)7032 void Document::InitContentSecurityPolicy(ContentSecurityPolicy* csp) {
7033   GetSecurityContext().SetContentSecurityPolicy(csp);
7034   GetContentSecurityPolicy()->BindToDelegate(
7035       GetContentSecurityPolicyDelegate());
7036 }
7037 
InitSecurityContext(const DocumentInit & initializer)7038 void Document::InitSecurityContext(const DocumentInit& initializer) {
7039   DCHECK(GetSecurityOrigin());
7040   // If the CSP was provided by the DocumentLoader or is from ImportsController
7041   // it doesn't need to be bound right now. ImportsController takes a reference
7042   // to a master document's CSP which is already bound. Document construction
7043   // occurs in the DocumentLoader occurs before the frame reference is bound so
7044   // callbacks from binding the CSP delegate immediately would not get called
7045   // if it was bound immediately. eg. Callbacks back to browser or console
7046   // logging.
7047   if (!initializer.HasSecurityContext()) {
7048     // No source for a security context.
7049     // This can occur via document.implementation.createDocument().
7050     cookie_url_ = KURL(g_empty_string);
7051     return;
7052   }
7053   GetSecurityContext().SetInsecureRequestPolicy(
7054       initializer.GetInsecureRequestPolicy());
7055   if (initializer.InsecureNavigationsToUpgrade()) {
7056     for (auto to_upgrade : *initializer.InsecureNavigationsToUpgrade())
7057       GetSecurityContext().AddInsecureNavigationUpgrade(to_upgrade);
7058   }
7059 
7060   bool inherit_cookie_url_from_owner = initializer.IsSrcdocDocument() ||
7061                                        url_.IsAboutBlankURL() ||
7062                                        !initializer.OriginToCommit();
7063 
7064   cookie_url_ = inherit_cookie_url_from_owner && initializer.OwnerDocument()
7065                     ? initializer.OwnerDocument()->CookieURL()
7066                     : url_;
7067 
7068   GetSecurityContext().SetAddressSpace(initializer.GetIPAddressSpace());
7069 }
7070 
BindContentSecurityPolicy()7071 void Document::BindContentSecurityPolicy() {
7072   DCHECK(!GetContentSecurityPolicy()->IsBound());
7073   GetContentSecurityPolicy()->BindToDelegate(
7074       GetContentSecurityPolicyDelegate());
7075 }
7076 
CanExecuteScripts(ReasonForCallingCanExecuteScripts reason)7077 bool Document::CanExecuteScripts(ReasonForCallingCanExecuteScripts reason) {
7078   DCHECK(GetFrame())
7079       << "you are querying canExecuteScripts on a non contextDocument.";
7080 
7081   // Normally, scripts are not allowed in sandboxed contexts that disallow them.
7082   // However, there is an exception for cases when the script should bypass the
7083   // main world's CSP (such as for privileged isolated worlds). See
7084   // https://crbug.com/811528.
7085   if (IsSandboxed(mojom::blink::WebSandboxFlags::kScripts) &&
7086       !ContentSecurityPolicy::ShouldBypassMainWorld(domWindow())) {
7087     // FIXME: This message should be moved off the console once a solution to
7088     // https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
7089     if (reason == kAboutToExecuteScript) {
7090       AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
7091           mojom::ConsoleMessageSource::kSecurity,
7092           mojom::ConsoleMessageLevel::kError,
7093           "Blocked script execution in '" + Url().ElidedString() +
7094               "' because the document's frame is sandboxed and the "
7095               "'allow-scripts' permission is not set."));
7096     }
7097     return false;
7098   }
7099 
7100   // No scripting on a detached frame.
7101   if (!GetFrame()->Client())
7102     return false;
7103 
7104   WebContentSettingsClient* settings_client =
7105       GetFrame()->GetContentSettingsClient();
7106 
7107   Settings* settings = GetFrame()->GetSettings();
7108   bool script_enabled = settings && settings->GetScriptEnabled();
7109   if (settings_client)
7110     script_enabled = settings_client->AllowScript(script_enabled);
7111   if (!script_enabled && reason == kAboutToExecuteScript && settings_client)
7112     settings_client->DidNotAllowScript();
7113   return script_enabled;
7114 }
7115 
AllowInlineEventHandler(Node * node,EventListener * listener,const String & context_url,const WTF::OrdinalNumber & context_line)7116 bool Document::AllowInlineEventHandler(Node* node,
7117                                        EventListener* listener,
7118                                        const String& context_url,
7119                                        const WTF::OrdinalNumber& context_line) {
7120   auto* element = DynamicTo<Element>(node);
7121 
7122   // https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-content-attributes
7123   // Step 5.1. If the Should element's inline behavior be blocked by Content
7124   // Security Policy? algorithm returns "Blocked" when executed upon element,
7125   // "script attribute", and value, then return. [CSP] [spec text]
7126   if (!GetContentSecurityPolicyForWorld()->AllowInline(
7127           ContentSecurityPolicy::InlineType::kScriptAttribute, element,
7128           listener->ScriptBody(), String() /* nonce */, context_url,
7129           context_line))
7130     return false;
7131 
7132   // HTML says that inline script needs browsing context to create its execution
7133   // environment.
7134   // http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#event-handler-attributes
7135   // Also, if the listening node came from other document, which happens on
7136   // context-less event dispatching, we also need to ask the owner document of
7137   // the node.
7138   LocalFrame* frame = ExecutingFrame();
7139   if (!frame)
7140     return false;
7141   if (!ContextDocument()->CanExecuteScripts(kNotAboutToExecuteScript))
7142     return false;
7143   if (node && node->GetDocument() != this &&
7144       !node->GetDocument().AllowInlineEventHandler(node, listener, context_url,
7145                                                    context_line))
7146     return false;
7147 
7148   return true;
7149 }
7150 
UpdateFocusAppearanceAfterLayout()7151 void Document::UpdateFocusAppearanceAfterLayout() {
7152   update_focus_appearance_after_layout_ = true;
7153 }
7154 
CancelFocusAppearanceUpdate()7155 void Document::CancelFocusAppearanceUpdate() {
7156   update_focus_appearance_after_layout_ = false;
7157 }
7158 
WillUpdateFocusAppearance() const7159 bool Document::WillUpdateFocusAppearance() const {
7160   return update_focus_appearance_after_layout_;
7161 }
7162 
UpdateFocusAppearance()7163 void Document::UpdateFocusAppearance() {
7164   update_focus_appearance_after_layout_ = false;
7165   Element* element = FocusedElement();
7166   if (!element)
7167     return;
7168   if (element->IsFocusable())
7169     element->UpdateFocusAppearance(SelectionBehaviorOnFocus::kRestore);
7170 }
7171 
AttachRange(Range * range)7172 void Document::AttachRange(Range* range) {
7173   DCHECK(!ranges_.Contains(range));
7174   ranges_.insert(range);
7175 }
7176 
DetachRange(Range * range)7177 void Document::DetachRange(Range* range) {
7178   // We don't DCHECK ranges_.contains(range) to allow us to call this
7179   // unconditionally to fix: https://bugs.webkit.org/show_bug.cgi?id=26044
7180   ranges_.erase(range);
7181 }
7182 
InitDNSPrefetch()7183 void Document::InitDNSPrefetch() {
7184   Settings* settings = GetSettings();
7185 
7186   have_explicitly_disabled_dns_prefetch_ = false;
7187   is_dns_prefetch_enabled_ = settings && settings->GetDNSPrefetchingEnabled() &&
7188                              GetSecurityOrigin()->Protocol() == "http";
7189 
7190   // Inherit DNS prefetch opt-out from parent frame
7191   if (Document* parent = ParentDocument()) {
7192     if (!parent->IsDNSPrefetchEnabled())
7193       is_dns_prefetch_enabled_ = false;
7194   }
7195 }
7196 
ParseDNSPrefetchControlHeader(const String & dns_prefetch_control)7197 void Document::ParseDNSPrefetchControlHeader(
7198     const String& dns_prefetch_control) {
7199   if (EqualIgnoringASCIICase(dns_prefetch_control, "on") &&
7200       !have_explicitly_disabled_dns_prefetch_) {
7201     is_dns_prefetch_enabled_ = true;
7202     return;
7203   }
7204 
7205   is_dns_prefetch_enabled_ = false;
7206   have_explicitly_disabled_dns_prefetch_ = true;
7207 }
7208 
GetIntersectionObserverController()7209 IntersectionObserverController* Document::GetIntersectionObserverController() {
7210   return intersection_observer_controller_;
7211 }
7212 
7213 IntersectionObserverController&
EnsureIntersectionObserverController()7214 Document::EnsureIntersectionObserverController() {
7215   if (!intersection_observer_controller_) {
7216     intersection_observer_controller_ =
7217         MakeGarbageCollected<IntersectionObserverController>(
7218             GetExecutionContext());
7219   }
7220   return *intersection_observer_controller_;
7221 }
7222 
7223 ElementIntersectionObserverData*
DocumentExplicitRootIntersectionObserverData() const7224 Document::DocumentExplicitRootIntersectionObserverData() const {
7225   return document_explicit_root_intersection_observer_data_.Get();
7226 }
7227 
7228 ElementIntersectionObserverData&
EnsureDocumentExplicitRootIntersectionObserverData()7229 Document::EnsureDocumentExplicitRootIntersectionObserverData() {
7230   if (!document_explicit_root_intersection_observer_data_) {
7231     document_explicit_root_intersection_observer_data_ =
7232         MakeGarbageCollected<ElementIntersectionObserverData>();
7233   }
7234   return *document_explicit_root_intersection_observer_data_;
7235 }
7236 
EnsureResizeObserverController()7237 ResizeObserverController& Document::EnsureResizeObserverController() {
7238   if (!resize_observer_controller_) {
7239     resize_observer_controller_ =
7240         MakeGarbageCollected<ResizeObserverController>();
7241   }
7242   return *resize_observer_controller_;
7243 }
7244 
AddConsoleMessage(ConsoleMessage * message,bool discard_duplicates)7245 void Document::AddConsoleMessage(ConsoleMessage* message,
7246                                  bool discard_duplicates) {
7247   // Don't let non-attached Documents spam the console.
7248   if (domWindow())
7249     domWindow()->AddConsoleMessage(message, discard_duplicates);
7250 }
7251 
AddInspectorIssue(InspectorIssue * issue)7252 void Document::AddInspectorIssue(InspectorIssue* issue) {
7253   Page* page = GetPage();
7254 
7255   if (!page) {
7256     return;
7257   }
7258 
7259   page->GetInspectorIssueStorage().AddInspectorIssue(GetExecutionContext(),
7260                                                      issue);
7261 }
7262 
AddToTopLayer(Element * element,const Element * before)7263 void Document::AddToTopLayer(Element* element, const Element* before) {
7264   if (element->IsInTopLayer())
7265     return;
7266 
7267   DCHECK(!top_layer_elements_.Contains(element));
7268   DCHECK(!before || top_layer_elements_.Contains(before));
7269   if (before) {
7270     wtf_size_t before_position = top_layer_elements_.Find(before);
7271     top_layer_elements_.insert(before_position, element);
7272   } else {
7273     top_layer_elements_.push_back(element);
7274   }
7275   element->SetIsInTopLayer(true);
7276 }
7277 
RemoveFromTopLayer(Element * element)7278 void Document::RemoveFromTopLayer(Element* element) {
7279   if (!element->IsInTopLayer())
7280     return;
7281   wtf_size_t position = top_layer_elements_.Find(element);
7282   DCHECK_NE(position, kNotFound);
7283   top_layer_elements_.EraseAt(position);
7284   element->SetIsInTopLayer(false);
7285 }
7286 
ActiveModalDialog() const7287 HTMLDialogElement* Document::ActiveModalDialog() const {
7288   for (auto it = top_layer_elements_.rbegin(); it != top_layer_elements_.rend();
7289        ++it) {
7290     if (auto* dialog = DynamicTo<HTMLDialogElement>(*it->Get()))
7291       return dialog;
7292   }
7293 
7294   return nullptr;
7295 }
7296 
exitPointerLock()7297 void Document::exitPointerLock() {
7298   if (!GetPage())
7299     return;
7300   if (Element* target = GetPage()->GetPointerLockController().GetElement()) {
7301     if (target->GetDocument() != this)
7302       return;
7303     GetPage()->GetPointerLockController().RequestPointerUnlock();
7304   }
7305 }
7306 
PointerLockElement() const7307 Element* Document::PointerLockElement() const {
7308   if (!GetPage() || GetPage()->GetPointerLockController().LockPending())
7309     return nullptr;
7310   if (Element* element = GetPage()->GetPointerLockController().GetElement()) {
7311     if (element->GetDocument() == this)
7312       return element;
7313   }
7314   return nullptr;
7315 }
7316 
DecrementLoadEventDelayCount()7317 void Document::DecrementLoadEventDelayCount() {
7318   DCHECK(load_event_delay_count_);
7319   --load_event_delay_count_;
7320 
7321   if (!load_event_delay_count_)
7322     CheckLoadEventSoon();
7323 }
7324 
DecrementLoadEventDelayCountAndCheckLoadEvent()7325 void Document::DecrementLoadEventDelayCountAndCheckLoadEvent() {
7326   DCHECK(load_event_delay_count_);
7327   --load_event_delay_count_;
7328 
7329   if (!load_event_delay_count_)
7330     CheckCompleted();
7331 }
7332 
CheckLoadEventSoon()7333 void Document::CheckLoadEventSoon() {
7334   if (GetFrame() && !load_event_delay_timer_.IsActive())
7335     load_event_delay_timer_.StartOneShot(base::TimeDelta(), FROM_HERE);
7336 }
7337 
IsDelayingLoadEvent()7338 bool Document::IsDelayingLoadEvent() {
7339   // Always delay load events until after garbage collection.
7340   // This way we don't have to explicitly delay load events via
7341   // incrementLoadEventDelayCount and decrementLoadEventDelayCount in
7342   // Node destructors.
7343   if (ThreadState::Current()->SweepForbidden()) {
7344     if (!load_event_delay_count_)
7345       CheckLoadEventSoon();
7346     return true;
7347   }
7348   return load_event_delay_count_;
7349 }
7350 
LoadEventDelayTimerFired(TimerBase *)7351 void Document::LoadEventDelayTimerFired(TimerBase*) {
7352   CheckCompleted();
7353 }
7354 
LoadPluginsSoon()7355 void Document::LoadPluginsSoon() {
7356   // FIXME: Remove this timer once we don't need to compute layout to load
7357   // plugins.
7358   if (!plugin_loading_timer_.IsActive())
7359     plugin_loading_timer_.StartOneShot(base::TimeDelta(), FROM_HERE);
7360 }
7361 
PluginLoadingTimerFired(TimerBase *)7362 void Document::PluginLoadingTimerFired(TimerBase*) {
7363   UpdateStyleAndLayout(DocumentUpdateReason::kPlugin);
7364 }
7365 
GetScriptedAnimationController()7366 ScriptedAnimationController& Document::GetScriptedAnimationController() {
7367   return *scripted_animation_controller_;
7368 }
7369 
RequestAnimationFrame(FrameRequestCallbackCollection::FrameCallback * callback)7370 int Document::RequestAnimationFrame(
7371     FrameRequestCallbackCollection::FrameCallback* callback) {
7372   return scripted_animation_controller_->RegisterFrameCallback(callback);
7373 }
7374 
CancelAnimationFrame(int id)7375 void Document::CancelAnimationFrame(int id) {
7376   scripted_animation_controller_->CancelFrameCallback(id);
7377 }
7378 
ServiceScriptedAnimations(base::TimeTicks monotonic_animation_start_time)7379 void Document::ServiceScriptedAnimations(
7380     base::TimeTicks monotonic_animation_start_time) {
7381   auto start_time = base::TimeTicks::Now();
7382   scripted_animation_controller_->ServiceScriptedAnimations(
7383       monotonic_animation_start_time);
7384   if (GetFrame()) {
7385     GetFrame()->GetFrameScheduler()->AddTaskTime(base::TimeTicks::Now() -
7386                                                  start_time);
7387   }
7388 }
7389 
RequestPostAnimationFrame(FrameRequestCallbackCollection::FrameCallback * cb)7390 int Document::RequestPostAnimationFrame(
7391     FrameRequestCallbackCollection::FrameCallback* cb) {
7392   return scripted_animation_controller_->RegisterPostFrameCallback(cb);
7393 }
7394 
CancelPostAnimationFrame(int id)7395 void Document::CancelPostAnimationFrame(int id) {
7396   scripted_animation_controller_->CancelPostFrameCallback(id);
7397 }
7398 
RunPostAnimationFrameCallbacks()7399 void Document::RunPostAnimationFrameCallbacks() {
7400   bool was_throttled = current_frame_is_throttled_;
7401   current_frame_is_throttled_ = false;
7402   if (was_throttled)
7403     return;
7404   scripted_animation_controller_->RunPostFrameCallbacks();
7405 }
7406 
EnsureScriptedIdleTaskController()7407 ScriptedIdleTaskController& Document::EnsureScriptedIdleTaskController() {
7408   if (!scripted_idle_task_controller_) {
7409     scripted_idle_task_controller_ =
7410         ScriptedIdleTaskController::Create(domWindow());
7411     // We need to make sure that we don't start up if we're detached.
7412     if (!domWindow() || domWindow()->IsContextDestroyed()) {
7413       scripted_idle_task_controller_->ContextLifecycleStateChanged(
7414           mojom::FrameLifecycleState::kFrozen);
7415     }
7416   }
7417   return *scripted_idle_task_controller_;
7418 }
7419 
RequestIdleCallback(ScriptedIdleTaskController::IdleTask * idle_task,const IdleRequestOptions * options)7420 int Document::RequestIdleCallback(
7421     ScriptedIdleTaskController::IdleTask* idle_task,
7422     const IdleRequestOptions* options) {
7423   return EnsureScriptedIdleTaskController().RegisterCallback(idle_task,
7424                                                              options);
7425 }
7426 
CancelIdleCallback(int id)7427 void Document::CancelIdleCallback(int id) {
7428   if (!scripted_idle_task_controller_)
7429     return;
7430   scripted_idle_task_controller_->CancelCallback(id);
7431 }
7432 
Loader() const7433 DocumentLoader* Document::Loader() const {
7434   if (!frame_)
7435     return nullptr;
7436 
7437   // TODO(dcheng): remove this check. frame_ is guaranteed to be non-null only
7438   // if frame_->GetDocument() == this.
7439   if (frame_->GetDocument() != this)
7440     return nullptr;
7441 
7442   return frame_->Loader().GetDocumentLoader();
7443 }
7444 
EventTargetNodeForDocument(Document * doc)7445 Node* EventTargetNodeForDocument(Document* doc) {
7446   if (!doc)
7447     return nullptr;
7448   Node* node = doc->FocusedElement();
7449   auto* plugin_document = DynamicTo<PluginDocument>(doc);
7450   if (plugin_document && !node) {
7451     node = plugin_document->PluginNode();
7452   }
7453   if (!node && IsA<HTMLDocument>(doc))
7454     node = doc->body();
7455   if (!node)
7456     node = doc->documentElement();
7457   return node;
7458 }
7459 
AdjustFloatQuadsForScrollAndAbsoluteZoom(Vector<FloatQuad> & quads,const LayoutObject & layout_object) const7460 void Document::AdjustFloatQuadsForScrollAndAbsoluteZoom(
7461     Vector<FloatQuad>& quads,
7462     const LayoutObject& layout_object) const {
7463   if (!View())
7464     return;
7465 
7466   for (wtf_size_t i = 0; i < quads.size(); ++i) {
7467     AdjustForAbsoluteZoom::AdjustFloatQuad(quads[i], layout_object);
7468   }
7469 }
7470 
AdjustFloatRectForScrollAndAbsoluteZoom(FloatRect & rect,const LayoutObject & layout_object) const7471 void Document::AdjustFloatRectForScrollAndAbsoluteZoom(
7472     FloatRect& rect,
7473     const LayoutObject& layout_object) const {
7474   if (!View())
7475     return;
7476 
7477   AdjustForAbsoluteZoom::AdjustFloatRect(rect, layout_object);
7478 }
7479 
SetThreadedParsingEnabledForTesting(bool enabled)7480 void Document::SetThreadedParsingEnabledForTesting(bool enabled) {
7481   g_threaded_parsing_enabled_for_testing = enabled;
7482 }
7483 
ThreadedParsingEnabledForTesting()7484 bool Document::ThreadedParsingEnabledForTesting() {
7485   return g_threaded_parsing_enabled_for_testing;
7486 }
7487 
GetSnapCoordinator()7488 SnapCoordinator& Document::GetSnapCoordinator() {
7489   if (!snap_coordinator_)
7490     snap_coordinator_ = MakeGarbageCollected<SnapCoordinator>();
7491 
7492   return *snap_coordinator_;
7493 }
7494 
PerformScrollSnappingTasks()7495 void Document::PerformScrollSnappingTasks() {
7496   SnapCoordinator& snap_coordinator = GetSnapCoordinator();
7497   if (!snap_coordinator.AnySnapContainerDataNeedsUpdate())
7498     return;
7499   snap_coordinator.UpdateAllSnapContainerDataIfNeeded();
7500   if (RuntimeEnabledFeatures::ScrollSnapAfterLayoutEnabled())
7501     snap_coordinator.ResnapAllContainersIfNeeded();
7502 }
7503 
SetContextFeatures(ContextFeatures & features)7504 void Document::SetContextFeatures(ContextFeatures& features) {
7505   context_features_ = &features;
7506 }
7507 
UpdateHoverActiveState(bool is_active,bool update_active_chain,Element * inner_element)7508 void Document::UpdateHoverActiveState(bool is_active,
7509                                       bool update_active_chain,
7510                                       Element* inner_element) {
7511   if (is_active && frame_)
7512     frame_->GetEventHandler().NotifyElementActivated();
7513 
7514   Element* inner_element_in_document = inner_element;
7515 
7516   while (inner_element_in_document &&
7517          inner_element_in_document->GetDocument() != this) {
7518     inner_element_in_document->GetDocument().UpdateHoverActiveState(
7519         is_active, update_active_chain, inner_element_in_document);
7520     inner_element_in_document =
7521         inner_element_in_document->GetDocument().LocalOwner();
7522   }
7523 
7524   UpdateDistributionForFlatTreeTraversal();
7525 
7526   UpdateActiveState(is_active, update_active_chain, inner_element_in_document);
7527   UpdateHoverState(inner_element_in_document);
7528 }
7529 
UpdateActiveState(bool is_active,bool update_active_chain,Element * inner_element_in_document)7530 void Document::UpdateActiveState(bool is_active,
7531                                  bool update_active_chain,
7532                                  Element* inner_element_in_document) {
7533   Element* old_active_element = GetActiveElement();
7534   if (old_active_element && !is_active) {
7535     // The oldActiveElement layoutObject is null, dropped on :active by setting
7536     // display: none, for instance. We still need to clear the ActiveChain as
7537     // the mouse is released.
7538     for (Element* element = old_active_element; element;
7539          element = FlatTreeTraversal::ParentElement(*element)) {
7540       element->SetActive(false);
7541       user_action_elements_.SetInActiveChain(element, false);
7542     }
7543     SetActiveElement(nullptr);
7544   } else {
7545     Element* new_active_element = inner_element_in_document;
7546     if (!old_active_element && new_active_element &&
7547         !new_active_element->IsDisabledFormControl() && is_active) {
7548       // We are setting the :active chain and freezing it. If future moves
7549       // happen, they will need to reference this chain.
7550       for (Element* element = new_active_element; element;
7551            element = FlatTreeTraversal::ParentElement(*element)) {
7552         user_action_elements_.SetInActiveChain(element, true);
7553       }
7554       SetActiveElement(new_active_element);
7555     }
7556   }
7557 
7558   // If the mouse has just been pressed, set :active on the chain. Those (and
7559   // only those) nodes should remain :active until the mouse is released.
7560   bool allow_active_changes = !old_active_element && GetActiveElement();
7561   if (!allow_active_changes)
7562     return;
7563 
7564   DCHECK(is_active);
7565 
7566   Element* new_element = SkipDisplayNoneAncestors(inner_element_in_document);
7567 
7568   // Now set the active state for our new object up to the root.  If the mouse
7569   // is down and if this is a mouse move event, we want to restrict changes in
7570   // :active to only apply to elements that are in the :active chain that we
7571   // froze at the time the mouse went down.
7572   for (Element* curr = new_element; curr;
7573        curr = FlatTreeTraversal::ParentElement(*curr)) {
7574     if (update_active_chain || curr->InActiveChain())
7575       curr->SetActive(true);
7576   }
7577 }
7578 
UpdateHoverState(Element * inner_element_in_document)7579 void Document::UpdateHoverState(Element* inner_element_in_document) {
7580   Element* old_hover_element = HoverElement();
7581 
7582   // The passed in innerElement may not be a result of a hit test for the
7583   // current up-to-date flat/layout tree. That means the element may be
7584   // display:none at this point. Skip up the ancestor chain until we reach an
7585   // element with a layoutObject or a display:contents element.
7586   Element* new_hover_element =
7587       SkipDisplayNoneAncestors(inner_element_in_document);
7588 
7589   // Update our current hover element.
7590   SetHoverElement(new_hover_element);
7591 
7592   if (old_hover_element == new_hover_element)
7593     return;
7594 
7595   Node* ancestor_element = nullptr;
7596   if (old_hover_element && old_hover_element->isConnected() &&
7597       new_hover_element) {
7598     Node* ancestor = FlatTreeTraversal::CommonAncestor(*old_hover_element,
7599                                                        *new_hover_element);
7600     if (auto* element = DynamicTo<Element>(ancestor))
7601       ancestor_element = element;
7602   }
7603 
7604   HeapVector<Member<Element>, 32> elements_to_remove_from_chain;
7605   HeapVector<Member<Element>, 32> elements_to_add_to_hover_chain;
7606 
7607   // The old hover path only needs to be cleared up to (and not including) the
7608   // common ancestor;
7609   //
7610   // TODO(emilio): old_hover_element may be disconnected from the tree already.
7611   if (old_hover_element && old_hover_element->isConnected()) {
7612     for (Element* curr = old_hover_element; curr && curr != ancestor_element;
7613          curr = FlatTreeTraversal::ParentElement(*curr)) {
7614       elements_to_remove_from_chain.push_back(curr);
7615     }
7616   }
7617 
7618   // Now set the hover state for our new object up to the root.
7619   for (Element* curr = new_hover_element; curr;
7620        curr = FlatTreeTraversal::ParentElement(*curr)) {
7621     elements_to_add_to_hover_chain.push_back(curr);
7622   }
7623 
7624   for (Element* element : elements_to_remove_from_chain)
7625     element->SetHovered(false);
7626 
7627   bool saw_common_ancestor = false;
7628   for (Element* element : elements_to_add_to_hover_chain) {
7629     if (element == ancestor_element)
7630       saw_common_ancestor = true;
7631     if (!saw_common_ancestor || element == hover_element_)
7632       element->SetHovered(true);
7633   }
7634 }
7635 
HaveScriptBlockingStylesheetsLoaded() const7636 bool Document::HaveScriptBlockingStylesheetsLoaded() const {
7637   return style_engine_->HaveScriptBlockingStylesheetsLoaded();
7638 }
7639 
HaveRenderBlockingResourcesLoaded() const7640 bool Document::HaveRenderBlockingResourcesLoaded() const {
7641   return HaveImportsLoaded() &&
7642          style_engine_->HaveRenderBlockingStylesheetsLoaded() &&
7643          !font_preload_manager_.HasPendingRenderBlockingFonts();
7644 }
7645 
GetCachedLocale(const AtomicString & locale)7646 Locale& Document::GetCachedLocale(const AtomicString& locale) {
7647   AtomicString locale_key = locale;
7648   if (locale.IsEmpty() ||
7649       !RuntimeEnabledFeatures::LangAttributeAwareFormControlUIEnabled())
7650     return Locale::DefaultLocale();
7651   LocaleIdentifierToLocaleMap::AddResult result =
7652       locale_cache_.insert(locale_key, nullptr);
7653   if (result.is_new_entry)
7654     result.stored_value->value = Locale::Create(locale_key);
7655   return *(result.stored_value->value);
7656 }
7657 
GetAnimationClock()7658 AnimationClock& Document::GetAnimationClock() {
7659   DCHECK(GetPage());
7660   return GetPage()->Animator().Clock();
7661 }
7662 
GetAnimationClock() const7663 const AnimationClock& Document::GetAnimationClock() const {
7664   DCHECK(GetPage());
7665   return GetPage()->Animator().Clock();
7666 }
7667 
EnsureTemplateDocument()7668 Document& Document::EnsureTemplateDocument() {
7669   if (IsTemplateDocument())
7670     return *this;
7671 
7672   if (template_document_)
7673     return *template_document_;
7674 
7675   if (IsA<HTMLDocument>(this)) {
7676     template_document_ = MakeGarbageCollected<HTMLDocument>(
7677         DocumentInit::Create()
7678             .WithContextDocument(ContextDocument())
7679             .WithURL(BlankURL())
7680             .WithNewRegistrationContext());
7681   } else {
7682     template_document_ = MakeGarbageCollected<Document>(
7683         DocumentInit::Create()
7684             .WithContextDocument(ContextDocument())
7685             .WithURL(BlankURL()));
7686   }
7687 
7688   template_document_->template_document_host_ = this;  // balanced in dtor.
7689 
7690   return *template_document_.Get();
7691 }
7692 
DidAssociateFormControl(Element * element)7693 void Document::DidAssociateFormControl(Element* element) {
7694   if (!GetFrame() || !GetFrame()->GetPage() || !HasFinishedParsing())
7695     return;
7696 
7697   // We add a slight delay because this could be called rapidly.
7698   if (!did_associate_form_controls_timer_.IsActive()) {
7699     did_associate_form_controls_timer_.StartOneShot(
7700         base::TimeDelta::FromMilliseconds(300), FROM_HERE);
7701   }
7702 }
7703 
DidAssociateFormControlsTimerFired(TimerBase * timer)7704 void Document::DidAssociateFormControlsTimerFired(TimerBase* timer) {
7705   DCHECK_EQ(timer, &did_associate_form_controls_timer_);
7706   if (!GetFrame() || !GetFrame()->GetPage())
7707     return;
7708 
7709   GetFrame()->GetPage()->GetChromeClient().DidAssociateFormControlsAfterLoad(
7710       GetFrame());
7711 }
7712 
DevicePixelRatio() const7713 float Document::DevicePixelRatio() const {
7714   return frame_ ? frame_->DevicePixelRatio() : 1.0;
7715 }
7716 
GetTextAutosizer()7717 TextAutosizer* Document::GetTextAutosizer() {
7718   if (!text_autosizer_)
7719     text_autosizer_ = MakeGarbageCollected<TextAutosizer>(this);
7720   return text_autosizer_.Get();
7721 }
7722 
SetPseudoStateForTesting(Element & element,const String & pseudo,bool matches)7723 bool Document::SetPseudoStateForTesting(Element& element,
7724                                         const String& pseudo,
7725                                         bool matches) {
7726   DCHECK(WebTestSupport::IsRunningWebTest());
7727   auto& set = UserActionElements();
7728   if (pseudo == ":focus") {
7729     set.SetFocused(&element, matches);
7730     element.PseudoStateChanged(CSSSelector::kPseudoFocus);
7731   } else if (pseudo == ":focus-within") {
7732     set.SetHasFocusWithin(&element, matches);
7733     element.PseudoStateChanged(CSSSelector::kPseudoFocusWithin);
7734   } else if (pseudo == ":active") {
7735     set.SetActive(&element, matches);
7736     element.PseudoStateChanged(CSSSelector::kPseudoActive);
7737   } else if (pseudo == ":hover") {
7738     set.SetHovered(&element, matches);
7739     element.PseudoStateChanged(CSSSelector::kPseudoHover);
7740   } else {
7741     return false;
7742   }
7743   return true;
7744 }
7745 
EnqueueAutofocusCandidate(Element & element)7746 void Document::EnqueueAutofocusCandidate(Element& element) {
7747   // https://html.spec.whatwg.org/C#the-autofocus-attribute
7748   // 7. If topDocument's autofocus processed flag is false, then remove the
7749   // element from topDocument's autofocus candidates, and append the element
7750   // to topDocument's autofocus candidates.
7751   if (autofocus_processed_flag_)
7752     return;
7753   wtf_size_t index = autofocus_candidates_.Find(&element);
7754   if (index != WTF::kNotFound)
7755     autofocus_candidates_.EraseAt(index);
7756   autofocus_candidates_.push_back(element);
7757 }
7758 
HasAutofocusCandidates() const7759 bool Document::HasAutofocusCandidates() const {
7760   return autofocus_candidates_.size() > 0;
7761 }
7762 
7763 // https://html.spec.whatwg.org/C/#flush-autofocus-candidates
FlushAutofocusCandidates()7764 void Document::FlushAutofocusCandidates() {
7765   // 1. If topDocument's autofocus processed flag is true, then return.
7766   if (autofocus_processed_flag_)
7767     return;
7768 
7769   // 3. If candidates is empty, then return.
7770   if (autofocus_candidates_.IsEmpty())
7771     return;
7772 
7773   // 4. If topDocument's focused area is not topDocument itself, or
7774   //    topDocument's URL's fragment is not empty, then:
7775   //  1. Empty candidates.
7776   //  2. Set topDocument's autofocus processed flag to true.
7777   //  3. Return.
7778   if (AdjustedFocusedElement()) {
7779     autofocus_candidates_.clear();
7780     autofocus_processed_flag_ = true;
7781     AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
7782         mojom::ConsoleMessageSource::kRendering,
7783         mojom::ConsoleMessageLevel::kInfo,
7784         "Autofocus processing was blocked because a "
7785         "document already has a focused element."));
7786     return;
7787   }
7788   if (HasNonEmptyFragment()) {
7789     autofocus_candidates_.clear();
7790     autofocus_processed_flag_ = true;
7791     AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
7792         mojom::ConsoleMessageSource::kRendering,
7793         mojom::ConsoleMessageLevel::kInfo,
7794         "Autofocus processing was blocked because a "
7795         "document's URL has a fragment '#" +
7796             Url().FragmentIdentifier() + "'."));
7797     return;
7798   }
7799 
7800   // 5. While candidates is not empty:
7801   while (!autofocus_candidates_.IsEmpty()) {
7802     // 5.1. Let element be candidates[0].
7803     Element& element = *autofocus_candidates_[0];
7804 
7805     // 5.2. Let doc be element's node document.
7806     Document* doc = &element.GetDocument();
7807 
7808     // 5.3. If doc is not fully active, then remove element from candidates,
7809     // and continue.
7810     // 5.4. If doc's browsing context's top-level browsing context is not same
7811     // as topDocument's browsing context, then remove element from candidates,
7812     // and continue.
7813     if (&doc->TopDocument() != this) {
7814       autofocus_candidates_.EraseAt(0);
7815       continue;
7816     }
7817 
7818     // The element is in the fallback content of an OBJECT of which
7819     // fallback state is not fixed yet.
7820     // TODO(tkent): Standardize this behavior.
7821     if (IsInIndeterminateObjectAncestor(&element)) {
7822       return;
7823     }
7824 
7825     // 5.5. If doc's script-blocking style sheet counter is greater than 0,
7826     // then return.
7827     // TODO(tkent): Is this necessary? WPT spin-by-blocking-style-sheet.html
7828     // doesn't hit this condition, and FlushAutofocusCandidates() is not called
7829     // until the stylesheet is loaded.
7830     StyleEngine& engine = GetStyleEngine();
7831     if (engine.HasPendingScriptBlockingSheets() ||
7832         engine.HasPendingRenderBlockingSheets()) {
7833       return;
7834     }
7835 
7836     // 5.6. Remove element from candidates.
7837     autofocus_candidates_.EraseAt(0);
7838 
7839     // 5.7. Let inclusiveAncestorDocuments be a list consisting of doc, plus
7840     // the active documents of each of doc's browsing context's ancestor
7841     // browsing contexts.
7842     // 5.8. If URL's fragment of any Document in inclusiveAncestorDocuments
7843     // is not empty, then continue.
7844     if (doc != this) {
7845       for (HTMLFrameOwnerElement* frameOwner = doc->LocalOwner();
7846            !doc->HasNonEmptyFragment() && frameOwner;
7847            frameOwner = doc->LocalOwner()) {
7848         doc = &frameOwner->GetDocument();
7849       }
7850       if (doc->HasNonEmptyFragment()) {
7851         AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
7852             mojom::ConsoleMessageSource::kRendering,
7853             mojom::ConsoleMessageLevel::kInfo,
7854             "Autofocus processing was blocked because a "
7855             "document's URL has a fragment '#" +
7856                 doc->Url().FragmentIdentifier() + "'."));
7857         continue;
7858       }
7859       DCHECK_EQ(doc, this);
7860     }
7861 
7862     // 9. Let target be element.
7863     Element* target = &element;
7864 
7865     // 10. If target is not a focusable area, then set target to the result of
7866     // getting the focusable area for target.
7867     element.GetDocument().UpdateStyleAndLayoutTree();
7868     if (!target->IsFocusable())
7869       target = target->GetFocusableArea();
7870 
7871     // 11. If target is not null, then:
7872     if (target) {
7873       // 11.1. Empty candidates.
7874       // 11.2. Set topDocument's autofocus processed flag to true.
7875       FinalizeAutofocus();
7876       // 11.3. Run the focusing steps for element.
7877       element.focus();
7878     } else {
7879       // TODO(tkent): Show a console message, and fix LocalNTP*Test.*
7880       // in browser_tests.
7881     }
7882   }
7883 }
7884 
FinalizeAutofocus()7885 void Document::FinalizeAutofocus() {
7886   autofocus_candidates_.clear();
7887   autofocus_processed_flag_ = true;
7888 }
7889 
HasNonEmptyFragment() const7890 bool Document::HasNonEmptyFragment() const {
7891   return !Url().FragmentIdentifier().IsEmpty();
7892 }
7893 
ActiveElement() const7894 Element* Document::ActiveElement() const {
7895   if (Element* element = AdjustedFocusedElement())
7896     return element;
7897   return body();
7898 }
7899 
hasFocus() const7900 bool Document::hasFocus() const {
7901   return GetPage() && GetPage()->GetFocusController().IsDocumentFocused(*this);
7902 }
7903 
BodyAttributeValue(const QualifiedName & name) const7904 const AtomicString& Document::BodyAttributeValue(
7905     const QualifiedName& name) const {
7906   if (auto* bodyElement = body())
7907     return bodyElement->FastGetAttribute(name);
7908   return g_null_atom;
7909 }
7910 
SetBodyAttribute(const QualifiedName & name,const AtomicString & value)7911 void Document::SetBodyAttribute(const QualifiedName& name,
7912                                 const AtomicString& value) {
7913   if (auto* bodyElement = body()) {
7914     // FIXME: This check is apparently for benchmarks that set the same value
7915     // repeatedly.  It's not clear what benchmarks though, it's also not clear
7916     // why we don't avoid causing a style recalc when setting the same value to
7917     // a presentational attribute in the common case.
7918     if (bodyElement->FastGetAttribute(name) != value)
7919       bodyElement->setAttribute(name, value);
7920   }
7921 }
7922 
bgColor() const7923 const AtomicString& Document::bgColor() const {
7924   return BodyAttributeValue(html_names::kBgcolorAttr);
7925 }
7926 
setBgColor(const AtomicString & value)7927 void Document::setBgColor(const AtomicString& value) {
7928   if (!IsFrameSet())
7929     SetBodyAttribute(html_names::kBgcolorAttr, value);
7930 }
7931 
fgColor() const7932 const AtomicString& Document::fgColor() const {
7933   return BodyAttributeValue(html_names::kTextAttr);
7934 }
7935 
setFgColor(const AtomicString & value)7936 void Document::setFgColor(const AtomicString& value) {
7937   if (!IsFrameSet())
7938     SetBodyAttribute(html_names::kTextAttr, value);
7939 }
7940 
alinkColor() const7941 const AtomicString& Document::alinkColor() const {
7942   return BodyAttributeValue(html_names::kAlinkAttr);
7943 }
7944 
setAlinkColor(const AtomicString & value)7945 void Document::setAlinkColor(const AtomicString& value) {
7946   if (!IsFrameSet())
7947     SetBodyAttribute(html_names::kAlinkAttr, value);
7948 }
7949 
linkColor() const7950 const AtomicString& Document::linkColor() const {
7951   return BodyAttributeValue(html_names::kLinkAttr);
7952 }
7953 
setLinkColor(const AtomicString & value)7954 void Document::setLinkColor(const AtomicString& value) {
7955   if (!IsFrameSet())
7956     SetBodyAttribute(html_names::kLinkAttr, value);
7957 }
7958 
vlinkColor() const7959 const AtomicString& Document::vlinkColor() const {
7960   return BodyAttributeValue(html_names::kVlinkAttr);
7961 }
7962 
setVlinkColor(const AtomicString & value)7963 void Document::setVlinkColor(const AtomicString& value) {
7964   if (!IsFrameSet())
7965     SetBodyAttribute(html_names::kVlinkAttr, value);
7966 }
7967 
7968 template <unsigned type>
ShouldInvalidateNodeListCachesForAttr(const LiveNodeListRegistry & node_lists,const QualifiedName & attr_name)7969 bool ShouldInvalidateNodeListCachesForAttr(
7970     const LiveNodeListRegistry& node_lists,
7971     const QualifiedName& attr_name) {
7972   auto invalidation_type = static_cast<NodeListInvalidationType>(type);
7973   if (node_lists.ContainsInvalidationType(invalidation_type) &&
7974       LiveNodeListBase::ShouldInvalidateTypeOnAttributeChange(invalidation_type,
7975                                                               attr_name))
7976     return true;
7977   return ShouldInvalidateNodeListCachesForAttr<type + 1>(node_lists, attr_name);
7978 }
7979 
7980 template <>
ShouldInvalidateNodeListCachesForAttr(const LiveNodeListRegistry &,const QualifiedName &)7981 bool ShouldInvalidateNodeListCachesForAttr<kNumNodeListInvalidationTypes>(
7982     const LiveNodeListRegistry&,
7983     const QualifiedName&) {
7984   return false;
7985 }
7986 
ShouldInvalidateNodeListCaches(const QualifiedName * attr_name) const7987 bool Document::ShouldInvalidateNodeListCaches(
7988     const QualifiedName* attr_name) const {
7989   if (attr_name) {
7990     return ShouldInvalidateNodeListCachesForAttr<
7991         kDoNotInvalidateOnAttributeChanges + 1>(node_lists_, *attr_name);
7992   }
7993 
7994   // If the invalidation is not for an attribute, invalidation is needed if
7995   // there is any node list present (with any invalidation type).
7996   return !node_lists_.IsEmpty();
7997 }
7998 
InvalidateNodeListCaches(const QualifiedName * attr_name)7999 void Document::InvalidateNodeListCaches(const QualifiedName* attr_name) {
8000   for (const LiveNodeListBase* list : lists_invalidated_at_document_)
8001     list->InvalidateCacheForAttribute(attr_name);
8002 }
8003 
PlatformColorsChanged()8004 void Document::PlatformColorsChanged() {
8005   if (!IsActive())
8006     return;
8007 
8008   GetStyleEngine().PlatformColorsChanged();
8009 }
8010 
DidEnforceInsecureRequestPolicy()8011 void Document::DidEnforceInsecureRequestPolicy() {
8012   if (!GetFrame())
8013     return;
8014   GetFrame()->GetLocalFrameHostRemote().EnforceInsecureRequestPolicy(
8015       GetSecurityContext().GetInsecureRequestPolicy());
8016 }
8017 
DidEnforceInsecureNavigationsSet()8018 void Document::DidEnforceInsecureNavigationsSet() {
8019   if (!GetFrame())
8020     return;
8021   GetFrame()->GetLocalFrameHostRemote().EnforceInsecureNavigationsSet(
8022       SecurityContext::SerializeInsecureNavigationSet(
8023           GetSecurityContext().InsecureNavigationsToUpgrade()));
8024 }
8025 
SetShadowCascadeOrder(ShadowCascadeOrder order)8026 void Document::SetShadowCascadeOrder(ShadowCascadeOrder order) {
8027   DCHECK_NE(order, ShadowCascadeOrder::kShadowCascadeNone);
8028   if (order == shadow_cascade_order_)
8029     return;
8030 
8031   if (order == ShadowCascadeOrder::kShadowCascadeV0) {
8032     may_contain_v0_shadow_ = true;
8033     if (shadow_cascade_order_ == ShadowCascadeOrder::kShadowCascadeV1) {
8034       // ::slotted() rules has to be moved to tree boundary rule sets.
8035       style_engine_->V0ShadowAddedOnV1Document();
8036       UseCounter::Count(*this, WebFeature::kMixedShadowRootV0AndV1);
8037     }
8038   }
8039 
8040   // For V0 -> V1 upgrade, we need style recalculation for all elements.
8041   if (shadow_cascade_order_ == ShadowCascadeOrder::kShadowCascadeV0 &&
8042       order == ShadowCascadeOrder::kShadowCascadeV1) {
8043     GetStyleEngine().MarkAllElementsForStyleRecalc(
8044         StyleChangeReasonForTracing::Create(style_change_reason::kShadow));
8045     UseCounter::Count(*this, WebFeature::kMixedShadowRootV0AndV1);
8046   }
8047 
8048   if (order > shadow_cascade_order_)
8049     shadow_cascade_order_ = order;
8050 }
8051 
GetPropertyRegistry()8052 PropertyRegistry* Document::GetPropertyRegistry() {
8053   // TODO(timloh): When the flag is removed, return a reference instead.
8054   if (!property_registry_ && RuntimeEnabledFeatures::CSSVariables2Enabled())
8055     property_registry_ = MakeGarbageCollected<PropertyRegistry>();
8056   return property_registry_;
8057 }
8058 
GetPropertyRegistry() const8059 const PropertyRegistry* Document::GetPropertyRegistry() const {
8060   return const_cast<Document*>(this)->GetPropertyRegistry();
8061 }
8062 
MaybeQueueSendDidEditFieldInInsecureContext()8063 void Document::MaybeQueueSendDidEditFieldInInsecureContext() {
8064   if (logged_field_edit_ || sensitive_input_edited_task_.IsActive() ||
8065       IsSecureContext()) {
8066     // Send a message on the first edit; the browser process doesn't care
8067     // about the presence of additional edits.
8068     //
8069     // The browser process only cares about editing fields on pages where the
8070     // top-level URL is not secure. Secure contexts must have a top-level URL
8071     // that is secure, so there is no need to send notifications for editing
8072     // in secure contexts.
8073     return;
8074   }
8075   logged_field_edit_ = true;
8076   sensitive_input_edited_task_ = PostCancellableTask(
8077       *GetTaskRunner(TaskType::kUserInteraction), FROM_HERE,
8078       WTF::Bind(&Document::SendDidEditFieldInInsecureContext,
8079                 WrapWeakPersistent(this)));
8080 }
8081 
GetProbeSink()8082 CoreProbeSink* Document::GetProbeSink() {
8083   LocalFrame* frame = GetFrame();
8084   if (!frame && TemplateDocumentHost())
8085     frame = TemplateDocumentHost()->GetFrame();
8086   return probe::ToCoreProbeSink(frame);
8087 }
8088 
GetBrowserInterfaceBroker()8089 BrowserInterfaceBrokerProxy& Document::GetBrowserInterfaceBroker() {
8090   if (!GetFrame())
8091     return GetEmptyBrowserInterfaceBroker();
8092 
8093   return GetFrame()->GetBrowserInterfaceBroker();
8094 }
8095 
GetResourceCoordinator()8096 DocumentResourceCoordinator* Document::GetResourceCoordinator() {
8097   if (!resource_coordinator_ && GetFrame()) {
8098     resource_coordinator_ =
8099         DocumentResourceCoordinator::MaybeCreate(GetBrowserInterfaceBroker());
8100   }
8101   return resource_coordinator_.get();
8102 }
8103 
GetScheduler()8104 FrameOrWorkerScheduler* Document::GetScheduler() {
8105   DCHECK(IsMainThread());
8106   return GetExecutionContext()->GetScheduler();
8107 }
8108 
GetTaskRunner(TaskType type)8109 scoped_refptr<base::SingleThreadTaskRunner> Document::GetTaskRunner(
8110     TaskType type) {
8111   DCHECK(IsMainThread());
8112 
8113   if (ContextDocument() && ContextDocument()->GetFrame())
8114     return ContextDocument()->GetFrame()->GetTaskRunner(type);
8115   // In most cases, ContextDocument() will get us to a relevant Frame. In some
8116   // cases, though, there isn't a good candidate (most commonly when either the
8117   // passed-in document or ContextDocument() used to be attached to a Frame but
8118   // has since been detached).
8119   return Thread::Current()->GetTaskRunner();
8120 }
8121 
featurePolicy()8122 DOMFeaturePolicy* Document::featurePolicy() {
8123   if (!policy_)
8124     policy_ = MakeGarbageCollected<DOMDocumentPolicy>(this);
8125   return policy_.Get();
8126 }
8127 
RequiredCSP()8128 const AtomicString& Document::RequiredCSP() {
8129   if (!Loader())
8130     return g_null_atom;
8131   return frame_->Loader().RequiredCSP();
8132 }
8133 
ComputedStyleMap(Element * element)8134 StylePropertyMapReadOnly* Document::ComputedStyleMap(Element* element) {
8135   ElementComputedStyleMap::AddResult add_result =
8136       element_computed_style_map_.insert(element, nullptr);
8137   if (add_result.is_new_entry) {
8138     add_result.stored_value->value =
8139         MakeGarbageCollected<ComputedStylePropertyMap>(element);
8140   }
8141   return add_result.stored_value->value;
8142 }
8143 
AddComputedStyleMapItem(Element * element,StylePropertyMapReadOnly * computed_style)8144 void Document::AddComputedStyleMapItem(
8145     Element* element,
8146     StylePropertyMapReadOnly* computed_style) {
8147   element_computed_style_map_.insert(element, computed_style);
8148 }
8149 
RemoveComputedStyleMapItem(Element * element)8150 StylePropertyMapReadOnly* Document::RemoveComputedStyleMapItem(
8151     Element* element) {
8152   return element_computed_style_map_.Take(element);
8153 }
8154 
Trace(Visitor * visitor)8155 void Document::Trace(Visitor* visitor) {
8156   visitor->Trace(security_context_);
8157   visitor->Trace(imports_controller_);
8158   visitor->Trace(use_counter_during_construction_);
8159   visitor->Trace(doc_type_);
8160   visitor->Trace(implementation_);
8161   visitor->Trace(autofocus_candidates_);
8162   visitor->Trace(focused_element_);
8163   visitor->Trace(sequential_focus_navigation_starting_point_);
8164   visitor->Trace(hover_element_);
8165   visitor->Trace(active_element_);
8166   visitor->Trace(document_element_);
8167   visitor->Trace(root_scroller_controller_);
8168   visitor->Trace(title_element_);
8169   visitor->Trace(ax_object_cache_);
8170   visitor->Trace(markers_);
8171   visitor->Trace(css_target_);
8172   visitor->Trace(current_script_stack_);
8173   visitor->Trace(script_runner_);
8174   visitor->Trace(lists_invalidated_at_document_);
8175   visitor->Trace(node_lists_);
8176   visitor->Trace(top_layer_elements_);
8177   visitor->Trace(elem_sheet_);
8178   visitor->Trace(node_iterators_);
8179   visitor->Trace(ranges_);
8180   visitor->Trace(document_explicit_root_intersection_observer_data_);
8181   visitor->Trace(style_engine_);
8182   visitor->Trace(form_controller_);
8183   visitor->Trace(visited_link_state_);
8184   visitor->Trace(element_computed_style_map_);
8185   visitor->Trace(window_agent_factory_);
8186   visitor->Trace(frame_);
8187   visitor->Trace(dom_window_);
8188   visitor->Trace(fetcher_);
8189   visitor->Trace(parser_);
8190   visitor->Trace(context_features_);
8191   visitor->Trace(http_refresh_scheduler_);
8192   visitor->Trace(style_sheet_list_);
8193   visitor->Trace(document_timing_);
8194   visitor->Trace(media_query_matcher_);
8195   visitor->Trace(scripted_animation_controller_);
8196   visitor->Trace(scripted_idle_task_controller_);
8197   visitor->Trace(text_autosizer_);
8198   visitor->Trace(registration_context_);
8199   visitor->Trace(custom_element_microtask_run_queue_);
8200   visitor->Trace(element_data_cache_);
8201   visitor->Trace(use_elements_needing_update_);
8202   visitor->Trace(template_document_);
8203   visitor->Trace(template_document_host_);
8204   visitor->Trace(user_action_elements_);
8205   visitor->Trace(svg_extensions_);
8206   visitor->Trace(document_animations_);
8207   visitor->Trace(timeline_);
8208   visitor->Trace(pending_animations_);
8209   visitor->Trace(worklet_animation_controller_);
8210   visitor->Trace(context_document_);
8211   visitor->Trace(canvas_font_cache_);
8212   visitor->Trace(intersection_observer_controller_);
8213   visitor->Trace(snap_coordinator_);
8214   visitor->Trace(resize_observer_controller_);
8215   visitor->Trace(property_registry_);
8216   visitor->Trace(network_state_observer_);
8217   visitor->Trace(policy_);
8218   visitor->Trace(slot_assignment_engine_);
8219   visitor->Trace(viewport_data_);
8220   visitor->Trace(display_lock_contexts_);
8221   visitor->Trace(navigation_initiator_);
8222   visitor->Trace(lazy_load_image_observer_);
8223   visitor->Trace(isolated_world_csp_map_);
8224   visitor->Trace(find_in_page_root_);
8225   visitor->Trace(computed_node_mapping_);
8226   visitor->Trace(mime_handler_view_before_unload_event_listener_);
8227   visitor->Trace(cookie_jar_);
8228   visitor->Trace(synchronous_mutation_observer_list_);
8229   visitor->Trace(element_explicitly_set_attr_elements_map_);
8230   visitor->Trace(display_lock_activation_observer_);
8231   visitor->Trace(permission_service_);
8232   visitor->Trace(font_preload_manager_);
8233   Supplementable<Document>::Trace(visitor);
8234   TreeScope::Trace(visitor);
8235   ContainerNode::Trace(visitor);
8236 }
8237 
RecordUkmOutliveTimeAfterShutdown(int outlive_time_count)8238 void Document::RecordUkmOutliveTimeAfterShutdown(int outlive_time_count) {
8239   if (!needs_to_record_ukm_outlive_time_)
8240     return;
8241 
8242   DCHECK(ukm_recorder_);
8243   DCHECK(ukm_source_id_ != ukm::kInvalidSourceId);
8244 
8245   ukm::builders::Document_OutliveTimeAfterShutdown(ukm_source_id_)
8246       .SetGCCount(outlive_time_count)
8247       .Record(ukm_recorder_.get());
8248 }
8249 
CurrentFrameHadRAF() const8250 bool Document::CurrentFrameHadRAF() const {
8251   return scripted_animation_controller_->CurrentFrameHadRAF();
8252 }
8253 
NextFrameHasPendingRAF() const8254 bool Document::NextFrameHasPendingRAF() const {
8255   return scripted_animation_controller_->NextFrameHasPendingRAF();
8256 }
8257 
NavigateLocalAdsFrames()8258 void Document::NavigateLocalAdsFrames() {
8259   // This navigates all the frames detected as an advertisement to about:blank.
8260   DCHECK(frame_);
8261   for (Frame* child = frame_->Tree().FirstChild(); child;
8262        child = child->Tree().TraverseNext(frame_)) {
8263     if (auto* child_local_frame = DynamicTo<LocalFrame>(child)) {
8264       if (child_local_frame->IsAdSubframe()) {
8265         FrameLoadRequest request(this, ResourceRequest(BlankURL()));
8266         child_local_frame->Navigate(request, WebFrameLoadType::kStandard);
8267       }
8268     }
8269     // TODO(yuzus): Once AdsTracker for remote frames is implemented and OOPIF
8270     // is enabled on low-end devices, navigate remote ads as well.
8271   }
8272 }
8273 
GetSlotAssignmentEngine()8274 SlotAssignmentEngine& Document::GetSlotAssignmentEngine() {
8275   if (!slot_assignment_engine_)
8276     slot_assignment_engine_ = MakeGarbageCollected<SlotAssignmentEngine>();
8277   return *slot_assignment_engine_;
8278 }
8279 
IsSlotAssignmentOrLegacyDistributionDirty() const8280 bool Document::IsSlotAssignmentOrLegacyDistributionDirty() const {
8281   if (ChildNeedsDistributionRecalc())
8282     return true;
8283   if (slot_assignment_engine_ &&
8284       slot_assignment_engine_->HasPendingSlotAssignmentRecalc()) {
8285     return true;
8286   }
8287   return false;
8288 }
8289 
IsLazyLoadPolicyEnforced() const8290 bool Document::IsLazyLoadPolicyEnforced() const {
8291   return RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled() &&
8292          !GetSecurityContext().GetFeaturePolicy()->IsFeatureEnabled(
8293              mojom::blink::FeaturePolicyFeature::kLazyLoad);
8294 }
8295 
IsFocusAllowed() const8296 bool Document::IsFocusAllowed() const {
8297   if (frame_ && frame_->GetPage()->InsidePortal())
8298     return false;
8299 
8300   if (!frame_ || frame_->IsMainFrame() ||
8301       LocalFrame::HasTransientUserActivation(frame_)) {
8302     // 'autofocus' runs Element::focus asynchronously at which point the
8303     // document might not have a frame (see https://crbug.com/960224).
8304     return true;
8305   }
8306 
8307   WebFeature uma_type;
8308   bool sandboxed = IsSandboxed(mojom::blink::WebSandboxFlags::kNavigation);
8309   bool ad = frame_->IsAdSubframe();
8310   if (sandboxed) {
8311     uma_type = ad ? WebFeature::kFocusWithoutUserActivationSandboxedAdFrame
8312                   : WebFeature::kFocusWithoutUserActivationSandboxedNotAdFrame;
8313   } else {
8314     uma_type =
8315         ad ? WebFeature::kFocusWithoutUserActivationNotSandboxedAdFrame
8316            : WebFeature::kFocusWithoutUserActivationNotSandboxedNotAdFrame;
8317   }
8318   CountUse(uma_type);
8319   if (!RuntimeEnabledFeatures::BlockingFocusWithoutUserActivationEnabled())
8320     return true;
8321   return IsFeatureEnabled(
8322       mojom::blink::FeaturePolicyFeature::kFocusWithoutUserActivation);
8323 }
8324 
NavigationInitiator()8325 NavigationInitiatorImpl& Document::NavigationInitiator() {
8326   if (!navigation_initiator_) {
8327     navigation_initiator_ =
8328         MakeGarbageCollected<NavigationInitiatorImpl>(*this);
8329   }
8330   return *navigation_initiator_;
8331 }
8332 
EnsureLazyLoadImageObserver()8333 LazyLoadImageObserver& Document::EnsureLazyLoadImageObserver() {
8334   if (!lazy_load_image_observer_) {
8335     lazy_load_image_observer_ =
8336         MakeGarbageCollected<LazyLoadImageObserver>(*this);
8337   }
8338   return *lazy_load_image_observer_;
8339 }
8340 
GetWindowAgent()8341 WindowAgent& Document::GetWindowAgent() {
8342   return *static_cast<WindowAgent*>(GetAgent());
8343 }
8344 
CountPotentialFeaturePolicyViolation(mojom::blink::FeaturePolicyFeature feature) const8345 void Document::CountPotentialFeaturePolicyViolation(
8346     mojom::blink::FeaturePolicyFeature feature) const {
8347   wtf_size_t index = static_cast<wtf_size_t>(feature);
8348   if (potentially_violated_features_.size() == 0) {
8349     potentially_violated_features_.resize(
8350         static_cast<wtf_size_t>(mojom::blink::FeaturePolicyFeature::kMaxValue) +
8351         1);
8352   } else if (potentially_violated_features_[index]) {
8353     return;
8354   }
8355   potentially_violated_features_[index] = true;
8356   UMA_HISTOGRAM_ENUMERATION("Blink.UseCounter.FeaturePolicy.PotentialViolation",
8357                             feature);
8358 }
ReportFeaturePolicyViolation(mojom::blink::FeaturePolicyFeature feature,mojom::blink::PolicyDisposition disposition,const String & message,const String & source_file) const8359 void Document::ReportFeaturePolicyViolation(
8360     mojom::blink::FeaturePolicyFeature feature,
8361     mojom::blink::PolicyDisposition disposition,
8362     const String& message,
8363     const String& source_file) const {
8364   if (!RuntimeEnabledFeatures::FeaturePolicyReportingEnabled(this))
8365     return;
8366   LocalFrame* frame = GetFrame();
8367   if (!frame)
8368     return;
8369 
8370   // Construct the feature policy violation report.
8371   const String& feature_name = GetNameForFeature(feature);
8372   const String& disp_str =
8373       (disposition == mojom::blink::PolicyDisposition::kReport ? "report"
8374                                                                : "enforce");
8375 
8376   FeaturePolicyViolationReportBody* body =
8377       source_file.IsEmpty()
8378           ? MakeGarbageCollected<FeaturePolicyViolationReportBody>(
8379                 feature_name, "Feature policy violation", disp_str)
8380           : MakeGarbageCollected<FeaturePolicyViolationReportBody>(
8381                 feature_name, "Feature policy violation", disp_str,
8382                 source_file);
8383 
8384   Report* report = MakeGarbageCollected<Report>(
8385       ReportType::kFeaturePolicyViolation, Url().GetString(), body);
8386 
8387   // Send the feature policy violation report to any ReportingObservers.
8388   auto* reporting_context = ReportingContext::From(domWindow());
8389   reporting_context->QueueReport(report);
8390 
8391   // TODO(iclelland): Report something different in report-only mode
8392   if (disposition == mojom::blink::PolicyDisposition::kEnforce) {
8393     frame->Console().AddMessage(MakeGarbageCollected<ConsoleMessage>(
8394         mojom::ConsoleMessageSource::kViolation,
8395         mojom::ConsoleMessageLevel::kError,
8396         (message.IsEmpty() ? ("Feature policy violation: " + feature_name +
8397                               " is not allowed in this document.")
8398                            : message)));
8399   }
8400 }
8401 
ReportDocumentPolicyViolation(mojom::blink::DocumentPolicyFeature feature,mojom::blink::PolicyDisposition disposition,const String & message,const String & source_file) const8402 void Document::ReportDocumentPolicyViolation(
8403     mojom::blink::DocumentPolicyFeature feature,
8404     mojom::blink::PolicyDisposition disposition,
8405     const String& message,
8406     const String& source_file) const {
8407   LocalFrame* frame = GetFrame();
8408   if (!frame)
8409     return;
8410 
8411   // Construct the document policy violation report.
8412   const String& feature_name =
8413       GetDocumentPolicyFeatureInfoMap().at(feature).feature_name.c_str();
8414   bool is_report_only = disposition == mojom::blink::PolicyDisposition::kReport;
8415   const String& disp_str = is_report_only ? "report" : "enforce";
8416   const DocumentPolicy* relevant_document_policy =
8417       is_report_only ? GetSecurityContext().GetReportOnlyDocumentPolicy()
8418                      : GetSecurityContext().GetDocumentPolicy();
8419 
8420   DocumentPolicyViolationReportBody* body =
8421       source_file.IsEmpty()
8422           ? MakeGarbageCollected<DocumentPolicyViolationReportBody>(
8423                 feature_name, "Document policy violation", disp_str)
8424           : MakeGarbageCollected<DocumentPolicyViolationReportBody>(
8425                 feature_name, "Document policy violation", disp_str,
8426                 source_file);
8427 
8428   Report* report = MakeGarbageCollected<Report>(
8429       ReportType::kDocumentPolicyViolation, Url().GetString(), body);
8430 
8431   // Send the document policy violation report to any ReportingObservers.
8432   auto* reporting_context = ReportingContext::From(domWindow());
8433   const base::Optional<std::string> endpoint =
8434       relevant_document_policy->GetFeatureEndpoint(feature);
8435 
8436   reporting_context->QueueReport(
8437       report, endpoint ? Vector<String>{endpoint->c_str()} : Vector<String>{});
8438 
8439   // TODO(iclelland): Report something different in report-only mode
8440   if (!is_report_only) {
8441     frame->Console().AddMessage(MakeGarbageCollected<ConsoleMessage>(
8442         mojom::blink::ConsoleMessageSource::kViolation,
8443         mojom::blink::ConsoleMessageLevel::kError,
8444         (message.IsEmpty() ? ("Document policy violation: " + feature_name +
8445                               " is not allowed in this document.")
8446                            : message)));
8447   }
8448 }
8449 
IncrementNumberOfCanvases()8450 void Document::IncrementNumberOfCanvases() {
8451   num_canvases_++;
8452 }
8453 
IncrementDisplayLockBlockingAllActivation()8454 void Document::IncrementDisplayLockBlockingAllActivation() {
8455   ++display_lock_blocking_all_activation_count_;
8456 }
8457 
DecrementDisplayLockBlockingAllActivation()8458 void Document::DecrementDisplayLockBlockingAllActivation() {
8459   DCHECK_GT(display_lock_blocking_all_activation_count_, 0);
8460   --display_lock_blocking_all_activation_count_;
8461 }
8462 
DisplayLockBlockingAllActivationCount() const8463 int Document::DisplayLockBlockingAllActivationCount() const {
8464   return display_lock_blocking_all_activation_count_;
8465 }
8466 
AddLockedDisplayLock()8467 void Document::AddLockedDisplayLock() {
8468   ++locked_display_lock_count_;
8469   TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"),
8470                     "LockedDisplayLockCount", TRACE_ID_LOCAL(this),
8471                     locked_display_lock_count_);
8472 }
8473 
RemoveLockedDisplayLock()8474 void Document::RemoveLockedDisplayLock() {
8475   DCHECK_GT(locked_display_lock_count_, 0);
8476   --locked_display_lock_count_;
8477   TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"),
8478                     "LockedDisplayLockCount", TRACE_ID_LOCAL(this),
8479                     locked_display_lock_count_);
8480 }
8481 
LockedDisplayLockCount() const8482 int Document::LockedDisplayLockCount() const {
8483   return locked_display_lock_count_;
8484 }
8485 
AddDisplayLockContext(DisplayLockContext * context)8486 void Document::AddDisplayLockContext(DisplayLockContext* context) {
8487   display_lock_contexts_.insert(context);
8488 }
8489 
RemoveDisplayLockContext(DisplayLockContext * context)8490 void Document::RemoveDisplayLockContext(DisplayLockContext* context) {
8491   display_lock_contexts_.erase(context);
8492 }
8493 
DisplayLockCount() const8494 int Document::DisplayLockCount() const {
8495   return display_lock_contexts_.size();
8496 }
8497 
NotifySelectionRemovedFromDisplayLocks()8498 void Document::NotifySelectionRemovedFromDisplayLocks() {
8499   for (auto context : display_lock_contexts_)
8500     context->NotifySubtreeLostSelection();
8501 }
8502 
8503 Document::ScopedForceActivatableDisplayLocks
GetScopedForceActivatableLocks()8504 Document::GetScopedForceActivatableLocks() {
8505   return ScopedForceActivatableDisplayLocks(this);
8506 }
8507 
8508 Document::ScopedForceActivatableDisplayLocks::
ScopedForceActivatableDisplayLocks(Document * document)8509     ScopedForceActivatableDisplayLocks(Document* document)
8510     : document_(document) {
8511   if (++document_->activatable_display_locks_forced_ == 1) {
8512     for (auto context : document_->display_lock_contexts_)
8513       context->DidForceActivatableDisplayLocks();
8514   }
8515 }
8516 
8517 Document::ScopedForceActivatableDisplayLocks::
ScopedForceActivatableDisplayLocks(ScopedForceActivatableDisplayLocks && other)8518     ScopedForceActivatableDisplayLocks(
8519         ScopedForceActivatableDisplayLocks&& other)
8520     : document_(other.document_) {
8521   other.document_ = nullptr;
8522 }
8523 
8524 Document::ScopedForceActivatableDisplayLocks&
operator =(ScopedForceActivatableDisplayLocks && other)8525 Document::ScopedForceActivatableDisplayLocks::operator=(
8526     ScopedForceActivatableDisplayLocks&& other) {
8527   document_ = other.document_;
8528   other.document_ = nullptr;
8529   return *this;
8530 }
8531 
8532 Document::ScopedForceActivatableDisplayLocks::
~ScopedForceActivatableDisplayLocks()8533     ~ScopedForceActivatableDisplayLocks() {
8534   if (!document_)
8535     return;
8536   DCHECK(document_->activatable_display_locks_forced_);
8537   --document_->activatable_display_locks_forced_;
8538 }
8539 
RegisterDisplayLockActivationObservation(Element * element)8540 void Document::RegisterDisplayLockActivationObservation(Element* element) {
8541   EnsureDisplayLockActivationObserver().observe(element);
8542 }
8543 
UnregisterDisplayLockActivationObservation(Element * element)8544 void Document::UnregisterDisplayLockActivationObservation(Element* element) {
8545   EnsureDisplayLockActivationObserver().unobserve(element);
8546 }
8547 
EnsureDisplayLockActivationObserver()8548 IntersectionObserver& Document::EnsureDisplayLockActivationObserver() {
8549   if (!display_lock_activation_observer_) {
8550     // Use kPostTaskToDeliver method, since a commit can dirty layout, and we
8551     // want to avoid dirtying layout during post-lifecycle steps.
8552     // Note that we use 50% margin (on the viewport) so that we get the
8553     // observation before the element enters the viewport.
8554     display_lock_activation_observer_ = IntersectionObserver::Create(
8555         {Length::Percent(50.f)}, {std::numeric_limits<float>::min()}, this,
8556         WTF::BindRepeating(&Document::ProcessDisplayLockActivationObservation,
8557                            WrapWeakPersistent(this)),
8558         IntersectionObserver::kDeliverDuringPostLifecycleSteps);
8559   }
8560   return *display_lock_activation_observer_;
8561 }
8562 
ProcessDisplayLockActivationObservation(const HeapVector<Member<IntersectionObserverEntry>> & entries)8563 void Document::ProcessDisplayLockActivationObservation(
8564     const HeapVector<Member<IntersectionObserverEntry>>& entries) {
8565   DCHECK(View());
8566   for (auto& entry : entries) {
8567     auto* context = entry->target()->GetDisplayLockContext();
8568     DCHECK(context);
8569     if (entry->isIntersecting()) {
8570       View()->EnqueueStartOfLifecycleTask(
8571           WTF::Bind(&DisplayLockContext::NotifyIsIntersectingViewport,
8572                     WrapWeakPersistent(context)));
8573     } else {
8574       View()->EnqueueStartOfLifecycleTask(
8575           WTF::Bind(&DisplayLockContext::NotifyIsNotIntersectingViewport,
8576                     WrapWeakPersistent(context)));
8577     }
8578   }
8579   View()->ScheduleAnimation();
8580 }
8581 
ExecuteJavaScriptUrls()8582 void Document::ExecuteJavaScriptUrls() {
8583   DCHECK(frame_);
8584   Vector<PendingJavascriptUrl> urls_to_execute;
8585   urls_to_execute.swap(pending_javascript_urls_);
8586 
8587   for (auto& url_to_execute : urls_to_execute) {
8588     frame_->GetScriptController().ExecuteJavaScriptURL(
8589         url_to_execute.url, url_to_execute.disposition);
8590     if (!frame_)
8591       break;
8592   }
8593   CheckCompleted();
8594 }
8595 
ProcessJavaScriptUrl(const KURL & url,network::mojom::CSPDisposition disposition)8596 void Document::ProcessJavaScriptUrl(
8597     const KURL& url,
8598     network::mojom::CSPDisposition disposition) {
8599   DCHECK(url.ProtocolIsJavaScript());
8600   if (frame_->Loader().StateMachine()->IsDisplayingInitialEmptyDocument())
8601     load_event_progress_ = kLoadEventNotRun;
8602   frame_->Loader().Progress().ProgressStarted();
8603   pending_javascript_urls_.push_back(PendingJavascriptUrl(url, disposition));
8604   if (!javascript_url_task_handle_.IsActive()) {
8605     javascript_url_task_handle_ = PostCancellableTask(
8606         *GetTaskRunner(TaskType::kNetworking), FROM_HERE,
8607         WTF::Bind(&Document::ExecuteJavaScriptUrls, WrapWeakPersistent(this)));
8608   }
8609 }
8610 
CancelPendingJavaScriptUrls()8611 void Document::CancelPendingJavaScriptUrls() {
8612   if (javascript_url_task_handle_.IsActive())
8613     javascript_url_task_handle_.Cancel();
8614   pending_javascript_urls_.clear();
8615 }
8616 
IsInWebAppScope() const8617 bool Document::IsInWebAppScope() const {
8618   if (!GetSettings())
8619     return false;
8620 
8621   const String& web_app_scope = GetSettings()->GetWebAppScope();
8622   if (web_app_scope.IsNull() || web_app_scope.IsEmpty())
8623     return false;
8624 
8625   DCHECK_EQ(KURL(web_app_scope).GetString(), web_app_scope);
8626   return Url().GetString().StartsWith(web_app_scope);
8627 }
8628 
ClearIsolatedWorldCSPForTesting(int32_t world_id)8629 void Document::ClearIsolatedWorldCSPForTesting(int32_t world_id) {
8630   isolated_world_csp_map_->erase(world_id);
8631 }
8632 
ChildrenCanHaveStyle() const8633 bool Document::ChildrenCanHaveStyle() const {
8634   if (LayoutObject* view = GetLayoutView())
8635     return view->CanHaveChildren();
8636   return false;
8637 }
8638 
GetOrCreateComputedAccessibleNode(AXID ax_id,WebComputedAXTree * tree)8639 ComputedAccessibleNode* Document::GetOrCreateComputedAccessibleNode(
8640     AXID ax_id,
8641     WebComputedAXTree* tree) {
8642   if (computed_node_mapping_.find(ax_id) == computed_node_mapping_.end()) {
8643     auto* node =
8644         MakeGarbageCollected<ComputedAccessibleNode>(ax_id, tree, this);
8645     computed_node_mapping_.insert(ax_id, node);
8646   }
8647   return computed_node_mapping_.at(ax_id);
8648 }
8649 
SetShowBeforeUnloadDialog(bool show_dialog)8650 void Document::SetShowBeforeUnloadDialog(bool show_dialog) {
8651   if (!mime_handler_view_before_unload_event_listener_) {
8652     if (!show_dialog)
8653       return;
8654 
8655     mime_handler_view_before_unload_event_listener_ =
8656         MakeGarbageCollected<BeforeUnloadEventListener>(this);
8657     domWindow()->addEventListener(
8658         event_type_names::kBeforeunload,
8659         mime_handler_view_before_unload_event_listener_, false);
8660   }
8661   mime_handler_view_before_unload_event_listener_->SetShowBeforeUnloadDialog(
8662       show_dialog);
8663 }
8664 
ColorSchemeChanged()8665 void Document::ColorSchemeChanged() {
8666   UpdateForcedColors();
8667   GetStyleEngine().ColorSchemeChanged();
8668   MediaQueryAffectingValueChanged(MediaValueChange::kOther);
8669 }
8670 
VisionDeficiencyChanged()8671 void Document::VisionDeficiencyChanged() {
8672   GetStyleEngine().VisionDeficiencyChanged();
8673 }
8674 
UpdateForcedColors()8675 void Document::UpdateForcedColors() {
8676   auto* web_theme_engine =
8677       RuntimeEnabledFeatures::ForcedColorsEnabled() && Platform::Current()
8678           ? Platform::Current()->ThemeEngine()
8679           : nullptr;
8680   ForcedColors forced_colors = web_theme_engine
8681                                    ? web_theme_engine->GetForcedColors()
8682                                    : ForcedColors::kNone;
8683   in_forced_colors_mode_ = forced_colors != ForcedColors::kNone;
8684 }
8685 
InForcedColorsMode() const8686 bool Document::InForcedColorsMode() const {
8687   return in_forced_colors_mode_ && !Printing();
8688 }
8689 
IsCrossSiteSubframe() const8690 bool Document::IsCrossSiteSubframe() const {
8691   // It'd be nice to avoid the url::Origin temporaries, but that would require
8692   // exposing the net internal helper.
8693   // TODO: If the helper gets exposed, we could do this without any new
8694   // allocations using StringUTF8Adaptor.
8695   return TopFrameOrigin() &&
8696          !net::registry_controlled_domains::SameDomainOrHost(
8697              TopFrameOrigin()->ToUrlOrigin(),
8698              GetSecurityOrigin()->ToUrlOrigin(),
8699              net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
8700 }
8701 
CountUse(mojom::WebFeature feature) const8702 void Document::CountUse(mojom::WebFeature feature) const {
8703   if (use_counter_during_construction_)
8704     use_counter_during_construction_->CountUse(feature);
8705   else if (DocumentLoader* loader = Loader())
8706     loader->CountUse(feature);
8707 }
8708 
CountUse(mojom::WebFeature feature)8709 void Document::CountUse(mojom::WebFeature feature) {
8710   if (use_counter_during_construction_)
8711     use_counter_during_construction_->CountUse(feature);
8712   else if (DocumentLoader* loader = Loader())
8713     loader->CountUse(feature);
8714 }
8715 
CountDeprecation(mojom::WebFeature feature)8716 void Document::CountDeprecation(mojom::WebFeature feature) {
8717   // TODO(yoichio): We should remove these counters when v0 APIs are removed.
8718   // crbug.com/946875.
8719   if (const OriginTrialContext* origin_trial_context =
8720           GetOriginTrialContext()) {
8721     if (feature == WebFeature::kHTMLImports &&
8722         origin_trial_context->IsFeatureEnabled(
8723             OriginTrialFeature::kHTMLImports)) {
8724       CountUse(WebFeature::kHTMLImportsOnReverseOriginTrials);
8725     } else if (feature == WebFeature::kElementCreateShadowRoot &&
8726                origin_trial_context->IsFeatureEnabled(
8727                    OriginTrialFeature::kShadowDOMV0)) {
8728       CountUse(WebFeature::kElementCreateShadowRootOnReverseOriginTrials);
8729     } else if (feature == WebFeature::kDocumentRegisterElement &&
8730                origin_trial_context->IsFeatureEnabled(
8731                    OriginTrialFeature::kCustomElementsV0)) {
8732       CountUse(WebFeature::kDocumentRegisterElementOnReverseOriginTrials);
8733     }
8734   }
8735 
8736   // Don't count usage of WebComponentsV0 for chrome:// URLs, but still report
8737   // the deprecation messages.
8738   if (Url().ProtocolIs("chrome") &&
8739       (feature == WebFeature::kHTMLImports ||
8740        feature == WebFeature::kElementCreateShadowRoot ||
8741        feature == WebFeature::kDocumentRegisterElement)) {
8742     Deprecation::DeprecationWarningOnly(Loader(), feature);
8743   } else {
8744     Deprecation::CountDeprecation(Loader(), feature);
8745   }
8746 }
8747 
CountProperty(CSSPropertyID property) const8748 void Document::CountProperty(CSSPropertyID property) const {
8749   if (DocumentLoader* loader = Loader()) {
8750     loader->GetUseCounterHelper().Count(
8751         property, UseCounterHelper::CSSPropertyType::kDefault, GetFrame());
8752   }
8753 }
8754 
CountAnimatedProperty(CSSPropertyID property) const8755 void Document::CountAnimatedProperty(CSSPropertyID property) const {
8756   if (DocumentLoader* loader = Loader()) {
8757     loader->GetUseCounterHelper().Count(
8758         property, UseCounterHelper::CSSPropertyType::kAnimation, GetFrame());
8759   }
8760 }
8761 
CountUseOnlyInCrossOriginIframe(mojom::WebFeature feature) const8762 void Document::CountUseOnlyInCrossOriginIframe(
8763     mojom::WebFeature feature) const {
8764   LocalFrame* frame = GetFrame();
8765   if (frame && frame->IsCrossOriginToMainFrame())
8766     CountUse(feature);
8767 }
8768 
IsUseCounted(mojom::WebFeature feature) const8769 bool Document::IsUseCounted(mojom::WebFeature feature) const {
8770   if (DocumentLoader* loader = Loader()) {
8771     return loader->GetUseCounterHelper().HasRecordedMeasurement(feature);
8772   }
8773   return false;
8774 }
8775 
IsPropertyCounted(CSSPropertyID property) const8776 bool Document::IsPropertyCounted(CSSPropertyID property) const {
8777   if (DocumentLoader* loader = Loader()) {
8778     return loader->GetUseCounterHelper().IsCounted(
8779         property, UseCounterHelper::CSSPropertyType::kDefault);
8780   }
8781   return false;
8782 }
8783 
IsAnimatedPropertyCounted(CSSPropertyID property) const8784 bool Document::IsAnimatedPropertyCounted(CSSPropertyID property) const {
8785   if (DocumentLoader* loader = Loader()) {
8786     return loader->GetUseCounterHelper().IsCounted(
8787         property, UseCounterHelper::CSSPropertyType::kAnimation);
8788   }
8789   return false;
8790 }
8791 
ClearUseCounterForTesting(mojom::WebFeature feature)8792 void Document::ClearUseCounterForTesting(mojom::WebFeature feature) {
8793   if (DocumentLoader* loader = Loader())
8794     loader->GetUseCounterHelper().ClearMeasurementForTesting(feature);
8795 }
8796 
FontPreloadingFinishedOrTimedOut()8797 void Document::FontPreloadingFinishedOrTimedOut() {
8798   DCHECK(!font_preload_manager_.HasPendingRenderBlockingFonts());
8799   if (IsA<HTMLDocument>(this) && body()) {
8800     // For HTML, we resume only when we're past the body tag, so that we should
8801     // have something to paint now.
8802     BeginLifecycleUpdatesIfRenderingReady();
8803   } else if (!IsA<HTMLDocument>(this) && documentElement()) {
8804     // For non-HTML there is no body so resume as soon as font preloading is
8805     // done or has timed out.
8806     BeginLifecycleUpdatesIfRenderingReady();
8807   }
8808 }
8809 
8810 template class CORE_TEMPLATE_EXPORT Supplement<Document>;
8811 
8812 }  // namespace blink
8813 #ifndef NDEBUG
liveDocumentSet()8814 static WeakDocumentSet& liveDocumentSet() {
8815   DEFINE_STATIC_LOCAL(blink::Persistent<WeakDocumentSet>, set,
8816                       (blink::MakeGarbageCollected<WeakDocumentSet>()));
8817   return *set;
8818 }
8819 
showLiveDocumentInstances()8820 void showLiveDocumentInstances() {
8821   WeakDocumentSet& set = liveDocumentSet();
8822   fprintf(stderr, "There are %u documents currently alive:\n", set.size());
8823   for (blink::Document* document : set) {
8824     fprintf(stderr, "- Document %p URL: %s\n", document,
8825             document->Url().GetString().Utf8().c_str());
8826   }
8827 }
8828 #endif
8829