diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-07-16 11:45:35 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-07-17 08:59:23 +0000 |
commit | 552906b0f222c5d5dd11b9fd73829d510980461a (patch) | |
tree | 3a11e6ed0538a81dd83b20cf3a4783e297f26d91 /chromium/third_party/blink/renderer/core/dom | |
parent | 1b05827804eaf047779b597718c03e7d38344261 (diff) | |
download | qtwebengine-chromium-552906b0f222c5d5dd11b9fd73829d510980461a.tar.gz |
BASELINE: Update Chromium to 83.0.4103.122
Change-Id: Ie3a82f5bb0076eec2a7c6a6162326b4301ee291e
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/core/dom')
138 files changed, 3848 insertions, 3556 deletions
diff --git a/chromium/third_party/blink/renderer/core/dom/BUILD.gn b/chromium/third_party/blink/renderer/core/dom/BUILD.gn index a53843730ce..9d751fa8499 100644 --- a/chromium/third_party/blink/renderer/core/dom/BUILD.gn +++ b/chromium/third_party/blink/renderer/core/dom/BUILD.gn @@ -62,10 +62,6 @@ blink_core_sources("dom") { "document_parser_client.h", "document_parser_timing.cc", "document_parser_timing.h", - "document_shutdown_notifier.cc", - "document_shutdown_notifier.h", - "document_shutdown_observer.cc", - "document_shutdown_observer.h", "document_statistics_collector.cc", "document_statistics_collector.h", "document_timing.cc", @@ -238,8 +234,6 @@ blink_core_sources("dom") { "static_node_list.h", "static_range.cc", "static_range.h", - "synchronous_mutation_notifier.cc", - "synchronous_mutation_notifier.h", "synchronous_mutation_observer.cc", "synchronous_mutation_observer.h", "tag_collection.cc", diff --git a/chromium/third_party/blink/renderer/core/dom/abort_controller.idl b/chromium/third_party/blink/renderer/core/dom/abort_controller.idl index 84afef572ad..f3f881c922d 100644 --- a/chromium/third_party/blink/renderer/core/dom/abort_controller.idl +++ b/chromium/third_party/blink/renderer/core/dom/abort_controller.idl @@ -5,11 +5,9 @@ // https://dom.spec.whatwg.org/#interface-abortcontroller [ - Constructor, - ConstructorCallWith=ExecutionContext, - Exposed=(Window,Worker), - Measure + Exposed=(Window,Worker) ] interface AbortController { + [CallWith=ExecutionContext, Measure] constructor(); [SameObject] readonly attribute AbortSignal signal; void abort(); diff --git a/chromium/third_party/blink/renderer/core/dom/aria_attributes.idl b/chromium/third_party/blink/renderer/core/dom/aria_attributes.idl index 393f49022da..31bee8c6dc3 100644 --- a/chromium/third_party/blink/renderer/core/dom/aria_attributes.idl +++ b/chromium/third_party/blink/renderer/core/dom/aria_attributes.idl @@ -16,6 +16,7 @@ [CEReactions, Reflect=aria_colindex] attribute DOMString? ariaColIndex; [CEReactions, Reflect=aria_colspan] attribute DOMString? ariaColSpan; [CEReactions, Reflect=aria_current] attribute DOMString? ariaCurrent; + [RuntimeEnabled=AccessibilityExposeARIAAnnotations, CEReactions, Reflect=aria_description] attribute DOMString? ariaDescription; [CEReactions, Reflect=aria_disabled] attribute DOMString? ariaDisabled; [CEReactions, Reflect=aria_expanded] attribute DOMString? ariaExpanded; [CEReactions, Reflect=aria_haspopup] attribute DOMString? ariaHasPopup; diff --git a/chromium/third_party/blink/renderer/core/dom/aria_relationship_attributes.idl b/chromium/third_party/blink/renderer/core/dom/aria_relationship_attributes.idl index 7a2a504040e..2229d59ed6a 100644 --- a/chromium/third_party/blink/renderer/core/dom/aria_relationship_attributes.idl +++ b/chromium/third_party/blink/renderer/core/dom/aria_relationship_attributes.idl @@ -10,7 +10,7 @@ [CEReactions, Reflect=aria_activedescendant] attribute Element? ariaActiveDescendantElement; [CEReactions, Reflect=aria_controls] attribute FrozenArray<Element>? ariaControlsElements; [CEReactions, Reflect=aria_describedby] attribute FrozenArray<Element>? ariaDescribedByElements; - [CEReactions, Reflect=aria_details] attribute Element? ariaDetailsElement; + [CEReactions, Reflect=aria_details] attribute FrozenArray<Element>? ariaDetailsElements; [CEReactions, Reflect=aria_errormessage] attribute Element? ariaErrorMessageElement; [CEReactions, Reflect=aria_flowto] attribute FrozenArray<Element>? ariaFlowToElements; [CEReactions, Reflect=aria_labelledby] attribute FrozenArray<Element>? ariaLabelledByElements; diff --git a/chromium/third_party/blink/renderer/core/dom/beforeunload_event_listener.cc b/chromium/third_party/blink/renderer/core/dom/beforeunload_event_listener.cc index bc289cf7748..a66ac3a2b91 100644 --- a/chromium/third_party/blink/renderer/core/dom/beforeunload_event_listener.cc +++ b/chromium/third_party/blink/renderer/core/dom/beforeunload_event_listener.cc @@ -18,7 +18,7 @@ void BeforeUnloadEventListener::Invoke(ExecutionContext* execution_context, Event* event) { DCHECK_EQ(event->type(), event_type_names::kBeforeunload); if (show_dialog_) - ToBeforeUnloadEvent(event)->setReturnValue(g_empty_string); + To<BeforeUnloadEvent>(event)->setReturnValue(g_empty_string); } void BeforeUnloadEventListener::Trace(Visitor* visitor) { diff --git a/chromium/third_party/blink/renderer/core/dom/character_data.cc b/chromium/third_party/blink/renderer/core/dom/character_data.cc index 146bd34ff72..55a99d7eb1c 100644 --- a/chromium/third_party/blink/renderer/core/dom/character_data.cc +++ b/chromium/third_party/blink/renderer/core/dom/character_data.cc @@ -38,19 +38,13 @@ namespace blink { -void CharacterData::MakeParkableOrAtomize() { +void CharacterData::MakeParkable() { if (is_parkable_) return; - // ParkableStrings have some overhead, don't pay it if we're not going to - // park a string at all. - if (ParkableStringManager::ShouldPark(*data_.Impl())) { - parkable_data_ = ParkableString(data_.ReleaseImpl()); - data_ = String(); - is_parkable_ = true; - } else { - data_ = AtomicString(data_); - } + parkable_data_ = ParkableString(data_.ReleaseImpl()); + data_ = String(); + is_parkable_ = true; } void CharacterData::setData(const String& data) { @@ -233,8 +227,14 @@ void CharacterData::DidModifyData(const String& old_data, UpdateSource source) { if (parentNode()) { ContainerNode::ChildrenChange change = { - ContainerNode::kTextChanged, this, previousSibling(), nextSibling(), - ContainerNode::kChildrenChangeSourceAPI}; + ContainerNode::ChildrenChangeType::kTextChanged, + source == kUpdateFromParser + ? ContainerNode::ChildrenChangeSource::kParser + : ContainerNode::ChildrenChangeSource::kAPI, + this, + previousSibling(), + nextSibling(), + nullptr}; parentNode()->ChildrenChanged(change); } diff --git a/chromium/third_party/blink/renderer/core/dom/character_data.h b/chromium/third_party/blink/renderer/core/dom/character_data.h index b3acf286820..cfd038dce61 100644 --- a/chromium/third_party/blink/renderer/core/dom/character_data.h +++ b/chromium/third_party/blink/renderer/core/dom/character_data.h @@ -38,9 +38,8 @@ class CORE_EXPORT CharacterData : public Node { DEFINE_WRAPPERTYPEINFO(); public: - // Makes the data either Parkable or Atomic. This enables de-duplication in - // both cases, the first one allowing compression as well. - void MakeParkableOrAtomize(); + // Makes the data Parkable. This enables de-duplication and compression. + void MakeParkable(); const String& data() const { return is_parkable_ ? parkable_data_.ToString() : data_; } diff --git a/chromium/third_party/blink/renderer/core/dom/child_frame_disconnector.h b/chromium/third_party/blink/renderer/core/dom/child_frame_disconnector.h index 5d17d81682b..02155cd2151 100644 --- a/chromium/third_party/blink/renderer/core/dom/child_frame_disconnector.h +++ b/chromium/third_party/blink/renderer/core/dom/child_frame_disconnector.h @@ -18,7 +18,7 @@ class ChildFrameDisconnector { public: enum DisconnectPolicy { kRootAndDescendants, kDescendantsOnly }; - explicit ChildFrameDisconnector(Node& root) : root_(root) {} + explicit ChildFrameDisconnector(Node& root) : root_(&root) {} void Disconnect(DisconnectPolicy = kRootAndDescendants); @@ -28,7 +28,7 @@ class ChildFrameDisconnector { Node& Root() const { return *root_; } HeapVector<Member<HTMLFrameOwnerElement>, 10> frame_owners_; - Member<Node> root_; + Node* root_; }; } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/child_list_mutation_scope.h b/chromium/third_party/blink/renderer/core/dom/child_list_mutation_scope.h index 718d39de507..e8290df1d71 100644 --- a/chromium/third_party/blink/renderer/core/dom/child_list_mutation_scope.h +++ b/chromium/third_party/blink/renderer/core/dom/child_list_mutation_scope.h @@ -119,7 +119,7 @@ class ChildListMutationScope final { } private: - Member<ChildListMutationAccumulator> accumulator_; + ChildListMutationAccumulator* accumulator_ = nullptr; DISALLOW_COPY_AND_ASSIGN(ChildListMutationScope); }; diff --git a/chromium/third_party/blink/renderer/core/dom/child_node_list.cc b/chromium/third_party/blink/renderer/core/dom/child_node_list.cc index 457df191759..fbd31f32306 100644 --- a/chromium/third_party/blink/renderer/core/dom/child_node_list.cc +++ b/chromium/third_party/blink/renderer/core/dom/child_node_list.cc @@ -23,7 +23,6 @@ #include "third_party/blink/renderer/core/dom/child_node_list.h" -#include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/node_rare_data.h" @@ -38,10 +37,7 @@ Node* ChildNodeList::VirtualOwnerNode() const { ChildNodeList::~ChildNodeList() = default; Node* ChildNodeList::item(unsigned index) const { - Node* node = collection_index_cache_.NodeAt(*this, index); - if (node && node->GetDocument().InDOMNodeRemovedHandler()) - node->GetDocument().CountDetachingNodeAccessInDOMNodeRemovedHandler(); - return node; + return collection_index_cache_.NodeAt(*this, index); } void ChildNodeList::ChildrenChanged( diff --git a/chromium/third_party/blink/renderer/core/dom/child_node_list.h b/chromium/third_party/blink/renderer/core/dom/child_node_list.h index b52dc467877..80d86082530 100644 --- a/chromium/third_party/blink/renderer/core/dom/child_node_list.h +++ b/chromium/third_party/blink/renderer/core/dom/child_node_list.h @@ -70,11 +70,12 @@ class ChildNodeList final : public NodeList { mutable CollectionIndexCache<ChildNodeList, Node> collection_index_cache_; }; -DEFINE_TYPE_CASTS(ChildNodeList, - NodeList, - nodeList, - nodeList->IsChildNodeList(), - nodeList.IsChildNodeList()); +template <> +struct DowncastTraits<ChildNodeList> { + static bool AllowFrom(const NodeList& nodeList) { + return nodeList.IsChildNodeList(); + } +}; } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/class_collection.h b/chromium/third_party/blink/renderer/core/dom/class_collection.h index d4f30f19010..24f67d9420a 100644 --- a/chromium/third_party/blink/renderer/core/dom/class_collection.h +++ b/chromium/third_party/blink/renderer/core/dom/class_collection.h @@ -50,11 +50,12 @@ class ClassCollection final : public HTMLCollection { SpaceSplitString class_names_; }; -DEFINE_TYPE_CASTS(ClassCollection, - LiveNodeListBase, - collection, - collection->GetType() == kClassCollectionType, - collection.GetType() == kClassCollectionType); +template <> +struct DowncastTraits<ClassCollection> { + static bool AllowFrom(const LiveNodeListBase& collection) { + return collection.GetType() == kClassCollectionType; + } +}; inline bool ClassCollection::ElementMatches(const Element& test_element) const { if (!test_element.HasClass()) diff --git a/chromium/third_party/blink/renderer/core/dom/comment.idl b/chromium/third_party/blink/renderer/core/dom/comment.idl index 06e5126c605..428d0366b40 100644 --- a/chromium/third_party/blink/renderer/core/dom/comment.idl +++ b/chromium/third_party/blink/renderer/core/dom/comment.idl @@ -20,8 +20,7 @@ // https://dom.spec.whatwg.org/#interface-comment [ - Constructor(optional DOMString data = ""), - ConstructorCallWith=Document, Exposed=Window ] interface Comment : CharacterData { + [CallWith=Document] constructor(optional DOMString data = ""); }; diff --git a/chromium/third_party/blink/renderer/core/dom/container_node.cc b/chromium/third_party/blink/renderer/core/dom/container_node.cc index bb3119ce25a..b946eea979a 100644 --- a/chromium/third_party/blink/renderer/core/dom/container_node.cc +++ b/chromium/third_party/blink/renderer/core/dom/container_node.cc @@ -47,6 +47,7 @@ #include "third_party/blink/renderer/core/frame/web_feature.h" #include "third_party/blink/renderer/core/html/forms/radio_node_list.h" #include "third_party/blink/renderer/core/html/html_collection.h" +#include "third_party/blink/renderer/core/html/html_document.h" #include "third_party/blink/renderer/core/html/html_frame_owner_element.h" #include "third_party/blink/renderer/core/html/html_tag_collection.h" #include "third_party/blink/renderer/core/layout/layout_block_flow.h" @@ -84,9 +85,9 @@ class DOMTreeMutationDetector { public: DOMTreeMutationDetector(const Node& node, const Node& parent) : node_(&node), - node_document_(node.GetDocument()), - parent_document_(parent.GetDocument()), - parent_(parent), + node_document_(&node.GetDocument()), + parent_document_(&parent.GetDocument()), + parent_(&parent), original_node_document_version_(node_document_->DomTreeVersion()), original_parent_document_version_(parent_document_->DomTreeVersion()) {} @@ -105,10 +106,10 @@ class DOMTreeMutationDetector { } private: - const Member<const Node> node_; - const Member<Document> node_document_; - const Member<Document> parent_document_; - const Member<const Node> parent_; + const Node* const node_; + Document* const node_document_; + Document* const parent_document_; + const Node* const parent_; const uint64_t original_node_document_version_; const uint64_t original_parent_document_version_; }; @@ -341,7 +342,7 @@ void ContainerNode::DidInsertNodeVector( targets.size() > 0 ? targets[0]->previousSibling() : nullptr; for (const auto& target_node : targets) { ChildrenChanged(ChildrenChange::ForInsertion( - *target_node, unchanged_previous, next, kChildrenChangeSourceAPI)); + *target_node, unchanged_previous, next, ChildrenChangeSource::kAPI)); } for (const auto& descendant : post_insertion_notification_targets) { if (descendant->isConnected()) @@ -516,7 +517,7 @@ void ContainerNode::ParserInsertBefore(Node* new_child, Node& next_child) { ChildListMutationScope(*this).ChildAdded(*new_child); } - NotifyNodeInserted(*new_child, kChildrenChangeSourceParser); + NotifyNodeInserted(*new_child, ChildrenChangeSource::kParser); } Node* ContainerNode::ReplaceChild(Node* new_child, @@ -720,7 +721,7 @@ Node* ContainerNode::RemoveChild(Node* old_child, NotifyNodeRemoved(*child); } ChildrenChanged(ChildrenChange::ForRemoval(*child, prev, next, - kChildrenChangeSourceAPI)); + ChildrenChangeSource::kAPI)); } DispatchSubtreeModifiedEvent(); return child; @@ -781,7 +782,7 @@ void ContainerNode::ParserRemoveChild(Node& old_child) { NotifyNodeRemoved(old_child); } ChildrenChanged(ChildrenChange::ForRemoval(old_child, prev, next, - kChildrenChangeSourceParser)); + ChildrenChangeSource::kParser)); } // This differs from other remove functions because it forcibly removes all the @@ -809,6 +810,11 @@ void ContainerNode::RemoveChildren(SubtreeModificationAction action) { GetDocument().NodeChildrenWillBeRemoved(*this); } + HeapVector<Member<Node>>* removed_nodes = nullptr; + if (ChildrenChangedAllChildrenRemovedNeedsList()) { + removed_nodes = + MakeGarbageCollected<HeapVector<Member<Node>>>(CountChildren()); + } { HTMLFrameOwnerElement::PluginDisposeSuspendScope suspend_plugin_dispose; TreeOrderedMap::RemoveScope tree_remove_scope; @@ -821,11 +827,17 @@ void ContainerNode::RemoveChildren(SubtreeModificationAction action) { while (Node* child = first_child_) { RemoveBetween(nullptr, child->nextSibling(), *child); NotifyNodeRemoved(*child); + if (removed_nodes) + removed_nodes->push_back(child); } } - ChildrenChange change = {kAllChildrenRemoved, nullptr, nullptr, nullptr, - kChildrenChangeSourceAPI}; + ChildrenChange change = {ChildrenChangeType::kAllChildrenRemoved, + ChildrenChangeSource::kAPI, + nullptr, + nullptr, + nullptr, + removed_nodes}; ChildrenChanged(change); } @@ -896,7 +908,7 @@ void ContainerNode::ParserAppendChild(Node* new_child) { ChildListMutationScope(*this).ChildAdded(*new_child); } - NotifyNodeInserted(*new_child, kChildrenChangeSourceParser); + NotifyNodeInserted(*new_child, ChildrenChangeSource::kParser); } DISABLE_CFI_PERF @@ -1007,13 +1019,16 @@ void ContainerNode::ChildrenChanged(const ChildrenChange& change) { GetDocument().IncDOMTreeVersion(); GetDocument().NotifyChangeChildren(*this); InvalidateNodeListCachesInAncestors(nullptr, nullptr, &change); - - if (change.IsChildRemoval() || change.type == kAllChildrenRemoved) { + if (change.IsChildRemoval() || + change.type == ChildrenChangeType::kAllChildrenRemoved) { GetDocument().GetStyleEngine().ChildrenRemoved(*this); return; } if (!change.IsChildInsertion()) return; + Node* inserted_node = change.sibling_changed; + if (inserted_node->IsContainerNode() || inserted_node->IsTextNode()) + inserted_node->ClearFlatTreeNodeDataIfHostChanged(*this); if (!InActiveDocument()) return; if (IsElementNode() && !GetComputedStyle()) { @@ -1024,11 +1039,12 @@ void ContainerNode::ChildrenChanged(const ChildrenChange& change) { // the ComputedStyle goes from null to non-null. return; } - Node* inserted_node = change.sibling_changed; - if (inserted_node->IsContainerNode() || inserted_node->IsTextNode()) { - inserted_node->ClearFlatTreeNodeDataIfHostChanged(*this); + if (inserted_node->IsContainerNode() || inserted_node->IsTextNode()) inserted_node->SetStyleChangeOnInsertion(); - } +} + +bool ContainerNode::ChildrenChangedAllChildrenRemovedNeedsList() const { + return false; } void ContainerNode::CloneChildNodesFrom(const ContainerNode& node) { @@ -1101,7 +1117,8 @@ void ContainerNode::FocusWithinStateChanged() { this_element->PseudoStateChanged(CSSSelector::kPseudoFocusWithin); } -void ContainerNode::SetFocused(bool received, WebFocusType focus_type) { +void ContainerNode::SetFocused(bool received, + mojom::blink::FocusType focus_type) { // Recurse up author shadow trees to mark shadow hosts if it matches :focus. // TODO(kochi): Handle UA shadows which marks multiple nodes as focused such // as <input type="date"> the same way as author shadow. @@ -1227,12 +1244,7 @@ Element* ContainerNode::QuerySelector(const AtomicString& selectors, selectors, GetDocument(), exception_state); if (!selector_query) return nullptr; - Element* element = selector_query->QueryFirst(*this); - if (element && element->GetDocument().InDOMNodeRemovedHandler()) { - if (NodeChildRemovalTracker::IsBeingRemoved(*element)) - GetDocument().CountDetachingNodeAccessInDOMNodeRemovedHandler(); - } - return element; + return selector_query->QueryFirst(*this); } Element* ContainerNode::QuerySelector(const AtomicString& selectors) { @@ -1300,43 +1312,20 @@ static void DispatchChildRemovalEvents(Node& child) { // Dispatch pre-removal mutation events. if (c->parentNode() && document.HasListenerType(Document::kDOMNodeRemovedListener)) { - bool original_node_flag = c->InDOMNodeRemovedHandler(); - auto original_document_state = document.GetInDOMNodeRemovedHandlerState(); - if (ScopedEventQueue::Instance()->ShouldQueueEvents()) { - UseCounter::Count(document, WebFeature::kDOMNodeRemovedEventDelayed); - } else { - c->SetInDOMNodeRemovedHandler(true); - document.SetInDOMNodeRemovedHandlerState( - Document::InDOMNodeRemovedHandlerState::kDOMNodeRemoved); - } NodeChildRemovalTracker scope(child); c->DispatchScopedEvent( *MutationEvent::Create(event_type_names::kDOMNodeRemoved, Event::Bubbles::kYes, c->parentNode())); - document.SetInDOMNodeRemovedHandlerState(original_document_state); - c->SetInDOMNodeRemovedHandler(original_node_flag); } // Dispatch the DOMNodeRemovedFromDocument event to all descendants. if (c->isConnected() && document.HasListenerType(Document::kDOMNodeRemovedFromDocumentListener)) { - bool original_node_flag = c->InDOMNodeRemovedHandler(); - auto original_document_state = document.GetInDOMNodeRemovedHandlerState(); - if (ScopedEventQueue::Instance()->ShouldQueueEvents()) { - UseCounter::Count(document, - WebFeature::kDOMNodeRemovedFromDocumentEventDelayed); - } else { - c->SetInDOMNodeRemovedHandler(true); - document.SetInDOMNodeRemovedHandlerState( - Document::InDOMNodeRemovedHandlerState::kDOMNodeRemovedFromDocument); - } NodeChildRemovalTracker scope(child); for (; c; c = NodeTraversal::Next(*c, &child)) { c->DispatchScopedEvent(*MutationEvent::Create( event_type_names::kDOMNodeRemovedFromDocument, Event::Bubbles::kNo)); } - document.SetInDOMNodeRemovedHandlerState(original_document_state); - child.SetInDOMNodeRemovedHandler(original_node_flag); } } @@ -1486,7 +1475,7 @@ void ContainerNode::InvalidateNodeListCachesInAncestors( const ChildrenChange* change) { // This is a performance optimization, NodeList cache invalidation is // not necessary for a text change. - if (change && change->type == kTextChanged) + if (change && change->type == ChildrenChangeType::kTextChanged) return; if (HasRareData() && (!attr_name || IsAttributeNode())) { @@ -1521,7 +1510,7 @@ HTMLCollection* ContainerNode::getElementsByTagName( const AtomicString& qualified_name) { DCHECK(!qualified_name.IsNull()); - if (GetDocument().IsHTMLDocument()) { + if (IsA<HTMLDocument>(GetDocument())) { return EnsureCachedCollection<HTMLTagCollection>(kHTMLTagCollectionType, qualified_name); } @@ -1540,15 +1529,14 @@ HTMLCollection* ContainerNode::getElementsByTagNameNS( // Takes an AtomicString in argument because it is common for elements to share // the same name attribute. Therefore, the NameNodeList factory function // expects an AtomicString type. -NameNodeList* ContainerNode::getElementsByName( - const AtomicString& element_name) { +NodeList* ContainerNode::getElementsByName(const AtomicString& element_name) { return EnsureCachedCollection<NameNodeList>(kNameNodeListType, element_name); } // Takes an AtomicString in argument because it is common for elements to share // the same set of class names. Therefore, the ClassNodeList factory function // expects an AtomicString type. -ClassCollection* ContainerNode::getElementsByClassName( +HTMLCollection* ContainerNode::getElementsByClassName( const AtomicString& class_names) { return EnsureCachedCollection<ClassCollection>(kClassCollectionType, class_names); diff --git a/chromium/third_party/blink/renderer/core/dom/container_node.h b/chromium/third_party/blink/renderer/core/dom/container_node.h index 8649528aac9..c3582de6bfc 100644 --- a/chromium/third_party/blink/renderer/core/dom/container_node.h +++ b/chromium/third_party/blink/renderer/core/dom/container_node.h @@ -25,27 +25,25 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_CONTAINER_NODE_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_CONTAINER_NODE_H_ -#include "third_party/blink/public/platform/web_focus_type.h" +#include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/css/style_recalc.h" #include "third_party/blink/renderer/core/dom/node.h" +#include "third_party/blink/renderer/core/dom/static_node_list.h" #include "third_party/blink/renderer/core/html/collection_type.h" #include "third_party/blink/renderer/platform/wtf/casting.h" #include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink { -class ClassCollection; -class ExceptionState; class Element; +class ExceptionState; class HTMLCollection; -class NameNodeList; -template <typename NodeType> -class StaticNodeTypeList; -using StaticElementList = StaticNodeTypeList<Element>; class RadioNodeList; class WhitespaceAttacher; +using StaticElementList = StaticNodeTypeList<Element>; + enum class DynamicRestyleFlags { kChildrenOrSiblingsAffectedByFocus = 1 << 0, kChildrenOrSiblingsAffectedByHover = 1 << 1, @@ -131,8 +129,8 @@ class CORE_EXPORT ContainerNode : public Node { HTMLCollection* getElementsByTagName(const AtomicString&); HTMLCollection* getElementsByTagNameNS(const AtomicString& namespace_uri, const AtomicString& local_name); - NameNodeList* getElementsByName(const AtomicString& element_name); - ClassCollection* getElementsByClassName(const AtomicString& class_names); + NodeList* getElementsByName(const AtomicString& element_name); + HTMLCollection* getElementsByClassName(const AtomicString& class_names); RadioNodeList* GetRadioNodeList(const AtomicString&, bool only_match_img_elements = false); @@ -151,7 +149,7 @@ class CORE_EXPORT ContainerNode : public Node { void AttachLayoutTree(AttachContext&) override; void DetachLayoutTree(bool performing_reattach = false) override; PhysicalRect BoundingBox() const final; - void SetFocused(bool, WebFocusType) override; + void SetFocused(bool, mojom::blink::FocusType) override; void SetHasFocusWithinUpToAncestor(bool, Node* ancestor); void FocusStateChanged(); void FocusVisibleStateChanged(); @@ -296,7 +294,7 @@ class CORE_EXPORT ContainerNode : public Node { // Notification of document structure changes (see core/dom/node.h for more // notification methods) - enum ChildrenChangeType { + enum class ChildrenChangeType : uint8_t { kElementInserted, kNonElementInserted, kElementRemoved, @@ -304,10 +302,7 @@ class CORE_EXPORT ContainerNode : public Node { kAllChildrenRemoved, kTextChanged }; - enum ChildrenChangeSource { - kChildrenChangeSourceAPI, - kChildrenChangeSourceParser - }; + enum class ChildrenChangeSource : uint8_t { kAPI, kParser }; struct ChildrenChange { STACK_ALLOCATED(); @@ -316,9 +311,14 @@ class CORE_EXPORT ContainerNode : public Node { Node* unchanged_previous, Node* unchanged_next, ChildrenChangeSource by_parser) { - ChildrenChange change = { - node.IsElementNode() ? kElementInserted : kNonElementInserted, &node, - unchanged_previous, unchanged_next, by_parser}; + ChildrenChange change = {node.IsElementNode() + ? ChildrenChangeType::kElementInserted + : ChildrenChangeType::kNonElementInserted, + by_parser, + &node, + unchanged_previous, + unchanged_next, + nullptr}; return change; } @@ -326,43 +326,63 @@ class CORE_EXPORT ContainerNode : public Node { Node* previous_sibling, Node* next_sibling, ChildrenChangeSource by_parser) { - ChildrenChange change = { - node.IsElementNode() ? kElementRemoved : kNonElementRemoved, &node, - previous_sibling, next_sibling, by_parser}; + ChildrenChange change = {node.IsElementNode() + ? ChildrenChangeType::kElementRemoved + : ChildrenChangeType::kNonElementRemoved, + by_parser, + &node, + previous_sibling, + next_sibling, + nullptr}; return change; } bool IsChildInsertion() const { - return type == kElementInserted || type == kNonElementInserted; + return type == ChildrenChangeType::kElementInserted || + type == ChildrenChangeType::kNonElementInserted; } bool IsChildRemoval() const { - return type == kElementRemoved || type == kNonElementRemoved; + return type == ChildrenChangeType::kElementRemoved || + type == ChildrenChangeType::kNonElementRemoved; } bool IsChildElementChange() const { - return type == kElementInserted || type == kElementRemoved; + return type == ChildrenChangeType::kElementInserted || + type == ChildrenChangeType::kElementRemoved; } + bool ByParser() const { return by_parser == ChildrenChangeSource::kParser; } + ChildrenChangeType type; - Member<Node> sibling_changed; + ChildrenChangeSource by_parser; + Node* sibling_changed = nullptr; // |siblingBeforeChange| is // - siblingChanged.previousSibling before node removal // - siblingChanged.previousSibling after single node insertion // - previousSibling of the first inserted node after multiple node // insertion - Member<Node> sibling_before_change; + Node* sibling_before_change = nullptr; // |siblingAfterChange| is // - siblingChanged.nextSibling before node removal // - siblingChanged.nextSibling after single node insertion // - nextSibling of the last inserted node after multiple node insertion. - Member<Node> sibling_after_change; - ChildrenChangeSource by_parser; + Node* sibling_after_change = nullptr; + // List of removed nodes for ChildrenChangeType::kAllChildrenRemoved. + // This is available only if ChildrenChangedAllChildrenRemovedNeedsList() + // returns true. + HeapVector<Member<Node>>* removed_nodes; }; // Notifies the node that it's list of children have changed (either by adding // or removing child nodes), or a child node that is of the type - // CDATA_SECTION_NODE, TEXT_NODE or COMMENT_NODE has changed its value. + // kCdataSectionNode, kTextNode or kCommentNode has changed its value. + // + // ChildrenChanged() implementations may modify the DOM tree, and may dispatch + // synchronous events. virtual void ChildrenChanged(const ChildrenChange&); + // Provides ChildrenChange::removed_nodes for kAllChildrenRemoved. + virtual bool ChildrenChangedAllChildrenRemovedNeedsList() const; + virtual bool ChildrenCanHaveStyle() const { return true; } void Trace(Visitor*) override; @@ -429,7 +449,7 @@ class CORE_EXPORT ContainerNode : public Node { void AddChildNodesToDeletionQueue(Node*&, Node*&, ContainerNode&); void NotifyNodeInserted(Node&, - ChildrenChangeSource = kChildrenChangeSourceAPI); + ChildrenChangeSource = ChildrenChangeSource::kAPI); void NotifyNodeInsertedInternal( Node&, NodeVector& post_insertion_notification_targets); diff --git a/chromium/third_party/blink/renderer/core/dom/document.cc b/chromium/third_party/blink/renderer/core/dom/document.cc index 2247f71c3c9..f55c90df996 100644 --- a/chromium/third_party/blink/renderer/core/dom/document.cc +++ b/chromium/third_party/blink/renderer/core/dom/document.cc @@ -41,6 +41,8 @@ #include "components/performance_manager/public/mojom/coordination_unit.mojom-blink.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" +#include "mojo/public/mojom/base/text_direction.mojom-blink.h" +#include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "services/metrics/public/cpp/mojo_ukm_recorder.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_source_id.h" @@ -48,16 +50,16 @@ #include "services/network/public/mojom/ip_address_space.mojom-blink.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/blink/public/common/browser_interface_broker_proxy.h" +#include "third_party/blink/public/common/feature_policy/document_policy_features.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h" -#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h" +#include "third_party/blink/public/mojom/feature_policy/policy_disposition.mojom-blink.h" +#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h" #include "third_party/blink/public/mojom/insecure_input/insecure_input_service.mojom-blink.h" #include "third_party/blink/public/mojom/ukm/ukm.mojom-blink.h" -#include "third_party/blink/public/platform/interface_provider.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/public/platform/web_content_settings_client.h" -#include "third_party/blink/public/platform/web_prerendering_support.h" #include "third_party/blink/public/platform/web_theme_engine.h" #include "third_party/blink/renderer/bindings/core/v8/html_script_element_or_svg_script_element.h" #include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h" @@ -68,6 +70,7 @@ #include "third_party/blink/renderer/bindings/core/v8/string_or_element_creation_options.h" #include "third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.h" #include "third_party/blink/renderer/bindings/core/v8/v8_element_creation_options.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_element_registration_options.h" #include "third_party/blink/renderer/bindings/core/v8/window_proxy.h" #include "third_party/blink/renderer/core/accessibility/ax_context.h" #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h" @@ -95,6 +98,7 @@ #include "third_party/blink/renderer/core/css/style_engine.h" #include "third_party/blink/renderer/core/css/style_sheet_contents.h" #include "third_party/blink/renderer/core/css/style_sheet_list.h" +#include "third_party/blink/renderer/core/display_lock/display_lock_context.h" #include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h" #include "third_party/blink/renderer/core/dom/attr.h" #include "third_party/blink/renderer/core/dom/beforeunload_event_listener.h" @@ -107,9 +111,7 @@ #include "third_party/blink/renderer/core/dom/document_type.h" #include "third_party/blink/renderer/core/dom/dom_implementation.h" #include "third_party/blink/renderer/core/dom/element.h" -#include "third_party/blink/renderer/core/dom/element_creation_options.h" #include "third_party/blink/renderer/core/dom/element_data_cache.h" -#include "third_party/blink/renderer/core/dom/element_registration_options.h" #include "third_party/blink/renderer/core/dom/element_traversal.h" #include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h" @@ -151,12 +153,14 @@ #include "third_party/blink/renderer/core/events/visual_viewport_resize_event.h" #include "third_party/blink/renderer/core/events/visual_viewport_scroll_event.h" #include "third_party/blink/renderer/core/execution_context/agent_metrics_collector.h" +#include "third_party/blink/renderer/core/execution_context/security_context_init.h" #include "third_party/blink/renderer/core/execution_context/window_agent.h" #include "third_party/blink/renderer/core/execution_context/window_agent_factory.h" #include "third_party/blink/renderer/core/feature_policy/dom_document_policy.h" #include "third_party/blink/renderer/core/feature_policy/feature_policy_parser.h" #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h" #include "third_party/blink/renderer/core/frame/csp/navigation_initiator_impl.h" +#include "third_party/blink/renderer/core/frame/document_policy_violation_report_body.h" #include "third_party/blink/renderer/core/frame/dom_timer.h" #include "third_party/blink/renderer/core/frame/dom_visual_viewport.h" #include "third_party/blink/renderer/core/frame/event_handler_registry.h" @@ -187,6 +191,7 @@ #include "third_party/blink/renderer/core/html/document_all_name_collection.h" #include "third_party/blink/renderer/core/html/document_name_collection.h" #include "third_party/blink/renderer/core/html/forms/form_controller.h" +#include "third_party/blink/renderer/core/html/forms/html_form_element.h" #include "third_party/blink/renderer/core/html/forms/html_input_element.h" #include "third_party/blink/renderer/core/html/html_all_collection.h" #include "third_party/blink/renderer/core/html/html_anchor_element.h" @@ -222,9 +227,12 @@ #include "third_party/blink/renderer/core/input/event_handler.h" #include "third_party/blink/renderer/core/input/touch_list.h" #include "third_party/blink/renderer/core/inspector/console_message.h" +#include "third_party/blink/renderer/core/inspector/inspector_issue.h" +#include "third_party/blink/renderer/core/inspector/inspector_issue_storage.h" #include "third_party/blink/renderer/core/inspector/inspector_trace_events.h" -#include "third_party/blink/renderer/core/inspector/main_thread_debugger.h" +#include "third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h" #include "third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h" +#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h" #include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h" #include "third_party/blink/renderer/core/layout/hit_test_canvas_result.h" #include "third_party/blink/renderer/core/layout/hit_test_result.h" @@ -243,6 +251,7 @@ #include "third_party/blink/renderer/core/loader/progress_tracker.h" #include "third_party/blink/renderer/core/loader/text_resource_decoder_builder.h" #include "third_party/blink/renderer/core/mathml/mathml_element.h" +#include "third_party/blink/renderer/core/mathml/mathml_row_element.h" #include "third_party/blink/renderer/core/mathml_element_factory.h" #include "third_party/blink/renderer/core/mathml_names.h" #include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h" @@ -261,8 +270,10 @@ #include "third_party/blink/renderer/core/page/scrolling/text_fragment_anchor.h" #include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h" #include "third_party/blink/renderer/core/page/spatial_navigation_controller.h" +#include "third_party/blink/renderer/core/page/validation_message_client.h" #include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h" #include "third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h" +#include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" #include "third_party/blink/renderer/core/probe/core_probes.h" #include "third_party/blink/renderer/core/resize_observer/resize_observer_controller.h" @@ -275,11 +286,10 @@ #include "third_party/blink/renderer/core/svg/svg_use_element.h" #include "third_party/blink/renderer/core/svg_element_factory.h" #include "third_party/blink/renderer/core/svg_names.h" -#include "third_party/blink/renderer/core/timing/dom_window_performance.h" -#include "third_party/blink/renderer/core/timing/window_performance.h" #include "third_party/blink/renderer/core/trustedtypes/trusted_html.h" #include "third_party/blink/renderer/core/xml/parser/xml_document_parser.h" #include "third_party/blink/renderer/core/xml_names.h" +#include "third_party/blink/renderer/core/xmlhttprequest/main_thread_disallow_synchronous_xhr_scope.h" #include "third_party/blink/renderer/core/xmlns_names.h" #include "third_party/blink/renderer/platform/bindings/dom_data_store.h" #include "third_party/blink/renderer/platform/bindings/exception_messages.h" @@ -303,7 +313,6 @@ #include "third_party/blink/renderer/platform/network/http_parsers.h" #include "third_party/blink/renderer/platform/network/network_state_notifier.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" -#include "third_party/blink/renderer/platform/scheduler/public/dummy_schedulers.h" #include "third_party/blink/renderer/platform/scheduler/public/event_loop.h" #include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" @@ -573,12 +582,12 @@ static bool g_threaded_parsing_enabled_for_testing = true; class Document::NetworkStateObserver final : public GarbageCollected<Document::NetworkStateObserver>, public NetworkStateNotifier::NetworkStateObserver, - public ContextLifecycleObserver { + public ExecutionContextLifecycleObserver { USING_GARBAGE_COLLECTED_MIXIN(Document::NetworkStateObserver); public: - explicit NetworkStateObserver(Document& document) - : ContextLifecycleObserver(&document) { + explicit NetworkStateObserver(ExecutionContext* context) + : ExecutionContextLifecycleObserver(context) { online_observer_handle_ = GetNetworkStateNotifier().AddOnLineObserver( this, GetExecutionContext()->GetTaskRunner(TaskType::kNetworking)); } @@ -586,15 +595,13 @@ class Document::NetworkStateObserver final void OnLineStateChange(bool on_line) override { AtomicString event_name = on_line ? event_type_names::kOnline : event_type_names::kOffline; - Document* document = To<Document>(GetExecutionContext()); - if (!document->domWindow()) - return; - document->domWindow()->DispatchEvent(*Event::Create(event_name)); - probe::NetworkStateChanged(document->GetFrame(), on_line); + auto* window = To<LocalDOMWindow>(GetExecutionContext()); + window->DispatchEvent(*Event::Create(event_name)); + probe::NetworkStateChanged(window->GetFrame(), on_line); } - void ContextDestroyed(ExecutionContext* context) override { - UnregisterAsObserver(context); + void ContextDestroyed() override { + UnregisterAsObserver(GetExecutionContext()); } void UnregisterAsObserver(ExecutionContext* context) { @@ -603,7 +610,7 @@ class Document::NetworkStateObserver final } void Trace(Visitor* visitor) override { - ContextLifecycleObserver::Trace(visitor); + ExecutionContextLifecycleObserver::Trace(visitor); } private: @@ -611,460 +618,6 @@ class Document::NetworkStateObserver final online_observer_handle_; }; -// A helper class that allows the security context be initialized in the -// process of constructing the document. -class Document::SecurityContextInit : public FeaturePolicyParserDelegate { - STACK_ALLOCATED(); - - public: - SecurityContextInit(const DocumentInit& initializer, - DocumentClassFlags document_classes) { - // Content Security Policy can provide sandbox flags. In CSP - // 'self' will be determined when the policy is bound. That occurs - // once the document is constructed. - InitializeContentSecurityPolicy(initializer, document_classes); - - // Sandbox flags can come from initializer, loader or CSP. - InitializeSandboxFlags(initializer); - - // The origin can be opaque based on sandbox flags. - InitializeOrigin(initializer); - - // The secure context state is based on the origin. - InitializeSecureContextState(initializer); - - // Initialize origin trials, requires the post sandbox flags - // security origin and secure context state. - InitializeOriginTrials(initializer); - - // Initialize feature policy, depends on origin trials. - InitializeFeaturePolicy(initializer, document_classes); - - // Initialize the agent. Depends on security origin. - InitializeAgent(initializer); - } - - const scoped_refptr<SecurityOrigin>& GetSecurityOrigin() const { - return security_origin_; - } - - WebSandboxFlags GetSandboxFlags() { return sandbox_flags_; } - - ContentSecurityPolicy* GetCSP() const { return csp_; } - - std::unique_ptr<FeaturePolicy> TakeFeaturePolicy() { - DCHECK(feature_policy_); - return std::move(feature_policy_); - } - - const Vector<String>& FeaturePolicyParseMessages() const { - return feature_policy_parse_messages_; - } - const ParsedFeaturePolicy& ParsedHeader() const { return parsed_header_; } - - OriginTrialContext* GetOriginTrialContext() { return origin_trials_; } - - WindowAgentFactory* GetWindowAgentFactory() { return window_agent_factory_; } - Agent* GetAgent() { return agent_; } - SecureContextState GetSecureContextState() { - return secure_context_state_.value(); - } - - void CountFeaturePolicyUsage(mojom::WebFeature feature) override { - feature_count_.insert(feature); - } - - bool FeaturePolicyFeatureObserved( - mojom::FeaturePolicyFeature feature) override { - if (parsed_feature_policies_.Contains(feature)) - return true; - parsed_feature_policies_.insert(feature); - return false; - } - - bool FeatureEnabled(OriginTrialFeature feature) const override { - return origin_trials_->IsFeatureEnabled(feature); - } - - void ApplyPendingDataToDocument(Document& document) { - for (auto feature : feature_count_) - UseCounter::Count(document, feature); - for (auto feature : parsed_feature_policies_) - document.FeaturePolicyFeatureObserved(feature); - } - - bool BindCSPImmediately() const { return bind_csp_immediately_; } - - private: - void InitializeContentSecurityPolicy(const DocumentInit& initializer, - DocumentClassFlags document_classes) { - auto* frame = initializer.GetFrame(); - ContentSecurityPolicy* last_origin_document_csp = - frame ? frame->Loader().GetLastOriginDocumentCSP() : nullptr; - - KURL url; - if (initializer.ShouldSetURL()) - url = initializer.Url().IsEmpty() ? BlankURL() : initializer.Url(); - - // Alias certain security properties from |owner_document|. Used for the - // case of about:blank pages inheriting the security properties of their - // requestor context. - // - // Note that this is currently somewhat broken; Blink always inherits from - // the parent or opener, even though it should actually be inherited from - // the request initiator. - if (url.IsEmpty() && initializer.HasSecurityContext() && - !initializer.OriginToCommit() && initializer.OwnerDocument()) { - last_origin_document_csp = - initializer.OwnerDocument()->GetContentSecurityPolicy(); - } - - csp_ = initializer.GetContentSecurityPolicy(); - - if (!csp_) { - if (initializer.ImportsController()) { - // If this document is an HTML import, grab a reference to its master - // document's Content Security Policy. We don't bind the CSP's delegate - // in 'InitSecurityPolicy' in this case, as we can't rebind the master - // document's policy object: The Content Security Policy's delegate - // needs to remain set to the master document. - csp_ = initializer.ImportsController() - ->Master() - ->GetContentSecurityPolicy(); - return; - } - - csp_ = MakeGarbageCollected<ContentSecurityPolicy>(); - bind_csp_immediately_ = true; - } - - // We should inherit the navigation initiator CSP if the document is loaded - // using a local-scheme url. - // - // Note: about:srcdoc inherits CSP from its parent, not from its initiator. - // In this case, the initializer.GetContentSecurityPolicy() is used. - if (last_origin_document_csp && !url.IsAboutSrcdocURL() && - (url.IsEmpty() || url.ProtocolIsAbout() || url.ProtocolIsData() || - url.ProtocolIs("blob") || url.ProtocolIs("filesystem"))) { - csp_->CopyStateFrom(last_origin_document_csp); - } - - if (document_classes & kPluginDocumentClass) { - if (last_origin_document_csp) { - csp_->CopyPluginTypesFrom(last_origin_document_csp); - return; - } - - // TODO(andypaicu): This should inherit the origin document's plugin types - // but because this could be a OOPIF document it might not have access. In - // this situation we fallback on using the parent/opener: - if (frame) { - Frame* inherit_from = frame->Tree().Parent() - ? frame->Tree().Parent() - : frame->Client()->Opener(); - if (inherit_from && frame != inherit_from) { - csp_->CopyPluginTypesFrom( - inherit_from->GetSecurityContext()->GetContentSecurityPolicy()); - } - } - } - } - - void InitializeSandboxFlags(const DocumentInit& initializer) { - sandbox_flags_ = initializer.GetSandboxFlags() | csp_->GetSandboxMask(); - auto* frame = initializer.GetFrame(); - if (frame && frame->Loader().GetDocumentLoader()->Archive()) { - // The URL of a Document loaded from a MHTML archive is controlled by - // the Content-Location header. This would allow UXSS, since - // Content-Location can be arbitrarily controlled to control the - // Document's URL and origin. Instead, force a Document loaded from a - // MHTML archive to be sandboxed, providing exceptions only for creating - // new windows. - sandbox_flags_ |= - (WebSandboxFlags::kAll & - ~(WebSandboxFlags::kPopups | - WebSandboxFlags::kPropagatesToAuxiliaryBrowsingContexts)); - } - } - - void InitializeOrigin(const DocumentInit& initializer) { - scoped_refptr<SecurityOrigin> document_origin = - initializer.GetDocumentOrigin(); - if ((sandbox_flags_ & WebSandboxFlags::kOrigin) != WebSandboxFlags::kNone) { - scoped_refptr<SecurityOrigin> sandboxed_origin = - initializer.OriginToCommit() - ? initializer.OriginToCommit() - : document_origin->DeriveNewOpaqueOrigin(); - - // If we're supposed to inherit our security origin from our - // owner, but we're also sandboxed, the only things we inherit are - // the origin's potential trustworthiness and the ability to - // load local resources. The latter lets about:blank iframes in - // file:// URL documents load images and other resources from - // the file system. - // - // Note: Sandboxed about:srcdoc iframe without "allow-same-origin" aren't - // allowed to load user's file, even if its parent can. - if (initializer.OwnerDocument()) { - if (document_origin->IsPotentiallyTrustworthy()) - sandboxed_origin->SetOpaqueOriginIsPotentiallyTrustworthy(true); - if (document_origin->CanLoadLocalResources() && - !initializer.IsSrcdocDocument()) - sandboxed_origin->GrantLoadLocalResources(); - } - security_origin_ = sandboxed_origin; - } else { - security_origin_ = document_origin; - } - - // If we are a page popup in LayoutTests ensure we use the popup - // owner's security origin so the tests can possibly access the - // document via internals API. - auto* frame = initializer.GetFrame(); - if (IsPagePopupRunningInWebTest(frame)) { - security_origin_ = frame->PagePopupOwner() - ->GetDocument() - .GetSecurityOrigin() - ->IsolatedCopy(); - } - - if (initializer.HasSecurityContext()) { - if (Settings* settings = initializer.GetSettings()) { - if (!settings->GetWebSecurityEnabled()) { - // Web security is turned off. We should let this document access - // every other document. This is used primary by testing harnesses for - // web sites. - security_origin_->GrantUniversalAccess(); - } else if (security_origin_->IsLocal()) { - if (settings->GetAllowUniversalAccessFromFileURLs()) { - // Some clients want local URLs to have universal access, but that - // setting is dangerous for other clients. - security_origin_->GrantUniversalAccess(); - } else if (!settings->GetAllowFileAccessFromFileURLs()) { - // Some clients do not want local URLs to have access to other local - // URLs. - security_origin_->BlockLocalAccessFromLocalOrigin(); - } - } - } - } - - if (initializer.GrantLoadLocalResources()) - security_origin_->GrantLoadLocalResources(); - - if (security_origin_->IsOpaque() && initializer.ShouldSetURL()) { - KURL url = initializer.Url().IsEmpty() ? BlankURL() : initializer.Url(); - if (SecurityOrigin::Create(url)->IsPotentiallyTrustworthy()) - security_origin_->SetOpaqueOriginIsPotentiallyTrustworthy(true); - } - } - - void InitializeFeaturePolicy(const DocumentInit& initializer, - DocumentClassFlags document_classes) { - auto* frame = initializer.GetFrame(); - // For a main frame, get inherited feature policy from the opener if any. - const FeaturePolicy::FeatureState* opener_feature_state = nullptr; - if (frame && frame->IsMainFrame() && !frame->OpenerFeatureState().empty()) { - opener_feature_state = &frame->OpenerFeatureState(); - } - - parsed_header_ = FeaturePolicyParser::ParseHeader( - initializer.FeaturePolicyHeader(), security_origin_, - &feature_policy_parse_messages_, this); - - if (sandbox_flags_ != WebSandboxFlags::kNone && - RuntimeEnabledFeatures::FeaturePolicyForSandboxEnabled()) { - // The sandbox flags might have come from CSP header or the browser; in - // such cases the sandbox is not part of the container policy. They are - // added to the header policy (which specifically makes sense in the case - // of CSP sandbox). - ApplySandboxFlagsToParsedFeaturePolicy(sandbox_flags_, parsed_header_); - } - - ParsedFeaturePolicy container_policy; - - if (frame && frame->Owner()) { - // TODO(chenleihu): Due to the data replication mechanism in - // multi-process site-per-process environment, the container_policy - // value in remote frame owner gets lazily updated only when the next - // navigation is initiated on the remote frame. We need a more robust way - // to enforce the validity of container_policy value. - // https://crbug.com/972089 - if (frame->Owner()->IsRemote()) { - container_policy = frame->Owner()->GetFramePolicy().container_policy; - } else { - container_policy = initializer.GetFramePolicy() - .value_or(FramePolicy()) - .container_policy; - } - } - - // TODO(icelland): This is problematic querying sandbox flags before - // feature policy is initialized. - if (RuntimeEnabledFeatures::BlockingFocusWithoutUserActivationEnabled() && - frame && frame->Tree().Parent() && - (sandbox_flags_ & WebSandboxFlags::kNavigation) != - WebSandboxFlags::kNone) { - // Enforcing the policy for sandbox frames (for context see - // https://crbug.com/954349). - DisallowFeatureIfNotPresent( - mojom::FeaturePolicyFeature::kFocusWithoutUserActivation, - container_policy); - } - - const FeaturePolicy* parent_feature_policy = nullptr; - if (frame && !frame->IsMainFrame()) { - parent_feature_policy = - frame->Tree().Parent()->GetSecurityContext()->GetFeaturePolicy(); - } - - // If we are a HTMLViewSourceDocument we use container, header or - // inherited policies. https://crbug.com/898688 - if (document_classes & kViewSourceDocumentClass) { - feature_policy_ = FeaturePolicy::CreateFromParentPolicy( - nullptr, {}, security_origin_->ToUrlOrigin()); - return; - } - - // Feature policy should either come from a parent in the case of an - // embedded child frame, or from an opener if any when a new window is - // created by an opener. A main frame without an opener would not have a - // parent policy nor an opener feature state. - DCHECK(!parent_feature_policy || !opener_feature_state); - if (!opener_feature_state || - !RuntimeEnabledFeatures::FeaturePolicyForSandboxEnabled()) { - feature_policy_ = FeaturePolicy::CreateFromParentPolicy( - parent_feature_policy, container_policy, - security_origin_->ToUrlOrigin()); - } else { - DCHECK(!parent_feature_policy); - feature_policy_ = FeaturePolicy::CreateWithOpenerPolicy( - *opener_feature_state, security_origin_->ToUrlOrigin()); - } - feature_policy_->SetHeaderPolicy(parsed_header_); - } - - void InitializeSecureContextState(const DocumentInit& initializer) { - auto* frame = initializer.GetFrame(); - if (!security_origin_->IsPotentiallyTrustworthy()) { - secure_context_state_ = SecureContextState::kNonSecure; - } else if (SchemeRegistry::SchemeShouldBypassSecureContextCheck( - security_origin_->Protocol())) { - secure_context_state_ = SecureContextState::kSecure; - } else if (frame) { - Frame* parent = frame->Tree().Parent(); - while (parent) { - if (!parent->GetSecurityContext() - ->GetSecurityOrigin() - ->IsPotentiallyTrustworthy()) { - secure_context_state_ = SecureContextState::kNonSecure; - break; - } - parent = parent->Tree().Parent(); - } - if (!secure_context_state_.has_value()) - secure_context_state_ = SecureContextState::kSecure; - } else { - secure_context_state_ = SecureContextState::kNonSecure; - } - bool is_secure = secure_context_state_ == SecureContextState::kSecure; - if (GetSandboxFlags() != WebSandboxFlags::kNone) { - feature_count_.insert( - is_secure ? WebFeature::kSecureContextCheckForSandboxedOriginPassed - : WebFeature::kSecureContextCheckForSandboxedOriginFailed); - } - feature_count_.insert(is_secure ? WebFeature::kSecureContextCheckPassed - : WebFeature::kSecureContextCheckFailed); - } - - void InitializeOriginTrials(const DocumentInit& initializer) { - DCHECK(secure_context_state_.has_value()); - origin_trials_ = MakeGarbageCollected<OriginTrialContext>(); - - const String& header_value = initializer.OriginTrialsHeader(); - - if (header_value.IsEmpty()) - return; - std::unique_ptr<Vector<String>> tokens( - OriginTrialContext::ParseHeaderValue(header_value)); - if (!tokens) - return; - origin_trials_->AddTokens( - security_origin_.get(), - secure_context_state_ == SecureContextState::kSecure /*is_secure*/, - *tokens); - } - - void InitializeAgent(const DocumentInit& initializer) { - auto* frame = initializer.GetFrame(); - - // If we are a page popup in LayoutTests ensure we use the popup - // owner's frame for looking up the Agent so the tests can possibly - // access the document via internals API. - if (IsPagePopupRunningInWebTest(frame)) { - frame = frame->PagePopupOwner()->GetDocument().GetFrame(); - } else if (!frame) { - if (Document* context_document = initializer.ContextDocument()) { - frame = context_document->GetFrame(); - window_agent_factory_ = context_document->window_agent_factory_; - } else if (const Document* owner_document = initializer.OwnerDocument()) { - frame = owner_document->GetFrame(); - window_agent_factory_ = owner_document->window_agent_factory_; - } - } - - if (!window_agent_factory_ && frame) - window_agent_factory_ = &frame->window_agent_factory(); - - // If we are allowed to share our document with other windows then we need - // to look at the window agent factory, otherwise we should create our own - // window agent. - if (window_agent_factory_) { - bool has_potential_universal_access_privilege = false; - if (frame) { - if (Settings* settings = frame->GetSettings()) { - // TODO(keishi): Also check if AllowUniversalAccessFromFileURLs might - // dynamically change. - if (!settings->GetWebSecurityEnabled() || - settings->GetAllowUniversalAccessFromFileURLs()) - has_potential_universal_access_privilege = true; - } - } - agent_ = window_agent_factory_->GetAgentForOrigin( - has_potential_universal_access_privilege, - V8PerIsolateData::MainThreadIsolate(), security_origin_.get()); - } else { - // ContextDocument is null only for Documents created in unit tests. - // In that case, use a throw away WindowAgent. - agent_ = MakeGarbageCollected<WindowAgent>( - V8PerIsolateData::MainThreadIsolate()); - } - - // Derive possibly a new security origin that contains the cluster id. - security_origin_ = - security_origin_->GetOriginForAgentCluster(agent_->cluster_id()); - } - - bool IsPagePopupRunningInWebTest(LocalFrame* frame) { - return frame && frame->GetPage()->GetChromeClient().IsPopup() && - WebTestSupport::IsRunningWebTest(); - } - - scoped_refptr<SecurityOrigin> security_origin_; - WebSandboxFlags sandbox_flags_ = WebSandboxFlags::kNone; - std::unique_ptr<FeaturePolicy> feature_policy_; - Vector<String> feature_policy_parse_messages_; - ParsedFeaturePolicy parsed_header_; - Member<ContentSecurityPolicy> csp_; - Member<OriginTrialContext> origin_trials_; - Member<Agent> agent_; - Member<WindowAgentFactory> window_agent_factory_; - HashSet<mojom::FeaturePolicyFeature> parsed_feature_policies_; - HashSet<mojom::WebFeature> feature_count_; - bool bind_csp_immediately_ = false; - base::Optional<SecureContextState> secure_context_state_; -}; - ExplicitlySetAttrElementsMap* Document::GetExplicitlySetAttrElementsMap( Element* element) { DCHECK(element); @@ -1093,28 +646,24 @@ Document::Document() : Document(DocumentInit::Create()) {} Document::Document(const DocumentInit& initializer, DocumentClassFlags document_classes) : Document(initializer, - SecurityContextInit(initializer, document_classes), + SecurityContextInit(initializer), document_classes) {} Document::Document(const DocumentInit& initializer, - SecurityContextInit security_initializer, + const SecurityContextInit& security_initializer, DocumentClassFlags document_classes) : ContainerNode(nullptr, kCreateDocument), TreeScope(*this), - SecurityContext(security_initializer.GetSecurityOrigin(), - security_initializer.GetSandboxFlags(), - security_initializer.TakeFeaturePolicy()), - ExecutionContext(V8PerIsolateData::MainThreadIsolate(), - security_initializer.GetAgent(), - security_initializer.GetOriginTrialContext()), evaluate_media_queries_on_style_recalc_(false), pending_sheet_layout_(kNoLayoutWithPendingSheets), - window_agent_factory_(security_initializer.GetWindowAgentFactory()), + window_agent_factory_(initializer.GetWindowAgentFactory()), frame_(initializer.GetFrame()), // TODO(dcheng): Why does this need both a LocalFrame and LocalDOMWindow // pointer? dom_window_(frame_ ? frame_->DomWindow() : nullptr), imports_controller_(initializer.ImportsController()), + security_context_(security_initializer, SecurityContext::kLocal), + use_counter_during_construction_(initializer.GetUseCounter()), context_document_(initializer.ContextDocument()), context_features_(ContextFeatures::DefaultSwitch()), http_refresh_scheduler_(MakeGarbageCollected<HttpRefreshScheduler>(this)), @@ -1123,7 +672,7 @@ Document::Document(const DocumentInit& initializer, is_painting_preview_(false), compatibility_mode_(kNoQuirksMode), compatibility_mode_locked_(false), - last_focus_type_(kWebFocusTypeNone), + last_focus_type_(mojom::blink::FocusType::kNone), had_keyboard_event_(false), clear_focused_element_timer_( GetTaskRunner(TaskType::kInternalUserInteraction), @@ -1135,7 +684,17 @@ Document::Document(const DocumentInit& initializer, mutation_observer_types_(0), visited_link_state_(MakeGarbageCollected<VisitedLinkState>(*this)), visually_ordered_(false), - ready_state_(kComplete), + // https://html.spec.whatwg.org/multipage/dom.html#current-document-readiness + // says the ready state starts as 'loading' if there's an associated + // parser and 'complete' otherwise. We don't know whether there's an + // associated parser here (we create the parser in ImplicitOpen). But + // waiting to set the ready state to 'loading' in ImplicitOpen fires a + // readystatechange event, which can be observed in the case where we + // reuse a window. If there's a window being reused, then there must be + // a frame, and if there's a frame, there must be an associated parser, so + // setting based on frame_ here is sufficient to ensure that the quirk of + // when we set the ready state is not web-observable. + ready_state_(frame_ ? kLoading : kComplete), parsing_state_(kFinishedParsing), contains_plugins_(false), ignore_destructive_write_count_(0), @@ -1175,12 +734,15 @@ Document::Document(const DocumentInit& initializer, document_timing_(*this), write_recursion_is_too_deep_(false), write_recursion_depth_(0), + scripted_animation_controller_( + MakeGarbageCollected<ScriptedAnimationController>(domWindow())), current_frame_is_throttled_(false), registration_context_(initializer.RegistrationContext(this)), element_data_cache_clear_timer_( GetTaskRunner(TaskType::kInternalUserInteraction), this, &Document::ElementDataCacheClearTimerFired), + document_animations_(MakeGarbageCollected<DocumentAnimations>(this)), timeline_(MakeGarbageCollected<DocumentTimeline>(this)), pending_animations_(MakeGarbageCollected<PendingAnimations>(*this)), worklet_animation_controller_( @@ -1194,14 +756,23 @@ Document::Document(const DocumentInit& initializer, parser_sync_policy_(kAllowAsynchronousParsing), node_count_(0), logged_field_edit_(false), - secure_context_state_(security_initializer.GetSecureContextState()), ukm_source_id_(ukm::UkmRecorder::GetNewSourceID()), needs_to_record_ukm_outlive_time_(false), viewport_data_(MakeGarbageCollected<ViewportData>(*this)), + is_for_external_handler_(initializer.IsForExternalHandler()), isolated_world_csp_map_( MakeGarbageCollected< - HeapHashMap<int, Member<ContentSecurityPolicy>>>()) { + HeapHashMap<int, Member<ContentSecurityPolicy>>>()), + permission_service_(GetExecutionContext()), + font_preload_manager_(*this) { security_initializer.ApplyPendingDataToDocument(*this); + GetOriginTrialContext()->BindExecutionContext(GetExecutionContext()); + + if (frame_) { + pending_fp_headers_ = security_initializer.FeaturePolicyHeader(); + pending_dp_headers_ = initializer.GetDocumentPolicy().feature_state; + } + if (frame_) { DCHECK(frame_->GetPage()); ProvideContextFeaturesToDocumentFrom(*this, *frame_->GetPage()); @@ -1213,11 +784,7 @@ Document::Document(const DocumentInit& initializer, : nullptr; if (registry && registration_context_) registry->Entangle(registration_context_); - cookie_jar_ = std::make_unique<CookieJar>(this); - } else if (imports_controller_ && - !base::FeatureList::IsEnabled( - features::kHtmlImportsRequestInitiatorLock)) { - fetcher_ = FrameFetchContext::CreateFetcherForImportedDocument(this); + cookie_jar_ = MakeGarbageCollected<CookieJar>(this); } else { // We disable fetches for frame-less Documents, including HTML-imported // Documents (if kHtmlImportsRequestInitiatorLock is enabled). Subresources @@ -1253,15 +820,21 @@ Document::Document(const DocumentInit& initializer, UpdateBaseURL(); } - InitSecurityContext(initializer, security_initializer); - FeaturePolicyInitialized(initializer, security_initializer); + if (initializer.GetWebBundleClaimedUrl().IsValid()) { + web_bundle_claimed_url_ = initializer.GetWebBundleClaimedUrl(); + SetBaseURLOverride(initializer.GetWebBundleClaimedUrl()); + } + InitSecurityContext(initializer); + PoliciesInitialized(initializer); InitDNSPrefetch(); InstanceCounters::IncrementCounter(InstanceCounters::kDocumentCounter); lifecycle_.AdvanceTo(DocumentLifecycle::kInactive); + UpdateForcedColors(); + // Since CSSFontSelector requires Document::fetcher_ and StyleEngine owns // CSSFontSelector, need to initialize |style_engine_| after initializing // |fetcher_|. @@ -1279,6 +852,9 @@ Document::Document(const DocumentInit& initializer, if (frame_ && frame_->GetPage()->GetAgentMetricsCollector()) frame_->GetPage()->GetAgentMetricsCollector()->DidAttachDocument(*this); + + // We will use Loader() as UseCounter after initialization. + use_counter_during_construction_ = nullptr; } Document::~Document() { @@ -1319,8 +895,8 @@ MediaQueryMatcher& Document::GetMediaQueryMatcher() { return *media_query_matcher_; } -void Document::MediaQueryAffectingValueChanged() { - GetStyleEngine().MediaQueryAffectingValueChanged(); +void Document::MediaQueryAffectingValueChanged(MediaValueChange change) { + GetStyleEngine().MediaQueryAffectingValueChanged(change); if (NeedsLayoutTreeUpdate()) evaluate_media_queries_on_style_recalc_ = true; else @@ -1372,12 +948,10 @@ Location* Document::location() const { return domWindow()->location(); } -bool Document::ShouldInstallV8Extensions() const { - return frame_->Client()->AllowScriptExtensions(); -} - ContentSecurityPolicy* Document::GetContentSecurityPolicyForWorld() { v8::Isolate* isolate = GetIsolate(); + if (!isolate) + return GetContentSecurityPolicy(); v8::HandleScope handle_scope(isolate); v8::Local<v8::Context> v8_context = isolate->GetCurrentContext(); @@ -1404,6 +978,161 @@ ContentSecurityPolicy* Document::GetContentSecurityPolicyForWorld() { return policy; } +// static +Document& Document::From(ExecutionContext& context) { + SECURITY_DCHECK(context.IsDocument()); + return *static_cast<LocalDOMWindow&>(context).document(); +} + +// static +const Document& Document::From(const ExecutionContext& context) { + SECURITY_DCHECK(context.IsDocument()); + return *static_cast<const LocalDOMWindow&>(context).document(); +} + +ExecutionContext* Document::ToExecutionContext() { + return GetExecutionContext(); +} + +const ExecutionContext* Document::ToExecutionContext() const { + return GetExecutionContext(); +} + +bool Document::FeatureEnabled(OriginTrialFeature feature) const { + return GetOriginTrialContext()->IsFeatureEnabled(feature); +} + +void Document::CountFeaturePolicyUsage(mojom::WebFeature feature) { + UseCounter::Count(*this, feature); +} + +bool Document::FeaturePolicyFeatureObserved( + mojom::blink::FeaturePolicyFeature feature) { + wtf_size_t feature_index = static_cast<wtf_size_t>(feature); + if (parsed_feature_policies_.size() == 0) { + parsed_feature_policies_.resize( + static_cast<wtf_size_t>(mojom::blink::FeaturePolicyFeature::kMaxValue) + + 1); + } else if (parsed_feature_policies_[feature_index]) { + return true; + } + parsed_feature_policies_[feature_index] = true; + return false; +} + +const SecurityOrigin* Document::GetSecurityOrigin() const { + return GetSecurityContext().GetSecurityOrigin(); +} + +SecurityOrigin* Document::GetMutableSecurityOrigin() { + return GetSecurityContext().GetMutableSecurityOrigin(); +} + +ContentSecurityPolicy* Document::GetContentSecurityPolicy() const { + return GetSecurityContext().GetContentSecurityPolicy(); +} + +mojom::blink::WebSandboxFlags Document::GetSandboxFlags() const { + return GetSecurityContext().GetSandboxFlags(); +} + +bool Document::IsSandboxed(mojom::blink::WebSandboxFlags mask) const { + return GetSecurityContext().IsSandboxed(mask); +} + +PublicURLManager& Document::GetPublicURLManager() { + DCHECK(GetExecutionContext()); + return GetExecutionContext()->GetPublicURLManager(); +} + +bool Document::IsContextPaused() const { + return GetExecutionContext() ? GetExecutionContext()->IsContextPaused() + : false; +} + +bool Document::IsContextDestroyed() const { + return GetExecutionContext() ? GetExecutionContext()->IsContextDestroyed() + : true; +} + +ContentSecurityPolicyDelegate& Document::GetContentSecurityPolicyDelegate() { + return GetExecutionContext()->GetContentSecurityPolicyDelegate(); +} + +SecureContextMode Document::GetSecureContextMode() const { + return GetSecurityContext().GetSecureContextMode(); +} + +bool Document::IsSecureContext() const { + return GetExecutionContext()->IsSecureContext(); +} + +bool Document::IsSecureContext(String& error_message) const { + return GetExecutionContext()->IsSecureContext(error_message); +} + +void Document::SetReferrerPolicy(network::mojom::ReferrerPolicy policy) { + GetExecutionContext()->SetReferrerPolicy(policy); +} + +v8::Isolate* Document::GetIsolate() const { + return GetExecutionContext() ? GetExecutionContext()->GetIsolate() : nullptr; +} + +Agent* Document::GetAgent() const { + return GetSecurityContext().GetAgent(); +} + +OriginTrialContext* Document::GetOriginTrialContext() const { + return MasterDocument().GetSecurityContext().GetOriginTrialContext(); +} + +void Document::SetSecureContextModeForTesting(SecureContextMode mode) { + GetSecurityContext().SetSecureContextModeForTesting(mode); +} + +bool Document::IsFeatureEnabled(mojom::blink::FeaturePolicyFeature feature, + ReportOptions report_on_failure, + const String& message, + const String& source_file) const { + return GetExecutionContext() && + GetExecutionContext()->IsFeatureEnabled(feature, report_on_failure, + message, source_file); +} + +bool Document::IsFeatureEnabled(mojom::blink::FeaturePolicyFeature feature, + PolicyValue threshold_value, + ReportOptions report_on_failure, + const String& message, + const String& source_file) const { + return GetExecutionContext() && + GetExecutionContext()->IsFeatureEnabled( + feature, threshold_value, report_on_failure, message, source_file); +} + +bool Document::IsFeatureEnabled(mojom::blink::DocumentPolicyFeature feature, + ReportOptions report_option, + const String& message, + const String& source_file) const { + return GetExecutionContext() && + GetExecutionContext()->IsFeatureEnabled(feature, report_option, + message, source_file); +} + +bool Document::IsFeatureEnabled(mojom::blink::DocumentPolicyFeature feature, + PolicyValue threshold_value, + ReportOptions report_option, + const String& message, + const String& source_file) const { + return GetExecutionContext() && + GetExecutionContext()->IsFeatureEnabled( + feature, threshold_value, report_option, message, source_file); +} + +String Document::addressSpaceForBindings() const { + return GetExecutionContext()->addressSpaceForBindings(); +} + void Document::ChildrenChanged(const ChildrenChange& change) { ContainerNode::ChildrenChanged(change); document_element_ = ElementTraversal::FirstWithin(*this); @@ -1413,7 +1142,7 @@ void Document::ChildrenChanged(const ChildrenChange& change) { // documents there may never be a <body> (since the parser won't always // insert one), so we resume here too. That does mean XHTML documents make // frames when there's only a <head>, but such documents are pretty rare. - if (document_element_ && !IsHTMLDocument()) + if (document_element_ && !IsA<HTMLDocument>(this)) BeginLifecycleUpdatesIfRenderingReady(); } @@ -1430,7 +1159,7 @@ bool Document::IsInMainFrame() const { } AtomicString Document::ConvertLocalName(const AtomicString& name) { - return IsHTMLDocument() ? name.LowerASCII() : name; + return IsA<HTMLDocument>(this) ? name.LowerASCII() : name; } // Just creates an element with specified qualified name without any @@ -1463,10 +1192,11 @@ Element* Document::CreateRawElement(const QualifiedName& qname, } else if (RuntimeEnabledFeatures::MathMLCoreEnabled() && qname.NamespaceURI() == mathml_names::kNamespaceURI) { element = MathMLElementFactory::Create(qname.LocalName(), *this, flags); + // An unknown MathML element is treated like an <mrow> element. // TODO(crbug.com/1021837): Determine if we need to introduce a - // MathMLUnknownClass. + // MathMLUnknownElement IDL. if (!element) - element = MakeGarbageCollected<MathMLElement>(qname, *this); + element = MakeGarbageCollected<MathMLRowElement>(qname, *this); saw_elements_in_known_namespaces_ = true; } else { element = MakeGarbageCollected<Element>(qname, this); @@ -1489,7 +1219,7 @@ Element* Document::CreateElementForBinding(const AtomicString& name, return nullptr; } - if (IsXHTMLDocument() || IsHTMLDocument()) { + if (IsXHTMLDocument() || IsA<HTMLDocument>(this)) { // 2. If the context object is an HTML document, let localName be // converted to ASCII lowercase. AtomicString local_name = ConvertLocalName(name); @@ -1554,7 +1284,7 @@ Element* Document::CreateElementForBinding( // 2. localName converted to ASCII lowercase const AtomicString& converted_local_name = ConvertLocalName(local_name); QualifiedName q_name(g_null_atom, converted_local_name, - IsXHTMLDocument() || IsHTMLDocument() + IsXHTMLDocument() || IsA<HTMLDocument>(this) ? html_names::xhtmlNamespaceURI : g_null_atom); @@ -1798,7 +1528,7 @@ Comment* Document::createComment(const String& data) { CDATASection* Document::createCDATASection(const String& data, ExceptionState& exception_state) { - if (IsHTMLDocument()) { + if (IsA<HTMLDocument>(this)) { exception_state.ThrowDOMException( DOMExceptionCode::kNotSupportedError, "This operation is not supported for HTML documents."); @@ -1830,7 +1560,7 @@ ProcessingInstruction* Document::createProcessingInstruction( "The data provided ('" + data + "') contains '?>'."); return nullptr; } - if (IsHTMLDocument()) { + if (IsA<HTMLDocument>(this)) { UseCounter::Count(*this, WebFeature::kHTMLDocumentCreateProcessingInstruction); } @@ -1910,7 +1640,7 @@ Node* Document::adoptNode(Node* source, ExceptionState& exception_state) { return nullptr; // The above removeChild() can execute arbitrary JavaScript code. if (source->parentNode()) { - AddConsoleMessage(ConsoleMessage::Create( + AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( mojom::ConsoleMessageSource::kJavaScript, mojom::ConsoleMessageLevel::kWarning, ExceptionMessages::FailedToExecute("adoptNode", "Document", @@ -2049,7 +1779,7 @@ void Document::SetContent(const String& content) { } String Document::SuggestedMIMEType() const { - if (IsXMLDocument()) { + if (IsA<XMLDocument>(this)) { if (IsXHTMLDocument()) return "application/xhtml+xml"; if (IsSVGDocument()) @@ -2058,7 +1788,7 @@ String Document::SuggestedMIMEType() const { } if (xmlStandalone()) return "text/xml"; - if (IsHTMLDocument()) + if (IsA<HTMLDocument>(this)) return "text/html"; if (DocumentLoader* document_loader = Loader()) @@ -2197,6 +1927,11 @@ void Document::UpdateTitle(const String& title) { } void Document::DispatchDidReceiveTitle() { + if (GetFrame() && !GetFrame()->Tree().Parent()) { + String shortened_title = title_.Substring(0, mojom::blink::kMaxTitleChars); + GetFrame()->GetLocalFrameHostRemote().UpdateTitle( + shortened_title, mojo_base::mojom::blink::TextDirection::LEFT_TO_RIGHT); + } frame_->Client()->DispatchDidReceiveTitle(title_); } @@ -2256,7 +1991,7 @@ void Document::RemoveTitle(Element* title_element) { title_element_ = nullptr; // Update title based on first title element in the document, if one exists. - if (IsHTMLDocument() || IsXHTMLDocument()) { + if (IsA<HTMLDocument>(this) || IsXHTMLDocument()) { if (HTMLTitleElement* title = Traversal<HTMLTitleElement>::FirstWithin(*this)) SetTitleElement(title); @@ -2450,7 +2185,7 @@ bool Document::NeedsFullLayoutTreeUpdate() const { return true; if (IsSlotAssignmentOrLegacyDistributionDirty()) return true; - if (DocumentAnimations::NeedsAnimationTimingUpdate(*this)) + if (document_animations_->NeedsAnimationTimingUpdate()) return true; return false; } @@ -2476,6 +2211,11 @@ void Document::ScheduleLayoutTreeUpdate() { if (!View()->CanThrottleRendering()) GetPage()->Animator().ScheduleVisualUpdate(GetFrame()); + + // FrameSelection caches visual selection information, which must be + // invalidated on dirty layout tree. + GetFrame()->Selection().MarkCacheDirty(); + lifecycle_.EnsureStateAtMost(DocumentLifecycle::kVisualUpdatePending); TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), @@ -2503,8 +2243,7 @@ void Document::UpdateStyleInvalidationIfNeeded() { void Document::SetupFontBuilder(ComputedStyle& document_style) { FontBuilder font_builder(this); - CSSFontSelector* selector = GetStyleEngine().GetFontSelector(); - font_builder.CreateFontForDocument(selector, document_style); + font_builder.CreateFontForDocument(document_style); } #define PROPAGATE_FROM(source, getter, setter, initial) \ @@ -2714,9 +2453,9 @@ void Document::PropagateStyleToViewport() { // Misc { PROPAGATE_FROM(document_element_style, GetEffectiveTouchAction, - SetEffectiveTouchAction, TouchAction::kTouchActionAuto); + SetEffectiveTouchAction, TouchAction::kAuto); PROPAGATE_FROM(document_element_style, GetScrollBehavior, SetScrollBehavior, - kScrollBehaviorAuto); + mojom::blink::ScrollBehavior::kAuto); PROPAGATE_FROM(document_element_style, DarkColorScheme, SetDarkColorScheme, false); } @@ -2746,27 +2485,43 @@ void Document::PropagateStyleToViewport() { #undef PROPAGATE_FROM #if DCHECK_IS_ON() +static void AssertNodeClean(const Node& node) { + DCHECK(!node.NeedsStyleRecalc()); + DCHECK(!node.ChildNeedsStyleRecalc()); + DCHECK(!node.NeedsReattachLayoutTree()); + DCHECK(!node.ChildNeedsReattachLayoutTree()); + DCHECK(!node.ChildNeedsDistributionRecalc()); + DCHECK(!node.NeedsStyleInvalidation()); + DCHECK(!node.ChildNeedsStyleInvalidation()); + DCHECK(!node.GetForceReattachLayoutTree()); +} + +static void AssertLayoutTreeUpdatedForPseudoElements(const Element& element) { + WTF::Vector<PseudoId> pseudo_ids = {kPseudoIdFirstLetter, kPseudoIdBefore, + kPseudoIdAfter, kPseudoIdMarker, + kPseudoIdBackdrop}; + for (auto pseudo_id : pseudo_ids) { + if (auto* pseudo_element = element.GetPseudoElement(pseudo_id)) + AssertNodeClean(*pseudo_element); + } +} + static void AssertLayoutTreeUpdated(Node& root) { Node* node = &root; while (node) { - auto* element = DynamicTo<Element>(node); - if (element && - RuntimeEnabledFeatures::DisplayLockingEnabled( - root.GetExecutionContext()) && - element->StyleRecalcBlockedByDisplayLock( - DisplayLockLifecycleTarget::kChildren)) { - node = FlatTreeTraversal::NextSkippingChildren(*node); - continue; + if (auto* element = DynamicTo<Element>(node)) { + if (RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() && + element->StyleRecalcBlockedByDisplayLock( + DisplayLockLifecycleTarget::kChildren)) { + node = FlatTreeTraversal::NextSkippingChildren(*node); + continue; + } + // Check pseudo elements. + AssertLayoutTreeUpdatedForPseudoElements(*element); } - DCHECK(!node->NeedsStyleRecalc()); - DCHECK(!node->ChildNeedsStyleRecalc()); - DCHECK(!node->NeedsReattachLayoutTree()); - DCHECK(!node->ChildNeedsReattachLayoutTree()); - DCHECK(!node->ChildNeedsDistributionRecalc()); - DCHECK(!node->NeedsStyleInvalidation()); - DCHECK(!node->ChildNeedsStyleInvalidation()); - DCHECK(!node->GetForceReattachLayoutTree()); + AssertNodeClean(*node); + // Make sure there is no node which has a LayoutObject, but doesn't have a // parent in a flat tree. If there is such a node, we forgot to detach the // node. DocumentNode is only an exception. @@ -2845,13 +2600,14 @@ void Document::UpdateStyleAndLayoutTree() { probe::RecalculateStyle recalculate_style_scope(this); - DocumentAnimations::UpdateAnimationTimingIfNeeded(*this); + document_animations_->UpdateAnimationTimingIfNeeded(); EvaluateMediaQueryListIfNeeded(); UpdateUseShadowTreesIfNeeded(); UpdateDistributionForLegacyDistributedNodes(); UpdateActiveStyle(); + InvalidateStyleAndLayoutForFontUpdates(); UpdateStyleInvalidationIfNeeded(); UpdateStyle(); @@ -2861,7 +2617,7 @@ void Document::UpdateStyleAndLayoutTree() { ClearFocusedElementSoon(); GetLayoutView()->ClearHitTestCache(); - DCHECK(!DocumentAnimations::NeedsAnimationTimingUpdate(*this)); + DCHECK(!document_animations_->NeedsAnimationTimingUpdate()); unsigned element_count = GetStyleEngine().StyleForElementCount() - start_element_count; @@ -2881,6 +2637,12 @@ void Document::UpdateActiveStyle() { GetStyleEngine().UpdateActiveStyle(); } +void Document::InvalidateStyleAndLayoutForFontUpdates() { + DCHECK(IsActive()); + DCHECK(IsMainThread()); + GetStyleEngine().InvalidateStyleAndLayoutForFontUpdates(); +} + void Document::UpdateStyle() { DCHECK(!View()->ShouldThrottleRendering()); TRACE_EVENT_BEGIN0("blink,blink_style", "Document::updateStyle"); @@ -3024,20 +2786,127 @@ void Document::UpdateStyleAndLayoutTreeForSubtree(const Node* node) { } } -void Document::UpdateStyleAndLayoutForNode(const Node* node) { +void Document::UpdateStyleAndLayoutForNode(const Node* node, + DocumentUpdateReason reason) { DCHECK(node); if (!node->InActiveDocument()) return; DisplayLockUtilities::ScopedChainForcedUpdate scoped_update_forced(node); - UpdateStyleAndLayout(); + UpdateStyleAndLayout(reason); } -void Document::UpdateStyleAndLayout(ForcedLayoutStatus status) { +void Document::ApplyScrollRestorationLogic() { + // This function in not re-entrant. However, the places that invoke this are + // re-entrant. Specifically, UpdateStyleAndLayout() calls this, which in turn + // can do a find-in-page for the scroll-to-text feature, which can cause + // UpdateStyleAndLayout to happen with subtree-visibility, which gets back here + // and recurses indefinitely. As a result, we ensure to early out from this + // function if are currently in process of restoring scroll. + if (applying_scroll_restoration_logic_) + return; + base::AutoReset<bool> applying_scroll_restoration_logic_scope( + &applying_scroll_restoration_logic_, true); + + // If we're restoring a scroll position from history, that takes precedence + // over scrolling to the anchor in the URL. + View()->InvokeFragmentAnchor(); + + auto& frame_loader = GetFrame()->Loader(); + auto* document_loader = frame_loader.GetDocumentLoader(); + if (!document_loader) + return; + if (frame_->IsLoading() && + !FrameLoader::NeedsHistoryItemRestore(document_loader->LoadType())) + return; + + auto* history_item = document_loader->GetHistoryItem(); + + if (!history_item || !history_item->GetViewState()) + return; + + if (!View()->GetScrollableArea()->HasPendingHistoryRestoreScrollOffset()) + return; + + bool should_restore_scroll = + history_item->ScrollRestorationType() != kScrollRestorationManual; + auto& scroll_offset = history_item->GetViewState()->scroll_offset_; + + // This tries to balance: + // 1. restoring as soon as possible. + // 2. not overriding user scroll (TODO(majidvp): also respect user scale). + // 3. detecting clamping to avoid repeatedly popping the scroll position + // down + // as the page height increases. + // 4. ignoring clamp detection if scroll state is not being restored, if + // load + // is complete, or if the navigation is same-document (as the new page + // may be smaller than the previous page). + bool can_restore_without_clamping = + View()->LayoutViewport()->ClampScrollOffset(scroll_offset) == + scroll_offset; + + bool can_restore_without_annoying_user = + !document_loader->GetInitialScrollState().was_scrolled_by_user && + (can_restore_without_clamping || !frame_->IsLoading() || + !should_restore_scroll); + if (!can_restore_without_annoying_user) + return; + + // Apply scroll restoration to the LayoutView's scroller. Note that we do + // *not* apply it to the RootFrameViewport's LayoutViewport, because that + // may be for child frame's implicit root scroller, which is not the right + // one to apply to because scroll restoration does not affect implicit root + // scrollers. + auto* layout_scroller = View()->LayoutViewport(); + layout_scroller->ApplyPendingHistoryRestoreScrollOffset(); + + // Also apply restoration to the visual viewport of the root frame, if needed. + auto* root_frame_scroller = View()->GetScrollableArea(); + if (root_frame_scroller != layout_scroller) + root_frame_scroller->ApplyPendingHistoryRestoreScrollOffset(); + + document_loader->GetInitialScrollState().did_restore_from_history = true; +} + +void Document::MarkHasFindInPageRequest() { + // Note that although find-in-page requests happen in non-main frames, we only + // record the main frame results (per UKM policy). Additionally, we only + // record the event once. + if (had_find_in_page_request_ || !IsInMainFrame()) + return; + + auto* recorder = UkmRecorder(); + DCHECK(recorder); + DCHECK(UkmSourceID() != ukm::kInvalidSourceId); + ukm::builders::Blink_FindInPage(UkmSourceID()) + .SetDidSearch(true) + .Record(recorder); + had_find_in_page_request_ = true; +} + +void Document::MarkHasFindInPageSubtreeVisibilityActiveMatch() { + // Note that although find-in-page in subtree-visibility requests happen in + // non-main frames, we only record the main frame results (per UKM policy). + // Additionally, we only record the event once. + if (had_find_in_page_render_subtree_active_match_ || !IsInMainFrame()) + return; + + auto* recorder = UkmRecorder(); + DCHECK(recorder); + DCHECK(UkmSourceID() != ukm::kInvalidSourceId); + // TODO(vmpstr): Rename UKM values if possible. + ukm::builders::Blink_FindInPage(UkmSourceID()) + .SetDidHaveRenderSubtreeMatch(true) + .Record(recorder); + had_find_in_page_render_subtree_active_match_ = true; +} + +void Document::UpdateStyleAndLayout(DocumentUpdateReason reason) { DCHECK(IsMainThread()); LocalFrameView* frame_view = View(); - if (status == IsForcedLayout && frame_view) + if (reason != DocumentUpdateReason::kBeginMainFrame && frame_view) frame_view->WillStartForcedLayout(); HTMLFrameOwnerElement::PluginDisposeSuspendScope suspend_plugin_dispose; @@ -3047,12 +2916,15 @@ void Document::UpdateStyleAndLayout(ForcedLayoutStatus status) { << "View layout should not be re-entrant"; if (HTMLFrameOwnerElement* owner = LocalOwner()) - owner->GetDocument().UpdateStyleAndLayout(); + owner->GetDocument().UpdateStyleAndLayout(reason); UpdateStyleAndLayoutTree(); - if (!IsActive()) + if (!IsActive()) { + if (reason != DocumentUpdateReason::kBeginMainFrame && frame_view) + frame_view->DidFinishForcedLayout(reason); return; + } if (frame_view && frame_view->NeedsLayout()) frame_view->UpdateLayout(); @@ -3060,11 +2932,14 @@ void Document::UpdateStyleAndLayout(ForcedLayoutStatus status) { if (Lifecycle().GetState() < DocumentLifecycle::kLayoutClean) Lifecycle().AdvanceTo(DocumentLifecycle::kLayoutClean); + ApplyScrollRestorationLogic(); + if (LocalFrameView* frame_view_anchored = View()) frame_view_anchored->PerformScrollAnchoringAdjustments(); + PerformScrollSnappingTasks(); - if (status == IsForcedLayout && frame_view) - frame_view->DidFinishForcedLayout(); + if (reason != DocumentUpdateReason::kBeginMainFrame && frame_view) + frame_view->DidFinishForcedLayout(reason); if (update_focus_appearance_after_layout_) UpdateFocusAppearance(); @@ -3074,11 +2949,6 @@ void Document::LayoutUpdated() { DCHECK(GetFrame()); DCHECK(View()); - // If we're restoring a scroll position from history, that takes precedence - // over scrolling to the anchor in the URL. - View()->InvokeFragmentAnchor(); - GetFrame()->Loader().RestoreScrollPositionAndViewState(); - // Plugins can run script inside layout which can detach the page. // TODO(dcheng): Does it make sense to do any of this work if detached? if (GetFrame()) { @@ -3089,23 +2959,40 @@ void Document::LayoutUpdated() { // don't have a good place that has access to its local root's FrameWidget. // TODO(dcheng): If we create FrameWidget before Frame then we could move // this to Document::Initialize(). - if (Platform::Current()->IsThreadedAnimationEnabled() && - GetSettings()->GetAcceleratedCompositingEnabled()) { - GetPage()->GetChromeClient().AttachCompositorAnimationTimeline( - Timeline().CompositorTimeline(), GetFrame()); - } + AttachCompositorTimeline(Timeline().CompositorTimeline()); } Markers().InvalidateRectsForAllTextMatchMarkers(); +} - // TODO(esprehn): This doesn't really make sense, why not track the first - // beginFrame? This will catch the first layout in a page that does lots - // of layout thrashing even though that layout might not be followed by - // a paint for many seconds. - if (HaveRenderBlockingResourcesLoaded()) { - if (document_timing_.FirstLayout().is_null()) - document_timing_.MarkFirstLayout(); - } +void Document::AttachCompositorTimeline( + CompositorAnimationTimeline* timeline) const { + if (!Platform::Current()->IsThreadedAnimationEnabled() || + !GetSettings()->GetAcceleratedCompositingEnabled()) + return; + + if (timeline->GetAnimationTimeline()->IsScrollTimeline() && + timeline->GetAnimationTimeline()->animation_host()) + return; + + GetPage()->GetChromeClient().AttachCompositorAnimationTimeline(timeline, + GetFrame()); +} + +void Document::DetachCompositorTimeline( + CompositorAnimationTimeline* timeline) const { + if (!Platform::Current()->IsThreadedAnimationEnabled() || + !GetSettings()->GetAcceleratedCompositingEnabled()) + return; + + // This requires detaching all animations from timeline first before detaching + // timeline. + if (timeline->GetAnimationTimeline()->IsScrollTimeline() && + timeline->GetAnimationTimeline()->HasAnimation()) + return; + + GetPage()->GetChromeClient().DetachCompositorAnimationTimeline(timeline, + GetFrame()); } void Document::ClearFocusedElementSoon() { @@ -3125,7 +3012,9 @@ scoped_refptr<const ComputedStyle> Document::StyleForPage(int page_index) { return EnsureStyleResolver().StyleForPage(page_index); } -void Document::EnsurePaintLocationDataValidForNode(const Node* node) { +void Document::EnsurePaintLocationDataValidForNode( + const Node* node, + DocumentUpdateReason reason) { DCHECK(node); if (!node->InActiveDocument()) return; @@ -3134,7 +3023,7 @@ void Document::EnsurePaintLocationDataValidForNode(const Node* node) { // For all nodes we must have up-to-date style and have performed layout to do // any location-based calculation. - UpdateStyleAndLayout(); + UpdateStyleAndLayout(reason); // The location of elements that are position: sticky is not known until // compositing inputs are cleaned. Therefore, for any elements that are either @@ -3145,9 +3034,9 @@ void Document::EnsurePaintLocationDataValidForNode(const Node* node) { bool success = false; if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { // In CAP, compositing inputs are cleaned as part of PrePaint. - success = View()->UpdateAllLifecyclePhasesExceptPaint(); + success = View()->UpdateAllLifecyclePhasesExceptPaint(reason); } else { - success = View()->UpdateLifecycleToCompositingInputsClean(); + success = View()->UpdateLifecycleToCompositingInputsClean(reason); } // The lifecycle update should always succeed, because forced lifecycles // from script are never throttled. @@ -3170,18 +3059,18 @@ void Document::PageSizeAndMarginsInPixels(int page_index, double width = page_size.Width(); double height = page_size.Height(); - switch (style->PageSizeType()) { - case EPageSizeType::kAuto: + switch (style->GetPageSizeType()) { + case PageSizeType::kAuto: break; - case EPageSizeType::kLandscape: + case PageSizeType::kLandscape: if (width < height) std::swap(width, height); break; - case EPageSizeType::kPortrait: + case PageSizeType::kPortrait: if (width > height) std::swap(width, height); break; - case EPageSizeType::kResolved: { + case PageSizeType::kFixed: { FloatSize size = style->PageSize(); width = size.Width(); height = size.Height(); @@ -3215,27 +3104,43 @@ void Document::SetIsViewSource(bool is_view_source) { return; } -void Document::SetIsImmersiveArOverlay(bool val) { +void Document::SetIsXrOverlay(bool val, Element* overlay_element) { if (!documentElement()) return; - if (val != is_immersive_ar_overlay_) { - DCHECK(RuntimeEnabledFeatures::WebXRARDOMOverlayEnabled(this)); - is_immersive_ar_overlay_ = val; + if (val == is_xr_overlay_) + return; - // If the property has changed, apply the pseudo-style change to the root - // element. This will cascade further UA stylesheet changes such as setting - // the fullscreened element and its backdrop transparent. - documentElement()->PseudoStateChanged( - CSSSelector::kPseudoXrImmersiveDomOverlay); + is_xr_overlay_ = val; - // Ensure that the graphics layer tree gets fully rebuilt on changes, - // similar to HTMLVideoElement::DidEnterFullscreen(). This may not be - // strictly necessary if the compositing changes are based on visibility - // settings, but helps ensure consistency in case it's changed to - // detaching layers or re-rooting the graphics layer tree. - GetLayoutView()->Compositor()->SetNeedsCompositingUpdate( - kCompositingUpdateRebuildTree); + // On navigation, the layout view may be invalid, skip style changes. + if (!GetLayoutView()) + return; + + if (val) { + // The UA style sheet for the :xr-overlay pseudoclass uses lazy loading. + // If we get here, we need to ensure that it's present. + GetStyleEngine().EnsureUAStyleForXrOverlay(); + } + + if (overlay_element) { + // Now that the custom style sheet is loaded, update the pseudostyle for + // the overlay element. + overlay_element->PseudoStateChanged(CSSSelector::kPseudoXrOverlay); + } + + // The DOM overlay may change the effective root element. Need to update + // compositing inputs to avoid a mismatch in CompositingRequirementsUpdater. + GetLayoutView()->Layer()->SetNeedsCompositingInputsUpdate(); + + // Ensure that the graphics layer tree gets fully rebuilt on changes, + // similar to HTMLVideoElement::DidEnterFullscreen(). This may not be + // strictly necessary if the compositing changes are based on visibility + // settings, but helps ensure consistency in case it's changed to + // detaching layers or re-rooting the graphics layer tree. + if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { + auto* compositor = GetLayoutView()->Compositor(); + compositor->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree); } } @@ -3249,17 +3154,15 @@ void Document::UnscheduleUseShadowTreeUpdate(SVGUseElement& element) { } void Document::UpdateUseShadowTreesIfNeeded() { - if (use_elements_needing_update_.IsEmpty()) - return; - ScriptForbiddenScope forbid_script; - HeapHashSet<Member<SVGUseElement>> elements; - use_elements_needing_update_.swap(elements); - for (SVGUseElement* element : elements) - element->BuildPendingResource(); - - DCHECK(use_elements_needing_update_.IsEmpty()); + // Breadth-first search since nested use elements add to the queue. + while (!use_elements_needing_update_.IsEmpty()) { + HeapHashSet<Member<SVGUseElement>> elements; + use_elements_needing_update_.swap(elements); + for (SVGUseElement* element : elements) + element->BuildPendingResource(); + } } StyleResolver* Document::GetStyleResolver() const { @@ -3294,14 +3197,14 @@ void Document::Initialize() { View()->DidAttachDocument(); // Observer(s) should not be initialized until the document is initialized / - // attached to a frame. Otherwise ContextLifecycleObserver::contextDestroyed - // wouldn't be fired. - network_state_observer_ = MakeGarbageCollected<NetworkStateObserver>(*this); + // attached to a frame. Otherwise + // ExecutionContextLifecycleObserver::contextDestroyed wouldn't be fired. + network_state_observer_ = + MakeGarbageCollected<NetworkStateObserver>(GetExecutionContext()); - // Check for frame_ so we only attach execution contexts with its own - // scheduler. + // Check for frame_ so we only attach documents with its own scheduler. if (frame_) - GetAgent()->AttachExecutionContext(this); + GetAgent()->AttachDocument(this); } void Document::Shutdown() { @@ -3368,11 +3271,6 @@ void Document::Shutdown() { probe::DocumentDetached(this); - // FIXME: consider using ContextLifecycleStateObserver. - if (scripted_animation_controller_) - scripted_animation_controller_->ClearDocumentPointer(); - scripted_animation_controller_.Clear(); - scripted_idle_task_controller_.Clear(); if (SvgExtensions()) @@ -3380,16 +3278,14 @@ void Document::Shutdown() { CancelPendingJavaScriptUrls(); http_refresh_scheduler_->Cancel(); + GetFrame()->CancelFormSubmission(); - if (Platform::Current()->IsThreadedAnimationEnabled() && - GetSettings()->GetAcceleratedCompositingEnabled()) { - GetPage()->GetChromeClient().DetachCompositorAnimationTimeline( - Timeline().CompositorTimeline(), GetFrame()); - } + DetachCompositorTimeline(Timeline().CompositorTimeline()); if (frame_->IsLocalRoot()) GetPage()->GetChromeClient().AttachRootLayer(nullptr, frame_.Get()); - layout_view_->CleanUpCompositor(); + if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) + layout_view_->CleanUpCompositor(); if (RegistrationContext()) RegistrationContext()->DocumentWasDetached(); @@ -3435,8 +3331,12 @@ void Document::Shutdown() { frame_->GetEventHandlerRegistry().DocumentDetached(*this); // Signal destruction to mutation observers. - DocumentShutdownNotifier::NotifyContextDestroyed(); - SynchronousMutationNotifier::NotifyContextDestroyed(); + synchronous_mutation_observer_list_.ForEachObserver( + [](SynchronousMutationObserver* observer) { + observer->ContextDestroyed(); + observer->ObserverListWillBeCleared(); + }); + synchronous_mutation_observer_list_.Clear(); cookie_jar_ = nullptr; // Not accessible after navigated away. fetcher_->ClearContext(); @@ -3455,22 +3355,12 @@ void Document::Shutdown() { // TODO(crbug.com/729196): Trace why LocalFrameView::DetachFromLayout crashes. CHECK(!View()->IsAttached()); - // Check for frame_ so we only detach execution contexts with its own - // scheduler. + // Check for frame_ so we only detach documents with its own scheduler. // TODO(bokan): Can this happen? |frame_| is dereferenced above and CHECKed // at top. if (frame_) - GetAgent()->DetachExecutionContext(this); - - // TODO(haraken): Call contextDestroyed() before we start any disruptive - // operations. - // TODO(haraken): Currently we call notifyContextDestroyed() only in - // Document::detachLayoutTree(), which means that we don't call - // notifyContextDestroyed() for a document that doesn't get detached. - // If such a document has any observer, the observer won't get - // a contextDestroyed() notification. This can happen for a document - // created by DOMImplementation::createDocument(). - ExecutionContext::NotifyContextDestroyed(); + GetAgent()->DetachDocument(this); + // TODO(crbug.com/729196): Trace why LocalFrameView::DetachFromLayout crashes. CHECK(!View()->IsAttached()); @@ -3585,8 +3475,8 @@ CanvasFontCache* Document::GetCanvasFontCache() { } DocumentParser* Document::CreateParser() { - if (IsHTMLDocument()) { - return MakeGarbageCollected<HTMLDocumentParser>(ToHTMLDocument(*this), + if (auto* html_document = DynamicTo<HTMLDocument>(this)) { + return MakeGarbageCollected<HTMLDocumentParser>(*html_document, parser_sync_policy_); } // FIXME: this should probably pass the frame instead @@ -3594,7 +3484,7 @@ DocumentParser* Document::CreateParser() { } bool Document::IsFrameSet() const { - if (!IsHTMLDocument()) + if (!IsA<HTMLDocument>(this)) return false; return IsA<HTMLFrameSetElement>(body()); } @@ -3647,7 +3537,7 @@ void Document::open(Document* entered_document, // If |document| is an XML document, then throw an "InvalidStateError" // DOMException exception. - if (!IsHTMLDocument()) { + if (!IsA<HTMLDocument>(this)) { exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, "Only HTML documents support open()."); return; @@ -3687,6 +3577,7 @@ void Document::open(Document* entered_document, if (ignore_opens_during_unload_count_) return; + // If |document|'s active parser was aborted is true, then return |document|. if (ignore_opens_and_writes_for_abort_) return; @@ -3697,7 +3588,7 @@ void Document::open(Document* entered_document, csp->CopyStateFrom(entered_document->GetContentSecurityPolicy()); // We inherit the sandbox flags of the entered document, so mask on // the ones contained in the CSP. - sandbox_flags_ |= csp->GetSandboxMask(); + GetSecurityContext().ApplySandboxFlags(csp->GetSandboxMask()); InitContentSecurityPolicy(csp); // Clear the hash fragment from the inherited URL to prevent a // scroll-into-view for any document.open()'d frame. @@ -3707,7 +3598,8 @@ void Document::open(Document* entered_document, if (Loader()) Loader()->UpdateUrlForDocumentOpen(new_url); - SetSecurityOrigin(entered_document->GetMutableSecurityOrigin()); + GetSecurityContext().SetSecurityOrigin( + entered_document->GetMutableSecurityOrigin()); SetReferrerPolicy(entered_document->GetReferrerPolicy()); SetCookieURL(entered_document->CookieURL()); } @@ -3745,6 +3637,12 @@ void Document::open() { } CancelPendingJavaScriptUrls(); + // TODO(crbug.com/1085514): Consider making HasProvisionalNavigation() return + // true when form submission task is active, in which case we can delete this + // redundant attempt to cancel it. + if (GetFrame()) + GetFrame()->CancelFormSubmission(); + // For each shadow-including inclusive descendant |node| of |document|, erase // all event listeners and handlers given |node|. // @@ -3978,7 +3876,7 @@ void Document::close(ExceptionState& exception_state) { // If the Document object is an XML document, then throw an // "InvalidStateError" DOMException. - if (!IsHTMLDocument()) { + if (!IsA<HTMLDocument>(this)) { exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, "Only HTML documents support close()."); return; @@ -4039,6 +3937,9 @@ void Document::ImplicitClose() { if (domWindow()) domWindow()->DocumentWasClosed(); + if (GetFrame() && GetFrame()->IsMainFrame()) + GetFrame()->GetLocalFrameHostRemote().DocumentOnLoadCompleted(); + if (GetFrame()) { GetFrame()->Client()->DispatchDidHandleOnloadEvents(); Loader()->GetApplicationCacheHost()->StopDeferringEvents(); @@ -4141,19 +4042,6 @@ bool Document::CheckCompletedInternal() { return false; } - // !ukm_binding_ is checked to avoid repeating work. - if (frame_ && frame_->Client()->GetRemoteNavigationAssociatedInterfaces() && - !ukm_binding_) { - ukm_binding_ = std::make_unique< - mojo::AssociatedRemote<mojom::blink::UkmSourceIdFrameHost>>(); - frame_->Client()->GetRemoteNavigationAssociatedInterfaces()->GetInterface( - ukm_binding_.get()); - DCHECK(ukm_binding_->is_bound()); - auto callback = - WTF::Bind(&Document::SetNavigationSourceId, WrapPersistent(this)); - (*ukm_binding_.get())->GetNavigationSourceId(std::move(callback)); - } - // OK, completed. Fire load completion events as needed. SetReadyState(kComplete); if (LoadEventStillNeeded()) @@ -4175,13 +4063,17 @@ bool Document::CheckCompletedInternal() { GetViewportData().GetViewportDescription().ReportMobilePageStats(frame_); Loader()->SetSentDidFinishLoad(); frame_->Client()->DispatchDidFinishLoad(); + frame_->GetLocalFrameHostRemote().DidFinishLoad(Loader()->Url()); if (!frame_) return false; // Send the source ID of the document to the browser. if (frame_->Client()->GetRemoteNavigationAssociatedInterfaces()) { - DCHECK(ukm_binding_->is_bound()); - (*ukm_binding_.get())->SetDocumentSourceId(ukm_source_id_); + mojo::AssociatedRemote<mojom::blink::UkmSourceIdFrameHost> ukm_binding; + frame_->Client()->GetRemoteNavigationAssociatedInterfaces()->GetInterface( + &ukm_binding); + DCHECK(ukm_binding.is_bound()); + ukm_binding->SetDocumentSourceId(ukm_source_id_); } frame_->GetFrameScheduler()->RegisterStickyFeature( @@ -4200,6 +4092,16 @@ bool Document::CheckCompletedInternal() { } } + if (auto* view = View()) { + if (view->GetFragmentAnchor()) { + // Schedule an animation frame to process fragment anchors. The frame + // can't be scheduled when the fragment anchor is set because, per spec, + // we must wait for the document to be loaded before invoking fragment + // anchors. + View()->ScheduleAnimation(); + } + } + return true; } @@ -4215,6 +4117,7 @@ bool Document::DispatchBeforeUnloadEvent(ChromeClient* chrome_client, if (ProcessingBeforeUnload()) return false; + MainThreadDisallowSynchronousXHRScope disallow_synchronous_xhr; auto& before_unload_event = *MakeGarbageCollected<BeforeUnloadEvent>(); before_unload_event.initEvent(event_type_names::kBeforeunload, false, true); load_event_progress_ = kBeforeUnloadEventInProgress; @@ -4246,7 +4149,7 @@ bool Document::DispatchBeforeUnloadEvent(ChromeClient* chrome_client, if (!GetFrame() || before_unload_event.returnValue().IsNull()) return true; - if (!GetFrame()->HasBeenActivated()) { + if (!GetFrame()->HasStickyUserActivation()) { beforeunload_dialog_histogram.Count(kNoDialogNoUserGesture); String message = "Blocked attempt to show a 'beforeunload' confirmation panel for a " @@ -4298,6 +4201,7 @@ void Document::DispatchUnloadEvents( SecurityOrigin* committing_origin, base::Optional<Document::UnloadEventTiming>* unload_timing) { PluginScriptForbiddenScope forbid_plugin_destructor_scripting; + MainThreadDisallowSynchronousXHRScope disallow_synchronous_xhr; if (parser_) parser_->StopParsing(); @@ -4455,7 +4359,7 @@ void Document::write(const String& text, return; } - if (!IsHTMLDocument()) { + if (!IsA<HTMLDocument>(this)) { exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, "Only HTML documents support write()."); return; @@ -4493,7 +4397,7 @@ void Document::write(const String& text, if (!has_insertion_point) { if (ignore_destructive_write_count_) { - AddConsoleMessage(ConsoleMessage::Create( + AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( mojom::ConsoleMessageSource::kJavaScript, mojom::ConsoleMessageLevel::kWarning, ExceptionMessages::FailedToExecute( @@ -4511,12 +4415,12 @@ void Document::write(const String& text, DCHECK(parser_); PerformanceMonitor::ReportGenericViolation( - this, PerformanceMonitor::kDiscouragedAPIUse, + domWindow(), PerformanceMonitor::kDiscouragedAPIUse, "Avoid using document.write(). " "https://developers.google.com/web/updates/2016/08/" "removing-document-write", base::TimeDelta(), nullptr); - probe::BreakableLocation(this, "Document.write"); + probe::BreakableLocation(domWindow(), "Document.write"); parser_->insert(text); } @@ -4539,7 +4443,7 @@ void Document::write(v8::Isolate* isolate, for (const String& string : text) builder.Append(string); String string = - GetStringFromTrustedHTML(builder.ToString(), this, exception_state); + TrustedTypesCheckForHTML(builder.ToString(), this, exception_state); if (exception_state.HadException()) return; @@ -4556,7 +4460,7 @@ void Document::writeln(v8::Isolate* isolate, for (const String& string : text) builder.Append(string); String string = - GetStringFromTrustedHTML(builder.ToString(), this, exception_state); + TrustedTypesCheckForHTML(builder.ToString(), this, exception_state); if (exception_state.HadException()) return; @@ -4564,7 +4468,7 @@ void Document::writeln(v8::Isolate* isolate, } bool Document::IsTrustedTypesEnabledForDoc() const { - return ExecutionContext::RequireTrustedTypes(); + return GetExecutionContext()->RequireTrustedTypes(); } void Document::write(v8::Isolate* isolate, @@ -4583,15 +4487,10 @@ void Document::writeln(v8::Isolate* isolate, exception_state); } -EventTarget* Document::ErrorEventTarget() { - return domWindow(); -} - -void Document::ExceptionThrown(ErrorEvent* event) { - MainThreadDebugger::Instance()->ExceptionThrown(this, event); -} - KURL Document::urlForBinding() const { + if (WebBundleClaimedUrl().IsValid()) { + return WebBundleClaimedUrl(); + } if (!Url().IsNull()) { return Url(); } @@ -4761,7 +4660,7 @@ void Document::ProcessBaseElement() { if (base_element_url.ProtocolIsData() || base_element_url.ProtocolIsJavaScript()) { UseCounter::Count(*this, WebFeature::kBaseWithDataHref); - AddConsoleMessage(ConsoleMessage::Create( + AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( mojom::ConsoleMessageSource::kSecurity, mojom::ConsoleMessageLevel::kError, "'" + base_element_url.Protocol() + @@ -4794,13 +4693,6 @@ String Document::UserAgent() const { return GetFrame() ? GetFrame()->Loader().UserAgent() : String(); } -void Document::DisableEval(const String& error_message) { - if (!GetFrame()) - return; - - GetFrame()->GetScriptController().DisableEval(error_message); -} - void Document::DidLoadAllImports() { if (!HaveScriptBlockingStylesheetsLoaded()) return; @@ -4834,11 +4726,11 @@ void Document::DidLoadAllScriptBlockingResources() { WTF::Bind(&Document::ExecuteScriptsWaitingForResources, WrapWeakPersistent(this))); - if (IsHTMLDocument() && body()) { + if (IsA<HTMLDocument>(this) && body()) { // For HTML if we have no more stylesheets to load and we're past the body // tag, we should have something to paint so resume. BeginLifecycleUpdatesIfRenderingReady(); - } else if (!IsHTMLDocument() && documentElement()) { + } else if (!IsA<HTMLDocument>(this) && documentElement()) { // For non-HTML there is no body so resume as soon as the sheets are loaded. BeginLifecycleUpdatesIfRenderingReady(); } @@ -4876,21 +4768,21 @@ void Document::MaybeHandleHttpRefresh(const String& content, if (refresh_url.ProtocolIsJavaScript()) { String message = "Refused to refresh " + url_.ElidedString() + " to a javascript: URL"; - AddConsoleMessage( - ConsoleMessage::Create(mojom::ConsoleMessageSource::kSecurity, - mojom::ConsoleMessageLevel::kError, message)); + AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::ConsoleMessageSource::kSecurity, + mojom::ConsoleMessageLevel::kError, message)); return; } if (http_refresh_type == kHttpRefreshFromMetaTag && - IsSandboxed(WebSandboxFlags::kAutomaticFeatures)) { + IsSandboxed(mojom::blink::WebSandboxFlags::kAutomaticFeatures)) { String message = "Refused to execute the redirect specified via '<meta " "http-equiv='refresh' content='...'>'. The document is sandboxed, and " "the 'allow-scripts' keyword is not set."; - AddConsoleMessage( - ConsoleMessage::Create(mojom::ConsoleMessageSource::kSecurity, - mojom::ConsoleMessageLevel::kError, message)); + AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::ConsoleMessageSource::kSecurity, + mojom::ConsoleMessageLevel::kError, message)); return; } if (http_refresh_type == kHttpRefreshFromHeader) { @@ -4933,24 +4825,15 @@ String Document::OutgoingReferrer() const { } network::mojom::ReferrerPolicy Document::GetReferrerPolicy() const { - network::mojom::ReferrerPolicy policy = ExecutionContext::GetReferrerPolicy(); - // For srcdoc documents without their own policy, walk up the frame - // tree to find the document that is either not a srcdoc or doesn't - // have its own policy. This algorithm is defined in - // https://html.spec.whatwg.org/C/#set-up-a-window-environment-settings-object. - if (!frame_ || policy != network::mojom::ReferrerPolicy::kDefault || - !IsSrcdocDocument()) { - return policy; - } - LocalFrame* frame = To<LocalFrame>(frame_->Tree().Parent()); - return frame->GetDocument()->GetReferrerPolicy(); + return GetExecutionContext() ? GetExecutionContext()->GetReferrerPolicy() + : network::mojom::ReferrerPolicy::kDefault; } MouseEventWithHitTestResults Document::PerformMouseEventHitTest( const HitTestRequest& request, const PhysicalOffset& document_point, const WebMouseEvent& event) { - DCHECK(!GetLayoutView() || GetLayoutView()->IsLayoutView()); + DCHECK(!GetLayoutView() || IsA<LayoutView>(GetLayoutView())); // LayoutView::hitTest causes a layout, and we don't want to hit that until // the first layout because until then, there is nothing shown on the screen - @@ -5172,7 +5055,7 @@ Document* Document::CloneDocumentWithoutChildren() const { .WithContextDocument(ContextDocument()) .WithOwnerDocument(const_cast<Document*>(this)) .WithURL(Url()); - if (IsXMLDocument()) { + if (IsA<XMLDocument>(this)) { if (IsXHTMLDocument()) return XMLDocument::CreateXHTML( init.WithRegistrationContext(RegistrationContext())); @@ -5303,7 +5186,7 @@ void Document::SetAnnotatedRegions( SetAnnotatedRegionsDirty(false); } -void Document::SetLastFocusType(WebFocusType last_focus_type) { +void Document::SetLastFocusType(mojom::blink::FocusType last_focus_type) { last_focus_type_ = last_focus_type; } @@ -5341,6 +5224,8 @@ bool Document::SetFocusedElement(Element* new_focused_element, old_focused_element->SetFocused(false, params.type); old_focused_element->SetHasFocusWithinUpToAncestor(false, ancestor); + DisplayLockUtilities::ElementLostFocus(old_focused_element); + // Dispatch the blur event and let the node do any other blur related // activities (important for text fields) // If page lost focus, blur event will have already been dispatched @@ -5389,11 +5274,12 @@ bool Document::SetFocusedElement(Element* new_focused_element, SetSequentialFocusNavigationStartingPoint(focused_element_.Get()); // Keep track of last focus from user interaction, ignoring focus from code. - if (params.type != kWebFocusTypeNone) + if (params.type != mojom::blink::FocusType::kNone) last_focus_type_ = params.type; focused_element_->SetFocused(true, params.type); focused_element_->SetHasFocusWithinUpToAncestor(true, ancestor); + DisplayLockUtilities::ElementGainedFocus(focused_element_.Get()); // Element::setFocused for frames can dispatch events. if (focused_element_ != new_focused_element) { @@ -5403,7 +5289,8 @@ bool Document::SetFocusedElement(Element* new_focused_element, return false; } CancelFocusAppearanceUpdate(); - EnsurePaintLocationDataValidForNode(focused_element_); + EnsurePaintLocationDataValidForNode(focused_element_, + DocumentUpdateReason::kFocus); focused_element_->UpdateFocusAppearanceWithOptions( params.selection_behavior, params.options); @@ -5462,20 +5349,47 @@ bool Document::SetFocusedElement(Element* new_focused_element, } void Document::ClearFocusedElement() { - SetFocusedElement(nullptr, FocusParams(SelectionBehaviorOnFocus::kNone, - kWebFocusTypeNone, nullptr)); + SetFocusedElement(nullptr, + FocusParams(SelectionBehaviorOnFocus::kNone, + mojom::blink::FocusType::kNone, nullptr)); } void Document::NotifyFocusedElementChanged(Element* old_focused_element, Element* new_focused_element) { + // |old_focused_element| may not belong to this document by invoking + // adoptNode in event handlers during moving the focus to the new element. + DCHECK(!new_focused_element || new_focused_element->GetDocument() == this); + if (AXObjectCache* cache = ExistingAXObjectCache()) { cache->HandleFocusedUIElementChanged(old_focused_element, new_focused_element); } if (GetPage()) { - GetPage()->GetChromeClient().FocusedElementChanged(old_focused_element, - new_focused_element); + GetPage()->GetValidationMessageClient().DidChangeFocusTo( + new_focused_element); + + bool is_editable = false; + gfx::Rect element_bounds; + if (new_focused_element) { + IntRect rect = new_focused_element->BoundsInViewport(); + View()->FrameToScreen(rect); + is_editable = IsEditableElement(*new_focused_element); + element_bounds = gfx::Rect(rect); + } + + GetFrame()->GetLocalFrameHostRemote().FocusedElementChanged(is_editable, + element_bounds); + + Document* old_document = + old_focused_element ? &old_focused_element->GetDocument() : nullptr; + if (old_document && old_document != this && old_document->GetFrame()) + old_document->GetFrame()->Client()->FocusedElementChanged(nullptr); + + GetFrame()->Client()->FocusedElementChanged(new_focused_element); + + GetPage()->GetChromeClient().SetKeyboardFocusURL(new_focused_element); + if (GetSettings()->GetSpatialNavigationEnabled()) GetPage()->GetSpatialNavigationController().FocusedNodeChanged(this); } @@ -5496,7 +5410,7 @@ void Document::SetSequentialFocusNavigationStartingPoint(Node* node) { } Element* Document::SequentialFocusNavigationStartingPoint( - WebFocusType type) const { + mojom::blink::FocusType type) const { if (focused_element_) return focused_element_.Get(); if (!sequential_focus_navigation_starting_point_) @@ -5508,7 +5422,7 @@ Element* Document::SequentialFocusNavigationStartingPoint( sequential_focus_navigation_starting_point_->endContainer()); if (auto* element = DynamicTo<Element>(node)) return element; - if (Element* neighbor_element = type == kWebFocusTypeForward + if (Element* neighbor_element = type == mojom::blink::FocusType::kForward ? ElementTraversal::Previous(*node) : ElementTraversal::Next(*node)) return neighbor_element; @@ -5532,7 +5446,7 @@ Element* Document::SequentialFocusNavigationStartingPoint( // TODO(tkent): Using FlatTreeTraversal is inconsistent with // FocusController. Ideally we should find backward/forward focusable // elements before the starting point is disconnected. crbug.com/606582 - if (type == kWebFocusTypeForward) { + if (type == mojom::blink::FocusType::kForward) { Node* previous = FlatTreeTraversal::Previous(*next_node); for (; previous; previous = FlatTreeTraversal::Previous(*previous)) { if (auto* element = DynamicTo<Element>(previous)) @@ -5605,7 +5519,10 @@ void Document::DidMoveTreeToNewDocument(const Node& root) { for (Range* range : ranges) range->UpdateOwnerDocumentIfNeeded(); } - NotifyMoveTreeToNewDocument(root); + synchronous_mutation_observer_list_.ForEachObserver( + [&](SynchronousMutationObserver* observer) { + observer->DidMoveTreeToNewDocument(root); + }); } void Document::NodeChildrenWillBeRemoved(ContainerNode& container) { @@ -5621,7 +5538,10 @@ void Document::NodeChildrenWillBeRemoved(ContainerNode& container) { ni->NodeWillBeRemoved(n); } - NotifyNodeChildrenWillBeRemoved(container); + synchronous_mutation_observer_list_.ForEachObserver( + [&](SynchronousMutationObserver* observer) { + observer->NodeChildrenWillBeRemoved(container); + }); if (ContainsV1ShadowTree()) { for (Node& n : NodeTraversal::ChildrenOf(container)) @@ -5639,7 +5559,10 @@ void Document::NodeWillBeRemoved(Node& n) { range->FixupRemovedNodeAcrossShadowBoundary(n); } - NotifyNodeWillBeRemoved(n); + synchronous_mutation_observer_list_.ForEachObserver( + [&](SynchronousMutationObserver* observer) { + observer->NodeWillBeRemoved(n); + }); if (ContainsV1ShadowTree()) n.CheckSlotChangeBeforeRemoved(); @@ -5648,6 +5571,24 @@ void Document::NodeWillBeRemoved(Node& n) { GetStyleEngine().NodeWillBeRemoved(n); } +void Document::NotifyUpdateCharacterData(CharacterData* character_data, + unsigned offset, + unsigned old_length, + unsigned new_length) { + synchronous_mutation_observer_list_.ForEachObserver( + [&](SynchronousMutationObserver* observer) { + observer->DidUpdateCharacterData(character_data, offset, old_length, + new_length); + }); +} + +void Document::NotifyChangeChildren(const ContainerNode& container) { + synchronous_mutation_observer_list_.ForEachObserver( + [&](SynchronousMutationObserver* observer) { + observer->DidChangeChildren(container); + }); +} + void Document::DidInsertText(const CharacterData& text, unsigned offset, unsigned length) { @@ -5672,7 +5613,11 @@ void Document::DidMergeTextNodes(const Text& merged_node, range->DidMergeTextNodes(node_to_be_removed_with_index, old_length); } - NotifyMergeTextNodes(merged_node, node_to_be_removed_with_index, old_length); + synchronous_mutation_observer_list_.ForEachObserver( + [&](SynchronousMutationObserver* observer) { + observer->DidMergeTextNodes(merged_node, node_to_be_removed_with_index, + old_length); + }); // FIXME: This should update markers for spelling and grammar checking. } @@ -5681,7 +5626,10 @@ void Document::DidSplitTextNode(const Text& old_node) { for (Range* range : ranges_) range->DidSplitTextNode(old_node); - NotifySplitTextNode(old_node); + synchronous_mutation_observer_list_.ForEachObserver( + [&](SynchronousMutationObserver* observer) { + observer->DidSplitTextNode(old_node); + }); // FIXME: This should update markers for spelling and grammar checking. } @@ -5703,79 +5651,83 @@ EventListener* Document::GetWindowAttributeEventListener( } void Document::EnqueueDisplayLockActivationTask(base::OnceClosure task) { - EnsureScriptedAnimationController().EnqueueTask(std::move(task)); + scripted_animation_controller_->EnqueueTask(std::move(task)); } void Document::EnqueueAnimationFrameTask(base::OnceClosure task) { - EnsureScriptedAnimationController().EnqueueTask(std::move(task)); + scripted_animation_controller_->EnqueueTask(std::move(task)); } void Document::EnqueueAnimationFrameEvent(Event* event) { - EnsureScriptedAnimationController().EnqueueEvent(event); + scripted_animation_controller_->EnqueueEvent(event); } void Document::EnqueueUniqueAnimationFrameEvent(Event* event) { - EnsureScriptedAnimationController().EnqueuePerFrameEvent(event); + scripted_animation_controller_->EnqueuePerFrameEvent(event); } void Document::EnqueueScrollEventForNode(Node* target) { // Per the W3C CSSOM View Module only scroll events fired at the document // should bubble. + overscroll_accumulated_delta_x_ = overscroll_accumulated_delta_y_ = 0; Event* scroll_event = target->IsDocumentNode() ? Event::CreateBubble(event_type_names::kScroll) : Event::Create(event_type_names::kScroll); scroll_event->SetTarget(target); - EnsureScriptedAnimationController().EnqueuePerFrameEvent(scroll_event); + scripted_animation_controller_->EnqueuePerFrameEvent(scroll_event); } void Document::EnqueueScrollEndEventForNode(Node* target) { // Mimic bubbling behavior of scroll event for consistency. + overscroll_accumulated_delta_x_ = overscroll_accumulated_delta_y_ = 0; Event* scroll_end_event = target->IsDocumentNode() ? Event::CreateBubble(event_type_names::kScrollend) : Event::Create(event_type_names::kScrollend); scroll_end_event->SetTarget(target); - EnsureScriptedAnimationController().EnqueuePerFrameEvent(scroll_end_event); + scripted_animation_controller_->EnqueuePerFrameEvent(scroll_end_event); } void Document::EnqueueOverscrollEventForNode(Node* target, double delta_x, double delta_y) { // Mimic bubbling behavior of scroll event for consistency. + overscroll_accumulated_delta_x_ += delta_x; + overscroll_accumulated_delta_y_ += delta_y; bool bubbles = target->IsDocumentNode(); Event* overscroll_event = OverscrollEvent::Create( - event_type_names::kOverscroll, bubbles, delta_x, delta_y); + event_type_names::kOverscroll, bubbles, overscroll_accumulated_delta_x_, + overscroll_accumulated_delta_y_); overscroll_event->SetTarget(target); - EnsureScriptedAnimationController().EnqueuePerFrameEvent(overscroll_event); + scripted_animation_controller_->EnqueuePerFrameEvent(overscroll_event); } void Document::EnqueueResizeEvent() { Event* event = Event::Create(event_type_names::kResize); event->SetTarget(domWindow()); - EnsureScriptedAnimationController().EnqueuePerFrameEvent(event); + scripted_animation_controller_->EnqueuePerFrameEvent(event); } void Document::EnqueueMediaQueryChangeListeners( HeapVector<Member<MediaQueryListListener>>& listeners) { - EnsureScriptedAnimationController().EnqueueMediaQueryChangeListeners( - listeners); + scripted_animation_controller_->EnqueueMediaQueryChangeListeners(listeners); } void Document::EnqueueVisualViewportScrollEvent() { - VisualViewportScrollEvent* event = VisualViewportScrollEvent::Create(); + VisualViewportScrollEvent* event = + MakeGarbageCollected<VisualViewportScrollEvent>(); event->SetTarget(domWindow()->visualViewport()); - EnsureScriptedAnimationController().EnqueuePerFrameEvent(event); + scripted_animation_controller_->EnqueuePerFrameEvent(event); } void Document::EnqueueVisualViewportResizeEvent() { - VisualViewportResizeEvent* event = VisualViewportResizeEvent::Create(); + VisualViewportResizeEvent* event = + MakeGarbageCollected<VisualViewportResizeEvent>(); event->SetTarget(domWindow()->visualViewport()); - EnsureScriptedAnimationController().EnqueuePerFrameEvent(event); + scripted_animation_controller_->EnqueuePerFrameEvent(event); } void Document::DispatchEventsForPrinting() { - if (!scripted_animation_controller_) - return; scripted_animation_controller_->DispatchEventsAndCallbacksForPrinting(); } @@ -5819,7 +5771,7 @@ Event* Document::createEvent(ScriptState* script_state, if (event) { // createEvent for TouchEvent should throw DOM exception if touch event // feature detection is not enabled. See crbug.com/392584#c22 - if (DeprecatedEqualIgnoringCase(event_type, "TouchEvent") && + if (EqualIgnoringASCIICase(event_type, "TouchEvent") && !RuntimeEnabledFeatures::TouchEventFeatureDetectionEnabled( execution_context)) break; @@ -5871,6 +5823,8 @@ void Document::AddListenerTypeIfNeeded(const AtomicString& event_type, // Need to re-evaluate time-to-effect-change for any running animations. View()->ScheduleAnimation(); } + } else if (event_type == event_type_names::kAnimationcancel) { + AddListenerType(kAnimationCancelListener); } else if (event_type == event_type_names::kTransitioncancel) { AddListenerType(kTransitionCancelListener); } else if (event_type == event_type_names::kTransitionrun) { @@ -5902,10 +5856,11 @@ HTMLFrameOwnerElement* Document::LocalOwner() const { return GetFrame()->DeprecatedLocalOwner(); } -void Document::WillChangeFrameOwnerProperties(int margin_width, - int margin_height, - ScrollbarMode scrolling_mode, - bool is_display_none) { +void Document::WillChangeFrameOwnerProperties( + int margin_width, + int margin_height, + mojom::blink::ScrollbarMode scrollbar_mode, + bool is_display_none) { DCHECK(GetFrame() && GetFrame()->Owner()); FrameOwner* owner = GetFrame()->Owner(); @@ -5926,8 +5881,9 @@ void Document::WillChangeFrameOwnerProperties(int margin_width, margin_height); } } - if (scrolling_mode != owner->ScrollingMode() && View()) { - View()->SetCanHaveScrollbars(scrolling_mode != ScrollbarMode::kAlwaysOff); + if (scrollbar_mode != owner->ScrollbarMode() && View()) { + View()->SetCanHaveScrollbars(scrollbar_mode != + mojom::blink::ScrollbarMode::kAlwaysOff); View()->SetNeedsLayout(); } } @@ -5939,10 +5895,10 @@ String Document::cookie(ExceptionState& exception_state) const { CountUse(WebFeature::kCookieGet); if (!GetSecurityOrigin()->CanAccessCookies()) { - if (IsSandboxed(WebSandboxFlags::kOrigin)) + if (IsSandboxed(mojom::blink::WebSandboxFlags::kOrigin)) exception_state.ThrowSecurityError( "The document is sandboxed and lacks the 'allow-same-origin' flag."); - else if (Url().ProtocolIs("data")) + else if (Url().ProtocolIsData()) exception_state.ThrowSecurityError( "Cookies are disabled inside 'data:' URLs."); else @@ -5965,10 +5921,10 @@ void Document::setCookie(const String& value, ExceptionState& exception_state) { UseCounter::Count(*this, WebFeature::kCookieSet); if (!GetSecurityOrigin()->CanAccessCookies()) { - if (IsSandboxed(WebSandboxFlags::kOrigin)) + if (IsSandboxed(mojom::blink::WebSandboxFlags::kOrigin)) exception_state.ThrowSecurityError( "The document is sandboxed and lacks the 'allow-same-origin' flag."); - else if (Url().ProtocolIs("data")) + else if (Url().ProtocolIsData()) exception_state.ThrowSecurityError( "Cookies are disabled inside 'data:' URLs."); else @@ -6011,7 +5967,7 @@ void Document::setDomain(const String& raw_domain, const String feature_policy_error = "Setting `document.domain` is disabled by Feature Policy."; - if (!IsFeatureEnabled(mojom::FeaturePolicyFeature::kDocumentDomain, + if (!IsFeatureEnabled(mojom::blink::FeaturePolicyFeature::kDocumentDomain, ReportOptions::kReportOnFailure, feature_policy_error)) { exception_state.ThrowSecurityError(feature_policy_error); @@ -6024,7 +5980,7 @@ void Document::setDomain(const String& raw_domain, return; } - if (IsSandboxed(WebSandboxFlags::kDocumentDomain)) { + if (IsSandboxed(mojom::blink::WebSandboxFlags::kDocumentDomain)) { exception_state.ThrowSecurityError( "Assignment is forbidden for sandboxed iframes."); return; @@ -6077,13 +6033,44 @@ void Document::setDomain(const String& raw_domain, GetSecurityOrigin()->Port() == 0 ? WebFeature::kDocumentDomainSetWithDefaultPort : WebFeature::kDocumentDomainSetWithNonDefaultPort); - bool was_cross_domain = frame_->IsCrossOriginSubframe(); + bool was_cross_origin_to_main_frame = frame_->IsCrossOriginToMainFrame(); + bool was_cross_origin_to_parent_frame = + frame_->IsCrossOriginToParentFrame(); GetMutableSecurityOrigin()->SetDomainFromDOM(new_domain); - bool is_cross_domain = frame_->IsCrossOriginSubframe(); + bool is_cross_origin_to_main_frame = frame_->IsCrossOriginToMainFrame(); if (FrameScheduler* frame_scheduler = frame_->GetFrameScheduler()) - frame_scheduler->SetCrossOrigin(is_cross_domain); - if (View() && (was_cross_domain != is_cross_domain)) - View()->CrossOriginStatusChanged(); + frame_scheduler->SetCrossOriginToMainFrame(is_cross_origin_to_main_frame); + if (View() && + (was_cross_origin_to_main_frame != is_cross_origin_to_main_frame)) { + View()->CrossOriginToMainFrameChanged(); + } + if (frame_->IsMainFrame()) { + // Notify descendants if their cross-origin-to-main-frame status changed. + // TODO(pdr): This will notify even if |Frame::IsCrossOriginToMainFrame| + // is the same. Track whether each child was cross-origin to main before + // and after changing the domain, and only notify the changed ones. + for (Frame* child = frame_->Tree().FirstChild(); child; + child = child->Tree().TraverseNext(frame_)) { + auto* child_local_frame = DynamicTo<LocalFrame>(child); + if (child_local_frame && child_local_frame->View()) + child_local_frame->View()->CrossOriginToMainFrameChanged(); + } + } + + if (View() && was_cross_origin_to_parent_frame != + frame_->IsCrossOriginToParentFrame()) { + View()->CrossOriginToParentFrameChanged(); + } + // Notify all child frames if their cross-origin-to-parent status changed. + // TODO(pdr): This will notify even if |Frame::IsCrossOriginToParentFrame| + // is the same. Track whether each child was cross-origin-to-parent before + // and after changing the domain, and only notify the changed ones. + for (Frame* child = frame_->Tree().FirstChild(); child; + child = child->Tree().NextSibling()) { + auto* child_local_frame = DynamicTo<LocalFrame>(child); + if (child_local_frame && child_local_frame->View()) + child_local_frame->View()->CrossOriginToParentFrameChanged(); + } frame_->GetScriptController().UpdateSecurityOrigin(GetSecurityOrigin()); } @@ -6131,7 +6118,7 @@ scoped_refptr<const SecurityOrigin> Document::TopFrameOrigin() const { return GetFrame()->Tree().Top().GetSecurityContext()->GetSecurityOrigin(); } -const KURL Document::SiteForCookies() const { +net::SiteForCookies Document::SiteForCookies() const { // TODO(mkwst): This doesn't properly handle HTML Import documents. // If this is an imported document, grab its master document's first-party: @@ -6139,44 +6126,50 @@ const KURL Document::SiteForCookies() const { return ImportsController()->Master()->SiteForCookies(); if (!GetFrame()) - return NullURL(); + return net::SiteForCookies(); Frame& top = GetFrame()->Tree().Top(); const SecurityOrigin* origin = top.GetSecurityContext()->GetSecurityOrigin(); // TODO(yhirano): Ideally |origin| should not be null here. if (!origin) - return NullURL(); + return net::SiteForCookies(); + + net::SiteForCookies candidate = + net::SiteForCookies::FromOrigin(origin->ToUrlOrigin()); if (SchemeRegistry::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel( origin->Protocol())) { - return origin->IsOpaque() ? NullURL() : KURL(origin->ToRawString()); + return candidate; } - OriginAccessEntry access_entry( - *origin, network::mojom::CorsDomainMatchMode::kAllowRegistrableDomains); - const Frame* current_frame = GetFrame(); while (current_frame) { const SecurityOrigin* cur_security_origin = current_frame->GetSecurityContext()->GetSecurityOrigin(); - // We use 'matchesDomain' here, as it turns out that some folks embed HTTPS - // login forms into HTTP pages; we should allow this kind of upgrade. - // - // The second clause bypasses strange permissiveness of OriginAccessEntry on - // empty domain names. See the beginning of OriginAccessEntry::MatchesDomain - // in services/network/public/cpp/cors/origin_access_entry.cc - if (access_entry.MatchesDomain(*cur_security_origin) == - network::cors::OriginAccessEntry::kDoesNotMatchOrigin || - (origin->Domain().IsEmpty() != cur_security_origin->Host().IsEmpty())) { - return NullURL(); + if (!candidate.IsEquivalent(net::SiteForCookies::FromOrigin( + cur_security_origin->ToUrlOrigin()))) { + return net::SiteForCookies(); } - current_frame = current_frame->Tree().Parent(); } - // Note: don't want origin->ToString() here since that may mess up file:///, - // depending on AllowFileAccessFromFileURLs setting. - return origin->IsOpaque() ? NullURL() : KURL(origin->ToRawString()); + return candidate; +} + +mojom::blink::PermissionService* Document::GetPermissionService( + ExecutionContext* execution_context) { + if (!permission_service_.is_bound()) { + execution_context->GetBrowserInterfaceBroker().GetInterface( + permission_service_.BindNewPipeAndPassReceiver( + execution_context->GetTaskRunner(TaskType::kPermission))); + permission_service_.set_disconnect_handler(WTF::Bind( + &Document::PermissionServiceConnectionError, WrapWeakPersistent(this))); + } + return permission_service_.get(); +} + +void Document::PermissionServiceConnectionError() { + permission_service_.reset(); } ScriptPromise Document::hasStorageAccess(ScriptState* script_state) const { @@ -6193,14 +6186,39 @@ ScriptPromise Document::hasStorageAccess(ScriptState* script_state) const { return promise; } -ScriptPromise Document::requestStorageAccess(ScriptState* script_state) const { +ScriptPromise Document::requestStorageAccess(ScriptState* script_state) { + DCHECK(frame_); ScriptPromiseResolver* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); // TODO (http://crbug.com/989663) // Hookup actual logic to Resolve/Reject this request properly. + + // Access the promise first to ensure it is created so that the proper state + // can be changed when it is resolved or rejected. ScriptPromise promise = resolver->Promise(); - resolver->Reject(); + + const bool has_user_gesture = LocalFrame::HasTransientUserActivation(frame_); + if (has_user_gesture) { + auto descriptor = mojom::blink::PermissionDescriptor::New(); + descriptor->name = mojom::blink::PermissionName::STORAGE_ACCESS; + GetPermissionService(ExecutionContext::From(script_state)) + ->RequestPermission( + std::move(descriptor), has_user_gesture, + WTF::Bind( + [](ScriptPromiseResolver* resolver, + mojom::blink::PermissionStatus status) { + DCHECK(resolver); + (status == mojom::blink::PermissionStatus::GRANTED) + ? resolver->Resolve() + : resolver->Reject(); + }, + WrapPersistent(resolver))); + } else { + // Without a user gesture any request for storage access is immediately + // denied. + resolver->Reject(); + } return promise; } @@ -6471,9 +6489,8 @@ KURL Document::OpenSearchDescriptionURL() { Traversal<HTMLLinkElement>::FirstChild(*head()); link_element; link_element = Traversal<HTMLLinkElement>::NextSibling(*link_element)) { - if (!DeprecatedEqualIgnoringCase(link_element->GetType(), - kOpenSearchMIMEType) || - !DeprecatedEqualIgnoringCase(link_element->Rel(), kOpenSearchRelation)) + if (!EqualIgnoringASCIICase(link_element->GetType(), kOpenSearchMIMEType) || + !EqualIgnoringASCIICase(link_element->Rel(), kOpenSearchRelation)) continue; if (link_element->Href().IsEmpty()) continue; @@ -6528,10 +6545,10 @@ String Document::designMode() const { void Document::setDesignMode(const String& value) { bool new_value = design_mode_; - if (DeprecatedEqualIgnoringCase(value, "on")) { + if (EqualIgnoringASCIICase(value, "on")) { new_value = true; UseCounter::Count(*this, WebFeature::kDocumentDesignModeEnabeld); - } else if (DeprecatedEqualIgnoringCase(value, "off")) { + } else if (EqualIgnoringASCIICase(value, "off")) { new_value = false; } if (new_value == design_mode_) @@ -6564,11 +6581,8 @@ Document& Document::TopDocument() const { } Document* Document::ContextDocument() const { - if (context_document_) - return context_document_; - if (frame_) - return const_cast<Document*>(this); - return nullptr; + return context_document_ ? context_document_.Get() + : const_cast<Document*>(this); } Attr* Document::createAttribute(const AtomicString& name, @@ -6665,7 +6679,7 @@ HTMLCollection* Document::DocumentAllNamedItems(const AtomicString& name) { kDocumentAllNamedItems, name); } -LocalDOMWindow* Document::defaultView() const { +DOMWindow* Document::defaultView() const { // The HTML spec requires to return null if the document is detached from the // DOM. However, |dom_window_| is not cleared on the detachment. So, we need // to check |frame_| to tell whether the document is attached or not. @@ -6755,7 +6769,7 @@ void Document::FinishedParsing() { // Forward origin trial freeze policy to the corresponding frame object in // the resource coordinator. if (auto* document_resource_coordinator = GetResourceCoordinator()) - SetOriginTrialFreezePolicy(document_resource_coordinator, this); + SetOriginTrialFreezePolicy(document_resource_coordinator, domWindow()); } // Schedule dropping of the ElementDataCache. We keep it alive for a while @@ -6769,9 +6783,6 @@ void Document::FinishedParsing() { // Parser should have picked up all preloads by now fetcher_->ClearPreloads(ResourceFetcher::kClearSpeculativeMarkupPreloads); - - if (IsPrefetchOnly()) - WebPrerenderingSupport::Current()->PrefetchFinished(); } void Document::ElementDataCacheClearTimerFired(TimerBase*) { @@ -6783,6 +6794,7 @@ void Document::BeginLifecycleUpdatesIfRenderingReady() { return; if (!HaveRenderBlockingResourcesLoaded()) return; + font_preload_manager_.WillBeginRendering(); View()->BeginLifecycleUpdates(); } @@ -6808,23 +6820,30 @@ Vector<IconURL> Document::IconURLs(int icon_types_mask) { // required by the spec. for (HTMLLinkElement* link_element = first_element; link_element; link_element = find_next_candidate(*link_element)) { - if (!(link_element->GetIconType() & icon_types_mask)) + if (!((1 << static_cast<int>(link_element->GetIconType())) & + icon_types_mask)) { continue; + } if (link_element->Href().IsEmpty()) continue; IconURL new_url(link_element->Href(), link_element->IconSizes(), link_element->GetType(), link_element->GetIconType()); - if (link_element->GetIconType() == kFavicon) { - if (first_favicon.icon_type_ != kInvalidIcon) + if (link_element->GetIconType() == + mojom::blink::FaviconIconType::kFavicon) { + if (first_favicon.icon_type_ != mojom::blink::FaviconIconType::kInvalid) secondary_icons.push_back(first_favicon); first_favicon = new_url; - } else if (link_element->GetIconType() == kTouchIcon) { - if (first_touch_icon.icon_type_ != kInvalidIcon) + } else if (link_element->GetIconType() == + mojom::blink::FaviconIconType::kTouchIcon) { + if (first_touch_icon.icon_type_ != + mojom::blink::FaviconIconType::kInvalid) secondary_icons.push_back(first_touch_icon); first_touch_icon = new_url; - } else if (link_element->GetIconType() == kTouchPrecomposedIcon) { - if (first_touch_precomposed_icon.icon_type_ != kInvalidIcon) + } else if (link_element->GetIconType() == + mojom::blink::FaviconIconType::kTouchPrecomposedIcon) { + if (first_touch_precomposed_icon.icon_type_ != + mojom::blink::FaviconIconType::kInvalid) secondary_icons.push_back(first_touch_precomposed_icon); first_touch_precomposed_icon = new_url; } else { @@ -6833,14 +6852,18 @@ Vector<IconURL> Document::IconURLs(int icon_types_mask) { } Vector<IconURL> icon_urls; - if (first_favicon.icon_type_ != kInvalidIcon) + if (first_favicon.icon_type_ != mojom::blink::FaviconIconType::kInvalid) { icon_urls.push_back(first_favicon); - else if (url_.ProtocolIsInHTTPFamily() && icon_types_mask & kFavicon) + } else if (url_.ProtocolIsInHTTPFamily() && + icon_types_mask & 1 << static_cast<int>( + mojom::blink::FaviconIconType::kFavicon)) { icon_urls.push_back(IconURL::DefaultFavicon(url_)); + } - if (first_touch_icon.icon_type_ != kInvalidIcon) + if (first_touch_icon.icon_type_ != mojom::blink::FaviconIconType::kInvalid) icon_urls.push_back(first_touch_icon); - if (first_touch_precomposed_icon.icon_type_ != kInvalidIcon) + if (first_touch_precomposed_icon.icon_type_ != + mojom::blink::FaviconIconType::kInvalid) icon_urls.push_back(first_touch_precomposed_icon); for (int i = secondary_icons.size() - 1; i >= 0; --i) icon_urls.push_back(secondary_icons[i]); @@ -6854,7 +6877,7 @@ base::Optional<Color> Document::ThemeColor() const { for (HTMLMetaElement& meta_element : Traversal<HTMLMetaElement>::DescendantsOf(*root_element)) { Color color; - if (DeprecatedEqualIgnoringCase(meta_element.GetName(), "theme-color") && + if (EqualIgnoringASCIICase(meta_element.GetName(), "theme-color") && CSSParser::ParseColor( color, meta_element.Content().GetString().StripWhiteSpace(), true)) return color; @@ -6866,19 +6889,17 @@ void Document::ColorSchemeMetaChanged() { if (!RuntimeEnabledFeatures::MetaColorSchemeEnabled()) return; - auto* root_element = documentElement(); - if (!root_element) - return; - const CSSValue* color_scheme = nullptr; - for (HTMLMetaElement& meta_element : - Traversal<HTMLMetaElement>::DescendantsOf(*root_element)) { - if (EqualIgnoringASCIICase(meta_element.GetName(), "color-scheme")) { - if ((color_scheme = CSSParser::ParseSingleValue( - CSSPropertyID::kColorScheme, - meta_element.Content().GetString().StripWhiteSpace(), - ElementSheet().Contents()->ParserContext()))) { - break; + if (auto* head_element = head()) { + for (HTMLMetaElement& meta_element : + Traversal<HTMLMetaElement>::DescendantsOf(*head_element)) { + if (EqualIgnoringASCIICase(meta_element.GetName(), "color-scheme")) { + if ((color_scheme = CSSParser::ParseSingleValue( + CSSPropertyID::kColorScheme, + meta_element.Content().GetString().StripWhiteSpace(), + ElementSheet().Contents()->ParserContext()))) { + break; + } } } } @@ -6912,23 +6933,11 @@ HTMLLinkElement* Document::LinkCanonical() const { }); } -void Document::FeaturePolicyInitialized( - const DocumentInit& document_initializer, - const SecurityContextInit& security_initializer) { +void Document::PoliciesInitialized(const DocumentInit& document_initializer) { // Processing of the feature policy header is done before the SecurityContext // is initialized. This method just records the usage. if (!document_initializer.FeaturePolicyHeader().IsEmpty()) UseCounter::Count(*this, WebFeature::kFeaturePolicyHeader); - for (const auto& message : - security_initializer.FeaturePolicyParseMessages()) { - AddConsoleMessage( - ConsoleMessage::Create(mojom::ConsoleMessageSource::kSecurity, - mojom::ConsoleMessageLevel::kError, - "Error with Feature-Policy header: " + message)); - } - if (frame_) { - pending_parsed_headers_ = security_initializer.ParsedHeader(); - } // At this point, the document will not have been installed in the frame's // LocalDOMWindow, so we cannot call frame_->IsFeatureEnabled. This calls @@ -6937,8 +6946,8 @@ void Document::FeaturePolicyInitialized( is_vertical_scroll_enforced_ = frame_ && !frame_->IsMainFrame() && RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled() && - !GetFeaturePolicy()->IsFeatureEnabled( - mojom::FeaturePolicyFeature::kVerticalScroll); + !GetSecurityContext().GetFeaturePolicy()->IsFeatureEnabled( + mojom::blink::FeaturePolicyFeature::kVerticalScroll); } const ParsedFeaturePolicy Document::GetOwnerContainerPolicy() const { @@ -6957,46 +6966,13 @@ const FeaturePolicy* Document::GetParentFeaturePolicy() const { return nullptr; } -void Document::ApplyPendingFeaturePolicyHeaders() { +void Document::ApplyPendingFramePolicyHeaders() { if (frame_) { - frame_->Client()->DidSetFramePolicyHeaders(GetSandboxFlags(), - pending_parsed_headers_); + frame_->Client()->DidSetFramePolicyHeaders( + GetSandboxFlags(), pending_fp_headers_, pending_dp_headers_); } - pending_parsed_headers_.clear(); -} - -void Document::ApplyReportOnlyFeaturePolicyFromHeader( - const String& feature_policy_report_only_header) { - if (feature_policy_report_only_header.IsEmpty()) - return; - // TODO(iclelland): Remove this message when reporting is no longer part of an - // origin trial. - // Note that we do not return here. Instead, the header is parsed and the - // report-only policy is stored, in case a valid Origin Trial token is added - // later. In that case, any subsequent violations will be correctly reported. - if (!RuntimeEnabledFeatures::FeaturePolicyReportingEnabled(this)) { - AddConsoleMessage(ConsoleMessage::Create( - mojom::ConsoleMessageSource::kSecurity, - mojom::ConsoleMessageLevel::kWarning, - "Feature-Policy-Report-Only header will have no effect unless Feature " - "Policy reporting is enabled with an Origin Trial. Sign up at " - "https://developers.chrome.com/origintrials/")); - } - - UseCounter::Count(*this, WebFeature::kFeaturePolicyReportOnlyHeader); - Vector<String> messages; - const ParsedFeaturePolicy& report_only_policy = - FeaturePolicyParser::ParseHeader(feature_policy_report_only_header, - GetSecurityOrigin(), &messages, this); - for (auto& message : messages) { - AddConsoleMessage(ConsoleMessage::Create( - mojom::ConsoleMessageSource::kSecurity, - mojom::ConsoleMessageLevel::kError, - "Error with Feature-Policy-Report-Only header: " + message)); - } - - AddReportOnlyFeaturePolicy(report_only_policy, GetOwnerContainerPolicy(), - GetParentFeaturePolicy()); + pending_fp_headers_.clear(); + pending_dp_headers_.clear(); } bool Document::AllowedToUseDynamicMarkUpInsertion( @@ -7005,8 +6981,9 @@ bool Document::AllowedToUseDynamicMarkUpInsertion( if (!RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled()) { return true; } - if (!frame_ || IsFeatureEnabled(mojom::FeaturePolicyFeature::kDocumentWrite, - ReportOptions::kReportOnFailure)) { + if (!frame_ || + IsFeatureEnabled(mojom::blink::FeaturePolicyFeature::kDocumentWrite, + ReportOptions::kReportOnFailure)) { return true; } @@ -7053,16 +7030,13 @@ FontMatchingMetrics* Document::GetFontMatchingMetrics() { } void Document::InitContentSecurityPolicy(ContentSecurityPolicy* csp) { - SetContentSecurityPolicy(csp); + GetSecurityContext().SetContentSecurityPolicy(csp); GetContentSecurityPolicy()->BindToDelegate( GetContentSecurityPolicyDelegate()); } -void Document::InitSecurityContext( - const DocumentInit& initializer, - const SecurityContextInit& security_initializer) { +void Document::InitSecurityContext(const DocumentInit& initializer) { DCHECK(GetSecurityOrigin()); - // If the CSP was provided by the DocumentLoader or is from ImportsController // it doesn't need to be bound right now. ImportsController takes a reference // to a master document's CSP which is already bound. Document construction @@ -7070,21 +7044,17 @@ void Document::InitSecurityContext( // callbacks from binding the CSP delegate immediately would not get called // if it was bound immediately. eg. Callbacks back to browser or console // logging. - if (security_initializer.BindCSPImmediately()) { - InitContentSecurityPolicy(security_initializer.GetCSP()); - } else { - SetContentSecurityPolicy(security_initializer.GetCSP()); - } if (!initializer.HasSecurityContext()) { // No source for a security context. // This can occur via document.implementation.createDocument(). cookie_url_ = KURL(g_empty_string); return; } - SetInsecureRequestPolicy(initializer.GetInsecureRequestPolicy()); + GetSecurityContext().SetInsecureRequestPolicy( + initializer.GetInsecureRequestPolicy()); if (initializer.InsecureNavigationsToUpgrade()) { for (auto to_upgrade : *initializer.InsecureNavigationsToUpgrade()) - AddInsecureNavigationUpgrade(to_upgrade); + GetSecurityContext().AddInsecureNavigationUpgrade(to_upgrade); } bool inherit_cookie_url_from_owner = initializer.IsSrcdocDocument() || @@ -7095,15 +7065,7 @@ void Document::InitSecurityContext( ? initializer.OwnerDocument()->CookieURL() : url_; - SetAddressSpace(initializer.GetIPAddressSpace()); -} - -void Document::SetSecurityOrigin(scoped_refptr<SecurityOrigin> origin) { - // Enforce that we don't change access, we might change the reference (via - // IsolatedCopy but we can't change the security policy). - CHECK(origin); - CHECK(GetSecurityOrigin()->CanAccess(origin.get())); - SecurityContext::SetSecurityOrigin(origin); + GetSecurityContext().SetAddressSpace(initializer.GetIPAddressSpace()); } void Document::BindContentSecurityPolicy() { @@ -7120,12 +7082,12 @@ bool Document::CanExecuteScripts(ReasonForCallingCanExecuteScripts reason) { // However, there is an exception for cases when the script should bypass the // main world's CSP (such as for privileged isolated worlds). See // https://crbug.com/811528. - if (IsSandboxed(WebSandboxFlags::kScripts) && - !ContentSecurityPolicy::ShouldBypassMainWorld(this)) { + if (IsSandboxed(mojom::blink::WebSandboxFlags::kScripts) && + !ContentSecurityPolicy::ShouldBypassMainWorld(domWindow())) { // FIXME: This message should be moved off the console once a solution to // https://bugs.webkit.org/show_bug.cgi?id=103274 exists. if (reason == kAboutToExecuteScript) { - AddConsoleMessage(ConsoleMessage::Create( + AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( mojom::ConsoleMessageSource::kSecurity, mojom::ConsoleMessageLevel::kError, "Blocked script execution in '" + Url().ElidedString() + @@ -7186,10 +7148,6 @@ bool Document::AllowInlineEventHandler(Node* node, return true; } -bool Document::IsContextThread() const { - return IsMainThread(); -} - void Document::UpdateFocusAppearanceAfterLayout() { update_focus_appearance_after_layout_ = true; } @@ -7238,7 +7196,7 @@ void Document::InitDNSPrefetch() { void Document::ParseDNSPrefetchControlHeader( const String& dns_prefetch_control) { - if (DeprecatedEqualIgnoringCase(dns_prefetch_control, "on") && + if (EqualIgnoringASCIICase(dns_prefetch_control, "on") && !have_explicitly_disabled_dns_prefetch_) { is_dns_prefetch_enabled_ = true; return; @@ -7256,11 +7214,26 @@ IntersectionObserverController& Document::EnsureIntersectionObserverController() { if (!intersection_observer_controller_) { intersection_observer_controller_ = - MakeGarbageCollected<IntersectionObserverController>(this); + MakeGarbageCollected<IntersectionObserverController>( + GetExecutionContext()); } return *intersection_observer_controller_; } +ElementIntersectionObserverData* +Document::DocumentExplicitRootIntersectionObserverData() const { + return document_explicit_root_intersection_observer_data_.Get(); +} + +ElementIntersectionObserverData& +Document::EnsureDocumentExplicitRootIntersectionObserverData() { + if (!document_explicit_root_intersection_observer_data_) { + document_explicit_root_intersection_observer_data_ = + MakeGarbageCollected<ElementIntersectionObserverData>(); + } + return *document_explicit_root_intersection_observer_data_; +} + ResizeObserverController& Document::EnsureResizeObserverController() { if (!resize_observer_controller_) { resize_observer_controller_ = @@ -7269,76 +7242,22 @@ ResizeObserverController& Document::EnsureResizeObserverController() { return *resize_observer_controller_; } -static void RunAddConsoleMessageTask(mojom::ConsoleMessageSource source, - mojom::ConsoleMessageLevel level, - const String& message, - ExecutionContext* context, - bool discard_duplicates) { - ConsoleMessage* console_message = - ConsoleMessage::Create(source, level, message); - context->AddConsoleMessage(console_message, discard_duplicates); +void Document::AddConsoleMessage(ConsoleMessage* message, + bool discard_duplicates) { + // Don't let non-attached Documents spam the console. + if (domWindow()) + domWindow()->AddConsoleMessage(message, discard_duplicates); } -void Document::AddConsoleMessageImpl(ConsoleMessage* console_message, - bool discard_duplicates) { - if (!IsContextThread()) { - PostCrossThreadTask( - *GetTaskRunner(TaskType::kInternalInspector), FROM_HERE, - CrossThreadBindOnce( - &RunAddConsoleMessageTask, console_message->Source(), - console_message->Level(), console_message->Message(), - WrapCrossThreadPersistent(this), discard_duplicates)); - return; - } +void Document::AddInspectorIssue(InspectorIssue* issue) { + Page* page = GetPage(); - if (!frame_) { - if (imports_controller_) { - imports_controller_->Master()->GetFrame()->Console().AddMessage( - console_message); - } + if (!page) { return; } - if (console_message->Location()->IsUnknown()) { - // TODO(dgozman): capture correct location at call places instead. - unsigned line_number = 0; - if (!IsInDocumentWrite() && GetScriptableDocumentParser()) { - ScriptableDocumentParser* parser = GetScriptableDocumentParser(); - if (parser->IsParsingAtLineNumber()) - line_number = parser->LineNumber().OneBasedInt(); - } - Vector<DOMNodeId> nodes(console_message->Nodes()); - console_message = ConsoleMessage::Create( - console_message->Source(), console_message->Level(), - console_message->Message(), - std::make_unique<SourceLocation>(Url().GetString(), line_number, 0, - nullptr)); - console_message->SetNodes(frame_, std::move(nodes)); - } - - frame_->Console().AddMessage(console_message, discard_duplicates); -} - -void Document::TasksWerePaused() { - GetScriptRunner()->Suspend(); - - if (scripted_animation_controller_) - scripted_animation_controller_->Pause(); -} - -void Document::TasksWereUnpaused() { - GetScriptRunner()->Resume(); - - if (scripted_animation_controller_) - scripted_animation_controller_->Unpause(); - - if (dom_window_) - DOMWindowPerformance::performance(*dom_window_)->ResumeSuspendedObservers(); -} - -bool Document::TasksNeedPause() { - Page* page = GetPage(); - return page && page->Paused(); + page->GetInspectorIssueStorage().AddInspectorIssue(GetExecutionContext(), + issue); } void Document::AddToTopLayer(Element* element, const Element* before) { @@ -7441,36 +7360,24 @@ void Document::LoadPluginsSoon() { } void Document::PluginLoadingTimerFired(TimerBase*) { - UpdateStyleAndLayout(); + UpdateStyleAndLayout(DocumentUpdateReason::kPlugin); } -ScriptedAnimationController& Document::EnsureScriptedAnimationController() { - if (!scripted_animation_controller_) { - scripted_animation_controller_ = - MakeGarbageCollected<ScriptedAnimationController>(this); - // We need to make sure that we don't start up the animation controller on a - // background tab, for example. - if (!GetPage()) - scripted_animation_controller_->Pause(); - } +ScriptedAnimationController& Document::GetScriptedAnimationController() { return *scripted_animation_controller_; } int Document::RequestAnimationFrame( FrameRequestCallbackCollection::FrameCallback* callback) { - return EnsureScriptedAnimationController().RegisterFrameCallback(callback); + return scripted_animation_controller_->RegisterFrameCallback(callback); } void Document::CancelAnimationFrame(int id) { - if (!scripted_animation_controller_) - return; scripted_animation_controller_->CancelFrameCallback(id); } void Document::ServiceScriptedAnimations( base::TimeTicks monotonic_animation_start_time) { - if (!scripted_animation_controller_) - return; auto start_time = base::TimeTicks::Now(); scripted_animation_controller_->ServiceScriptedAnimations( monotonic_animation_start_time); @@ -7482,29 +7389,27 @@ void Document::ServiceScriptedAnimations( int Document::RequestPostAnimationFrame( FrameRequestCallbackCollection::FrameCallback* cb) { - return EnsureScriptedAnimationController().RegisterPostFrameCallback(cb); + return scripted_animation_controller_->RegisterPostFrameCallback(cb); } void Document::CancelPostAnimationFrame(int id) { - if (scripted_animation_controller_) - scripted_animation_controller_->CancelPostFrameCallback(id); + scripted_animation_controller_->CancelPostFrameCallback(id); } void Document::RunPostAnimationFrameCallbacks() { bool was_throttled = current_frame_is_throttled_; current_frame_is_throttled_ = false; - if (was_throttled || !scripted_animation_controller_) + if (was_throttled) return; scripted_animation_controller_->RunPostFrameCallbacks(); } ScriptedIdleTaskController& Document::EnsureScriptedIdleTaskController() { if (!scripted_idle_task_controller_) { - scripted_idle_task_controller_ = ScriptedIdleTaskController::Create(this); - // We need to make sure that we don't start up the idle controller if we - // don't have an attached frame and if execution context is destroyed. - if (!frame_ || !frame_->IsAttached() || - ExecutionContext::IsContextDestroyed()) { + scripted_idle_task_controller_ = + ScriptedIdleTaskController::Create(domWindow()); + // We need to make sure that we don't start up if we're detached. + if (!domWindow() || domWindow()->IsContextDestroyed()) { scripted_idle_task_controller_->ContextLifecycleStateChanged( mojom::FrameLifecycleState::kFrozen); } @@ -7541,11 +7446,11 @@ Node* EventTargetNodeForDocument(Document* doc) { if (!doc) return nullptr; Node* node = doc->FocusedElement(); - if (!node && doc->IsPluginDocument()) { - PluginDocument* plugin_document = ToPluginDocument(doc); + auto* plugin_document = DynamicTo<PluginDocument>(doc); + if (plugin_document && !node) { node = plugin_document->PluginNode(); } - if (!node && doc->IsHTMLDocument()) + if (!node && IsA<HTMLDocument>(doc)) node = doc->body(); if (!node) node = doc->documentElement(); @@ -7587,6 +7492,15 @@ SnapCoordinator& Document::GetSnapCoordinator() { return *snap_coordinator_; } +void Document::PerformScrollSnappingTasks() { + SnapCoordinator& snap_coordinator = GetSnapCoordinator(); + if (!snap_coordinator.AnySnapContainerDataNeedsUpdate()) + return; + snap_coordinator.UpdateAllSnapContainerDataIfNeeded(); + if (RuntimeEnabledFeatures::ScrollSnapAfterLayoutEnabled()) + snap_coordinator.ResnapAllContainersIfNeeded(); +} + void Document::SetContextFeatures(ContextFeatures& features) { context_features_ = &features; } @@ -7725,7 +7639,8 @@ bool Document::HaveScriptBlockingStylesheetsLoaded() const { bool Document::HaveRenderBlockingResourcesLoaded() const { return HaveImportsLoaded() && - style_engine_->HaveRenderBlockingStylesheetsLoaded(); + style_engine_->HaveRenderBlockingStylesheetsLoaded() && + !font_preload_manager_.HasPendingRenderBlockingFonts(); } Locale& Document::GetCachedLocale(const AtomicString& locale) { @@ -7757,7 +7672,7 @@ Document& Document::EnsureTemplateDocument() { if (template_document_) return *template_document_; - if (IsHTMLDocument()) { + if (IsA<HTMLDocument>(this)) { template_document_ = MakeGarbageCollected<HTMLDocument>( DocumentInit::Create() .WithContextDocument(ContextDocument()) @@ -7765,7 +7680,9 @@ Document& Document::EnsureTemplateDocument() { .WithNewRegistrationContext()); } else { template_document_ = MakeGarbageCollected<Document>( - DocumentInit::Create().WithURL(BlankURL())); + DocumentInit::Create() + .WithContextDocument(ContextDocument()) + .WithURL(BlankURL())); } template_document_->template_document_host_ = this; // balanced in dtor. @@ -7837,8 +7754,6 @@ void Document::EnqueueAutofocusCandidate(Element& element) { if (index != WTF::kNotFound) autofocus_candidates_.EraseAt(index); autofocus_candidates_.push_back(element); - // ScriptedAnimationController invokes FlushAutofocusCandidates(). - EnsureScriptedAnimationController(); } bool Document::HasAutofocusCandidates() const { @@ -7863,22 +7778,22 @@ void Document::FlushAutofocusCandidates() { if (AdjustedFocusedElement()) { autofocus_candidates_.clear(); autofocus_processed_flag_ = true; - AddConsoleMessage( - ConsoleMessage::Create(mojom::ConsoleMessageSource::kRendering, - mojom::ConsoleMessageLevel::kInfo, - "Autofocus processing was blocked because a " - "document already has a focused element.")); + AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::ConsoleMessageSource::kRendering, + mojom::ConsoleMessageLevel::kInfo, + "Autofocus processing was blocked because a " + "document already has a focused element.")); return; } if (HasNonEmptyFragment()) { autofocus_candidates_.clear(); autofocus_processed_flag_ = true; - AddConsoleMessage( - ConsoleMessage::Create(mojom::ConsoleMessageSource::kRendering, - mojom::ConsoleMessageLevel::kInfo, - "Autofocus processing was blocked because a " - "document's URL has a fragment '#" + - Url().FragmentIdentifier() + "'.")); + AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::ConsoleMessageSource::kRendering, + mojom::ConsoleMessageLevel::kInfo, + "Autofocus processing was blocked because a " + "document's URL has a fragment '#" + + Url().FragmentIdentifier() + "'.")); return; } @@ -7933,12 +7848,12 @@ void Document::FlushAutofocusCandidates() { doc = &frameOwner->GetDocument(); } if (doc->HasNonEmptyFragment()) { - AddConsoleMessage( - ConsoleMessage::Create(mojom::ConsoleMessageSource::kRendering, - mojom::ConsoleMessageLevel::kInfo, - "Autofocus processing was blocked because a " - "document's URL has a fragment '#" + - doc->Url().FragmentIdentifier() + "'.")); + AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::ConsoleMessageSource::kRendering, + mojom::ConsoleMessageLevel::kInfo, + "Autofocus processing was blocked because a " + "document's URL has a fragment '#" + + doc->Url().FragmentIdentifier() + "'.")); continue; } DCHECK_EQ(doc, this); @@ -8093,23 +8008,11 @@ void Document::PlatformColorsChanged() { GetStyleEngine().PlatformColorsChanged(); } -bool Document::IsSecureContext(String& error_message) const { - if (!IsSecureContext()) { - error_message = SecurityOrigin::IsPotentiallyTrustworthyErrorMessage(); - return false; - } - return true; -} - -bool Document::IsSecureContext() const { - return secure_context_state_ == SecureContextState::kSecure; -} - void Document::DidEnforceInsecureRequestPolicy() { if (!GetFrame()) return; GetFrame()->GetLocalFrameHostRemote().EnforceInsecureRequestPolicy( - GetInsecureRequestPolicy()); + GetSecurityContext().GetInsecureRequestPolicy()); } void Document::DidEnforceInsecureNavigationsSet() { @@ -8117,18 +8020,7 @@ void Document::DidEnforceInsecureNavigationsSet() { return; GetFrame()->GetLocalFrameHostRemote().EnforceInsecureNavigationsSet( SecurityContext::SerializeInsecureNavigationSet( - InsecureNavigationsToUpgrade())); -} - -void Document::CountDetachingNodeAccessInDOMNodeRemovedHandler() { - auto state = GetInDOMNodeRemovedHandlerState(); - DCHECK_NE(state, InDOMNodeRemovedHandlerState::kNone); - UseCounter::Count( - *this, - state == InDOMNodeRemovedHandlerState::kDOMNodeRemoved - ? WebFeature::kDOMNodeRemovedEventHandlerAccessDetachingNode - : WebFeature:: - kDOMNodeRemovedFromDocumentEventHandlerAccessDetachingNode); + GetSecurityContext().InsecureNavigationsToUpgrade())); } void Document::SetShadowCascadeOrder(ShadowCascadeOrder order) { @@ -8194,13 +8086,6 @@ CoreProbeSink* Document::GetProbeSink() { return probe::ToCoreProbeSink(frame); } -service_manager::InterfaceProvider* Document::GetInterfaceProvider() { - if (!GetFrame()) - return nullptr; - - return &GetFrame()->GetInterfaceProvider(); -} - BrowserInterfaceBrokerProxy& Document::GetBrowserInterfaceBroker() { if (!GetFrame()) return GetEmptyBrowserInterfaceBroker(); @@ -8218,17 +8103,7 @@ DocumentResourceCoordinator* Document::GetResourceCoordinator() { FrameOrWorkerScheduler* Document::GetScheduler() { DCHECK(IsMainThread()); - - if (ContextDocument() && ContextDocument()->GetFrame()) - return ContextDocument()->GetFrame()->GetFrameScheduler(); - // In most cases, ContextDocument() will get us to a relevant Frame. In some - // cases, though, there isn't a good candidate (most commonly when either the - // passed-in document or ContextDocument() used to be attached to a Frame but - // has since been detached). - if (!detached_scheduler_) { - detached_scheduler_ = scheduler::CreateDummyFrameScheduler(); - } - return detached_scheduler_.get(); + return GetExecutionContext()->GetScheduler(); } scoped_refptr<base::SingleThreadTaskRunner> Document::GetTaskRunner( @@ -8278,7 +8153,9 @@ StylePropertyMapReadOnly* Document::RemoveComputedStyleMapItem( } void Document::Trace(Visitor* visitor) { + visitor->Trace(security_context_); visitor->Trace(imports_controller_); + visitor->Trace(use_counter_during_construction_); visitor->Trace(doc_type_); visitor->Trace(implementation_); visitor->Trace(autofocus_candidates_); @@ -8300,6 +8177,7 @@ void Document::Trace(Visitor* visitor) { visitor->Trace(elem_sheet_); visitor->Trace(node_iterators_); visitor->Trace(ranges_); + visitor->Trace(document_explicit_root_intersection_observer_data_); visitor->Trace(style_engine_); visitor->Trace(form_controller_); visitor->Trace(visited_link_state_); @@ -8325,6 +8203,7 @@ void Document::Trace(Visitor* visitor) { visitor->Trace(template_document_host_); visitor->Trace(user_action_elements_); visitor->Trace(svg_extensions_); + visitor->Trace(document_animations_); visitor->Trace(timeline_); visitor->Trace(pending_animations_); visitor->Trace(worklet_animation_controller_); @@ -8338,21 +8217,22 @@ void Document::Trace(Visitor* visitor) { visitor->Trace(policy_); visitor->Trace(slot_assignment_engine_); visitor->Trace(viewport_data_); + visitor->Trace(display_lock_contexts_); visitor->Trace(navigation_initiator_); visitor->Trace(lazy_load_image_observer_); visitor->Trace(isolated_world_csp_map_); visitor->Trace(find_in_page_root_); visitor->Trace(computed_node_mapping_); visitor->Trace(mime_handler_view_before_unload_event_listener_); + visitor->Trace(cookie_jar_); + visitor->Trace(synchronous_mutation_observer_list_); visitor->Trace(element_explicitly_set_attr_elements_map_); visitor->Trace(display_lock_activation_observer_); + visitor->Trace(permission_service_); + visitor->Trace(font_preload_manager_); Supplementable<Document>::Trace(visitor); TreeScope::Trace(visitor); ContainerNode::Trace(visitor); - ExecutionContext::Trace(visitor); - SecurityContext::Trace(visitor); - DocumentShutdownNotifier::Trace(visitor); - SynchronousMutationNotifier::Trace(visitor); } void Document::RecordUkmOutliveTimeAfterShutdown(int outlive_time_count) { @@ -8368,13 +8248,11 @@ void Document::RecordUkmOutliveTimeAfterShutdown(int outlive_time_count) { } bool Document::CurrentFrameHadRAF() const { - return scripted_animation_controller_ && - scripted_animation_controller_->CurrentFrameHadRAF(); + return scripted_animation_controller_->CurrentFrameHadRAF(); } bool Document::NextFrameHasPendingRAF() const { - return scripted_animation_controller_ && - scripted_animation_controller_->NextFrameHasPendingRAF(); + return scripted_animation_controller_->NextFrameHasPendingRAF(); } void Document::NavigateLocalAdsFrames() { @@ -8384,9 +8262,8 @@ void Document::NavigateLocalAdsFrames() { child = child->Tree().TraverseNext(frame_)) { if (auto* child_local_frame = DynamicTo<LocalFrame>(child)) { if (child_local_frame->IsAdSubframe()) { - child_local_frame->Navigate( - FrameLoadRequest(this, ResourceRequest(BlankURL())), - WebFrameLoadType::kStandard); + FrameLoadRequest request(this, ResourceRequest(BlankURL())); + child_local_frame->Navigate(request, WebFrameLoadType::kStandard); } } // TODO(yuzus): Once AdsTracker for remote frames is implemented and OOPIF @@ -8412,11 +8289,14 @@ bool Document::IsSlotAssignmentOrLegacyDistributionDirty() const { bool Document::IsLazyLoadPolicyEnforced() const { return RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled() && - !GetFeaturePolicy()->IsFeatureEnabled( - mojom::FeaturePolicyFeature::kLazyLoad); + !GetSecurityContext().GetFeaturePolicy()->IsFeatureEnabled( + mojom::blink::FeaturePolicyFeature::kLazyLoad); } bool Document::IsFocusAllowed() const { + if (frame_ && frame_->GetPage()->InsidePortal()) + return false; + if (!frame_ || frame_->IsMainFrame() || LocalFrame::HasTransientUserActivation(frame_)) { // 'autofocus' runs Element::focus asynchronously at which point the @@ -8425,7 +8305,7 @@ bool Document::IsFocusAllowed() const { } WebFeature uma_type; - bool sandboxed = IsSandboxed(WebSandboxFlags::kNavigation); + bool sandboxed = IsSandboxed(mojom::blink::WebSandboxFlags::kNavigation); bool ad = frame_->IsAdSubframe(); if (sandboxed) { uma_type = ad ? WebFeature::kFocusWithoutUserActivationSandboxedAdFrame @@ -8439,7 +8319,7 @@ bool Document::IsFocusAllowed() const { if (!RuntimeEnabledFeatures::BlockingFocusWithoutUserActivationEnabled()) return true; return IsFeatureEnabled( - mojom::FeaturePolicyFeature::kFocusWithoutUserActivation); + mojom::blink::FeaturePolicyFeature::kFocusWithoutUserActivation); } NavigationInitiatorImpl& Document::NavigationInitiator() { @@ -8463,11 +8343,12 @@ WindowAgent& Document::GetWindowAgent() { } void Document::CountPotentialFeaturePolicyViolation( - mojom::FeaturePolicyFeature feature) const { + mojom::blink::FeaturePolicyFeature feature) const { wtf_size_t index = static_cast<wtf_size_t>(feature); if (potentially_violated_features_.size() == 0) { potentially_violated_features_.resize( - static_cast<wtf_size_t>(mojom::FeaturePolicyFeature::kMaxValue) + 1); + static_cast<wtf_size_t>(mojom::blink::FeaturePolicyFeature::kMaxValue) + + 1); } else if (potentially_violated_features_[index]) { return; } @@ -8476,8 +8357,8 @@ void Document::CountPotentialFeaturePolicyViolation( feature); } void Document::ReportFeaturePolicyViolation( - mojom::FeaturePolicyFeature feature, - mojom::FeaturePolicyDisposition disposition, + mojom::blink::FeaturePolicyFeature feature, + mojom::blink::PolicyDisposition disposition, const String& message, const String& source_file) const { if (!RuntimeEnabledFeatures::FeaturePolicyReportingEnabled(this)) @@ -8489,7 +8370,7 @@ void Document::ReportFeaturePolicyViolation( // Construct the feature policy violation report. const String& feature_name = GetNameForFeature(feature); const String& disp_str = - (disposition == mojom::FeaturePolicyDisposition::kReport ? "report" + (disposition == mojom::blink::PolicyDisposition::kReport ? "report" : "enforce"); FeaturePolicyViolationReportBody* body = @@ -8504,12 +8385,12 @@ void Document::ReportFeaturePolicyViolation( ReportType::kFeaturePolicyViolation, Url().GetString(), body); // Send the feature policy violation report to any ReportingObservers. - auto* reporting_context = ReportingContext::From(this); + auto* reporting_context = ReportingContext::From(domWindow()); reporting_context->QueueReport(report); // TODO(iclelland): Report something different in report-only mode - if (disposition == mojom::FeaturePolicyDisposition::kEnforce) { - frame->Console().AddMessage(ConsoleMessage::Create( + if (disposition == mojom::blink::PolicyDisposition::kEnforce) { + frame->Console().AddMessage(MakeGarbageCollected<ConsoleMessage>( mojom::ConsoleMessageSource::kViolation, mojom::ConsoleMessageLevel::kError, (message.IsEmpty() ? ("Feature policy violation: " + feature_name + @@ -8518,36 +8399,144 @@ void Document::ReportFeaturePolicyViolation( } } +void Document::ReportDocumentPolicyViolation( + mojom::blink::DocumentPolicyFeature feature, + mojom::blink::PolicyDisposition disposition, + const String& message, + const String& source_file) const { + LocalFrame* frame = GetFrame(); + if (!frame) + return; + + // Construct the document policy violation report. + const String& feature_name = + GetDocumentPolicyFeatureInfoMap().at(feature).feature_name.c_str(); + bool is_report_only = disposition == mojom::blink::PolicyDisposition::kReport; + const String& disp_str = is_report_only ? "report" : "enforce"; + const DocumentPolicy* relevant_document_policy = + is_report_only ? GetSecurityContext().GetReportOnlyDocumentPolicy() + : GetSecurityContext().GetDocumentPolicy(); + + DocumentPolicyViolationReportBody* body = + source_file.IsEmpty() + ? MakeGarbageCollected<DocumentPolicyViolationReportBody>( + feature_name, "Document policy violation", disp_str) + : MakeGarbageCollected<DocumentPolicyViolationReportBody>( + feature_name, "Document policy violation", disp_str, + source_file); + + Report* report = MakeGarbageCollected<Report>( + ReportType::kDocumentPolicyViolation, Url().GetString(), body); + + // Send the document policy violation report to any ReportingObservers. + auto* reporting_context = ReportingContext::From(domWindow()); + const base::Optional<std::string> endpoint = + relevant_document_policy->GetFeatureEndpoint(feature); + + reporting_context->QueueReport( + report, endpoint ? Vector<String>{endpoint->c_str()} : Vector<String>{}); + + // TODO(iclelland): Report something different in report-only mode + if (!is_report_only) { + frame->Console().AddMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::blink::ConsoleMessageSource::kViolation, + mojom::blink::ConsoleMessageLevel::kError, + (message.IsEmpty() ? ("Document policy violation: " + feature_name + + " is not allowed in this document.") + : message))); + } +} + void Document::IncrementNumberOfCanvases() { num_canvases_++; } -void Document::AddActivationBlockingDisplayLock() { - ++activation_blocking_display_lock_count_; +void Document::IncrementDisplayLockBlockingAllActivation() { + ++display_lock_blocking_all_activation_count_; } -void Document::RemoveActivationBlockingDisplayLock() { - DCHECK_GT(activation_blocking_display_lock_count_, 0); - --activation_blocking_display_lock_count_; +void Document::DecrementDisplayLockBlockingAllActivation() { + DCHECK_GT(display_lock_blocking_all_activation_count_, 0); + --display_lock_blocking_all_activation_count_; } -int Document::ActivationBlockingDisplayLockCount() const { - return activation_blocking_display_lock_count_; +int Document::DisplayLockBlockingAllActivationCount() const { + return display_lock_blocking_all_activation_count_; } void Document::AddLockedDisplayLock() { ++locked_display_lock_count_; + TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"), + "LockedDisplayLockCount", TRACE_ID_LOCAL(this), + locked_display_lock_count_); } void Document::RemoveLockedDisplayLock() { DCHECK_GT(locked_display_lock_count_, 0); --locked_display_lock_count_; + TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("blink.debug.display_lock"), + "LockedDisplayLockCount", TRACE_ID_LOCAL(this), + locked_display_lock_count_); } int Document::LockedDisplayLockCount() const { return locked_display_lock_count_; } +void Document::AddDisplayLockContext(DisplayLockContext* context) { + display_lock_contexts_.insert(context); +} + +void Document::RemoveDisplayLockContext(DisplayLockContext* context) { + display_lock_contexts_.erase(context); +} + +int Document::DisplayLockCount() const { + return display_lock_contexts_.size(); +} + +void Document::NotifySelectionRemovedFromDisplayLocks() { + for (auto context : display_lock_contexts_) + context->NotifySubtreeLostSelection(); +} + +Document::ScopedForceActivatableDisplayLocks +Document::GetScopedForceActivatableLocks() { + return ScopedForceActivatableDisplayLocks(this); +} + +Document::ScopedForceActivatableDisplayLocks:: + ScopedForceActivatableDisplayLocks(Document* document) + : document_(document) { + if (++document_->activatable_display_locks_forced_ == 1) { + for (auto context : document_->display_lock_contexts_) + context->DidForceActivatableDisplayLocks(); + } +} + +Document::ScopedForceActivatableDisplayLocks:: + ScopedForceActivatableDisplayLocks( + ScopedForceActivatableDisplayLocks&& other) + : document_(other.document_) { + other.document_ = nullptr; +} + +Document::ScopedForceActivatableDisplayLocks& +Document::ScopedForceActivatableDisplayLocks::operator=( + ScopedForceActivatableDisplayLocks&& other) { + document_ = other.document_; + other.document_ = nullptr; + return *this; +} + +Document::ScopedForceActivatableDisplayLocks:: + ~ScopedForceActivatableDisplayLocks() { + if (!document_) + return; + DCHECK(document_->activatable_display_locks_forced_); + --document_->activatable_display_locks_forced_; +} + void Document::RegisterDisplayLockActivationObservation(Element* element) { EnsureDisplayLockActivationObserver().observe(element); } @@ -8566,22 +8555,28 @@ IntersectionObserver& Document::EnsureDisplayLockActivationObserver() { {Length::Percent(50.f)}, {std::numeric_limits<float>::min()}, this, WTF::BindRepeating(&Document::ProcessDisplayLockActivationObservation, WrapWeakPersistent(this)), - IntersectionObserver::kPostTaskToDeliver); + IntersectionObserver::kDeliverDuringPostLifecycleSteps); } return *display_lock_activation_observer_; } void Document::ProcessDisplayLockActivationObservation( const HeapVector<Member<IntersectionObserverEntry>>& entries) { + DCHECK(View()); for (auto& entry : entries) { + auto* context = entry->target()->GetDisplayLockContext(); + DCHECK(context); if (entry->isIntersecting()) { - auto* context = entry->target()->GetDisplayLockContext(); - DCHECK(context); - DCHECK(context->ShouldCommitForActivation( - DisplayLockActivationReason::kViewportIntersection)); - context->CommitForActivationWithSignal(entry->target()); + View()->EnqueueStartOfLifecycleTask( + WTF::Bind(&DisplayLockContext::NotifyIsIntersectingViewport, + WrapWeakPersistent(context))); + } else { + View()->EnqueueStartOfLifecycleTask( + WTF::Bind(&DisplayLockContext::NotifyIsNotIntersectingViewport, + WrapWeakPersistent(context))); } } + View()->ScheduleAnimation(); } void Document::ExecuteJavaScriptUrls() { @@ -8600,7 +8595,7 @@ void Document::ExecuteJavaScriptUrls() { void Document::ProcessJavaScriptUrl( const KURL& url, - ContentSecurityPolicyDisposition disposition) { + network::mojom::CSPDisposition disposition) { DCHECK(url.ProtocolIsJavaScript()); if (frame_->Loader().StateMachine()->IsDisplayingInitialEmptyDocument()) load_event_progress_ = kLoadEventNotRun; @@ -8667,146 +8662,55 @@ void Document::SetShowBeforeUnloadDialog(bool show_dialog) { show_dialog); } -const Document* DocumentForTrustedTypes(const Document* doc) { - // The Trusted Type factory & friends are stored on the window. For - // programmatically created docs (like createHTMLDocument) let's use the one - // from the context document. - DCHECK(doc); - while (doc->ContextDocument() && !doc->ExecutingWindow()) - doc = doc->ContextDocument(); - return doc; +void Document::ColorSchemeChanged() { + UpdateForcedColors(); + GetStyleEngine().ColorSchemeChanged(); + MediaQueryAffectingValueChanged(MediaValueChange::kOther); } -TrustedTypePolicyFactory* Document::GetTrustedTypes() const { - const Document* doc = DocumentForTrustedTypes(this); - return doc->ExecutingWindow() ? doc->ExecutingWindow()->trustedTypes() - : nullptr; +void Document::VisionDeficiencyChanged() { + GetStyleEngine().VisionDeficiencyChanged(); } -bool Document::RequireTrustedTypes() const { - return DocumentForTrustedTypes(this)->ExecutionContext::RequireTrustedTypes(); +void Document::UpdateForcedColors() { + auto* web_theme_engine = + RuntimeEnabledFeatures::ForcedColorsEnabled() && Platform::Current() + ? Platform::Current()->ThemeEngine() + : nullptr; + ForcedColors forced_colors = web_theme_engine + ? web_theme_engine->GetForcedColors() + : ForcedColors::kNone; + in_forced_colors_mode_ = forced_colors != ForcedColors::kNone; } -void Document::ColorSchemeChanged() { - GetStyleEngine().ColorSchemeChanged(); - MediaQueryAffectingValueChanged(); +bool Document::InForcedColorsMode() const { + return in_forced_colors_mode_ && !Printing(); } -bool Document::InForcedColorsMode() const { - return RuntimeEnabledFeatures::ForcedColorsEnabled() && Platform::Current() && - Platform::Current()->ThemeEngine() && - Platform::Current()->ThemeEngine()->GetForcedColors() != - ForcedColors::kNone; +bool Document::IsCrossSiteSubframe() const { + // It'd be nice to avoid the url::Origin temporaries, but that would require + // exposing the net internal helper. + // TODO: If the helper gets exposed, we could do this without any new + // allocations using StringUTF8Adaptor. + return TopFrameOrigin() && + !net::registry_controlled_domains::SameDomainOrHost( + TopFrameOrigin()->ToUrlOrigin(), + GetSecurityOrigin()->ToUrlOrigin(), + net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); } void Document::CountUse(mojom::WebFeature feature) const { - if (DocumentLoader* loader = Loader()) { + if (use_counter_during_construction_) + use_counter_during_construction_->CountUse(feature); + else if (DocumentLoader* loader = Loader()) loader->CountUse(feature); - } } void Document::CountUse(mojom::WebFeature feature) { - if (DocumentLoader* loader = Loader()) { + if (use_counter_during_construction_) + use_counter_during_construction_->CountUse(feature); + else if (DocumentLoader* loader = Loader()) loader->CountUse(feature); - } -} - -void Document::RecordCallInDetachedWindow( - v8::Isolate::UseCounterFeature reason) { - // Emit each reason only once (max twice, in the case explained below). - // We're mainly interested if this kind of call occurred in a page or not. - // It would be nice to count how many times, but that would flood the UKM - // infrastructure with too many events. - if (calls_in_detached_window_emitted_.Contains(reason)) - return; - - if (navigation_source_id_ == ukm::kInvalidSourceId) { - // It's possible that navigation_source_id_ isn't set yet. Emit the event - // with invalid ID (at most once) so that we could potentially make use of - // it in combination with DocumentCreated event, using document's source ID. - // However, save it to give it a chance to be emitted again with valid - // navigation_source_id_. - if (calls_in_detached_window_orphaned_.Contains(reason)) - return; - calls_in_detached_window_orphaned_.insert(reason); - } - - HashSet<v8::Isolate::UseCounterFeature> reasons; - reasons.insert(reason); - EmitDetachedWindowsUkmEvent(reasons); -} - -void Document::SetNavigationSourceId(int64_t source_id) { - navigation_source_id_ = source_id; - if (navigation_source_id_ != ukm::kInvalidSourceId) { - // Now that a valid navigation_source_id_ is set, re-emit the DetacheWindows - // event for cases that were emitted with invalid ID. - EmitDetachedWindowsUkmEvent(calls_in_detached_window_orphaned_); - calls_in_detached_window_orphaned_.clear(); - } -} - -void Document::EmitDetachedWindowsUkmEvent( - const HashSet<v8::Isolate::UseCounterFeature>& reasons) { - if (reasons.IsEmpty()) - return; - - DCHECK_NE(ukm_source_id_, ukm::kInvalidSourceId); - ukm::builders::DetachedWindows_Experimental builder(ukm_source_id_); - // Invalid ID should be 0 to take advantage of the protobuf default. - DCHECK_EQ(ukm::kInvalidSourceId, 0); - if (navigation_source_id_ != ukm::kInvalidSourceId) - builder.SetNavigationSourceId(navigation_source_id_); - for (auto reason : reasons) { - if (navigation_source_id_ != ukm::kInvalidSourceId) - calls_in_detached_window_emitted_.insert(reason); - - switch (reason) { - case v8::Isolate::kCallInDetachedWindowByNavigation: - builder.SetNumberOfCallsInDetachedWindowByNavigation(1); - break; - case v8::Isolate::kCallInDetachedWindowByNavigationAfter10s: - builder - .SetNumberOfCallsInDetachedWindowByNavigation_After10sSinceDetaching( - 1); - break; - case v8::Isolate::kCallInDetachedWindowByNavigationAfter1min: - builder - .SetNumberOfCallsInDetachedWindowByNavigation_After1minSinceDetaching( - 1); - break; - case v8::Isolate::kCallInDetachedWindowByClosing: - builder.SetNumberOfCallsInDetachedWindowByClosing(1); - break; - case v8::Isolate::kCallInDetachedWindowByClosingAfter10s: - builder - .SetNumberOfCallsInDetachedWindowByClosing_After10sSinceDetaching( - 1); - break; - case v8::Isolate::kCallInDetachedWindowByClosingAfter1min: - builder - .SetNumberOfCallsInDetachedWindowByClosing_After1minSinceDetaching( - 1); - break; - case v8::Isolate::kCallInDetachedWindowByOtherReason: - builder.SetNumberOfCallsInDetachedWindowByOtherReason(1); - break; - case v8::Isolate::kCallInDetachedWindowByOtherReasonAfter10s: - builder - .SetNumberOfCallsInDetachedWindowByOtherReason_After10sSinceDetaching( - 1); - break; - case v8::Isolate::kCallInDetachedWindowByOtherReasonAfter1min: - builder - .SetNumberOfCallsInDetachedWindowByOtherReason_After1minSinceDetaching( - 1); - break; - default: - LOG(DFATAL) << "Use counter not related to detached windows: " - << reason; - } - } - builder.Record(UkmRecorder()); } void Document::CountDeprecation(mojom::WebFeature feature) { @@ -8828,7 +8732,17 @@ void Document::CountDeprecation(mojom::WebFeature feature) { CountUse(WebFeature::kDocumentRegisterElementOnReverseOriginTrials); } } - Deprecation::CountDeprecation(Loader(), feature); + + // Don't count usage of WebComponentsV0 for chrome:// URLs, but still report + // the deprecation messages. + if (Url().ProtocolIs("chrome") && + (feature == WebFeature::kHTMLImports || + feature == WebFeature::kElementCreateShadowRoot || + feature == WebFeature::kDocumentRegisterElement)) { + Deprecation::DeprecationWarningOnly(Loader(), feature); + } else { + Deprecation::CountDeprecation(Loader(), feature); + } } void Document::CountProperty(CSSPropertyID property) const { @@ -8848,7 +8762,7 @@ void Document::CountAnimatedProperty(CSSPropertyID property) const { void Document::CountUseOnlyInCrossOriginIframe( mojom::WebFeature feature) const { LocalFrame* frame = GetFrame(); - if (frame && frame->IsCrossOriginSubframe()) + if (frame && frame->IsCrossOriginToMainFrame()) CountUse(feature); } @@ -8880,6 +8794,19 @@ void Document::ClearUseCounterForTesting(mojom::WebFeature feature) { loader->GetUseCounterHelper().ClearMeasurementForTesting(feature); } +void Document::FontPreloadingFinishedOrTimedOut() { + DCHECK(!font_preload_manager_.HasPendingRenderBlockingFonts()); + if (IsA<HTMLDocument>(this) && body()) { + // For HTML, we resume only when we're past the body tag, so that we should + // have something to paint now. + BeginLifecycleUpdatesIfRenderingReady(); + } else if (!IsA<HTMLDocument>(this) && documentElement()) { + // For non-HTML there is no body so resume as soon as font preloading is + // done or has timed out. + BeginLifecycleUpdatesIfRenderingReady(); + } +} + template class CORE_TEMPLATE_EXPORT Supplement<Document>; } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/document.h b/chromium/third_party/blink/renderer/core/dom/document.h index 3d25b6321cb..6733851f425 100644 --- a/chromium/third_party/blink/renderer/core/dom/document.h +++ b/chromium/third_party/blink/renderer/core/dom/document.h @@ -36,25 +36,24 @@ #include "base/memory/scoped_refptr.h" #include "base/timer/elapsed_timer.h" +#include "net/cookies/site_for_cookies.h" #include "services/metrics/public/cpp/ukm_source_id.h" -#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" -#include "third_party/blink/public/mojom/ukm/ukm.mojom-blink.h" -#include "third_party/blink/public/platform/web_focus_type.h" -#include "third_party/blink/public/platform/web_insecure_request_policy.h" +#include "third_party/blink/public/common/metrics/document_update_reason.h" +#include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h" +#include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h" +#include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h" #include "third_party/blink/renderer/core/accessibility/axid.h" #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/css/media_value_change.h" #include "third_party/blink/renderer/core/dom/container_node.h" #include "third_party/blink/renderer/core/dom/create_element_flags.h" #include "third_party/blink/renderer/core/dom/document_encoding_data.h" #include "third_party/blink/renderer/core/dom/document_lifecycle.h" -#include "third_party/blink/renderer/core/dom/document_shutdown_notifier.h" -#include "third_party/blink/renderer/core/dom/document_shutdown_observer.h" #include "third_party/blink/renderer/core/dom/document_timing.h" #include "third_party/blink/renderer/core/dom/frame_request_callback_collection.h" #include "third_party/blink/renderer/core/dom/live_node_list_registry.h" #include "third_party/blink/renderer/core/dom/qualified_name.h" #include "third_party/blink/renderer/core/dom/scripted_idle_task_controller.h" -#include "third_party/blink/renderer/core/dom/synchronous_mutation_notifier.h" #include "third_party/blink/renderer/core/dom/synchronous_mutation_observer.h" #include "third_party/blink/renderer/core/dom/text_link_colors.h" #include "third_party/blink/renderer/core/dom/tree_scope.h" @@ -62,10 +61,12 @@ #include "third_party/blink/renderer/core/editing/forward.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/execution_context/security_context.h" -#include "third_party/blink/renderer/core/frame/hosts_using_features.h" #include "third_party/blink/renderer/core/html/custom/v0_custom_element.h" #include "third_party/blink/renderer/core/html/parser/parser_synchronization_policy.h" +#include "third_party/blink/renderer/core/loader/font_preload_manager.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" +#include "third_party/blink/renderer/platform/heap_observer_list.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h" #include "third_party/blink/renderer/platform/timer.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" @@ -80,6 +81,12 @@ namespace ukm { class UkmRecorder; } // namespace ukm +namespace network { +namespace mojom { +enum class CSPDisposition : int32_t; +} // namespace mojom +} // namespace network + namespace blink { class AnimationClock; @@ -92,11 +99,15 @@ class CSSStyleSheet; class CanvasFontCache; class ChromeClient; class Comment; +class CompositorAnimationTimeline; class ComputedAccessibleNode; +class DisplayLockContext; +class ElementIntersectionObserverData; class WindowAgent; class WindowAgentFactory; class ComputedStyle; class ConsoleMessage; +class InspectorIssue; class ContextFeatures; class CookieJar; class V0CustomElementMicrotaskRunQueue; @@ -112,6 +123,7 @@ class DocumentOutliveTimeReporter; class DocumentParser; class DocumentResourceCoordinator; class DocumentState; +class DocumentAnimations; class DocumentTimeline; class DocumentType; class DOMFeaturePolicy; @@ -130,6 +142,7 @@ class FontMatchingMetrics; class FormController; class HTMLAllCollection; class HTMLBodyElement; +class FrameScheduler; class HTMLCollection; class HTMLDialogElement; class HTMLElement; @@ -178,6 +191,7 @@ class ScriptPromise; class ScriptRunner; class ScriptableDocumentParser; class ScriptedAnimationController; +class SecurityContextInit; class SecurityOrigin; class SelectorQueryCache; class SerializedScriptValue; @@ -198,9 +212,7 @@ class VisitedLinkState; class WebComputedAXTree; class WebMouseEvent; class WorkletAnimationController; -enum ContentSecurityPolicyDisposition : uint8_t; enum class CSSPropertyID; -enum class ScrollbarMode; struct AnnotatedRegionValue; struct FocusParams; struct IconURL; @@ -238,8 +250,6 @@ enum ShadowCascadeOrder { kShadowCascadeV1 }; -enum class SecureContextState { kNonSecure, kSecure }; - using DocumentClassFlags = unsigned char; // A map of IDL attribute name to Element value, for one particular element. @@ -262,10 +272,8 @@ using ExplicitlySetAttrElementsMap = // the user in a frame and an execution context for JavaScript code. class CORE_EXPORT Document : public ContainerNode, public TreeScope, - public SecurityContext, - public ExecutionContext, - public DocumentShutdownNotifier, - public SynchronousMutationNotifier, + public UseCounter, + public FeaturePolicyParserDelegate, public Supplementable<Document> { DEFINE_WRAPPERTYPEINFO(); USING_GARBAGE_COLLECTED_MIXIN(Document); @@ -292,17 +300,129 @@ class CORE_EXPORT Document : public ContainerNode, MediaQueryMatcher& GetMediaQueryMatcher(); - void MediaQueryAffectingValueChanged(); + void MediaQueryAffectingValueChanged(MediaValueChange change); - using SecurityContext::GetContentSecurityPolicy; - using SecurityContext::GetMutableSecurityOrigin; - using SecurityContext::GetSecurityOrigin; using TreeScope::getElementById; - // ExecutionContext overrides: - bool IsDocument() const final { return true; } - bool ShouldInstallV8Extensions() const final; - ContentSecurityPolicy* GetContentSecurityPolicyForWorld() override; + // TODO(crbug.com/1029822) Former ExecutionContext overrides. Most of these + // should move to LocalDOMWindow. + ContentSecurityPolicy* GetContentSecurityPolicyForWorld(); + LocalDOMWindow* ExecutingWindow() const; + String UserAgent() const; + // TODO(https://crbug.com/880986): Implement Document's HTTPS state in more + // spec-conformant way. + HttpsState GetHttpsState() const { + return CalculateHttpsState(GetSecurityOrigin()); + } + bool CanExecuteScripts(ReasonForCallingCanExecuteScripts); + String OutgoingReferrer() const; + network::mojom::ReferrerPolicy GetReferrerPolicy() const; + CoreProbeSink* GetProbeSink(); + BrowserInterfaceBrokerProxy& GetBrowserInterfaceBroker(); + FrameOrWorkerScheduler* GetScheduler(); + void CountPotentialFeaturePolicyViolation( + mojom::blink::FeaturePolicyFeature) const; + void ReportFeaturePolicyViolation( + mojom::blink::FeaturePolicyFeature, + mojom::blink::PolicyDisposition, + const String& message = g_empty_string, + // If source_file is set to empty string, + // current JS file would be used as source_file instead. + const String& source_file = g_empty_string) const; + void ReportDocumentPolicyViolation( + mojom::blink::DocumentPolicyFeature, + mojom::blink::PolicyDisposition disposition, + const String& message = g_empty_string, + // If source_file is set to empty string, + // current JS file would be used as source_file instead. + const String& source_file = g_empty_string) const; + + // FeaturePolicyParserDelegate override + // TODO(crbug.com/1029822) FeaturePolicyParserDelegate overrides, these + // should migrate to LocalDOMWindow. + bool FeatureEnabled(OriginTrialFeature) const override; + void CountFeaturePolicyUsage(mojom::WebFeature feature) override; + bool FeaturePolicyFeatureObserved( + mojom::blink::FeaturePolicyFeature feature) override; + + SecurityContext& GetSecurityContext() { return security_context_; } + const SecurityContext& GetSecurityContext() const { + return security_context_; + } + + // TODO(crbug.com/1029822): Temporary cast helpers while ExecutionContext is + // migrating to LocalDOMWindow. Callsite that permanently need to convert a + // Document to an ExecutionContext should use either GetExecutionContext() as + // inherited from Node, or domWindow(). + // Downcasts will cast to a LocalDOMWindow, then use + // LocalDOMWindow::document() if the Document is what is actually needed. + ExecutionContext* ToExecutionContext(); + const ExecutionContext* ToExecutionContext() const; + static Document* From(ExecutionContext* context) { + return context ? &From(*context) : nullptr; + } + static Document& From(ExecutionContext& context); + static const Document* From(const ExecutionContext* context) { + return context ? &From(*context) : nullptr; + } + static const Document& From(const ExecutionContext& context); + static Document* DynamicFrom(ExecutionContext* context) { + return context && context->IsDocument() ? From(context) : nullptr; + } + static Document* DynamicFrom(ExecutionContext& context) { + return context.IsDocument() ? &From(context) : nullptr; + } + static const Document* DynamicFrom(const ExecutionContext* context) { + return context && context->IsDocument() ? From(context) : nullptr; + } + static const Document* DynamicFrom(const ExecutionContext& context) { + return context.IsDocument() ? &From(context) : nullptr; + } + + // TODO(crbug.com/1029822): Temporary helpers to access ExecutionContext + // methods. These will need to be audited. Some might be useful permanent + // helpers. + const SecurityOrigin* GetSecurityOrigin() const; + SecurityOrigin* GetMutableSecurityOrigin(); + ContentSecurityPolicy* GetContentSecurityPolicy() const; + mojom::blink::WebSandboxFlags GetSandboxFlags() const; + bool IsSandboxed(mojom::blink::WebSandboxFlags mask) const; + PublicURLManager& GetPublicURLManager(); + bool IsContextPaused() const; + bool IsContextDestroyed() const; + ContentSecurityPolicyDelegate& GetContentSecurityPolicyDelegate(); + SecureContextMode GetSecureContextMode() const; + bool IsSecureContext() const; + bool IsSecureContext(String& error_message) const; + void SetSecureContextModeForTesting(SecureContextMode); + void SetReferrerPolicy(network::mojom::ReferrerPolicy); + v8::Isolate* GetIsolate() const; + Agent* GetAgent() const; + OriginTrialContext* GetOriginTrialContext() const; + bool IsFeatureEnabled( + mojom::blink::FeaturePolicyFeature, + ReportOptions report_on_failure = ReportOptions::kDoNotReport, + const String& message = g_empty_string, + const String& source_file = g_empty_string) const; + bool IsFeatureEnabled( + mojom::blink::FeaturePolicyFeature, + PolicyValue threshold_value, + ReportOptions report_on_failure = ReportOptions::kDoNotReport, + const String& message = g_empty_string, + const String& source_file = g_empty_string) const; + bool IsFeatureEnabled( + mojom::blink::DocumentPolicyFeature, + ReportOptions report_option = ReportOptions::kDoNotReport, + const String& message = g_empty_string, + const String& source_file = g_empty_string) const; + bool IsFeatureEnabled( + mojom::blink::DocumentPolicyFeature, + PolicyValue threshold_value, + ReportOptions report_option = ReportOptions::kDoNotReport, + const String& message = g_empty_string, + const String& source_file = g_empty_string) const; + + String addressSpaceForBindings() const; bool CanContainRangeEndPoint() const override { return true; } @@ -329,9 +449,6 @@ class CORE_EXPORT Document : public ContainerNode, ViewportData& GetViewportData() const { return *viewport_data_; } - String OutgoingReferrer() const override; - network::mojom::ReferrerPolicy GetReferrerPolicy() const override; - void SetDoctype(DocumentType*); DocumentType* doctype() const { return doc_type_.Get(); } @@ -445,7 +562,7 @@ class CORE_EXPORT Document : public ContainerNode, HTMLCollection* DocumentAllNamedItems(const AtomicString& name); // "defaultView" attribute defined in HTML spec. - LocalDOMWindow* defaultView() const; + DOMWindow* defaultView() const; bool IsHTMLDocument() const { return document_classes_ & kHTMLDocumentClass; } bool IsXHTMLDocument() const { @@ -476,23 +593,25 @@ class CORE_EXPORT Document : public ContainerNode, bool IsViewSource() const { return is_view_source_; } void SetIsViewSource(bool); - bool IsImmersiveArOverlay() const { return is_immersive_ar_overlay_; } - void SetIsImmersiveArOverlay(bool); + // WebXR DOM Overlay support, cf https://immersive-web.github.io/dom-overlays/ + // True if there's an ongoing "immersive-ar" WebXR session with a DOM Overlay + // element active. This is needed for applying the :xr-overlay pseudoclass + // and compositing/paint integration for this mode. + bool IsXrOverlay() const { return is_xr_overlay_; } + // Called from modules/xr's XRSystem when DOM Overlay mode starts and ends. + // This lazy-loads the UA stylesheet and updates the overlay element's + // pseudoclass. + void SetIsXrOverlay(bool enabled, Element* overlay_element); bool SawElementsInKnownNamespaces() const { return saw_elements_in_known_namespaces_; } - bool CanExecuteScripts(ReasonForCallingCanExecuteScripts) override; bool IsScriptExecutionReady() const { return HaveImportsLoaded() && HaveScriptBlockingStylesheetsLoaded(); } bool IsForExternalHandler() const { return is_for_external_handler_; } - void SetIsForExternalHandler() { - DCHECK(!is_for_external_handler_); - is_for_external_handler_ = true; - } // This is a DOM function. StyleSheetList& StyleSheets(); @@ -553,14 +672,13 @@ class CORE_EXPORT Document : public ContainerNode, void UpdateStyleAndLayoutTreeForNode(const Node*); void UpdateStyleAndLayoutTreeForSubtree(const Node*); - enum ForcedLayoutStatus { IsForcedLayout, IsNotForcedLayout }; - void UpdateStyleAndLayout(ForcedLayoutStatus = IsForcedLayout); + void UpdateStyleAndLayout(DocumentUpdateReason); void LayoutUpdated(); enum RunPostLayoutTasks { kRunPostLayoutTasksAsynchronously, kRunPostLayoutTasksSynchronously, }; - void UpdateStyleAndLayoutForNode(const Node*); + void UpdateStyleAndLayoutForNode(const Node*, DocumentUpdateReason); scoped_refptr<const ComputedStyle> StyleForPage(int page_index); // Ensures that location-based data will be valid for a given node. @@ -571,7 +689,8 @@ class CORE_EXPORT Document : public ContainerNode, // // Due to this you should only call this if you definitely need valid location // data, otherwise use one of the |UpdateStyleAndLayout...| methods above. - void EnsurePaintLocationDataValidForNode(const Node*); + void EnsurePaintLocationDataValidForNode(const Node*, + DocumentUpdateReason reason); // Returns true if page box (margin boxes and page borders) is visible. bool IsPageBoxVisible(int page_index); @@ -587,9 +706,7 @@ class CORE_EXPORT Document : public ContainerNode, int& margin_bottom, int& margin_left); - ResourceFetcher* Fetcher() const override { return fetcher_.Get(); } - - using ExecutionContext::NotifyContextDestroyed; + ResourceFetcher* Fetcher() const { return fetcher_.Get(); } void Initialize(); virtual void Shutdown(); @@ -711,7 +828,7 @@ class CORE_EXPORT Document : public ContainerNode, // Return the document URL, or an empty URL if it's unavailable. // This is not an implementation of web-exposed Document.prototype.URL. - const KURL& Url() const final { return url_; } + const KURL& Url() const { return url_; } void SetURL(const KURL&); // Bind the url to document.url, if unavailable bind to about:blank. @@ -722,7 +839,7 @@ class CORE_EXPORT Document : public ContainerNode, // Document base URL. // https://html.spec.whatwg.org/C/#document-base-url - const KURL& BaseURL() const final; + const KURL& BaseURL() const; void SetBaseURLOverride(const KURL&); const KURL& BaseURLOverride() const { return base_url_override_; } KURL ValidBaseElementURL() const; @@ -736,24 +853,17 @@ class CORE_EXPORT Document : public ContainerNode, // Creates URL based on passed relative url and this documents base URL. // Depending on base URL value it is possible that parent document // base URL will be used instead. Uses CompleteURLWithOverride internally. - KURL CompleteURL(const String&) const final; + KURL CompleteURL(const String&) const; // Creates URL based on passed relative url and passed base URL override. KURL CompleteURLWithOverride(const String&, const KURL& base_url_override) const; + const KURL& WebBundleClaimedUrl() const { return web_bundle_claimed_url_; } + // Determines whether a new document should take on the same origin as that of // the document which created it. static bool ShouldInheritSecurityOriginFromOwner(const KURL&); - String UserAgent() const final; - void DisableEval(const String& error_message) final; - - // TODO(https://crbug.com/880986): Implement Document's HTTPS state in more - // spec-conformant way. - HttpsState GetHttpsState() const final { - return CalculateHttpsState(GetSecurityOrigin()); - } - CSSStyleSheet& ElementSheet(); virtual DocumentParser* CreateParser(); @@ -800,6 +910,7 @@ class CORE_EXPORT Document : public ContainerNode, // https://html.spec.whatwg.org/C/#documentreadystate enum DocumentReadyState { kLoading, kInteractive, kComplete }; + DocumentReadyState GetReadyState() const { return ready_state_; } void SetReadyState(DocumentReadyState); bool IsLoadCompleted() const; @@ -824,8 +935,8 @@ class CORE_EXPORT Document : public ContainerNode, had_keyboard_event_ = had_keyboard_event; } bool HadKeyboardEvent() const { return had_keyboard_event_; } - void SetLastFocusType(WebFocusType last_focus_type); - WebFocusType LastFocusType() const { return last_focus_type_; } + void SetLastFocusType(mojom::blink::FocusType last_focus_type); + mojom::blink::FocusType LastFocusType() const { return last_focus_type_; } bool SetFocusedElement(Element*, const FocusParams&); void ClearFocusedElement(); Element* FocusedElement() const { return focused_element_.Get(); } @@ -845,7 +956,8 @@ class CORE_EXPORT Document : public ContainerNode, void FlushAutofocusCandidates(); void FinalizeAutofocus(); void SetSequentialFocusNavigationStartingPoint(Node*); - Element* SequentialFocusNavigationStartingPoint(WebFocusType) const; + Element* SequentialFocusNavigationStartingPoint( + mojom::blink::FocusType) const; void SetActiveElement(Element*); Element* GetActiveElement() const { return active_element_.Get(); } @@ -933,13 +1045,14 @@ class CORE_EXPORT Document : public ContainerNode, kAnimationEndListener = 1 << 6, kAnimationStartListener = 1 << 7, kAnimationIterationListener = 1 << 8, - kTransitionRunListener = 1 << 9, - kTransitionStartListener = 1 << 10, - kTransitionEndListener = 1 << 11, - kTransitionCancelListener = 1 << 12, - kScrollListener = 1 << 13, - kLoadListenerAtCapturePhaseOrAtStyleElement = 1 << 14 - // 1 bit remaining + kAnimationCancelListener = 1 << 9, + kTransitionRunListener = 1 << 10, + kTransitionStartListener = 1 << 11, + kTransitionEndListener = 1 << 12, + kTransitionCancelListener = 1 << 13, + kScrollListener = 1 << 14, + kLoadListenerAtCapturePhaseOrAtStyleElement = 1 << 15, + // 0 bits remaining }; bool HasListenerType(ListenerType listener_type) const { @@ -958,6 +1071,14 @@ class CORE_EXPORT Document : public ContainerNode, IntersectionObserverController* GetIntersectionObserverController(); IntersectionObserverController& EnsureIntersectionObserverController(); + // This is used to track IntersectionObservers for which this document is the + // explicit root. The IntersectionObserverController tracks *all* observers + // associated with this document; usually that's what you want. + ElementIntersectionObserverData* + DocumentExplicitRootIntersectionObserverData() const; + ElementIntersectionObserverData& + EnsureDocumentExplicitRootIntersectionObserverData(); + ResizeObserverController* GetResizeObserverController() const { return resize_observer_controller_; } @@ -969,7 +1090,7 @@ class CORE_EXPORT Document : public ContainerNode, void WillChangeFrameOwnerProperties(int margin_width, int margin_height, - ScrollbarMode, + mojom::blink::ScrollbarMode, bool is_display_none); String title() const { return title_; } @@ -1015,12 +1136,18 @@ class CORE_EXPORT Document : public ContainerNode, scoped_refptr<const SecurityOrigin> TopFrameOrigin() const; - const KURL SiteForCookies() const; + net::SiteForCookies SiteForCookies() const; + + // Permissions service helper methods to facilitate requesting and checking + // storage access permissions. + mojom::blink::PermissionService* GetPermissionService( + ExecutionContext* execution_context); + void PermissionServiceConnectionError(); // Storage Access API methods to check for or request access to storage that // may otherwise be blocked. ScriptPromise hasStorageAccess(ScriptState* script_state) const; - ScriptPromise requestStorageAccess(ScriptState* script_state) const; + ScriptPromise requestStorageAccess(ScriptState* script_state); // The following implements the rule from HTML 4 for what valid names are. // To get this right for all the XML cases, we probably have to improve this @@ -1130,10 +1257,6 @@ class CORE_EXPORT Document : public ContainerNode, bool IsDNSPrefetchEnabled() const { return is_dns_prefetch_enabled_; } void ParseDNSPrefetchControlHeader(const String&); - void TasksWerePaused() final; - void TasksWereUnpaused() final; - bool TasksNeedPause() final; - void FinishedParsing(); void SetEncodingData(const DocumentEncodingData& new_data); @@ -1192,9 +1315,6 @@ class CORE_EXPORT Document : public ContainerNode, void SetContainsPlugins() { contains_plugins_ = true; } bool ContainsPlugins() const { return contains_plugins_; } - bool IsContextThread() const final; - bool IsJSExecutionForbidden() const final { return false; } - void EnqueueResizeEvent(); void EnqueueScrollEventForNode(Node*); void EnqueueScrollEndEventForNode(Node*); @@ -1248,8 +1368,7 @@ class CORE_EXPORT Document : public ContainerNode, const IdleRequestOptions*); void CancelIdleCallback(int id); - EventTarget* ErrorEventTarget() final; - void ExceptionThrown(ErrorEvent*) final; + ScriptedAnimationController& GetScriptedAnimationController(); void InitDNSPrefetch(); @@ -1301,12 +1420,18 @@ class CORE_EXPORT Document : public ContainerNode, AnimationClock& GetAnimationClock(); const AnimationClock& GetAnimationClock() const; + DocumentAnimations& GetDocumentAnimations() const { + return *document_animations_; + } DocumentTimeline& Timeline() const { return *timeline_; } PendingAnimations& GetPendingAnimations() { return *pending_animations_; } WorkletAnimationController& GetWorkletAnimationController() { return *worklet_animation_controller_; } + void AttachCompositorTimeline(CompositorAnimationTimeline*) const; + void DetachCompositorTimeline(CompositorAnimationTimeline*) const; + void AddToTopLayer(Element*, const Element* before = nullptr); void RemoveFromTopLayer(Element*); const HeapVector<Member<Element>>& TopLayerElements() const { @@ -1324,9 +1449,10 @@ class CORE_EXPORT Document : public ContainerNode, // for controls outside of forms as well. void DidAssociateFormControl(Element*); - void AddConsoleMessageImpl(ConsoleMessage*, bool discard_duplicates) final; + void AddConsoleMessage(ConsoleMessage* message, + bool discard_duplicates = false); + void AddInspectorIssue(InspectorIssue*); - LocalDOMWindow* ExecutingWindow() const final; LocalFrame* ExecutingFrame(); DocumentLifecycle& Lifecycle() { return lifecycle_; } @@ -1349,6 +1475,7 @@ class CORE_EXPORT Document : public ContainerNode, void ClearResizedForViewportUnits(); void UpdateActiveStyle(); + void InvalidateStyleAndLayoutForFontUpdates(); void Trace(Visitor*) override; @@ -1356,18 +1483,8 @@ class CORE_EXPORT Document : public ContainerNode, void PlatformColorsChanged(); - HostsUsingFeatures::Value& HostsUsingFeaturesValue() { - return hosts_using_features_value_; - } - NthIndexCache* GetNthIndexCache() const { return nth_index_cache_; } - bool IsSecureContext(String& error_message) const override; - bool IsSecureContext() const override; - void SetSecureContextStateForTesting(SecureContextState state) { - secure_context_state_ = state; - } - CanvasFontCache* GetCanvasFontCache(); // Used by unit tests so that all parsing will be main thread for @@ -1383,28 +1500,11 @@ class CORE_EXPORT Document : public ContainerNode, int NodeCount() const { return node_count_; } SnapCoordinator& GetSnapCoordinator(); + void PerformScrollSnappingTasks(); void DidEnforceInsecureRequestPolicy(); void DidEnforceInsecureNavigationsSet(); - // Temporary flag for some UseCounter items. crbug.com/859391. - enum class InDOMNodeRemovedHandlerState { - kNone, - kDOMNodeRemoved, - kDOMNodeRemovedFromDocument - }; - void SetInDOMNodeRemovedHandlerState(InDOMNodeRemovedHandlerState state) { - in_dom_node_removed_handler_state_ = state; - } - InDOMNodeRemovedHandlerState GetInDOMNodeRemovedHandlerState() const { - return in_dom_node_removed_handler_state_; - } - bool InDOMNodeRemovedHandler() const { - return in_dom_node_removed_handler_state_ != - InDOMNodeRemovedHandlerState::kNone; - } - void CountDetachingNodeAccessInDOMNodeRemovedHandler(); - bool MayContainV0Shadow() const { return may_contain_v0_shadow_; } ShadowCascadeOrder GetShadowCascadeOrder() const { @@ -1432,21 +1532,11 @@ class CORE_EXPORT Document : public ContainerNode, // text field in a non-secure context. void MaybeQueueSendDidEditFieldInInsecureContext(); - CoreProbeSink* GetProbeSink() final; - service_manager::InterfaceProvider* GetInterfaceProvider() final; - - BrowserInterfaceBrokerProxy& GetBrowserInterfaceBroker() final; - // May return nullptr when PerformanceManager instrumentation is disabled. DocumentResourceCoordinator* GetResourceCoordinator(); - // Apply pending feature policy headers. - void ApplyPendingFeaturePolicyHeaders(); - - // Set the report-only feature policy on this document in response to an HTTP - // Feature-Policy-Report-Only header. - void ApplyReportOnlyFeaturePolicyFromHeader( - const String& feature_policy_report_only_header); + // Apply pending feature policy headers and document policy headers. + void ApplyPendingFramePolicyHeaders(); const AtomicString& bgColor() const; void setBgColor(const AtomicString&); @@ -1471,10 +1561,7 @@ class CORE_EXPORT Document : public ContainerNode, // attempts (both successful and not successful) by the page. FontMatchingMetrics* GetFontMatchingMetrics(); - // May return nullptr. - FrameOrWorkerScheduler* GetScheduler() override; - - scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override; + scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType); void RecordUkmOutliveTimeAfterShutdown(int outlive_time_count); @@ -1529,35 +1616,54 @@ class CORE_EXPORT Document : public ContainerNode, LazyLoadImageObserver& EnsureLazyLoadImageObserver(); WindowAgent& GetWindowAgent(); - WindowAgentFactory* GetWindowAgentFactory() { return window_agent_factory_; } - - void CountPotentialFeaturePolicyViolation( - mojom::FeaturePolicyFeature) const override; - void ReportFeaturePolicyViolation( - mojom::FeaturePolicyFeature, - mojom::FeaturePolicyDisposition, - const String& message = g_empty_string, - // If source_file is set to empty string, - // current JS file would be used as source_file instead. - const String& source_file = g_empty_string) const override; + WindowAgentFactory* GetWindowAgentFactory() const { + return window_agent_factory_; + } void IncrementNumberOfCanvases(); - void ProcessJavaScriptUrl(const KURL&, ContentSecurityPolicyDisposition); + void ProcessJavaScriptUrl(const KURL&, network::mojom::CSPDisposition); // Functions to keep count of display locks in this document. - void AddActivationBlockingDisplayLock(); - void RemoveActivationBlockingDisplayLock(); - int ActivationBlockingDisplayLockCount() const; + void IncrementDisplayLockBlockingAllActivation(); + void DecrementDisplayLockBlockingAllActivation(); + int DisplayLockBlockingAllActivationCount() const; void AddLockedDisplayLock(); void RemoveLockedDisplayLock(); int LockedDisplayLockCount() const; + void AddDisplayLockContext(DisplayLockContext*); + void RemoveDisplayLockContext(DisplayLockContext*); + int DisplayLockCount() const; + void NotifySelectionRemovedFromDisplayLocks(); + // Manage the element's observation for display lock activation. void RegisterDisplayLockActivationObservation(Element*); void UnregisterDisplayLockActivationObservation(Element*); + class ScopedForceActivatableDisplayLocks { + STACK_ALLOCATED(); + + public: + ScopedForceActivatableDisplayLocks(ScopedForceActivatableDisplayLocks&&); + ~ScopedForceActivatableDisplayLocks(); + + ScopedForceActivatableDisplayLocks& operator=( + ScopedForceActivatableDisplayLocks&&); + + private: + friend Document; + ScopedForceActivatableDisplayLocks(Document*); + + Document* document_; + }; + + ScopedForceActivatableDisplayLocks GetScopedForceActivatableLocks(); + bool ActivatableDisplayLocksForced() const { + return activatable_display_locks_forced_ > 0; + } + // Deferred compositor commits are disallowed by default, and are only allowed // for same-origin navigations to an html document fetched with http. bool DeferredCompositorCommitIsAllowed() { @@ -1583,11 +1689,11 @@ class CORE_EXPORT Document : public ContainerNode, // inside a cross-process frame (MimeHandlerView). void SetShowBeforeUnloadDialog(bool show_dialog); - TrustedTypePolicyFactory* GetTrustedTypes() const override; - bool RequireTrustedTypes() const override; - void ColorSchemeChanged(); + // A new vision deficiency is being emulated through DevTools. + void VisionDeficiencyChanged(); + void ClearIsolatedWorldCSPForTesting(int32_t world_id); // A META element with name=color-scheme was added, removed, or modified. @@ -1614,17 +1720,20 @@ class CORE_EXPORT Document : public ContainerNode, // NOTE: only for use in testing. bool IsAnimatedPropertyCounted(CSSPropertyID property) const; void ClearUseCounterForTesting(mojom::WebFeature); - void SetSecurityOrigin(scoped_refptr<SecurityOrigin>) final; - - void RecordCallInDetachedWindow(v8::Isolate::UseCounterFeature reason); // Bind Content Security Policy to this document. This will cause the // CSP to resolve the 'self' attribute and all policies will then be // applied to this document. void BindContentSecurityPolicy(); + void UpdateForcedColors(); bool InForcedColorsMode() const; + // Returns true if the subframe document is cross-site to the main frame. If + // we can't tell whether the document was ever cross-site or not (e.g. it is + // not the active Document in a browsing context), return false. + bool IsCrossSiteSubframe() const; + // Capture the toggle event during parsing either by HTML parser or XML // parser. void SetToggleDuringParsing(bool toggle_during_parsing) { @@ -1657,6 +1766,27 @@ class CORE_EXPORT Document : public ContainerNode, } #endif + void ApplyScrollRestorationLogic(); + + void MarkHasFindInPageRequest(); + void MarkHasFindInPageSubtreeVisibilityActiveMatch(); + + void CancelPendingJavaScriptUrls(); + + HeapObserverList<SynchronousMutationObserver>& + SynchronousMutationObserverList() { + return synchronous_mutation_observer_list_; + } + + void NotifyUpdateCharacterData(CharacterData* character_data, + unsigned offset, + unsigned old_length, + unsigned new_length); + void NotifyChangeChildren(const ContainerNode& container); + + FontPreloadManager& GetFontPreloadManager() { return font_preload_manager_; } + void FontPreloadingFinishedOrTimedOut(); + protected: void ClearXMLVersion() { xml_version_ = String(); } @@ -1674,17 +1804,16 @@ class CORE_EXPORT Document : public ContainerNode, friend class NthIndexCache; FRIEND_TEST_ALL_PREFIXES(FrameFetchContextSubresourceFilterTest, DuringOnFreeze); + FRIEND_TEST_ALL_PREFIXES(DocumentTest, FindInPageUkm); class NetworkStateObserver; - class SecurityContextInit; Document(const DocumentInit& initization, - SecurityContextInit init_helper, + const SecurityContextInit& init_helper, DocumentClassFlags document_classes); - // Post initialization of the object handling of the feature policy. - void FeaturePolicyInitialized( - const DocumentInit& document_initializer, - const SecurityContextInit& security_initializer); + // Post initialization of the object handling of both feature policy and + // document policy. + void PoliciesInitialized(const DocumentInit& document_initializer); friend class AXContext; void AddAXContext(AXContext*); @@ -1697,13 +1826,8 @@ class CORE_EXPORT Document : public ContainerNode, bool IsElementNode() const = delete; // This will catch anyone doing an unnecessary check. - ScriptedAnimationController& EnsureScriptedAnimationController(); ScriptedIdleTaskController& EnsureScriptedIdleTaskController(); - void InitSecurityContext(const DocumentInit&, - const SecurityContextInit& security_initializer); - void InitSecureContextState(); - SecurityContext& GetSecurityContext() final { return *this; } - const SecurityContext& GetSecurityContext() const final { return *this; } + void InitSecurityContext(const DocumentInit&); bool HasPendingVisualUpdate() const { return lifecycle_.GetState() == DocumentLifecycle::kVisualUpdatePending; @@ -1754,7 +1878,6 @@ class CORE_EXPORT Document : public ContainerNode, void ExecuteScriptsWaitingForResources(); void ExecuteJavaScriptUrls(); - void CancelPendingJavaScriptUrls(); void LoadEventDelayTimerFired(TimerBase*); void PluginLoadingTimerFired(TimerBase*); @@ -1815,12 +1938,6 @@ class CORE_EXPORT Document : public ContainerNode, void ProcessDisplayLockActivationObservation( const HeapVector<Member<IntersectionObserverEntry>>&); - void SetNavigationSourceId(int64_t source_id); - - // TODO(bartekn): Remove after investigation is completed. - void EmitDetachedWindowsUkmEvent( - const HashSet<v8::Isolate::UseCounterFeature>& reasons); - DocumentLifecycle lifecycle_; bool evaluate_media_queries_on_style_recalc_; @@ -1835,6 +1952,14 @@ class CORE_EXPORT Document : public ContainerNode, Member<LocalDOMWindow> dom_window_; Member<HTMLImportsController> imports_controller_; + SecurityContext security_context_; + + // Document::CountUse() attributes the feature counts to the DocumentLoader + // which is returned by Loader(). During construction Loader() returns null, + // so we use this UseCounter instead. + // TODO(dgozman): we should probably explicitly set and clear loader instead. + Member<UseCounter> use_counter_during_construction_; + // The document of creator browsing context for frame-less documents such as // documents created by DOMParser and DOMImplementation. WeakMember<Document> context_document_; @@ -1860,6 +1985,8 @@ class CORE_EXPORT Document : public ContainerNode, KURL cookie_url_; // The URL to use for cookie access. std::unique_ptr<OriginAccessEntry> access_entry_from_url_; + KURL web_bundle_claimed_url_; + AtomicString base_target_; // Mime-type of the document in case it was cloned or created by XHR. @@ -1882,16 +2009,16 @@ class CORE_EXPORT Document : public ContainerNode, struct PendingJavascriptUrl { public: PendingJavascriptUrl(const KURL& input_url, - ContentSecurityPolicyDisposition input_disposition) + network::mojom::CSPDisposition input_disposition) : url(input_url), disposition(input_disposition) {} KURL url; - ContentSecurityPolicyDisposition disposition; + network::mojom::CSPDisposition disposition; }; Vector<PendingJavascriptUrl> pending_javascript_urls_; // https://html.spec.whatwg.org/C/#autofocus-processed-flag bool autofocus_processed_flag_ = false; - WebFocusType last_focus_type_; + mojom::blink::FocusType last_focus_type_; bool had_keyboard_event_; TaskRunnerTimer<Document> clear_focused_element_timer_; // https://html.spec.whatwg.org/C/#autofocus-candidates @@ -1905,6 +2032,9 @@ class CORE_EXPORT Document : public ContainerNode, UserActionElementSet user_action_elements_; Member<RootScrollerController> root_scroller_controller_; + double overscroll_accumulated_delta_x_ = 0; + double overscroll_accumulated_delta_y_ = 0; + uint64_t dom_tree_version_; static uint64_t global_tree_version_; @@ -1918,6 +2048,9 @@ class CORE_EXPORT Document : public ContainerNode, MutationObserverOptions mutation_observer_types_; + Member<ElementIntersectionObserverData> + document_explicit_root_intersection_observer_data_; + Member<StyleEngine> style_engine_; Member<StyleSheetList> style_sheet_list_; @@ -2009,7 +2142,7 @@ class CORE_EXPORT Document : public ContainerNode, DocumentClassFlags document_classes_; bool is_view_source_; - bool is_immersive_ar_overlay_; + bool is_xr_overlay_; bool saw_elements_in_known_namespaces_; bool is_srcdoc_document_; bool is_mobile_document_; @@ -2049,6 +2182,7 @@ class CORE_EXPORT Document : public ContainerNode, HashMap<AtomicString, std::unique_ptr<Locale>>; LocaleIdentifierToLocaleMap locale_cache_; + Member<DocumentAnimations> document_animations_; Member<DocumentTimeline> timeline_; Member<PendingAnimations> pending_animations_; Member<WorkletAnimationController> worklet_animation_controller_; @@ -2064,8 +2198,6 @@ class CORE_EXPORT Document : public ContainerNode, ParserSynchronizationPolicy parser_sync_policy_; - HostsUsingFeatures::Value hosts_using_features_value_; - Member<CanvasFontCache> canvas_font_cache_; Member<IntersectionObserverController> intersection_observer_controller_; @@ -2073,9 +2205,6 @@ class CORE_EXPORT Document : public ContainerNode, int node_count_; - // Temporary flag for some UseCounter items. crbug.com/859391. - InDOMNodeRemovedHandlerState in_dom_node_removed_handler_state_ = - InDOMNodeRemovedHandlerState::kNone; bool may_contain_v0_shadow_ = false; Member<SnapCoordinator> snap_coordinator_; @@ -2086,8 +2215,6 @@ class CORE_EXPORT Document : public ContainerNode, TaskHandle sensitive_input_edited_task_; - SecureContextState secure_context_state_; - Member<NetworkStateObserver> network_state_observer_; std::unique_ptr<DocumentOutliveTimeReporter> document_outlive_time_reporter_; @@ -2098,10 +2225,6 @@ class CORE_EXPORT Document : public ContainerNode, int64_t ukm_source_id_; bool needs_to_record_ukm_outlive_time_; - std::unique_ptr<mojo::AssociatedRemote<mojom::blink::UkmSourceIdFrameHost>> - ukm_binding_; - uint64_t navigation_source_id_ = ukm::kInvalidSourceId; - // Tracks and reports UKM metrics of the number of attempted font family match // attempts (both successful and not successful) by the page. std::unique_ptr<FontMatchingMetrics> font_matching_metrics_; @@ -2125,10 +2248,14 @@ class CORE_EXPORT Document : public ContainerNode, // The number of canvas elements on the document int num_canvases_ = 0; - // Number of activation blocking display locks currently in this document. - int activation_blocking_display_lock_count_ = 0; + // Number of display locks in this document that block all activation. + int display_lock_blocking_all_activation_count_ = 0; // Number of locked display locks in the document. int locked_display_lock_count_ = 0; + // All of this document's display lock contexts. + HeapHashSet<WeakMember<DisplayLockContext>> display_lock_contexts_; + // If non-zero, then the activatable locks have been globally forced. + int activatable_display_locks_forced_ = 0; bool deferred_compositor_commit_is_allowed_ = false; @@ -2136,7 +2263,7 @@ class CORE_EXPORT Document : public ContainerNode, // types that are handled externally. The document in this case is the // counterpart to a PluginDocument except that it contains a FrameView as // opposed to a PluginView. - bool is_for_external_handler_ = false; + bool is_for_external_handler_; #if DCHECK_IS_ON() // Allow traversal of Shadow DOM V0 traversal with dirty distribution. @@ -2152,9 +2279,21 @@ class CORE_EXPORT Document : public ContainerNode, // We don't use std::bitset to avoid to include feature_policy.mojom-blink.h. mutable Vector<bool> potentially_violated_features_; - // Pending parsed headers to send to browser after DidCommitNavigation + // Pending feature policy headers to send to browser after DidCommitNavigation // IPC. - ParsedFeaturePolicy pending_parsed_headers_; + ParsedFeaturePolicy pending_fp_headers_; + + // Pending document policy headers to send to browser after + // DidCommitNavigation IPC. Note: pending_dp_headers is the document policy + // state used to initialize |document_policy_| in SecurityContext. Verifying + // its integrity against required_document_policy has already been done in + // DocumentLoader. + DocumentPolicy::FeatureState pending_dp_headers_; + + // Tracks which feature policies have already been parsed, so as not to count + // them multiple times. + // The size of this vector is 0 until FeaturePolicyFeatureObserved is called. + Vector<bool> parsed_feature_policies_; AtomicString override_last_modified_; @@ -2177,16 +2316,7 @@ class CORE_EXPORT Document : public ContainerNode, std::unique_ptr<DocumentResourceCoordinator> resource_coordinator_; // Used for document.cookie. May be null. - std::unique_ptr<CookieJar> cookie_jar_; - - // A dummy scheduler to return when the document is detached. - // All operations on it result in no-op, but due to this it's safe to - // use the returned value of GetScheduler() without additional checks. - // A task posted to a task runner obtained from one of its task runners - // will be forwarded to the default task runner. - // TODO(altimin): We should be able to remove it after we complete - // frame:document lifetime refactoring. - std::unique_ptr<FrameOrWorkerScheduler> detached_scheduler_; + Member<CookieJar> cookie_jar_; bool toggle_during_parsing_ = false; @@ -2199,10 +2329,24 @@ class CORE_EXPORT Document : public ContainerNode, HeapHashMap<WeakMember<Element>, Member<ExplicitlySetAttrElementsMap>> element_explicitly_set_attr_elements_map_; + HeapObserverList<SynchronousMutationObserver> + synchronous_mutation_observer_list_; + Member<IntersectionObserver> display_lock_activation_observer_; - HashSet<v8::Isolate::UseCounterFeature> calls_in_detached_window_orphaned_; - HashSet<v8::Isolate::UseCounterFeature> calls_in_detached_window_emitted_; + bool in_forced_colors_mode_; + + bool applying_scroll_restoration_logic_ = false; + + // Records find-in-page metrics, which are sent to UKM on shutdown. + bool had_find_in_page_request_ = false; + bool had_find_in_page_render_subtree_active_match_ = false; + + // Mojo remote used to determine if the document has permission to access + // storage or not. + HeapMojoRemote<mojom::blink::PermissionService> permission_service_; + + FontPreloadManager font_preload_manager_; }; extern template class CORE_EXTERN_TEMPLATE_EXPORT Supplement<Document>; @@ -2234,9 +2378,6 @@ Node* EventTargetNodeForDocument(Document*); template <> struct DowncastTraits<Document> { - static bool AllowFrom(const ExecutionContext& context) { - return context.IsDocument(); - } static bool AllowFrom(const Node& node) { return node.IsDocumentNode(); } }; diff --git a/chromium/third_party/blink/renderer/core/dom/document.idl b/chromium/third_party/blink/renderer/core/dom/document.idl index ec4b33c91e2..a8025f5cf65 100644 --- a/chromium/third_party/blink/renderer/core/dom/document.idl +++ b/chromium/third_party/blink/renderer/core/dom/document.idl @@ -34,10 +34,9 @@ typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement; // https://html.spec.whatwg.org/C/#documents [ - Exposed=Window, - Constructor(), - ConstructorCallWith=Document + Exposed=Window ] interface Document : Node { + [CallWith=Document] constructor(); [SameObject] readonly attribute DOMImplementation implementation; [ImplementedAs=urlForBinding] readonly attribute USVString URL; // FIXME: documentURI should not be nullable. @@ -170,7 +169,7 @@ typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement; // Custom Elements // https://w3c.github.io/webcomponents/spec/custom/#extensions-to-document-interface-to-register // FIXME: The registerElement return type should be Function. - [RuntimeEnabled=CustomElementsV0, CallWith=ScriptState, CustomElementCallbacks, RaisesException, DeprecateAs=DocumentRegisterElement] any registerElement(DOMString type, optional ElementRegistrationOptions options); + [RuntimeEnabled=CustomElementsV0, CallWith=ScriptState, CustomElementCallbacks, RaisesException, DeprecateAs=DocumentRegisterElement] any registerElement(DOMString type, optional ElementRegistrationOptions options = {}); // https://w3c.github.io/webcomponents/spec/custom/#extensions-to-document-interface-to-instantiate [CustomElementCallbacks, PerWorldBindings, RaisesException, ImplementedAs=CreateElementForBinding] Element createElement(DOMString localName, (DOMString or ElementCreationOptions) options); [CustomElementCallbacks, RaisesException] Element createElementNS(DOMString? namespaceURI, DOMString qualifiedName, (DOMString or ElementCreationOptions) options); @@ -186,7 +185,7 @@ typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement; [RuntimeEnabled=AddressSpace, ImplementedAs=addressSpaceForBindings] readonly attribute AddressSpace addressSpace; // Non-standard APIs - [MeasureAs=DocumentCaretRangeFromPoint] Range caretRangeFromPoint([DefaultValue=Undefined] optional long x, [DefaultValue=Undefined] optional long y); + [MeasureAs=DocumentCaretRangeFromPoint] Range caretRangeFromPoint(optional long x = 0, optional long y = 0); // Storage Access API [CallWith=ScriptState, NewObject, RuntimeEnabled=StorageAccessAPI] Promise<boolean> hasStorageAccess(); diff --git a/chromium/third_party/blink/renderer/core/dom/document_fragment.idl b/chromium/third_party/blink/renderer/core/dom/document_fragment.idl index e69c55f80cd..ddb78da3185 100644 --- a/chromium/third_party/blink/renderer/core/dom/document_fragment.idl +++ b/chromium/third_party/blink/renderer/core/dom/document_fragment.idl @@ -20,10 +20,9 @@ // https://dom.spec.whatwg.org/#interface-documentfragment [ - Constructor, - ConstructorCallWith=Document, Exposed=Window ] interface DocumentFragment : Node { + [CallWith=Document] constructor(); }; DocumentFragment includes ParentNode; diff --git a/chromium/third_party/blink/renderer/core/dom/document_init.cc b/chromium/third_party/blink/renderer/core/dom/document_init.cc index a06ea5d6947..c9c761dd34e 100644 --- a/chromium/third_party/blink/renderer/core/dom/document_init.cc +++ b/chromium/third_party/blink/renderer/core/dom/document_init.cc @@ -29,13 +29,24 @@ #include "third_party/blink/renderer/core/dom/document_init.h" +#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink.h" #include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/dom/dom_implementation.h" +#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.h" +#include "third_party/blink/renderer/core/html/html_document.h" #include "third_party/blink/renderer/core/html/html_frame_owner_element.h" #include "third_party/blink/renderer/core/html/imports/html_imports_controller.h" +#include "third_party/blink/renderer/core/html/media/html_media_element.h" #include "third_party/blink/renderer/core/loader/document_loader.h" +#include "third_party/blink/renderer/core/page/chrome_client.h" +#include "third_party/blink/renderer/core/page/page.h" +#include "third_party/blink/renderer/core/page/plugin_data.h" +#include "third_party/blink/renderer/platform/network/mime/content_type.h" +#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h" #include "third_party/blink/renderer/platform/network/network_utils.h" +#include "third_party/blink/renderer/platform/web_test_support.h" namespace blink { @@ -94,8 +105,8 @@ DocumentLoader* DocumentInit::MasterDocumentLoader() const { return nullptr; } -WebSandboxFlags DocumentInit::GetSandboxFlags() const { - WebSandboxFlags flags = sandbox_flags_; +mojom::blink::WebSandboxFlags DocumentInit::GetSandboxFlags() const { + mojom::blink::WebSandboxFlags flags = sandbox_flags_; if (DocumentLoader* loader = MasterDocumentLoader()) flags |= loader->GetFrame()->Loader().EffectiveSandboxFlags(); // If the load was blocked by CSP, force the Document's origin to be unique, @@ -103,15 +114,16 @@ WebSandboxFlags DocumentInit::GetSandboxFlags() const { // document's load per CSP spec: // https://www.w3.org/TR/CSP3/#directive-frame-ancestors. if (blocked_by_csp_) - flags |= WebSandboxFlags::kOrigin; + flags |= mojom::blink::WebSandboxFlags::kOrigin; return flags; } -WebInsecureRequestPolicy DocumentInit::GetInsecureRequestPolicy() const { +mojom::blink::InsecureRequestPolicy DocumentInit::GetInsecureRequestPolicy() + const { DCHECK(MasterDocumentLoader()); Frame* parent_frame = MasterDocumentLoader()->GetFrame()->Tree().Parent(); if (!parent_frame) - return kLeaveInsecureRequestsAlone; + return mojom::blink::InsecureRequestPolicy::kLeaveInsecureRequestsAlone; return parent_frame->GetSecurityContext()->GetInsecureRequestPolicy(); } @@ -146,6 +158,87 @@ LocalFrame* DocumentInit::GetFrame() const { return document_loader_ ? document_loader_->GetFrame() : nullptr; } +UseCounter* DocumentInit::GetUseCounter() const { + return document_loader_; +} + +DocumentInit& DocumentInit::WithTypeFrom(const String& type) { + mime_type_ = type; + + if (GetFrame() && GetFrame()->InViewSourceMode()) { + type_ = Type::kViewSource; + return *this; + } + + // Plugins cannot take HTML and XHTML from us, and we don't even need to + // initialize the plugin database for those. + if (type == "text/html") { + type_ = Type::kHTML; + return *this; + } + if (type == "application/xhtml+xml") { + type_ = Type::kXHTML; + return *this; + } + // multipart/x-mixed-replace is only supported for images. + if (MIMETypeRegistry::IsSupportedImageResourceMIMEType(type) || + type == "multipart/x-mixed-replace") { + type_ = Type::kImage; + return *this; + } + if (HTMLMediaElement::GetSupportsType(ContentType(type))) { + type_ = Type::kMedia; + return *this; + } + + PluginData* plugin_data = nullptr; + if (GetFrame() && GetFrame()->GetPage() && + GetFrame()->Loader().AllowPlugins(kNotAboutToInstantiatePlugin)) { + // If the document is being created for the main frame, + // frame()->tree().top()->securityContext() returns nullptr. + // For that reason, the origin must be retrieved directly from url(). + if (GetFrame()->IsMainFrame()) { + scoped_refptr<const SecurityOrigin> origin = + SecurityOrigin::Create(Url()); + plugin_data = GetFrame()->GetPage()->GetPluginData(origin.get()); + } else { + auto* top_security_origin = + GetFrame()->Tree().Top().GetSecurityContext()->GetSecurityOrigin(); + plugin_data = GetFrame()->GetPage()->GetPluginData(top_security_origin); + } + } + + // Everything else except text/plain can be overridden by plugins. + // Disallowing plugins to use text/plain prevents plugins from hijacking a + // fundamental type that the browser is expected to handle, and also serves as + // an optimization to prevent loading the plugin database in the common case. + if (type != "text/plain" && plugin_data && + plugin_data->SupportsMimeType(type)) { + // Plugins handled by MimeHandlerView do not create a PluginDocument. They + // are rendered inside cross-process frames and the notion of a PluginView + // (which is associated with PluginDocument) is irrelevant here. + if (plugin_data->IsExternalPluginMimeType(type)) { + type_ = Type::kHTML; + is_for_external_handler_ = true; + } else { + type_ = Type::kPlugin; + plugin_background_color_ = + plugin_data->PluginBackgroundColorForMimeType(type); + } + return *this; + } + + if (DOMImplementation::IsTextMIMEType(type)) + type_ = Type::kText; + else if (type == "image/svg+xml") + type_ = Type::kSVG; + else if (DOMImplementation::IsXMLMIMEType(type)) + type_ = Type::kXML; + else + type_ = Type::kHTML; + return *this; +} + DocumentInit& DocumentInit::WithContextDocument(Document* context_document) { DCHECK(!context_document_); context_document_ = context_document; @@ -239,13 +332,13 @@ DocumentInit& DocumentInit::WithNewRegistrationContext() { V0CustomElementRegistrationContext* DocumentInit::RegistrationContext( Document* document) const { - if (!document->IsHTMLDocument() && !document->IsXHTMLDocument()) + if (!IsA<HTMLDocument>(document) && !document->IsXHTMLDocument()) return nullptr; if (create_new_registration_context_) return MakeGarbageCollected<V0CustomElementRegistrationContext>(); - return registration_context_.Get(); + return registration_context_; } Document* DocumentInit::ContextDocument() const { @@ -258,13 +351,21 @@ DocumentInit& DocumentInit::WithFeaturePolicyHeader(const String& header) { return *this; } +DocumentInit& DocumentInit::WithReportOnlyFeaturePolicyHeader( + const String& header) { + DCHECK(report_only_feature_policy_header_.IsEmpty()); + report_only_feature_policy_header_ = header; + return *this; +} + DocumentInit& DocumentInit::WithOriginTrialsHeader(const String& header) { DCHECK(origin_trials_header_.IsEmpty()); origin_trials_header_ = header; return *this; } -DocumentInit& DocumentInit::WithSandboxFlags(WebSandboxFlags flags) { +DocumentInit& DocumentInit::WithSandboxFlags( + mojom::blink::WebSandboxFlags flags) { // Only allow adding more sandbox flags. sandbox_flags_ |= flags; return *this; @@ -284,15 +385,82 @@ DocumentInit& DocumentInit::WithContentSecurityPolicyFromContextDoc() { ContentSecurityPolicy* DocumentInit::GetContentSecurityPolicy() const { DCHECK( !(content_security_policy_ && content_security_policy_from_context_doc_)); - if (context_document_ && content_security_policy_from_context_doc_) - return context_document_->GetContentSecurityPolicy(); + if (context_document_ && content_security_policy_from_context_doc_) { + // Return a copy of the context documents' CSP. The return value will be + // modified, so this must be a copy. + ContentSecurityPolicy* csp = MakeGarbageCollected<ContentSecurityPolicy>(); + csp->CopyStateFrom(context_document_->GetContentSecurityPolicy()); + return csp; + } return content_security_policy_; } DocumentInit& DocumentInit::WithFramePolicy( const base::Optional<FramePolicy>& frame_policy) { frame_policy_ = frame_policy; + if (frame_policy_.has_value()) { + DCHECK(document_loader_); + // Make the snapshot value of sandbox flags from the beginning of navigation + // available in frame loader, so that the value could be further used to + // initialize sandbox flags in security context. crbug.com/1026627 + document_loader_->GetFrame()->Loader().SetFrameOwnerSandboxFlags( + frame_policy_.value().sandbox_flags); + } + return *this; +} + +DocumentInit& DocumentInit::WithDocumentPolicy( + const DocumentPolicy::ParsedDocumentPolicy& document_policy) { + document_policy_ = document_policy; return *this; } +DocumentInit& DocumentInit::WithReportOnlyDocumentPolicyHeader( + const String& header) { + DCHECK(report_only_document_policy_header_.IsEmpty()); + report_only_document_policy_header_ = header; + return *this; +} + +DocumentInit& DocumentInit::WithWebBundleClaimedUrl( + const KURL& web_bundle_claimed_url) { + web_bundle_claimed_url_ = web_bundle_claimed_url; + return *this; +} + +bool IsPagePopupRunningInWebTest(LocalFrame* frame) { + return frame && frame->GetPage()->GetChromeClient().IsPopup() && + WebTestSupport::IsRunningWebTest(); +} + +WindowAgentFactory* DocumentInit::GetWindowAgentFactory() const { + // If we are a page popup in LayoutTests ensure we use the popup + // owner's frame for looking up the Agent so the tests can possibly + // access the document via internals API. + if (IsPagePopupRunningInWebTest(GetFrame())) { + auto* frame = GetFrame()->PagePopupOwner()->GetDocument().GetFrame(); + return &frame->window_agent_factory(); + } + if (GetFrame()) + return &GetFrame()->window_agent_factory(); + if (Document* context_document = ContextDocument()) + return context_document->GetWindowAgentFactory(); + if (const Document* owner_document = OwnerDocument()) + return owner_document->GetWindowAgentFactory(); + return nullptr; +} + +Settings* DocumentInit::GetSettingsForWindowAgentFactory() const { + LocalFrame* frame = nullptr; + if (IsPagePopupRunningInWebTest(GetFrame())) + frame = GetFrame()->PagePopupOwner()->GetDocument().GetFrame(); + else if (GetFrame()) + frame = GetFrame(); + else if (Document* context_document = ContextDocument()) + frame = context_document->GetFrame(); + else if (const Document* owner_document = OwnerDocument()) + frame = owner_document->GetFrame(); + return frame ? frame->GetSettings() : nullptr; +} + } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/document_init.h b/chromium/third_party/blink/renderer/core/dom/document_init.h index 2a26b3a173a..7a7da46660d 100644 --- a/chromium/third_party/blink/renderer/core/dom/document_init.h +++ b/chromium/third_party/blink/renderer/core/dom/document_init.h @@ -32,11 +32,13 @@ #include "services/network/public/mojom/ip_address_space.mojom-shared.h" #include "third_party/blink/public/common/frame/frame_policy.h" -#include "third_party/blink/public/platform/web_insecure_request_policy.h" +#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h" +#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-blink-forward.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/execution_context/security_context.h" #include "third_party/blink/renderer/core/frame/sandbox_flags.h" #include "third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.h" +#include "third_party/blink/renderer/platform/graphics/color.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" @@ -48,6 +50,8 @@ class DocumentLoader; class LocalFrame; class HTMLImportsController; class Settings; +class UseCounter; +class WindowAgentFactory; class CORE_EXPORT DocumentInit final { STACK_ALLOCATED(); @@ -70,6 +74,19 @@ class CORE_EXPORT DocumentInit final { DocumentInit(const DocumentInit&); ~DocumentInit(); + enum class Type { + kHTML, + kXHTML, + kImage, + kPlugin, + kMedia, + kSVG, + kXML, + kViewSource, + kText, + kUnspecified + }; + HTMLImportsController* ImportsController() const { return imports_controller_; } @@ -77,8 +94,8 @@ class CORE_EXPORT DocumentInit final { bool HasSecurityContext() const { return MasterDocumentLoader(); } bool IsSrcdocDocument() const; bool ShouldSetURL() const; - WebSandboxFlags GetSandboxFlags() const; - WebInsecureRequestPolicy GetInsecureRequestPolicy() const; + mojom::blink::WebSandboxFlags GetSandboxFlags() const; + mojom::blink::InsecureRequestPolicy GetInsecureRequestPolicy() const; const SecurityContext::InsecureNavigationsSet* InsecureNavigationsToUpgrade() const; bool GrantLoadLocalResources() const { return grant_load_local_resources_; } @@ -87,6 +104,13 @@ class CORE_EXPORT DocumentInit final { DocumentInit& WithDocumentLoader(DocumentLoader*); LocalFrame* GetFrame() const; + UseCounter* GetUseCounter() const; + + DocumentInit& WithTypeFrom(const String& type); + Type GetType() const { return type_; } + const String& GetMimeType() const { return mime_type_; } + bool IsForExternalHandler() const { return is_for_external_handler_; } + Color GetPluginBackgroundColor() const { return plugin_background_color_; } // Used by the DOMImplementation and DOMParser to pass their parent Document // so that the created Document will return the Document when the @@ -101,7 +125,7 @@ class CORE_EXPORT DocumentInit final { // Specifies the Document to inherit security configurations from. DocumentInit& WithOwnerDocument(Document*); - Document* OwnerDocument() const { return owner_document_.Get(); } + Document* OwnerDocument() const { return owner_document_; } // Specifies the SecurityOrigin in which the URL was requested. This is // relevant for determining properties of the resulting document's origin @@ -130,10 +154,15 @@ class CORE_EXPORT DocumentInit final { DocumentInit& WithFeaturePolicyHeader(const String& header); const String& FeaturePolicyHeader() const { return feature_policy_header_; } + DocumentInit& WithReportOnlyFeaturePolicyHeader(const String& header); + const String& ReportOnlyFeaturePolicyHeader() const { + return report_only_feature_policy_header_; + } + DocumentInit& WithOriginTrialsHeader(const String& header); const String& OriginTrialsHeader() const { return origin_trials_header_; } - DocumentInit& WithSandboxFlags(WebSandboxFlags flags); + DocumentInit& WithSandboxFlags(mojom::blink::WebSandboxFlags flags); DocumentInit& WithContentSecurityPolicy(ContentSecurityPolicy* policy); DocumentInit& WithContentSecurityPolicyFromContextDoc(); @@ -145,6 +174,23 @@ class CORE_EXPORT DocumentInit final { return frame_policy_; } + DocumentInit& WithDocumentPolicy( + const DocumentPolicy::ParsedDocumentPolicy& document_policy); + const DocumentPolicy::ParsedDocumentPolicy& GetDocumentPolicy() const { + return document_policy_; + } + + DocumentInit& WithReportOnlyDocumentPolicyHeader(const String& header); + const String& ReportOnlyDocumentPolicyHeader() const { + return report_only_document_policy_header_; + } + + DocumentInit& WithWebBundleClaimedUrl(const KURL& web_bundle_claimed_url); + const KURL& GetWebBundleClaimedUrl() const { return web_bundle_claimed_url_; } + + WindowAgentFactory* GetWindowAgentFactory() const; + Settings* GetSettingsForWindowAgentFactory() const; + private: DocumentInit(HTMLImportsController*); @@ -154,14 +200,17 @@ class CORE_EXPORT DocumentInit final { // of its owning Document. DocumentLoader* MasterDocumentLoader() const; - Member<DocumentLoader> document_loader_; - Member<Document> parent_document_; + Type type_ = Type::kUnspecified; + String mime_type_; + + DocumentLoader* document_loader_ = nullptr; + Document* parent_document_ = nullptr; - Member<HTMLImportsController> imports_controller_; + HTMLImportsController* imports_controller_ = nullptr; - Member<Document> context_document_; + Document* context_document_ = nullptr; KURL url_; - Member<Document> owner_document_; + Document* owner_document_ = nullptr; // Initiator origin is used for calculating the document origin when the // navigation is started in a different process. In such cases, the document @@ -194,20 +243,22 @@ class CORE_EXPORT DocumentInit final { // Whether the document should be able to access local file:// resources. bool grant_load_local_resources_ = false; - Member<V0CustomElementRegistrationContext> registration_context_; + V0CustomElementRegistrationContext* registration_context_ = nullptr; bool create_new_registration_context_; // The feature policy set via response header. String feature_policy_header_; + String report_only_feature_policy_header_; // The origin trial set via response header. String origin_trials_header_; // Additional sandbox flags - WebSandboxFlags sandbox_flags_ = WebSandboxFlags::kNone; + mojom::blink::WebSandboxFlags sandbox_flags_ = + mojom::blink::WebSandboxFlags::kNone; // Loader's CSP - Member<ContentSecurityPolicy> content_security_policy_; + ContentSecurityPolicy* content_security_policy_ = nullptr; bool content_security_policy_from_context_doc_; network::mojom::IPAddressSpace ip_address_space_ = @@ -215,6 +266,18 @@ class CORE_EXPORT DocumentInit final { // The frame policy snapshot from the beginning of navigation. base::Optional<FramePolicy> frame_policy_ = base::nullopt; + + // The document policy set via response header. + DocumentPolicy::ParsedDocumentPolicy document_policy_; + String report_only_document_policy_header_; + + // The claimed URL inside Web Bundle file from which the document is loaded. + // This URL is used for window.location and document.URL and relative path + // computation in the document. + KURL web_bundle_claimed_url_; + + bool is_for_external_handler_ = false; + Color plugin_background_color_; }; } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/document_lifecycle.cc b/chromium/third_party/blink/renderer/core/dom/document_lifecycle.cc index 2a1c3b4d032..3b9b819c42b 100644 --- a/chromium/third_party/blink/renderer/core/dom/document_lifecycle.cc +++ b/chromium/third_party/blink/renderer/core/dom/document_lifecycle.cc @@ -91,8 +91,6 @@ DocumentLifecycle::DocumentLifecycle() disallow_transition_count_(0), check_no_transition_(false) {} -DocumentLifecycle::~DocumentLifecycle() = default; - #if DCHECK_IS_ON() bool DocumentLifecycle::CanAdvanceTo(LifecycleState next_state) const { @@ -200,6 +198,21 @@ bool DocumentLifecycle::CanAdvanceTo(LifecycleState next_state) const { return true; if (next_state == kStyleClean) return true; + // InAccessibility only runs if there is an ExistingAXObjectCache. + if (next_state == kInAccessibility) + return true; + if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && + next_state == kInCompositingUpdate) + return true; + if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && + next_state == kInPrePaint) + return true; + break; + case kInAccessibility: + if (next_state == kAccessibilityClean) + return true; + break; + case kAccessibilityClean: if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && next_state == kInCompositingUpdate) return true; @@ -222,6 +235,8 @@ bool DocumentLifecycle::CanAdvanceTo(LifecycleState next_state) const { return true; if (next_state == kInCompositingUpdate) return true; + if (next_state == kInAccessibility) + return true; // Otherwise, we can continue onwards. if (next_state == kCompositingClean) return true; @@ -236,6 +251,8 @@ bool DocumentLifecycle::CanAdvanceTo(LifecycleState next_state) const { return true; if (next_state == kInPrePaint) return true; + if (next_state == kInAccessibility) + return true; break; case kInPrePaint: if (next_state == kPrePaintClean) @@ -253,6 +270,8 @@ bool DocumentLifecycle::CanAdvanceTo(LifecycleState next_state) const { return true; if (next_state == kInPrePaint) return true; + if (next_state == kInAccessibility) + return true; break; case kInPaint: if (next_state == kPaintClean) @@ -270,6 +289,8 @@ bool DocumentLifecycle::CanAdvanceTo(LifecycleState next_state) const { return true; if (next_state == kInPaint) return true; + if (next_state == kInAccessibility) + return true; break; case kStopping: return next_state == kStopped; @@ -290,8 +311,9 @@ bool DocumentLifecycle::CanRewindTo(LifecycleState next_state) const { return true; return state_ == kStyleClean || state_ == kLayoutSubtreeChangeClean || state_ == kAfterPerformLayout || state_ == kLayoutClean || - state_ == kCompositingInputsClean || state_ == kCompositingClean || - state_ == kPrePaintClean || state_ == kPaintClean; + state_ == kAccessibilityClean || state_ == kCompositingInputsClean || + state_ == kCompositingClean || state_ == kPrePaintClean || + state_ == kPaintClean; } #define DEBUG_STRING_CASE(StateName) \ @@ -312,6 +334,8 @@ static WTF::String StateAsDebugString( DEBUG_STRING_CASE(kInPerformLayout); DEBUG_STRING_CASE(kAfterPerformLayout); DEBUG_STRING_CASE(kLayoutClean); + DEBUG_STRING_CASE(kInAccessibility); + DEBUG_STRING_CASE(kAccessibilityClean); DEBUG_STRING_CASE(kInCompositingUpdate); DEBUG_STRING_CASE(kCompositingInputsClean); DEBUG_STRING_CASE(kCompositingClean); diff --git a/chromium/third_party/blink/renderer/core/dom/document_lifecycle.h b/chromium/third_party/blink/renderer/core/dom/document_lifecycle.h index 5327f5ce96c..62ce22ed6e2 100644 --- a/chromium/third_party/blink/renderer/core/dom/document_lifecycle.h +++ b/chromium/third_party/blink/renderer/core/dom/document_lifecycle.h @@ -66,6 +66,11 @@ class CORE_EXPORT DocumentLifecycle { kAfterPerformLayout, kLayoutClean, + // In InAccessibility step, fire deferred accessibility events which + // require layout to be in a clean state. + kInAccessibility, + kAccessibilityClean, + kInCompositingUpdate, kCompositingInputsClean, kCompositingClean, @@ -87,9 +92,6 @@ class CORE_EXPORT DocumentLifecycle { kStopped, }; - // This must be kept coordinated with WebWidget::LifecycleUpdateReason - enum LifecycleUpdateReason { kBeginMainFrame, kTest, kOther }; - class Scope { STACK_ALLOCATED(); @@ -213,7 +215,6 @@ class CORE_EXPORT DocumentLifecycle { }; DocumentLifecycle(); - ~DocumentLifecycle(); bool IsActive() const { return state_ > kInactive && state_ < kStopping; } LifecycleState GetState() const { return state_; } diff --git a/chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.h b/chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.h index 6e0427e3566..cfed2ae42a7 100644 --- a/chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.h +++ b/chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.h @@ -5,6 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_OR_SHADOW_ROOT_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_OR_SHADOW_ROOT_H_ +#include "third_party/blink/renderer/core/animation/document_animation.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/shadow_root.h" #include "third_party/blink/renderer/core/frame/web_feature.h" @@ -50,6 +51,15 @@ class DocumentOrShadowRoot { return tree_scope.GetSelection(); } + static HeapVector<Member<Animation>> getAnimations(Document& document) { + return document.GetDocumentAnimations().getAnimations(document); + } + + static HeapVector<Member<Animation>> getAnimations(ShadowRoot& shadow_root) { + return shadow_root.GetDocument().GetDocumentAnimations().getAnimations( + shadow_root); + } + static Element* elementFromPoint(TreeScope& tree_scope, double x, double y) { return tree_scope.ElementFromPoint(x, y); } diff --git a/chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.idl b/chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.idl index f637e1a98b5..212bde8455e 100644 --- a/chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.idl +++ b/chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.idl @@ -10,6 +10,9 @@ // Selection API // https://w3c.github.io/selection-api/#extensions-to-document-interface [Affects=Nothing] Selection? getSelection(); + // Web-Animation-API + //https://drafts.csswg.org/web-animations/#extensions-to-the-documentorshadowroot-interface-mixin + [RuntimeEnabled=WebAnimationsAPI, Measure] sequence<Animation> getAnimations(); // CSSOM View Module // https://drafts.csswg.org/cssom-view/#extensions-to-the-document-interface Element? elementFromPoint(double x, double y); diff --git a/chromium/third_party/blink/renderer/core/dom/document_shutdown_notifier.cc b/chromium/third_party/blink/renderer/core/dom/document_shutdown_notifier.cc deleted file mode 100644 index 575a859ab7f..00000000000 --- a/chromium/third_party/blink/renderer/core/dom/document_shutdown_notifier.cc +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/core/dom/document_shutdown_notifier.h" - -#include "third_party/blink/renderer/core/dom/document.h" -#include "third_party/blink/renderer/core/dom/document_shutdown_observer.h" - -namespace blink { - -DocumentShutdownNotifier::DocumentShutdownNotifier() = default; - -} // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/document_shutdown_notifier.h b/chromium/third_party/blink/renderer/core/dom/document_shutdown_notifier.h deleted file mode 100644 index a7c241b01fd..00000000000 --- a/chromium/third_party/blink/renderer/core/dom/document_shutdown_notifier.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_SHUTDOWN_NOTIFIER_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_SHUTDOWN_NOTIFIER_H_ - -#include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/platform/lifecycle_notifier.h" - -namespace blink { - -class Document; -class DocumentShutdownObserver; - -// Sibling class of DocumentShutdownObserver; implemented by Document to notify -// subclasses of DocumentShutdownObserver of Document shutdown. -class CORE_EXPORT DocumentShutdownNotifier - : public LifecycleNotifier<Document, DocumentShutdownObserver> { - protected: - DocumentShutdownNotifier(); - - private: - DISALLOW_COPY_AND_ASSIGN(DocumentShutdownNotifier); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_SHUTDOWN_NOTIFIER_H_ diff --git a/chromium/third_party/blink/renderer/core/dom/document_shutdown_observer.cc b/chromium/third_party/blink/renderer/core/dom/document_shutdown_observer.cc deleted file mode 100644 index 76f3327775e..00000000000 --- a/chromium/third_party/blink/renderer/core/dom/document_shutdown_observer.cc +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/core/dom/document_shutdown_observer.h" - -#include "third_party/blink/renderer/core/dom/document.h" -#include "third_party/blink/renderer/core/dom/document_shutdown_notifier.h" - -namespace blink { - -void DocumentShutdownObserver::ContextDestroyed(Document*) {} - -DocumentShutdownObserver::DocumentShutdownObserver() - : LifecycleObserver(nullptr) {} - -} // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/document_shutdown_observer.h b/chromium/third_party/blink/renderer/core/dom/document_shutdown_observer.h deleted file mode 100644 index e7321eca284..00000000000 --- a/chromium/third_party/blink/renderer/core/dom/document_shutdown_observer.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. Use of -// this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_SHUTDOWN_OBSERVER_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_SHUTDOWN_OBSERVER_H_ - -#include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/platform/lifecycle_observer.h" - -namespace blink { - -class Document; - -// This class is a base class for classes which observe Document shutdown -// synchronously. -// Note: this functionality is also provided by SynchronousMutationObserver, -// but if you don't need to respond to the other events handled by that class, -// using this class is more efficient. -class CORE_EXPORT DocumentShutdownObserver - : public LifecycleObserver<Document, DocumentShutdownObserver> { - public: - // Called when detaching document. - virtual void ContextDestroyed(Document*); - - protected: - DocumentShutdownObserver(); - - private: - DISALLOW_COPY_AND_ASSIGN(DocumentShutdownObserver); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_SHUTDOWN_OBSERVER_H_ diff --git a/chromium/third_party/blink/renderer/core/dom/document_statistics_collector.cc b/chromium/third_party/blink/renderer/core/dom/document_statistics_collector.cc index dfbc4d3b1c6..b575ca1e27f 100644 --- a/chromium/third_party/blink/renderer/core/dom/document_statistics_collector.cc +++ b/chromium/third_party/blink/renderer/core/dom/document_statistics_collector.cc @@ -169,7 +169,7 @@ bool HasOpenGraphArticle(const Element& head) { if (meta->GetName() == og_type || meta->getAttribute(property_attr) == og_type) { - if (DeprecatedEqualIgnoringCase(meta->Content(), "article")) { + if (EqualIgnoringASCIICase(meta->Content(), "article")) { return true; } } diff --git a/chromium/third_party/blink/renderer/core/dom/document_statistics_collector_test.cc b/chromium/third_party/blink/renderer/core/dom/document_statistics_collector_test.cc index 1e4245e7d6f..cd881386004 100644 --- a/chromium/third_party/blink/renderer/core/dom/document_statistics_collector_test.cc +++ b/chromium/third_party/blink/renderer/core/dom/document_statistics_collector_test.cc @@ -35,7 +35,7 @@ class DocumentStatisticsCollectorTest : public PageTestBase { void DocumentStatisticsCollectorTest::SetHtmlInnerHTML( const String& html_content) { - GetDocument().documentElement()->SetInnerHTMLFromString((html_content)); + GetDocument().documentElement()->setInnerHTML((html_content)); } // This test checks open graph articles can be recognized. diff --git a/chromium/third_party/blink/renderer/core/dom/document_test.cc b/chromium/third_party/blink/renderer/core/dom/document_test.cc index e1cfa453dd4..5d3721c6624 100644 --- a/chromium/third_party/blink/renderer/core/dom/document_test.cc +++ b/chromium/third_party/blink/renderer/core/dom/document_test.cc @@ -34,9 +34,12 @@ #include "base/strings/stringprintf.h" #include "build/build_config.h" +#include "components/ukm/test_ukm_recorder.h" #include "services/network/public/mojom/referrer_policy.mojom-blink.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/feature_policy/document_policy_features.h" +#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" @@ -71,9 +74,13 @@ #include "third_party/blink/renderer/platform/weborigin/scheme_registry.h" #include "third_party/blink/renderer/platform/weborigin/security_origin.h" #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" +#include "url/url_util.h" namespace blink { +using network::mojom::ContentSecurityPolicySource; +using network::mojom::ContentSecurityPolicyType; + class DocumentTest : public PageTestBase { protected: void TearDown() override { @@ -85,8 +92,7 @@ class DocumentTest : public PageTestBase { }; void DocumentTest::SetHtmlInnerHTML(const char* html_content) { - GetDocument().documentElement()->SetInnerHTMLFromString( - String::FromUTF8(html_content)); + GetDocument().documentElement()->setInnerHTML(String::FromUTF8(html_content)); UpdateAllLifecyclePhasesForTest(); } @@ -135,11 +141,11 @@ class TestSynchronousMutationObserver void Trace(Visitor* visitor) { visitor->Trace(node_); } }; - TestSynchronousMutationObserver(Document&); + explicit TestSynchronousMutationObserver(Document&); virtual ~TestSynchronousMutationObserver() = default; int CountContextDestroyedCalled() const { - return context_destroyed_called_counter_; + return on_document_shutdown_called_counter_; } const HeapVector<Member<const ContainerNode>>& ChildrenChangedNodes() const { @@ -176,7 +182,7 @@ class TestSynchronousMutationObserver private: // Implement |SynchronousMutationObserver| member functions. - void ContextDestroyed(Document*) final; + void ContextDestroyed() final; void DidChangeChildren(const ContainerNode&) final; void DidMergeTextNodes(const Text&, const NodeWithIndex&, unsigned) final; void DidMoveTreeToNewDocument(const Node& root) final; @@ -188,7 +194,7 @@ class TestSynchronousMutationObserver void NodeChildrenWillBeRemoved(ContainerNode&) final; void NodeWillBeRemoved(Node&) final; - int context_destroyed_called_counter_ = 0; + int on_document_shutdown_called_counter_ = 0; HeapVector<Member<const ContainerNode>> children_changed_nodes_; HeapVector<Member<MergeTextNodesRecord>> merge_text_nodes_records_; HeapVector<Member<const Node>> move_tree_to_new_document_nodes_; @@ -202,11 +208,11 @@ class TestSynchronousMutationObserver TestSynchronousMutationObserver::TestSynchronousMutationObserver( Document& document) { - SetContext(&document); + SetDocument(&document); } -void TestSynchronousMutationObserver::ContextDestroyed(Document*) { - ++context_destroyed_called_counter_; +void TestSynchronousMutationObserver::ContextDestroyed() { + ++on_document_shutdown_called_counter_; } void TestSynchronousMutationObserver::DidChangeChildren( @@ -262,42 +268,6 @@ void TestSynchronousMutationObserver::Trace(Visitor* visitor) { SynchronousMutationObserver::Trace(visitor); } -class TestDocumentShutdownObserver - : public GarbageCollected<TestDocumentShutdownObserver>, - public DocumentShutdownObserver { - USING_GARBAGE_COLLECTED_MIXIN(TestDocumentShutdownObserver); - - public: - TestDocumentShutdownObserver(Document&); - virtual ~TestDocumentShutdownObserver() = default; - - int CountContextDestroyedCalled() const { - return context_destroyed_called_counter_; - } - - void Trace(Visitor*) override; - - private: - // Implement |DocumentShutdownObserver| member functions. - void ContextDestroyed(Document*) final; - - int context_destroyed_called_counter_ = 0; - - DISALLOW_COPY_AND_ASSIGN(TestDocumentShutdownObserver); -}; - -TestDocumentShutdownObserver::TestDocumentShutdownObserver(Document& document) { - SetContext(&document); -} - -void TestDocumentShutdownObserver::ContextDestroyed(Document*) { - ++context_destroyed_called_counter_; -} - -void TestDocumentShutdownObserver::Trace(Visitor* visitor) { - DocumentShutdownObserver::Trace(visitor); -} - class MockDocumentValidationMessageClient : public GarbageCollected<MockDocumentValidationMessageClient>, public ValidationMessageClient { @@ -362,8 +332,7 @@ class PrefersColorSchemeTestListener final : public MediaQueryListListener { } // anonymous namespace TEST_F(DocumentTest, CreateRangeAdjustedToTreeScopeWithPositionInShadowTree) { - GetDocument().body()->SetInnerHTMLFromString( - "<div><select><option>012</option></div>"); + GetDocument().body()->setInnerHTML("<div><select><option>012</option></div>"); Element* const select_element = GetDocument().QuerySelector("select"); const Position& position = Position(*select_element->UserAgentShadowRoot(), @@ -550,9 +519,7 @@ TEST_F(DocumentTest, referrerPolicyParsing) { {"same-origin", network::mojom::ReferrerPolicy::kSameOrigin, false}, {"strict-origin", network::mojom::ReferrerPolicy::kStrictOrigin, false}, {"strict-origin-when-cross-origin", - network::mojom::ReferrerPolicy:: - kNoReferrerWhenDowngradeOriginWhenCrossOrigin, - false}, + network::mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin, false}, {"unsafe-url", network::mojom::ReferrerPolicy::kAlways}, }; @@ -561,12 +528,15 @@ TEST_F(DocumentTest, referrerPolicyParsing) { if (test.is_legacy) { // Legacy keyword support must be explicitly enabled for the policy to // parse successfully. - GetDocument().ParseAndSetReferrerPolicy(test.policy); + GetDocument().GetExecutionContext()->ParseAndSetReferrerPolicy( + test.policy); EXPECT_EQ(network::mojom::ReferrerPolicy::kDefault, GetDocument().GetReferrerPolicy()); - GetDocument().ParseAndSetReferrerPolicy(test.policy, true); + GetDocument().GetExecutionContext()->ParseAndSetReferrerPolicy( + test.policy, true); } else { - GetDocument().ParseAndSetReferrerPolicy(test.policy); + GetDocument().GetExecutionContext()->ParseAndSetReferrerPolicy( + test.policy); } EXPECT_EQ(test.expected, GetDocument().GetReferrerPolicy()) << test.policy; } @@ -578,8 +548,8 @@ TEST_F(DocumentTest, OutgoingReferrer) { } TEST_F(DocumentTest, OutgoingReferrerWithUniqueOrigin) { - NavigateTo(KURL("https://www.example.com/hoge#fuga?piyo"), "", - "sandbox allow-scripts"); + NavigateTo(KURL("https://www.example.com/hoge#fuga?piyo"), + {{http_names::kContentSecurityPolicy, "sandbox allow-scripts"}}); EXPECT_TRUE(GetDocument().GetSecurityOrigin()->IsOpaque()); EXPECT_EQ(String(), GetDocument().OutgoingReferrer()); } @@ -614,30 +584,35 @@ TEST_F(DocumentTest, StyleVersion) { } TEST_F(DocumentTest, EnforceSandboxFlags) { - NavigateTo(KURL("http://example.test/"), "", "sandbox allow-same-origin"); + NavigateTo(KURL("http://example.test/"), {{http_names::kContentSecurityPolicy, + "sandbox allow-same-origin"}}); EXPECT_FALSE(GetDocument().GetSecurityOrigin()->IsOpaque()); EXPECT_FALSE(GetDocument().GetSecurityOrigin()->IsPotentiallyTrustworthy()); - NavigateTo(KURL("http://example.test/"), "", "sandbox"); + NavigateTo(KURL("http://example.test/"), + {{http_names::kContentSecurityPolicy, "sandbox"}}); EXPECT_TRUE(GetDocument().GetSecurityOrigin()->IsOpaque()); EXPECT_FALSE(GetDocument().GetSecurityOrigin()->IsPotentiallyTrustworthy()); // A unique origin does not bypass secure context checks unless it // is also potentially trustworthy. - url::AddStandardScheme("very-special-scheme", - url::SchemeType::SCHEME_WITH_HOST); + url::ScopedSchemeRegistryForTests scoped_registry; + url::AddStandardScheme("very-special-scheme", url::SCHEME_WITH_HOST); SchemeRegistry::RegisterURLSchemeBypassingSecureContextCheck( "very-special-scheme"); - NavigateTo(KURL("very-special-scheme://example.test"), "", "sandbox"); + NavigateTo(KURL("very-special-scheme://example.test"), + {{http_names::kContentSecurityPolicy, "sandbox"}}); EXPECT_TRUE(GetDocument().GetSecurityOrigin()->IsOpaque()); EXPECT_FALSE(GetDocument().GetSecurityOrigin()->IsPotentiallyTrustworthy()); SchemeRegistry::RegisterURLSchemeAsSecure("very-special-scheme"); - NavigateTo(KURL("very-special-scheme://example.test"), "", "sandbox"); + NavigateTo(KURL("very-special-scheme://example.test"), + {{http_names::kContentSecurityPolicy, "sandbox"}}); EXPECT_TRUE(GetDocument().GetSecurityOrigin()->IsOpaque()); EXPECT_TRUE(GetDocument().GetSecurityOrigin()->IsPotentiallyTrustworthy()); - NavigateTo(KURL("https://example.test"), "", "sandbox"); + NavigateTo(KURL("https://example.test"), + {{http_names::kContentSecurityPolicy, "sandbox"}}); EXPECT_TRUE(GetDocument().GetSecurityOrigin()->IsOpaque()); EXPECT_TRUE(GetDocument().GetSecurityOrigin()->IsPotentiallyTrustworthy()); } @@ -646,7 +621,7 @@ TEST_F(DocumentTest, SynchronousMutationNotifier) { auto& observer = *MakeGarbageCollected<TestSynchronousMutationObserver>(GetDocument()); - EXPECT_EQ(GetDocument(), observer.LifecycleContext()); + EXPECT_EQ(GetDocument(), observer.GetDocument()); EXPECT_EQ(0, observer.CountContextDestroyedCalled()); Element* div_node = GetDocument().CreateRawElement(html_names::kDivTag); @@ -673,7 +648,7 @@ TEST_F(DocumentTest, SynchronousMutationNotifier) { EXPECT_EQ(div_node, observer.RemovedChildrenNodes()[0]); GetDocument().Shutdown(); - EXPECT_EQ(nullptr, observer.LifecycleContext()); + EXPECT_EQ(nullptr, observer.GetDocument()); EXPECT_EQ(1, observer.CountContextDestroyedCalled()); } @@ -817,18 +792,6 @@ TEST_F(DocumentTest, SynchronousMutationNotifierUpdateCharacterData) { EXPECT_EQ(3u, observer.UpdatedCharacterDataRecords()[3]->new_length_); } -TEST_F(DocumentTest, DocumentShutdownNotifier) { - auto& observer = - *MakeGarbageCollected<TestDocumentShutdownObserver>(GetDocument()); - - EXPECT_EQ(GetDocument(), observer.LifecycleContext()); - EXPECT_EQ(0, observer.CountContextDestroyedCalled()); - - GetDocument().Shutdown(); - EXPECT_EQ(nullptr, observer.LifecycleContext()); - EXPECT_EQ(1, observer.CountContextDestroyedCalled()); -} - TEST_F(DocumentTest, AttachExecutionContext) { EXPECT_TRUE( GetDocument().GetAgent()->event_loop()->IsSchedulerAttachedForTest( @@ -880,7 +843,7 @@ TEST_F(DocumentTest, ValidationMessageCleanup) { "document.querySelector('input').reportValidity(); };"); GetDocument().body()->AppendChild(script); auto* input = To<HTMLInputElement>(GetDocument().body()->firstChild()); - DVLOG(0) << GetDocument().body()->OuterHTMLAsString(); + DVLOG(0) << GetDocument().body()->outerHTML(); // Sanity check. input->reportValidity(); @@ -897,7 +860,8 @@ TEST_F(DocumentTest, ValidationMessageCleanup) { } TEST_F(DocumentTest, SandboxDisablesAppCache) { - NavigateTo(KURL("https://test.com/foobar/document"), "", "sandbox"); + NavigateTo(KURL("https://test.com/foobar/document"), + {{http_names::kContentSecurityPolicy, "sandbox"}}); GetDocument().Loader()->SetApplicationCacheHostForTesting( MakeGarbageCollected<MockApplicationCacheHost>(GetDocument().Loader())); @@ -914,7 +878,7 @@ TEST_F(DocumentTest, SandboxDisablesAppCache) { // as it is more expensive than just doing layout. TEST_F(DocumentTest, EnsurePaintLocationDataValidForNodeCompositingInputsOnlyWhenNecessary) { - GetDocument().body()->SetInnerHTMLFromString(R"HTML( + GetDocument().body()->setInnerHTML(R"HTML( <div id='ancestor'> <div id='sticky' style='position:sticky;'> <div id='stickyChild'></div> @@ -929,19 +893,19 @@ TEST_F(DocumentTest, // Asking for any element that is not affected by a sticky element should only // advance the lifecycle to layout clean. GetDocument().EnsurePaintLocationDataValidForNode( - GetDocument().getElementById("ancestor")); + GetDocument().getElementById("ancestor"), DocumentUpdateReason::kTest); EXPECT_EQ(DocumentLifecycle::kLayoutClean, GetDocument().Lifecycle().GetState()); GetDocument().EnsurePaintLocationDataValidForNode( - GetDocument().getElementById("nonSticky")); + GetDocument().getElementById("nonSticky"), DocumentUpdateReason::kTest); EXPECT_EQ(DocumentLifecycle::kLayoutClean, GetDocument().Lifecycle().GetState()); // However, asking for either the sticky element or it's descendents should // clean compositing inputs as well. GetDocument().EnsurePaintLocationDataValidForNode( - GetDocument().getElementById("sticky")); + GetDocument().getElementById("sticky"), DocumentUpdateReason::kTest); EXPECT_EQ(DocumentLifecycle::kCompositingInputsClean, GetDocument().Lifecycle().GetState()); @@ -951,7 +915,7 @@ TEST_F(DocumentTest, GetDocument().Lifecycle().GetState()); GetDocument().EnsurePaintLocationDataValidForNode( - GetDocument().getElementById("stickyChild")); + GetDocument().getElementById("stickyChild"), DocumentUpdateReason::kTest); EXPECT_EQ(DocumentLifecycle::kCompositingInputsClean, GetDocument().Lifecycle().GetState()); } @@ -996,8 +960,8 @@ TEST_P(IsolatedWorldCSPTest, CSPForWorld) { // Set a CSP for the main world. const char* kMainWorldCSP = "connect-src https://google.com;"; GetDocument().GetContentSecurityPolicy()->DidReceiveHeader( - kMainWorldCSP, kContentSecurityPolicyHeaderTypeEnforce, - kContentSecurityPolicyHeaderSourceHTTP); + kMainWorldCSP, ContentSecurityPolicyType::kEnforce, + ContentSecurityPolicySource::kHTTP); LocalFrame* frame = GetDocument().GetFrame(); ScriptState* main_world_script_state = ToScriptStateForMainWorld(frame); @@ -1031,7 +995,7 @@ TEST_P(IsolatedWorldCSPTest, CSPForWorld) { ScriptState::Scope scope(main_world_script_state); EXPECT_THAT(get_csp_headers(), ElementsAre(CSPHeaderAndType( - {kMainWorldCSP, kContentSecurityPolicyHeaderTypeEnforce}))); + {kMainWorldCSP, ContentSecurityPolicyType::kEnforce}))); } { @@ -1042,7 +1006,7 @@ TEST_P(IsolatedWorldCSPTest, CSPForWorld) { // CSP. EXPECT_THAT(get_csp_headers(), ElementsAre(CSPHeaderAndType( - {kMainWorldCSP, kContentSecurityPolicyHeaderTypeEnforce}))); + {kMainWorldCSP, ContentSecurityPolicyType::kEnforce}))); } { @@ -1062,7 +1026,7 @@ TEST_P(IsolatedWorldCSPTest, CSPForWorld) { EXPECT_THAT( get_csp_headers(), ElementsAre(CSPHeaderAndType( - {kIsolatedWorldCSP, kContentSecurityPolicyHeaderTypeEnforce}))); + {kIsolatedWorldCSP, ContentSecurityPolicyType::kEnforce}))); } } } @@ -1072,7 +1036,8 @@ INSTANTIATE_TEST_SUITE_P(All, testing::Values(true, false)); TEST_F(DocumentTest, CanExecuteScriptsWithSandboxAndIsolatedWorld) { - NavigateTo(KURL("https://www.example.com/"), "", "sandbox"); + NavigateTo(KURL("https://www.example.com/"), + {{http_names::kContentSecurityPolicy, "sandbox"}}); LocalFrame* frame = GetDocument().GetFrame(); frame->GetSettings()->SetScriptEnabled(true); @@ -1178,6 +1143,8 @@ TEST_F(DocumentTest, ElementFromPointWithPageZoom) { } TEST_F(DocumentTest, PrefersColorSchemeChanged) { + ColorSchemeHelper color_scheme_helper(GetDocument()); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kLight); UpdateAllLifecyclePhasesForTest(); auto* list = GetDocument().GetMediaQueryMatcher().MatchMedia( @@ -1187,9 +1154,7 @@ TEST_F(DocumentTest, PrefersColorSchemeChanged) { EXPECT_FALSE(listener->IsNotified()); - ColorSchemeHelper color_scheme_helper; - color_scheme_helper.SetPreferredColorScheme(GetDocument(), - PreferredColorScheme::kDark); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kDark); UpdateAllLifecyclePhasesForTest(); GetDocument().ServiceScriptedAnimations(base::TimeTicks()); @@ -1197,43 +1162,61 @@ TEST_F(DocumentTest, PrefersColorSchemeChanged) { EXPECT_TRUE(listener->IsNotified()); } -TEST_F(DocumentTest, DocumentPolicyFeaturePolicyCoexist) { - blink::ScopedDocumentPolicyForTest sdp(true); - const auto test_feature = blink::mojom::FeaturePolicyFeature::kFontDisplay; - const auto report_option = blink::ReportOptions::kReportOnFailure; - - // When document_policy is not initialized, feature_policy should - // be sufficient to determine the result. - NavigateTo(KURL("https://www.example.com/"), "font-display-late-swap 'none'", - ""); - EXPECT_FALSE(GetDocument().IsFeatureEnabled(test_feature, report_option)); - - NavigateTo(KURL("https://www.example.com/"), "font-display-late-swap *", ""); - EXPECT_TRUE(GetDocument().IsFeatureEnabled(test_feature, report_option)); - - // When document_policy is specified, both feature_policy and - // document_policy need to return true for the feature to be - // enabled. - NavigateTo(KURL("https://www.example.com/"), "font-display-late-swap *", ""); - GetDocument().SetDocumentPolicyForTesting( - DocumentPolicy::CreateWithRequiredPolicy( - {{test_feature, blink::PolicyValue(true)}})); - EXPECT_TRUE(GetDocument().IsFeatureEnabled(test_feature, report_option)); - GetDocument().SetDocumentPolicyForTesting( - DocumentPolicy::CreateWithRequiredPolicy( - {{test_feature, blink::PolicyValue(false)}})); - EXPECT_FALSE(GetDocument().IsFeatureEnabled(test_feature, report_option)); - - NavigateTo(KURL("https://www.example.com/"), "font-display-late-swap 'none'", - ""); - GetDocument().SetDocumentPolicyForTesting( - DocumentPolicy::CreateWithRequiredPolicy( - {{test_feature, blink::PolicyValue(true)}})); - EXPECT_FALSE(GetDocument().IsFeatureEnabled(test_feature, report_option)); - GetDocument().SetDocumentPolicyForTesting( - DocumentPolicy::CreateWithRequiredPolicy( - {{test_feature, blink::PolicyValue(false)}})); - EXPECT_FALSE(GetDocument().IsFeatureEnabled(test_feature, report_option)); +TEST_F(DocumentTest, FindInPageUkm) { + GetDocument().ukm_recorder_ = std::make_unique<ukm::TestUkmRecorder>(); + auto* recorder = + static_cast<ukm::TestUkmRecorder*>(GetDocument().UkmRecorder()); + + EXPECT_EQ(recorder->entries_count(), 0u); + GetDocument().MarkHasFindInPageRequest(); + EXPECT_EQ(recorder->entries_count(), 1u); + GetDocument().MarkHasFindInPageRequest(); + EXPECT_EQ(recorder->entries_count(), 1u); + + auto entries = recorder->GetEntriesByName("Blink.FindInPage"); + EXPECT_EQ(entries.size(), 1u); + EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entries[0], "DidSearch")); + EXPECT_EQ(*ukm::TestUkmRecorder::GetEntryMetric(entries[0], "DidSearch"), 1); + EXPECT_FALSE(ukm::TestUkmRecorder::EntryHasMetric( + entries[0], "DidHaveRenderSubtreeMatch")); + + GetDocument().MarkHasFindInPageSubtreeVisibilityActiveMatch(); + EXPECT_EQ(recorder->entries_count(), 2u); + GetDocument().MarkHasFindInPageSubtreeVisibilityActiveMatch(); + EXPECT_EQ(recorder->entries_count(), 2u); + entries = recorder->GetEntriesByName("Blink.FindInPage"); + EXPECT_EQ(entries.size(), 2u); + + EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric(entries[0], "DidSearch")); + EXPECT_EQ(*ukm::TestUkmRecorder::GetEntryMetric(entries[0], "DidSearch"), 1); + EXPECT_FALSE(ukm::TestUkmRecorder::EntryHasMetric( + entries[0], "DidHaveRenderSubtreeMatch")); + + EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric( + entries[1], "DidHaveRenderSubtreeMatch")); + EXPECT_EQ(*ukm::TestUkmRecorder::GetEntryMetric(entries[1], + "DidHaveRenderSubtreeMatch"), + 1); + EXPECT_FALSE(ukm::TestUkmRecorder::EntryHasMetric(entries[1], "DidSearch")); +} + +TEST_F(DocumentTest, AtPageMarginWithDeviceScaleFactor) { + GetDocument().GetFrame()->SetPageZoomFactor(2); + SetBodyInnerHTML("<style>@page { margin: 50px; size: 400px 10in; }</style>"); + + constexpr FloatSize initial_page_size(800, 600); + + GetDocument().GetFrame()->StartPrinting(initial_page_size, initial_page_size); + GetDocument().View()->UpdateLifecyclePhasesForPrinting(); + + DoubleSize page_size; + int margin[4]; + GetDocument().PageSizeAndMarginsInPixels(0, page_size, margin[0], margin[1], + margin[2], margin[3]); + + for (int side_margin : margin) + EXPECT_EQ(50, side_margin); + EXPECT_EQ(DoubleSize(400, 960), page_size); } /** @@ -1321,7 +1304,7 @@ class ParameterizedViewportFitDocumentTest html.Append("'>"); } - GetDocument().documentElement()->SetInnerHTMLFromString(html.ToString()); + GetDocument().documentElement()->setInnerHTML(html.ToString()); UpdateAllLifecyclePhasesForTest(); } }; diff --git a/chromium/third_party/blink/renderer/core/dom/document_timing.cc b/chromium/third_party/blink/renderer/core/dom/document_timing.cc index beb3f9deb31..cb5d4b364e4 100644 --- a/chromium/third_party/blink/renderer/core/dom/document_timing.cc +++ b/chromium/third_party/blink/renderer/core/dom/document_timing.cc @@ -12,7 +12,10 @@ namespace blink { -DocumentTiming::DocumentTiming(Document& document) : document_(document) {} +DocumentTiming::DocumentTiming(Document& document) : document_(document) { + if (document_->GetReadyState() == Document::kLoading) + MarkDomLoading(); +} void DocumentTiming::Trace(Visitor* visitor) { visitor->Trace(document_); @@ -72,12 +75,4 @@ void DocumentTiming::MarkDomComplete() { NotifyDocumentTimingChanged(); } -void DocumentTiming::MarkFirstLayout() { - first_layout_ = base::TimeTicks::Now(); - TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing,rail", "firstLayout", - first_layout_, "frame", - ToTraceValue(GetFrame())); - NotifyDocumentTimingChanged(); -} - } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/document_timing.h b/chromium/third_party/blink/renderer/core/dom/document_timing.h index 5dd735d169d..b3401679130 100644 --- a/chromium/third_party/blink/renderer/core/dom/document_timing.h +++ b/chromium/third_party/blink/renderer/core/dom/document_timing.h @@ -44,7 +44,6 @@ class DocumentTiming final { void MarkDomContentLoadedEventStart(); void MarkDomContentLoadedEventEnd(); void MarkDomComplete(); - void MarkFirstLayout(); // These return monotonically-increasing time. base::TimeTicks DomLoading() const { return dom_loading_; } @@ -56,7 +55,6 @@ class DocumentTiming final { return dom_content_loaded_event_end_; } base::TimeTicks DomComplete() const { return dom_complete_; } - base::TimeTicks FirstLayout() const { return first_layout_; } void Trace(Visitor*); @@ -69,7 +67,6 @@ class DocumentTiming final { base::TimeTicks dom_content_loaded_event_start_; base::TimeTicks dom_content_loaded_event_end_; base::TimeTicks dom_complete_; - base::TimeTicks first_layout_; Member<Document> document_; }; diff --git a/chromium/third_party/blink/renderer/core/dom/dom_exception.idl b/chromium/third_party/blink/renderer/core/dom/dom_exception.idl index 2e3e9adac67..fee491b6b8a 100644 --- a/chromium/third_party/blink/renderer/core/dom/dom_exception.idl +++ b/chromium/third_party/blink/renderer/core/dom/dom_exception.idl @@ -32,10 +32,10 @@ [ Exposed=(Window,Worker), - Constructor(optional DOMString message = "", optional DOMString name = "Error"), Serializable, DoNotCheckConstants ] interface DOMException { + constructor(optional DOMString message = "", optional DOMString name = "Error"); readonly attribute unsigned short code; readonly attribute DOMString name; diff --git a/chromium/third_party/blink/renderer/core/dom/dom_implementation.cc b/chromium/third_party/blink/renderer/core/dom/dom_implementation.cc index 55f1adf5e98..7c1a0d0f2cf 100644 --- a/chromium/third_party/blink/renderer/core/dom/dom_implementation.cc +++ b/chromium/third_party/blink/renderer/core/dom/dom_implementation.cc @@ -32,6 +32,7 @@ #include "third_party/blink/renderer/core/dom/document_init.h" #include "third_party/blink/renderer/core/dom/document_type.h" #include "third_party/blink/renderer/core/dom/element.h" +#include "third_party/blink/renderer/core/dom/sink_document.h" #include "third_party/blink/renderer/core/dom/text.h" #include "third_party/blink/renderer/core/dom/xml_document.h" #include "third_party/blink/renderer/core/frame/local_frame.h" @@ -41,14 +42,11 @@ #include "third_party/blink/renderer/core/html/html_title_element.h" #include "third_party/blink/renderer/core/html/html_view_source_document.h" #include "third_party/blink/renderer/core/html/image_document.h" -#include "third_party/blink/renderer/core/html/media/html_media_element.h" #include "third_party/blink/renderer/core/html/media/media_document.h" #include "third_party/blink/renderer/core/html/plugin_document.h" #include "third_party/blink/renderer/core/html/text_document.h" #include "third_party/blink/renderer/core/html_names.h" #include "third_party/blink/renderer/core/loader/frame_loader.h" -#include "third_party/blink/renderer/core/page/page.h" -#include "third_party/blink/renderer/core/page/plugin_data.h" #include "third_party/blink/renderer/core/svg_names.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/graphics/image.h" @@ -206,84 +204,42 @@ Document* DOMImplementation::createHTMLDocument(const String& title) { return d; } -Document* DOMImplementation::createDocument(const String& type, - const DocumentInit& init, - bool in_view_source_mode) { - if (in_view_source_mode) - return MakeGarbageCollected<HTMLViewSourceDocument>(init, type); - - // Plugins cannot take HTML and XHTML from us, and we don't even need to - // initialize the plugin database for those. - if (type == "text/html") - return MakeGarbageCollected<HTMLDocument>(init); - if (type == "application/xhtml+xml") - return XMLDocument::CreateXHTML(init); - - PluginData* plugin_data = nullptr; - if (init.GetFrame() && init.GetFrame()->GetPage() && - init.GetFrame()->Loader().AllowPlugins(kNotAboutToInstantiatePlugin)) { - // If the document is being created for the main frame, - // init.frame()->tree().top()->securityContext() returns nullptr. - // For that reason, the origin must be retrieved directly from init.url(). - if (init.GetFrame()->IsMainFrame()) { - scoped_refptr<const SecurityOrigin> origin = - SecurityOrigin::Create(init.Url()); - plugin_data = init.GetFrame()->GetPage()->GetPluginData(origin.get()); - } else { - plugin_data = - init.GetFrame()->GetPage()->GetPluginData(init.GetFrame() - ->Tree() - .Top() - .GetSecurityContext() - ->GetSecurityOrigin()); +Document* DOMImplementation::createDocument(const DocumentInit& init) { + switch (init.GetType()) { + case DocumentInit::Type::kHTML: + return MakeGarbageCollected<HTMLDocument>(init); + case DocumentInit::Type::kXHTML: + return XMLDocument::CreateXHTML(init); + case DocumentInit::Type::kImage: + return MakeGarbageCollected<ImageDocument>(init); + case DocumentInit::Type::kPlugin: { + Document* document = MakeGarbageCollected<PluginDocument>(init); + // TODO(crbug.com/1029822): Final sandbox flags are calculated during + // document construction, so we have to construct a PluginDocument then + // replace it with a SinkDocument when plugins are sanboxed. If we move + // final sandbox flag calcuation earlier, we could construct the + // SinkDocument directly. + if (document->IsSandboxed(mojom::blink::WebSandboxFlags::kPlugins)) + document = MakeGarbageCollected<SinkDocument>(init); + return document; } + case DocumentInit::Type::kMedia: + return MakeGarbageCollected<MediaDocument>(init); + case DocumentInit::Type::kSVG: + return XMLDocument::CreateSVG(init); + case DocumentInit::Type::kXML: + return MakeGarbageCollected<XMLDocument>(init); + case DocumentInit::Type::kViewSource: + return MakeGarbageCollected<HTMLViewSourceDocument>(init); + case DocumentInit::Type::kText: + return MakeGarbageCollected<TextDocument>(init); + case DocumentInit::Type::kUnspecified: + FALLTHROUGH; + default: + break; } - - if (plugin_data && plugin_data->IsExternalPluginMimeType(type)) { - // Plugins handled by MimeHandlerView do not create a PluginDocument. They - // are rendered inside cross-process frames and the notion of a PluginView - // (which is associated with PluginDocument) is irrelevant here. - auto* html_document = MakeGarbageCollected<HTMLDocument>(init); - html_document->SetIsForExternalHandler(); - return html_document; - } - - // PDF is one image type for which a plugin can override built-in support. - // We do not want QuickTime to take over all image types, obviously. - if ((type == "application/pdf" || type == "text/pdf") && plugin_data && - plugin_data->SupportsMimeType(type)) { - return MakeGarbageCollected<PluginDocument>( - init, plugin_data->PluginBackgroundColorForMimeType(type)); - } - // multipart/x-mixed-replace is only supported for images. - if (MIMETypeRegistry::IsSupportedImageResourceMIMEType(type) || - type == "multipart/x-mixed-replace") { - return MakeGarbageCollected<ImageDocument>(init); - } - - // Check to see if the type can be played by our media player, if so create a - // MediaDocument - if (HTMLMediaElement::GetSupportsType(ContentType(type))) - return MakeGarbageCollected<MediaDocument>(init); - - // Everything else except text/plain can be overridden by plugins. In - // particular, Adobe SVG Viewer should be used for SVG, if installed. - // Disallowing plugins to use text/plain prevents plugins from hijacking a - // fundamental type that the browser is expected to handle, and also serves as - // an optimization to prevent loading the plugin database in the common case. - if (type != "text/plain" && plugin_data && - plugin_data->SupportsMimeType(type)) { - return MakeGarbageCollected<PluginDocument>( - init, plugin_data->PluginBackgroundColorForMimeType(type)); - } - if (IsTextMIMEType(type)) - return MakeGarbageCollected<TextDocument>(init); - if (type == "image/svg+xml") - return XMLDocument::CreateSVG(init); - if (IsXMLMIMEType(type)) - return MakeGarbageCollected<XMLDocument>(init); - - return MakeGarbageCollected<HTMLDocument>(init); + NOTREACHED(); + return nullptr; } void DOMImplementation::Trace(Visitor* visitor) { diff --git a/chromium/third_party/blink/renderer/core/dom/dom_implementation.h b/chromium/third_party/blink/renderer/core/dom/dom_implementation.h index 25e6d63e950..72599ffa7ed 100644 --- a/chromium/third_party/blink/renderer/core/dom/dom_implementation.h +++ b/chromium/third_party/blink/renderer/core/dom/dom_implementation.h @@ -56,9 +56,7 @@ class CORE_EXPORT DOMImplementation final : public ScriptWrappable { Document* createHTMLDocument(const String& title = String()); // Other methods (not part of DOM) - static Document* createDocument(const String& mime_type, - const DocumentInit&, - bool in_view_source_mode); + static Document* createDocument(const DocumentInit&); static bool IsXMLMIMEType(const String&); static bool IsTextMIMEType(const String&); diff --git a/chromium/third_party/blink/renderer/core/dom/dom_string_map.h b/chromium/third_party/blink/renderer/core/dom/dom_string_map.h index 04d281dfa45..5ae98a1a827 100644 --- a/chromium/third_party/blink/renderer/core/dom/dom_string_map.h +++ b/chromium/third_party/blink/renderer/core/dom/dom_string_map.h @@ -47,15 +47,16 @@ class DOMStringMap : public ScriptWrappable { const String& value, ExceptionState&) = 0; virtual bool DeleteItem(const String& name) = 0; - bool AnonymousNamedSetter(const String& name, - const String& value, - ExceptionState& exception_state) { + NamedPropertySetterResult AnonymousNamedSetter( + const String& name, + const String& value, + ExceptionState& exception_state) { SetItem(name, value, exception_state); - return true; + return NamedPropertySetterResult::kIntercepted; } - DeleteResult AnonymousNamedDeleter(const AtomicString& name) { - bool known_property = DeleteItem(name); - return known_property ? kDeleteSuccess : kDeleteUnknownProperty; + NamedPropertyDeleterResult AnonymousNamedDeleter(const AtomicString& name) { + return DeleteItem(name) ? NamedPropertyDeleterResult::kDeleted + : NamedPropertyDeleterResult::kDidNotIntercept; } void NamedPropertyEnumerator(Vector<String>& names, ExceptionState&) { GetNames(names); diff --git a/chromium/third_party/blink/renderer/core/dom/element.cc b/chromium/third_party/blink/renderer/core/dom/element.cc index a31d920c809..9801e9a3cf8 100644 --- a/chromium/third_party/blink/renderer/core/dom/element.cc +++ b/chromium/third_party/blink/renderer/core/dom/element.cc @@ -26,18 +26,22 @@ #include "third_party/blink/renderer/core/dom/element.h" +#include <algorithm> #include <bitset> +#include <limits> #include <memory> +#include <utility> #include "cc/input/snap_selection_strategy.h" -#include "third_party/blink/public/platform/web_scroll_into_view_params.h" +#include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/dictionary.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/core/v8/scroll_into_view_options_or_boolean.h" -#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html.h" #include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html_or_trusted_script_or_trusted_script_url.h" -#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_script.h" -#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_script_url.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_pointer_lock_options.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_into_view_options.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_scroll_to_options.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_shadow_root_init.h" #include "third_party/blink/renderer/core/accessibility/ax_context.h" #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h" #include "third_party/blink/renderer/core/animation/css/css_animations.h" @@ -76,12 +80,10 @@ #include "third_party/blink/renderer/core/dom/mutation_record.h" #include "third_party/blink/renderer/core/dom/named_node_map.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h" -#include "third_party/blink/renderer/core/dom/pointer_lock_options.h" #include "third_party/blink/renderer/core/dom/presentation_attribute_style.h" #include "third_party/blink/renderer/core/dom/pseudo_element.h" #include "third_party/blink/renderer/core/dom/scriptable_document_parser.h" #include "third_party/blink/renderer/core/dom/shadow_root.h" -#include "third_party/blink/renderer/core/dom/shadow_root_init.h" #include "third_party/blink/renderer/core/dom/shadow_root_v0.h" #include "third_party/blink/renderer/core/dom/slot_assignment.h" #include "third_party/blink/renderer/core/dom/space_split_string.h" @@ -100,8 +102,6 @@ #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" -#include "third_party/blink/renderer/core/frame/scroll_into_view_options.h" -#include "third_party/blink/renderer/core/frame/scroll_to_options.h" #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/frame/visual_viewport.h" #include "third_party/blink/renderer/core/fullscreen/fullscreen.h" @@ -174,7 +174,7 @@ namespace { class DisplayLockStyleScope { public: - DisplayLockStyleScope(Element* element) : element_(element) { + explicit DisplayLockStyleScope(Element* element) : element_(element) { // Note that we don't store context as a member of this scope, since it may // get created as part of element self style recalc. auto* context = element->GetDisplayLockContext(); @@ -232,7 +232,7 @@ bool IsRootEditableElementWithCounting(const Element& element) { auto user_modify = style->UserModify(); const AtomicString& ce_value = element.FastGetAttribute(html_names::kContenteditableAttr); - if (ce_value.IsNull() || DeprecatedEqualIgnoringCase(ce_value, "false")) { + if (ce_value.IsNull() || EqualIgnoringASCIICase(ce_value, "false")) { if (user_modify == EUserModify::kReadWritePlaintextOnly) { UseCounter::Count(doc, WebFeature::kPlainTextEditingEffective); UseCounter::Count(doc, WebFeature::kWebKitUserModifyPlainTextEffective); @@ -241,8 +241,7 @@ bool IsRootEditableElementWithCounting(const Element& element) { UseCounter::Count(doc, WebFeature::kWebKitUserModifyReadWriteEffective); UseCounter::Count(doc, WebFeature::kWebKitUserModifyEffective); } - } else if (ce_value.IsEmpty() || - DeprecatedEqualIgnoringCase(ce_value, "true")) { + } else if (ce_value.IsEmpty() || EqualIgnoringASCIICase(ce_value, "true")) { if (user_modify == EUserModify::kReadWritePlaintextOnly) { UseCounter::Count(doc, WebFeature::kPlainTextEditingEffective); UseCounter::Count(doc, WebFeature::kWebKitUserModifyPlainTextEffective); @@ -251,7 +250,7 @@ bool IsRootEditableElementWithCounting(const Element& element) { UseCounter::Count(doc, WebFeature::kWebKitUserModifyReadOnlyEffective); UseCounter::Count(doc, WebFeature::kWebKitUserModifyEffective); } - } else if (DeprecatedEqualIgnoringCase(ce_value, "plaintext-only")) { + } else if (EqualIgnoringASCIICase(ce_value, "plaintext-only")) { UseCounter::Count(doc, WebFeature::kPlainTextEditingEffective); if (user_modify == EUserModify::kReadWrite) { UseCounter::Count(doc, WebFeature::kWebKitUserModifyReadWriteEffective); @@ -330,28 +329,33 @@ bool CalculateStyleShouldForceLegacyLayout(const Element& element, return true; } - if (style.IsDeprecatedWebkitBox()) + if (style.IsDeprecatedWebkitBox() && + (!style.IsDeprecatedWebkitBoxWithVerticalLineClamp() || + !RuntimeEnabledFeatures::BlockFlowHandlesWebkitLineClampEnabled())) { return true; + } if (!RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled()) { - // Disable NG for the entire subtree if we're establishing a block - // fragmentation context. + // Disable NG for the entire subtree if we're establishing a multicol + // container. if (style.SpecifiesColumns()) return true; - if (document.Printing() && element == document.documentElement()) - return true; - - // Fall back to legacy layout for frameset documents. The frameset itself - // (and the frames) can only create legacy layout objects anyway (no NG - // counterpart for them yet). However, the layout object for the HTML root - // element would be an NG one. If we'd then print the document, we'd fall - // back to legacy layout (because of the above check), which would re-attach - // all layout objects, which would cause the frameset to lose state of some - // sort, leaving everything blank when printed. - if (document.IsFrameSet()) - return true; } + // No printing support in LayoutNG yet. + if (document.Printing() && element == document.documentElement()) + return true; + + // Fall back to legacy layout for frameset documents. The frameset itself (and + // the frames) can only create legacy layout objects anyway (no NG counterpart + // for them yet). However, the layout object for the HTML root element would + // be an NG one. If we'd then print the document, we'd fall back to legacy + // layout (because of the above check), which would re-attach all layout + // objects, which would cause the frameset to lose state of some sort, leaving + // everything blank when printed. + if (document.IsFrameSet()) + return true; + // 'text-combine-upright' property is not supported yet. if (style.HasTextCombine() && !style.IsHorizontalWritingMode()) return true; @@ -411,6 +415,8 @@ bool IsElementReflectionAttribute(const QualifiedName& name) { return true; if (name == html_names::kAriaFlowtoAttr) return true; + if (name == html_names::kAriaLabeledbyAttr) + return true; if (name == html_names::kAriaLabelledbyAttr) return true; if (name == html_names::kAriaOwnsAttr) @@ -420,7 +426,7 @@ bool IsElementReflectionAttribute(const QualifiedName& name) { HeapVector<Member<Element>>* GetExplicitlySetElementsForAttr( Element* element, - QualifiedName name) { + const QualifiedName& name) { ExplicitlySetAttrElementsMap* element_attribute_map = element->GetDocument().GetExplicitlySetAttrElementsMap(element); return element_attribute_map->at(name); @@ -473,8 +479,8 @@ void EnqueueAutofocus(Element& element) { // 4. If target's active sandboxing flag set has the sandboxed automatic // features browsing context flag, then return. - if (doc.IsSandboxed(WebSandboxFlags::kAutomaticFeatures)) { - doc.AddConsoleMessage(ConsoleMessage::Create( + if (doc.IsSandboxed(mojom::blink::WebSandboxFlags::kAutomaticFeatures)) { + doc.AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( mojom::ConsoleMessageSource::kSecurity, mojom::ConsoleMessageLevel::kError, "Blocked autofocusing on a form control because the form's frame is " @@ -488,7 +494,7 @@ void EnqueueAutofocus(Element& element) { // then return. if (!doc.IsInMainFrame() && !doc.TopFrameOrigin()->CanAccess(doc.GetSecurityOrigin())) { - doc.AddConsoleMessage(ConsoleMessage::Create( + doc.AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( mojom::ConsoleMessageSource::kSecurity, mojom::ConsoleMessageLevel::kError, "Blocked autofocusing on a form control in a cross-origin subframe.")); @@ -576,8 +582,10 @@ bool Element::IsFocusableStyle() const { // Update style if we're in a display-locked subtree, because it isn't // included in the normal style updates. We also need to update the layout // here because some callers expect the layout stays clean. - if (DisplayLockUtilities::NearestLockedExclusiveAncestor(*this)) - GetDocument().UpdateStyleAndLayoutForNode(this); + if (DisplayLockUtilities::NearestLockedExclusiveAncestor(*this)) { + GetDocument().UpdateStyleAndLayoutForNode( + this, DocumentUpdateReason::kDisplayLock); + } if (IsInsideInvisibleSubtree()) { const ComputedStyle* style = @@ -669,6 +677,11 @@ void Element::SetBooleanAttribute(const QualifiedName& name, bool value) { removeAttribute(name); } +bool Element::HasExplicitlySetAttrAssociatedElements( + const QualifiedName& name) { + return GetExplicitlySetElementsForAttr(this, name); +} + void Element::SynchronizeContentAttributeAndElementReference( const QualifiedName& name) { ExplicitlySetAttrElementsMap* element_attribute_map = @@ -716,6 +729,11 @@ void Element::SetElementAttribute(const QualifiedName& name, Element* element) { result.stored_value->value->clear(); } result.stored_value->value->push_back(element); + + if (isConnected()) { + if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache()) + cache->HandleAttributeChanged(name, this); + } } Element* Element::GetElementAttribute(const QualifiedName& name) { @@ -740,12 +758,11 @@ Element* Element::GetElementAttribute(const QualifiedName& name) { void Element::SetElementArrayAttribute( const QualifiedName& name, - HeapVector<Member<Element>> given_elements, - bool is_null) { + const base::Optional<HeapVector<Member<Element>>>& given_elements) { ExplicitlySetAttrElementsMap* element_attribute_map = GetDocument().GetExplicitlySetAttrElementsMap(this); - if (is_null) { + if (!given_elements) { element_attribute_map->erase(name); removeAttribute(name); return; @@ -762,7 +779,7 @@ void Element::SetElementArrayAttribute( elements->clear(); SpaceSplitString value; - for (auto element : given_elements) { + for (auto element : given_elements.value()) { // Elements that are not descendants of this element's shadow including // ancestors are dropped. if (!ElementIsDescendantOfShadowIncludingAncestor(*this, *element)) @@ -796,20 +813,43 @@ void Element::SetElementArrayAttribute( } setAttribute(name, value.SerializeToString()); + if (isConnected()) { + if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache()) + cache->HandleAttributeChanged(name, this); + } element_attribute_map->Set(name, elements); } -HeapVector<Member<Element>> Element::GetElementArrayAttribute( +void Element::SetElementArrayAttribute( const QualifiedName& name, - bool& is_null) { + HeapVector<Member<Element>> given_elements, + bool is_null) { + if (is_null) + SetElementArrayAttribute(name, base::nullopt); + else + SetElementArrayAttribute(name, std::move(given_elements)); +} + +base::Optional<HeapVector<Member<Element>>> Element::GetElementArrayAttribute( + const QualifiedName& name) { HeapVector<Member<Element>>* explicitly_set_elements = GetExplicitlySetElementsForAttr(this, name); - is_null = false; + if (explicitly_set_elements) { return *explicitly_set_elements; } - String attribute_value = getAttribute(name).GetString(); + QualifiedName attr = name; + + // Account for labelled vs labeled spelling + if (attr == html_names::kAriaLabelledbyAttr) { + attr = hasAttribute(html_names::kAriaLabeledbyAttr) && + !hasAttribute(html_names::kAriaLabelledbyAttr) + ? html_names::kAriaLabeledbyAttr + : html_names::kAriaLabelledbyAttr; + } + + String attribute_value = getAttribute(attr).GetString(); HeapVector<Member<Element>> content_elements; Vector<String> tokens; @@ -822,10 +862,18 @@ HeapVector<Member<Element>> Element::GetElementArrayAttribute( content_elements.push_back(candidate); } if (content_elements.IsEmpty()) - is_null = true; + return base::nullopt; return content_elements; } +HeapVector<Member<Element>> Element::GetElementArrayAttribute( + const QualifiedName& name, + bool& is_null) { + const auto& result = GetElementArrayAttribute(name); + is_null = !result.has_value(); + return result.value_or(HeapVector<Member<Element>>()); +} + NamedNodeMap* Element::attributesForBindings() const { ElementRareData& rare_data = const_cast<Element*>(this)->EnsureElementRareData(); @@ -898,11 +946,11 @@ void Element::SynchronizeAllAttributes() const { // NOTE: AnyAttributeMatches in selector_checker.cc currently assumes that all // lazy attributes have a null namespace. If that ever changes we'll need to // fix that code. - if (GetElementData()->style_attribute_is_dirty_) { + if (GetElementData()->style_attribute_is_dirty()) { DCHECK(IsStyledElement()); SynchronizeStyleAttributeInternal(); } - if (GetElementData()->animated_svg_attributes_are_dirty_) + if (GetElementData()->animated_svg_attributes_are_dirty()) To<SVGElement>(this)->SynchronizeAnimatedSVGAttribute(AnyQName()); } @@ -910,12 +958,12 @@ inline void Element::SynchronizeAttribute(const QualifiedName& name) const { if (!GetElementData()) return; if (UNLIKELY(name == html_names::kStyleAttr && - GetElementData()->style_attribute_is_dirty_)) { + GetElementData()->style_attribute_is_dirty())) { DCHECK(IsStyledElement()); SynchronizeStyleAttributeInternal(); return; } - if (UNLIKELY(GetElementData()->animated_svg_attributes_are_dirty_)) { + if (UNLIKELY(GetElementData()->animated_svg_attributes_are_dirty())) { // See comment in the AtomicString version of SynchronizeAttribute() // also. To<SVGElement>(this)->SynchronizeAnimatedSVGAttribute(name); @@ -927,13 +975,13 @@ void Element::SynchronizeAttribute(const AtomicString& local_name) const { // you don't have a full QualifiedName, e.g when called from DOM API. if (!GetElementData()) return; - if (GetElementData()->style_attribute_is_dirty_ && + if (GetElementData()->style_attribute_is_dirty() && LowercaseIfNecessary(local_name) == html_names::kStyleAttr.LocalName()) { DCHECK(IsStyledElement()); SynchronizeStyleAttributeInternal(); return; } - if (GetElementData()->animated_svg_attributes_are_dirty_) { + if (GetElementData()->animated_svg_attributes_are_dirty()) { // We're not passing a namespace argument on purpose. SVGNames::*Attr are // defined w/o namespaces as well. @@ -961,8 +1009,8 @@ const AtomicString& Element::getAttribute(const QualifiedName& name) const { } AtomicString Element::LowercaseIfNecessary(const AtomicString& name) const { - return IsHTMLElement() && GetDocument().IsHTMLDocument() ? name.LowerASCII() - : name; + return IsHTMLElement() && IsA<HTMLDocument>(GetDocument()) ? name.LowerASCII() + : name; } const AtomicString& Element::nonce() const { @@ -993,10 +1041,11 @@ void Element::scrollIntoView(bool align_to_top) { scrollIntoView(arg); } -static ScrollAlignment ToPhysicalAlignment(const ScrollIntoViewOptions* options, - ScrollOrientation axis, - WritingMode writing_mode, - bool is_ltr) { +static mojom::blink::ScrollAlignment ToPhysicalAlignment( + const ScrollIntoViewOptions* options, + ScrollOrientation axis, + WritingMode writing_mode, + bool is_ltr) { bool is_horizontal_writing_mode = IsHorizontalWritingMode(writing_mode); String alignment = ((axis == kHorizontalScroll && is_horizontal_writing_mode) || @@ -1005,40 +1054,40 @@ static ScrollAlignment ToPhysicalAlignment(const ScrollIntoViewOptions* options, : options->block(); if (alignment == "center") - return ScrollAlignment::kAlignCenterAlways; + return ScrollAlignment::CenterAlways(); if (alignment == "nearest") - return ScrollAlignment::kAlignToEdgeIfNeeded; + return ScrollAlignment::ToEdgeIfNeeded(); if (alignment == "start") { if (axis == kHorizontalScroll) { switch (writing_mode) { case WritingMode::kHorizontalTb: - return is_ltr ? ScrollAlignment::kAlignLeftAlways - : ScrollAlignment::kAlignRightAlways; + return is_ltr ? ScrollAlignment::LeftAlways() + : ScrollAlignment::RightAlways(); case WritingMode::kVerticalRl: case WritingMode::kSidewaysRl: - return ScrollAlignment::kAlignRightAlways; + return ScrollAlignment::RightAlways(); case WritingMode::kVerticalLr: case WritingMode::kSidewaysLr: - return ScrollAlignment::kAlignLeftAlways; + return ScrollAlignment::LeftAlways(); default: NOTREACHED(); - return ScrollAlignment::kAlignLeftAlways; + return ScrollAlignment::LeftAlways(); } } else { switch (writing_mode) { case WritingMode::kHorizontalTb: - return ScrollAlignment::kAlignTopAlways; + return ScrollAlignment::TopAlways(); case WritingMode::kVerticalRl: case WritingMode::kSidewaysRl: case WritingMode::kVerticalLr: - return is_ltr ? ScrollAlignment::kAlignTopAlways - : ScrollAlignment::kAlignBottomAlways; + return is_ltr ? ScrollAlignment::TopAlways() + : ScrollAlignment::BottomAlways(); case WritingMode::kSidewaysLr: - return is_ltr ? ScrollAlignment::kAlignBottomAlways - : ScrollAlignment::kAlignTopAlways; + return is_ltr ? ScrollAlignment::BottomAlways() + : ScrollAlignment::TopAlways(); default: NOTREACHED(); - return ScrollAlignment::kAlignTopAlways; + return ScrollAlignment::TopAlways(); } } } @@ -1046,49 +1095,50 @@ static ScrollAlignment ToPhysicalAlignment(const ScrollIntoViewOptions* options, if (axis == kHorizontalScroll) { switch (writing_mode) { case WritingMode::kHorizontalTb: - return is_ltr ? ScrollAlignment::kAlignRightAlways - : ScrollAlignment::kAlignLeftAlways; + return is_ltr ? ScrollAlignment::RightAlways() + : ScrollAlignment::LeftAlways(); case WritingMode::kVerticalRl: case WritingMode::kSidewaysRl: - return ScrollAlignment::kAlignLeftAlways; + return ScrollAlignment::LeftAlways(); case WritingMode::kVerticalLr: case WritingMode::kSidewaysLr: - return ScrollAlignment::kAlignRightAlways; + return ScrollAlignment::RightAlways(); default: NOTREACHED(); - return ScrollAlignment::kAlignRightAlways; + return ScrollAlignment::RightAlways(); } } else { switch (writing_mode) { case WritingMode::kHorizontalTb: - return ScrollAlignment::kAlignBottomAlways; + return ScrollAlignment::BottomAlways(); case WritingMode::kVerticalRl: case WritingMode::kSidewaysRl: case WritingMode::kVerticalLr: - return is_ltr ? ScrollAlignment::kAlignBottomAlways - : ScrollAlignment::kAlignTopAlways; + return is_ltr ? ScrollAlignment::BottomAlways() + : ScrollAlignment::TopAlways(); case WritingMode::kSidewaysLr: - return is_ltr ? ScrollAlignment::kAlignTopAlways - : ScrollAlignment::kAlignBottomAlways; + return is_ltr ? ScrollAlignment::TopAlways() + : ScrollAlignment::BottomAlways(); default: NOTREACHED(); - return ScrollAlignment::kAlignBottomAlways; + return ScrollAlignment::BottomAlways(); } } } // Default values if (is_horizontal_writing_mode) { - return (axis == kHorizontalScroll) ? ScrollAlignment::kAlignToEdgeIfNeeded - : ScrollAlignment::kAlignTopAlways; + return (axis == kHorizontalScroll) ? ScrollAlignment::ToEdgeIfNeeded() + : ScrollAlignment::TopAlways(); } - return (axis == kHorizontalScroll) ? ScrollAlignment::kAlignLeftAlways - : ScrollAlignment::kAlignToEdgeIfNeeded; + return (axis == kHorizontalScroll) ? ScrollAlignment::LeftAlways() + : ScrollAlignment::ToEdgeIfNeeded(); } void Element::scrollIntoViewWithOptions(const ScrollIntoViewOptions* options) { ActivateDisplayLockIfNeeded(DisplayLockActivationReason::kScrollIntoView); - GetDocument().EnsurePaintLocationDataValidForNode(this); + GetDocument().EnsurePaintLocationDataValidForNode( + this, DocumentUpdateReason::kJavaScript); ScrollIntoViewNoVisualUpdate(options); } @@ -1097,31 +1147,29 @@ void Element::ScrollIntoViewNoVisualUpdate( if (!GetLayoutObject() || !GetDocument().GetPage()) return; - if (DisplayLockPreventsActivation( - DisplayLockActivationReason::kScrollIntoView)) - return; - - ScrollBehavior behavior = (options->behavior() == "smooth") - ? kScrollBehaviorSmooth - : kScrollBehaviorAuto; + mojom::blink::ScrollBehavior behavior = + (options->behavior() == "smooth") ? mojom::blink::ScrollBehavior::kSmooth + : mojom::blink::ScrollBehavior::kAuto; WritingMode writing_mode = GetComputedStyle()->GetWritingMode(); bool is_ltr = GetComputedStyle()->IsLeftToRightDirection(); - ScrollAlignment align_x = + auto align_x = ToPhysicalAlignment(options, kHorizontalScroll, writing_mode, is_ltr); - ScrollAlignment align_y = + auto align_y = ToPhysicalAlignment(options, kVerticalScroll, writing_mode, is_ltr); PhysicalRect bounds = BoundingBoxForScrollIntoView(); GetLayoutObject()->ScrollRectToVisible( - bounds, {align_x, align_y, kProgrammaticScroll, - /*make_visible_in_visual_viewport=*/true, behavior}); + bounds, ScrollAlignment::CreateScrollIntoViewParams( + align_x, align_y, mojom::blink::ScrollType::kProgrammatic, + /*make_visible_in_visual_viewport=*/true, behavior)); GetDocument().SetSequentialFocusNavigationStartingPoint(this); } void Element::scrollIntoViewIfNeeded(bool center_if_needed) { - GetDocument().EnsurePaintLocationDataValidForNode(this); + GetDocument().EnsurePaintLocationDataValidForNode( + this, DocumentUpdateReason::kJavaScript); if (!GetLayoutObject()) return; @@ -1129,17 +1177,20 @@ void Element::scrollIntoViewIfNeeded(bool center_if_needed) { PhysicalRect bounds = BoundingBoxForScrollIntoView(); if (center_if_needed) { GetLayoutObject()->ScrollRectToVisible( - bounds, {ScrollAlignment::kAlignCenterIfNeeded, - ScrollAlignment::kAlignCenterIfNeeded}); + bounds, ScrollAlignment::CreateScrollIntoViewParams( + ScrollAlignment::CenterIfNeeded(), + ScrollAlignment::CenterIfNeeded())); } else { GetLayoutObject()->ScrollRectToVisible( - bounds, {ScrollAlignment::kAlignToEdgeIfNeeded, - ScrollAlignment::kAlignToEdgeIfNeeded}); + bounds, ScrollAlignment::CreateScrollIntoViewParams( + ScrollAlignment::ToEdgeIfNeeded(), + ScrollAlignment::ToEdgeIfNeeded())); } } int Element::OffsetLeft() { - GetDocument().EnsurePaintLocationDataValidForNode(this); + GetDocument().EnsurePaintLocationDataValidForNode( + this, DocumentUpdateReason::kJavaScript); if (LayoutBoxModelObject* layout_object = GetLayoutBoxModelObject()) return AdjustForAbsoluteZoom::AdjustLayoutUnit( LayoutUnit( @@ -1150,7 +1201,8 @@ int Element::OffsetLeft() { } int Element::OffsetTop() { - GetDocument().EnsurePaintLocationDataValidForNode(this); + GetDocument().EnsurePaintLocationDataValidForNode( + this, DocumentUpdateReason::kJavaScript); if (LayoutBoxModelObject* layout_object = GetLayoutBoxModelObject()) return AdjustForAbsoluteZoom::AdjustLayoutUnit( LayoutUnit(layout_object->PixelSnappedOffsetTop(OffsetParent())), @@ -1160,7 +1212,8 @@ int Element::OffsetTop() { } int Element::OffsetWidth() { - GetDocument().EnsurePaintLocationDataValidForNode(this); + GetDocument().EnsurePaintLocationDataValidForNode( + this, DocumentUpdateReason::kJavaScript); if (LayoutBoxModelObject* layout_object = GetLayoutBoxModelObject()) return AdjustForAbsoluteZoom::AdjustLayoutUnit( LayoutUnit( @@ -1171,7 +1224,8 @@ int Element::OffsetWidth() { } int Element::OffsetHeight() { - GetDocument().EnsurePaintLocationDataValidForNode(this); + GetDocument().EnsurePaintLocationDataValidForNode( + this, DocumentUpdateReason::kJavaScript); if (LayoutBoxModelObject* layout_object = GetLayoutBoxModelObject()) return AdjustForAbsoluteZoom::AdjustLayoutUnit( LayoutUnit( @@ -1182,14 +1236,16 @@ int Element::OffsetHeight() { } Element* Element::OffsetParent() { - GetDocument().UpdateStyleAndLayoutForNode(this); + GetDocument().UpdateStyleAndLayoutForNode(this, + DocumentUpdateReason::kJavaScript); LayoutObject* layout_object = GetLayoutObject(); return layout_object ? layout_object->OffsetParent() : nullptr; } int Element::clientLeft() { - GetDocument().UpdateStyleAndLayoutForNode(this); + GetDocument().UpdateStyleAndLayoutForNode(this, + DocumentUpdateReason::kJavaScript); if (LayoutBox* layout_object = GetLayoutBox()) return AdjustForAbsoluteZoom::AdjustLayoutUnit(layout_object->ClientLeft(), @@ -1199,7 +1255,8 @@ int Element::clientLeft() { } int Element::clientTop() { - GetDocument().UpdateStyleAndLayoutForNode(this); + GetDocument().UpdateStyleAndLayoutForNode(this, + DocumentUpdateReason::kJavaScript); if (LayoutBox* layout_object = GetLayoutBox()) return AdjustForAbsoluteZoom::AdjustLayoutUnit(layout_object->ClientTop(), @@ -1220,8 +1277,10 @@ int Element::clientWidth() { if (layout_view) { // TODO(crbug.com/740879): Use per-page overlay scrollbar settings. if (!ScrollbarThemeSettings::OverlayScrollbarsEnabled() || - !GetDocument().GetFrame()->IsLocalRoot()) - GetDocument().UpdateStyleAndLayoutForNode(this); + !GetDocument().GetFrame()->IsLocalRoot()) { + GetDocument().UpdateStyleAndLayoutForNode( + this, DocumentUpdateReason::kJavaScript); + } if (GetDocument().GetPage()->GetSettings().GetForceZeroLayoutHeight()) return AdjustForAbsoluteZoom::AdjustLayoutUnit( layout_view->OverflowClipRect(PhysicalOffset()).Width(), @@ -1234,7 +1293,8 @@ int Element::clientWidth() { } } - GetDocument().UpdateStyleAndLayoutForNode(this); + GetDocument().UpdateStyleAndLayoutForNode(this, + DocumentUpdateReason::kJavaScript); if (LayoutBox* layout_object = GetLayoutBox()) return AdjustForAbsoluteZoom::AdjustLayoutUnit( @@ -1259,8 +1319,10 @@ int Element::clientHeight() { if (layout_view) { // TODO(crbug.com/740879): Use per-page overlay scrollbar settings. if (!ScrollbarThemeSettings::OverlayScrollbarsEnabled() || - !GetDocument().GetFrame()->IsLocalRoot()) - GetDocument().UpdateStyleAndLayoutForNode(this); + !GetDocument().GetFrame()->IsLocalRoot()) { + GetDocument().UpdateStyleAndLayoutForNode( + this, DocumentUpdateReason::kJavaScript); + } if (GetDocument().GetPage()->GetSettings().GetForceZeroLayoutHeight()) return AdjustForAbsoluteZoom::AdjustLayoutUnit( layout_view->OverflowClipRect(PhysicalOffset()).Height(), @@ -1273,7 +1335,8 @@ int Element::clientHeight() { } } - GetDocument().UpdateStyleAndLayoutForNode(this); + GetDocument().UpdateStyleAndLayoutForNode(this, + DocumentUpdateReason::kJavaScript); if (LayoutBox* layout_object = GetLayoutBox()) return AdjustForAbsoluteZoom::AdjustLayoutUnit( @@ -1296,7 +1359,8 @@ double Element::scrollLeft() { if (!InActiveDocument()) return 0; - GetDocument().UpdateStyleAndLayoutForNode(this); + GetDocument().UpdateStyleAndLayoutForNode(this, + DocumentUpdateReason::kJavaScript); if (GetDocument().ScrollingElementNoLayout() == this) { if (GetDocument().domWindow()) @@ -1333,7 +1397,8 @@ double Element::scrollTop() { if (!InActiveDocument()) return 0; - GetDocument().UpdateStyleAndLayoutForNode(this); + GetDocument().UpdateStyleAndLayoutForNode(this, + DocumentUpdateReason::kJavaScript); if (GetDocument().ScrollingElementNoLayout() == this) { if (GetDocument().domWindow()) @@ -1370,7 +1435,8 @@ void Element::setScrollLeft(double new_left) { if (!InActiveDocument()) return; - GetDocument().UpdateStyleAndLayoutForNode(this); + GetDocument().UpdateStyleAndLayoutForNode(this, + DocumentUpdateReason::kJavaScript); new_left = ScrollableArea::NormalizeNonFiniteScroll(new_left); @@ -1411,8 +1477,9 @@ void Element::setScrollLeft(double new_left) { end_offset = scrollable_area->ScrollPositionToOffset(snap_point.value()); } - scrollable_area->SetScrollOffset(end_offset, kProgrammaticScroll, - kScrollBehaviorAuto); + scrollable_area->SetScrollOffset(end_offset, + mojom::blink::ScrollType::kProgrammatic, + mojom::blink::ScrollBehavior::kAuto); } else { FloatPoint end_point(new_left * box->Style()->EffectiveZoom(), scrollable_area->ScrollPosition().Y()); @@ -1425,8 +1492,8 @@ void Element::setScrollLeft(double new_left) { FloatPoint new_position(end_point.X(), scrollable_area->ScrollPosition().Y()); - scrollable_area->ScrollToAbsolutePosition(new_position, - kScrollBehaviorAuto); + scrollable_area->ScrollToAbsolutePosition( + new_position, mojom::blink::ScrollBehavior::kAuto); } } } @@ -1435,7 +1502,8 @@ void Element::setScrollTop(double new_top) { if (!InActiveDocument()) return; - GetDocument().UpdateStyleAndLayoutForNode(this); + GetDocument().UpdateStyleAndLayoutForNode(this, + DocumentUpdateReason::kJavaScript); new_top = ScrollableArea::NormalizeNonFiniteScroll(new_top); @@ -1477,8 +1545,9 @@ void Element::setScrollTop(double new_top) { scrollable_area->ScrollPositionToOffset(snap_point.value()); } - scrollable_area->SetScrollOffset(end_offset, kProgrammaticScroll, - kScrollBehaviorAuto); + scrollable_area->SetScrollOffset(end_offset, + mojom::blink::ScrollType::kProgrammatic, + mojom::blink::ScrollBehavior::kAuto); } else { FloatPoint end_point(scrollable_area->ScrollPosition().X(), new_top * box->Style()->EffectiveZoom()); @@ -1490,8 +1559,8 @@ void Element::setScrollTop(double new_top) { end_point); FloatPoint new_position(scrollable_area->ScrollPosition().X(), end_point.Y()); - scrollable_area->ScrollToAbsolutePosition(new_position, - kScrollBehaviorAuto); + scrollable_area->ScrollToAbsolutePosition( + new_position, mojom::blink::ScrollBehavior::kAuto); } } } @@ -1500,7 +1569,8 @@ int Element::scrollWidth() { if (!InActiveDocument()) return 0; - GetDocument().UpdateStyleAndLayoutForNode(this); + GetDocument().UpdateStyleAndLayoutForNode(this, + DocumentUpdateReason::kJavaScript); if (GetDocument().ScrollingElementNoLayout() == this) { if (GetDocument().View()) { @@ -1522,7 +1592,8 @@ int Element::scrollHeight() { if (!InActiveDocument()) return 0; - GetDocument().UpdateStyleAndLayoutForNode(this); + GetDocument().UpdateStyleAndLayoutForNode(this, + DocumentUpdateReason::kJavaScript); if (GetDocument().ScrollingElementNoLayout() == this) { if (GetDocument().View()) { @@ -1553,7 +1624,8 @@ void Element::scrollBy(const ScrollToOptions* scroll_to_options) { // FIXME: This should be removed once scroll updates are processed only after // the compositing update. See http://crbug.com/420741. - GetDocument().UpdateStyleAndLayoutForNode(this); + GetDocument().UpdateStyleAndLayoutForNode(this, + DocumentUpdateReason::kJavaScript); if (GetDocument().ScrollingElementNoLayout() == this) { ScrollFrameBy(scroll_to_options); @@ -1575,7 +1647,8 @@ void Element::scrollTo(const ScrollToOptions* scroll_to_options) { // FIXME: This should be removed once scroll updates are processed only after // the compositing update. See http://crbug.com/420741. - GetDocument().UpdateStyleAndLayoutForNode(this); + GetDocument().UpdateStyleAndLayoutForNode(this, + DocumentUpdateReason::kJavaScript); if (GetDocument().ScrollingElementNoLayout() == this) { ScrollFrameTo(scroll_to_options); @@ -1595,7 +1668,8 @@ void Element::ScrollLayoutBoxBy(const ScrollToOptions* scroll_to_options) { ScrollableArea::NormalizeNonFiniteScroll(scroll_to_options->top())); } - ScrollBehavior scroll_behavior = kScrollBehaviorAuto; + mojom::blink::ScrollBehavior scroll_behavior = + mojom::blink::ScrollBehavior::kAuto; ScrollableArea::ScrollBehaviorFromString(scroll_to_options->behavior(), scroll_behavior); if (PaintLayerScrollableArea* scrollable_area = GetScrollableArea()) { @@ -1608,8 +1682,9 @@ void Element::ScrollLayoutBoxBy(const ScrollToOptions* scroll_to_options) { FloatPoint new_position(new_offset.x(), new_offset.y()); std::unique_ptr<cc::SnapSelectionStrategy> strategy = - cc::SnapSelectionStrategy::CreateForEndAndDirection(current_position, - displacement); + cc::SnapSelectionStrategy::CreateForEndAndDirection( + current_position, displacement, + RuntimeEnabledFeatures::FractionalScrollOffsetsEnabled()); new_position = scrollable_area->GetSnapPositionAndSetTarget(*strategy).value_or( new_position); @@ -1618,7 +1693,8 @@ void Element::ScrollLayoutBoxBy(const ScrollToOptions* scroll_to_options) { } void Element::ScrollLayoutBoxTo(const ScrollToOptions* scroll_to_options) { - ScrollBehavior scroll_behavior = kScrollBehaviorAuto; + mojom::blink::ScrollBehavior scroll_behavior = + mojom::blink::ScrollBehavior::kAuto; ScrollableArea::ScrollBehaviorFromString(scroll_to_options->behavior(), scroll_behavior); @@ -1679,8 +1755,8 @@ void Element::ScrollLayoutBoxTo(const ScrollToOptions* scroll_to_options) { scrollable_area->ScrollPositionToOffset(snap_point.value()); } - scrollable_area->SetScrollOffset(new_offset, kProgrammaticScroll, - scroll_behavior); + scrollable_area->SetScrollOffset( + new_offset, mojom::blink::ScrollType::kProgrammatic, scroll_behavior); } else { FloatPoint new_position(scrollable_area->ScrollPosition().X(), scrollable_area->ScrollPosition().Y()); @@ -1718,7 +1794,8 @@ void Element::ScrollFrameBy(const ScrollToOptions* scroll_to_options) { ScrollableArea::NormalizeNonFiniteScroll(scroll_to_options->top())); } - ScrollBehavior scroll_behavior = kScrollBehaviorAuto; + mojom::blink::ScrollBehavior scroll_behavior = + mojom::blink::ScrollBehavior::kAuto; ScrollableArea::ScrollBehaviorFromString(scroll_to_options->behavior(), scroll_behavior); LocalFrame* frame = GetDocument().GetFrame(); @@ -1735,16 +1812,19 @@ void Element::ScrollFrameBy(const ScrollToOptions* scroll_to_options) { gfx::ScrollOffset current_position(viewport->ScrollPosition()); std::unique_ptr<cc::SnapSelectionStrategy> strategy = - cc::SnapSelectionStrategy::CreateForEndAndDirection(current_position, - displacement); + cc::SnapSelectionStrategy::CreateForEndAndDirection( + current_position, displacement, + RuntimeEnabledFeatures::FractionalScrollOffsetsEnabled()); new_position = viewport->GetSnapPositionAndSetTarget(*strategy).value_or(new_position); viewport->SetScrollOffset(viewport->ScrollPositionToOffset(new_position), - kProgrammaticScroll, scroll_behavior); + mojom::blink::ScrollType::kProgrammatic, + scroll_behavior); } void Element::ScrollFrameTo(const ScrollToOptions* scroll_to_options) { - ScrollBehavior scroll_behavior = kScrollBehaviorAuto; + mojom::blink::ScrollBehavior scroll_behavior = + mojom::blink::ScrollBehavior::kAuto; ScrollableArea::ScrollBehaviorFromString(scroll_to_options->behavior(), scroll_behavior); LocalFrame* frame = GetDocument().GetFrame(); @@ -1775,11 +1855,13 @@ void Element::ScrollFrameTo(const ScrollToOptions* scroll_to_options) { new_position = viewport->GetSnapPositionAndSetTarget(*strategy).value_or(new_position); new_offset = viewport->ScrollPositionToOffset(new_position); - viewport->SetScrollOffset(new_offset, kProgrammaticScroll, scroll_behavior); + viewport->SetScrollOffset(new_offset, mojom::blink::ScrollType::kProgrammatic, + scroll_behavior); } IntRect Element::BoundsInViewport() const { - GetDocument().EnsurePaintLocationDataValidForNode(this); + GetDocument().EnsurePaintLocationDataValidForNode( + this, DocumentUpdateReason::kUnknown); LocalFrameView* view = GetDocument().View(); if (!view) @@ -1798,7 +1880,7 @@ IntRect Element::BoundsInViewport() const { !GetLayoutObject()->IsSVGForeignObject()) { // Get the bounding rectangle from the SVG model. // TODO(pdr): This should include stroke. - if (svg_element->IsSVGGraphicsElement()) { + if (IsA<SVGGraphicsElement>(svg_element)) { quads.push_back(GetLayoutObject()->LocalToAbsoluteQuad( GetLayoutObject()->ObjectBoundingBox())); } @@ -1843,8 +1925,8 @@ IntRect Element::VisibleBoundsInVisualViewport() const { // expect the result to be in the coordinate system of the local root frame. // Either the method should be renamed to something which communicates that, // or callers should be updated to expect actual top-level frame coordinates. - rect.Move(-PhysicalOffset( - GetDocument().GetFrame()->LocalFrameRoot().RemoteViewportOffset())); + rect.Move(-PhysicalOffset(IntPoint( + GetDocument().GetFrame()->LocalFrameRoot().RemoteViewportOffset()))); IntRect visible_rect = PixelSnappedIntRect(rect); // If the rect is in the coordinates of the main frame, then it should @@ -1862,7 +1944,8 @@ IntRect Element::VisibleBoundsInVisualViewport() const { } void Element::ClientQuads(Vector<FloatQuad>& quads) { - GetDocument().EnsurePaintLocationDataValidForNode(this); + GetDocument().EnsurePaintLocationDataValidForNode( + this, DocumentUpdateReason::kJavaScript); LayoutObject* element_layout_object = GetLayoutObject(); if (!element_layout_object) @@ -1879,7 +1962,7 @@ void Element::ClientQuads(Vector<FloatQuad>& quads) { // TODO(pdr): ObjectBoundingBox does not include stroke and the spec is not // clear (see: https://github.com/w3c/svgwg/issues/339, crbug.com/529734). // If stroke is desired, we can update this to use AbsoluteQuads, below. - if (svg_element->IsSVGGraphicsElement()) { + if (IsA<SVGGraphicsElement>(svg_element)) { quads.push_back(element_layout_object->LocalToAbsoluteQuad( element_layout_object->ObjectBoundingBox())); } @@ -1896,13 +1979,13 @@ DOMRectList* Element::getClientRects() { Vector<FloatQuad> quads; ClientQuads(quads); if (quads.IsEmpty()) - return DOMRectList::Create(); + return MakeGarbageCollected<DOMRectList>(); LayoutObject* element_layout_object = GetLayoutObject(); DCHECK(element_layout_object); GetDocument().AdjustFloatQuadsForScrollAndAbsoluteZoom( quads, *element_layout_object); - return DOMRectList::Create(quads); + return MakeGarbageCollected<DOMRectList>(quads); } DOMRect* Element::getBoundingClientRect() { @@ -1926,7 +2009,7 @@ const AtomicString& Element::computedRole() { Document& document = GetDocument(); if (!document.IsActive()) return g_null_atom; - document.UpdateStyleAndLayoutForNode(this); + document.UpdateStyleAndLayoutForNode(this, DocumentUpdateReason::kJavaScript); UpdateDistributionForFlatTreeTraversal(); AXContext ax_context(document); return ax_context.GetAXObjectCache().ComputedRoleForNode(this); @@ -1936,7 +2019,7 @@ String Element::computedName() { Document& document = GetDocument(); if (!document.IsActive()) return String(); - document.UpdateStyleAndLayoutForNode(this); + document.UpdateStyleAndLayoutForNode(this, DocumentUpdateReason::kJavaScript); UpdateDistributionForFlatTreeTraversal(); AXContext ax_context(document); return ax_context.GetAXObjectCache().ComputedNameForNode(this); @@ -2175,9 +2258,9 @@ void Element::setAttribute(const AtomicString& local_name, QualifiedName q_name = QualifiedName::Null(); std::tie(index, q_name) = LookupAttributeQNameInternal(local_name); - String trusted_value = GetStringFromSpecificTrustedType( - value, ExpectedTrustedTypeForAttribute(q_name), &GetDocument(), - exception_state); + String trusted_value = + TrustedTypesCheckFor(ExpectedTrustedTypeForAttribute(q_name), value, + GetExecutionContext(), exception_state); if (exception_state.HadException()) return; @@ -2185,11 +2268,6 @@ void Element::setAttribute(const AtomicString& local_name, kNotInSynchronizationOfLazyAttribute); } -void Element::setAttribute(const AtomicString& name, - const AtomicString& value) { - setAttribute(name, value, ASSERT_NO_EXCEPTION); -} - void Element::setAttribute(const QualifiedName& name, const AtomicString& value) { SynchronizeAttribute(name); @@ -2208,9 +2286,9 @@ void Element::setAttribute(const QualifiedName& name, ? GetElementData()->Attributes().FindIndex(name) : kNotFound; - String trusted_value = GetStringFromSpecificTrustedType( - value, ExpectedTrustedTypeForAttribute(name), &GetDocument(), - exception_state); + String trusted_value = + TrustedTypesCheckFor(ExpectedTrustedTypeForAttribute(name), value, + GetExecutionContext(), exception_state); if (exception_state.HadException()) return; @@ -2228,7 +2306,8 @@ void Element::SetSynchronizedLazyAttribute(const QualifiedName& name, void Element::setAttribute( const AtomicString& local_name, - const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL& string_or_TT, + const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL& + string_or_trusted, ExceptionState& exception_state) { if (!Document::IsValidName(local_name)) { exception_state.ThrowDOMException( @@ -2241,9 +2320,9 @@ void Element::setAttribute( wtf_size_t index; QualifiedName q_name = QualifiedName::Null(); std::tie(index, q_name) = LookupAttributeQNameInternal(local_name); - String value = GetStringFromSpecificTrustedType( - string_or_TT, ExpectedTrustedTypeForAttribute(q_name), &GetDocument(), - exception_state); + String value = TrustedTypesCheckFor(ExpectedTrustedTypeForAttribute(q_name), + string_or_trusted, GetExecutionContext(), + exception_state); if (exception_state.HadException()) return; SetAttributeInternal(index, q_name, AtomicString(value), @@ -2278,40 +2357,17 @@ SpecificTrustedType Element::ExpectedTrustedTypeForAttribute( // starting with "on", including e.g. "one". We use this pattern elsewhere // (e.g. in IsEventHandlerAttribute) but it's not ideal. Consider using // the event attribute of the resulting AttributeTriggers. - return SpecificTrustedType::kTrustedScript; + return SpecificTrustedType::kScript; } return SpecificTrustedType::kNone; } void Element::setAttribute(const QualifiedName& name, - const StringOrTrustedHTML& stringOrHTML, - ExceptionState& exception_state) { - String valueString = - GetStringFromTrustedHTML(stringOrHTML, &GetDocument(), exception_state); - if (!exception_state.HadException()) { - setAttribute(name, AtomicString(valueString)); - } -} - -void Element::setAttribute(const QualifiedName& name, - const StringOrTrustedScript& stringOrScript, - ExceptionState& exception_state) { - String valueString = GetStringFromTrustedScript( - stringOrScript, &GetDocument(), exception_state); - if (!exception_state.HadException()) { - setAttribute(name, AtomicString(valueString)); - } -} - -void Element::setAttribute(const QualifiedName& name, - const StringOrTrustedScriptURL& stringOrURL, + const String& string, ExceptionState& exception_state) { - String valueString = GetStringFromTrustedScriptURL( - stringOrURL, &GetDocument(), exception_state); - if (!exception_state.HadException()) { - setAttribute(name, AtomicString(valueString)); - } + // TODO(lyf): Removes |exception_state| because this function never throws. + setAttribute(name, AtomicString(string)); } ALWAYS_INLINE void Element::SetAttributeInternal( @@ -2399,44 +2455,9 @@ void Element::AttributeChanged(const AttributeModificationParams& params) { if (name == html_names::kStyleAttr) { StyleAttributeChanged(params.new_value, params.reason); } else if (IsPresentationAttribute(name)) { - GetElementData()->presentation_attribute_style_is_dirty_ = true; + GetElementData()->SetPresentationAttributeStyleIsDirty(true); SetNeedsStyleRecalc(kLocalStyleChange, StyleChangeReasonForTracing::FromAttribute(name)); - } else if (RuntimeEnabledFeatures::DisplayLockingEnabled( - GetExecutionContext()) && - name == html_names::kRendersubtreeAttr && - params.old_value != params.new_value && - DisplayLockContext::IsAttributeVersion( - GetDisplayLockContext())) { - UseCounter::Count(GetDocument(), WebFeature::kRenderSubtreeAttribute); - - // This is needed to ensure that proper containment is put in place. - SetNeedsStyleRecalc(kLocalStyleChange, - StyleChangeReasonForTracing::FromAttribute(name)); - SpaceSplitString tokens(params.new_value.LowerASCII()); - uint16_t activation_mask = - static_cast<uint16_t>(DisplayLockActivationReason::kAny); - - // Figure out the activation mask. - if (tokens.Contains("skip-activation")) - activation_mask = 0; - if (tokens.Contains("skip-viewport-activation")) { - activation_mask &= - ~static_cast<uint16_t>(DisplayLockActivationReason::kViewport); - } - - EnsureDisplayLockContext(DisplayLockContextCreateMethod::kAttribute) - .SetActivatable(activation_mask); - const bool should_be_invisible = tokens.Contains("invisible"); - if (should_be_invisible) { - if (!GetDisplayLockContext()->IsLocked()) - GetDisplayLockContext()->StartAcquire(); - } else { - // Getting unlocked. - if (GetDisplayLockContext()->IsLocked()) - GetDisplayLockContext()->StartCommit(); - } - } else if (RuntimeEnabledFeatures::InvisibleDOMEnabled() && name == html_names::kInvisibleAttr && params.old_value != params.new_value) { @@ -2653,7 +2674,7 @@ String Element::nodeName() const { } AtomicString Element::LocalNameForSelectorMatching() const { - if (IsHTMLElement() || !GetDocument().IsHTMLDocument()) + if (IsHTMLElement() || !IsA<HTMLDocument>(GetDocument())) return localName(); return localName().LowerASCII(); } @@ -2700,16 +2721,14 @@ Node::InsertionNotificationRequest Element::InsertedInto( if (!insertion_point.IsInTreeScope()) return kInsertionDone; - if (HasRareData()) { + if (isConnected() && HasRareData()) { ElementRareData* rare_data = GetElementRareData(); if (ElementIntersectionObserverData* observer_data = rare_data->IntersectionObserverData()) { - if (observer_data->IsTargetOfImplicitRootObserver() || - observer_data->IsRoot()) { - GetDocument().EnsureIntersectionObserverController().AddTrackedElement( - *this, observer_data->NeedsOcclusionTracking()); - } - if (observer_data->IsTarget() || observer_data->IsRoot()) { + observer_data->InvalidateCachedRects(); + observer_data->TrackWithController( + GetDocument().EnsureIntersectionObserverController()); + if (!observer_data->IsEmpty()) { if (LocalFrameView* frame_view = GetDocument().View()) { frame_view->SetIntersectionObservationState( LocalFrameView::kRequired); @@ -2717,10 +2736,8 @@ Node::InsertionNotificationRequest Element::InsertedInto( } } - if (isConnected()) { - if (auto* context = rare_data->GetDisplayLockContext()) - context->ElementConnected(); - } + if (auto* context = rare_data->GetDisplayLockContext()) + context->ElementConnected(); } if (isConnected()) { @@ -2815,8 +2832,8 @@ void Element::RemovedFrom(ContainerNode& insertion_point) { IntersectionObservation::kExplicitRootObserversNeedUpdate | IntersectionObservation::kImplicitRootObserversNeedUpdate | IntersectionObservation::kIgnoreDelay); - GetDocument().EnsureIntersectionObserverController().RemoveTrackedElement( - *this); + data->IntersectionObserverData()->StopTrackingWithController( + GetDocument().EnsureIntersectionObserverController()); } if (auto* context = data->GetDisplayLockContext()) @@ -2896,14 +2913,11 @@ void Element::AttachLayoutTree(AttachContext& context) { AttachPseudoElement(kPseudoIdFirstLetter, children_context); if (layout_object) { - if (!layout_object->IsFloatingOrOutOfFlowPositioned()) + if (layout_object->AffectsWhitespaceSiblings()) context.previous_in_flow = layout_object; } else { context.previous_in_flow = children_context.previous_in_flow; } - - if (auto* display_lock_context = GetDisplayLockContext()) - display_lock_context->DidAttachLayoutTree(); } void Element::DetachLayoutTree(bool performing_reattach) { @@ -2915,11 +2929,6 @@ void Element::DetachLayoutTree(bool performing_reattach) { if (ElementAnimations* element_animations = data->GetElementAnimations()) { if (performing_reattach) { - // FIXME: We call detach from within style recalc, so compositingState - // is not up to date. - // https://code.google.com/p/chromium/issues/detail?id=339847 - DisableCompositingQueryAsserts disabler; - // FIXME: restart compositor animations rather than pull back to the // main thread element_animations->RestartAnimationOnCompositor(); @@ -2971,7 +2980,6 @@ void Element::DetachLayoutTree(bool performing_reattach) { GetDocument().UserActionElements().DidDetach(*this); } - SetNeedsResizeObserverUpdate(); GetDocument().GetStyleEngine().ClearNeedsWhitespaceReattachmentFor(this); } @@ -3269,11 +3277,9 @@ StyleRecalcChange Element::RecalcOwnStyle(const StyleRecalcChange change) { // change for children, since this could be the first time we unlocked the // context and as a result need to process more of the subtree than we would // normally. Note that if this is not the first time, then - // AdjustTyleRecalcChangeForChildren() won't do any adjustments. - if (!DisplayLockContext::IsAttributeVersion(context) && - !context->IsLocked()) { + // AdjustStyleRecalcChangeForChildren() won't do any adjustments. + if (!context->IsLocked()) child_change = context->AdjustStyleRecalcChangeForChildren(child_change); - } } if (new_style) { @@ -3358,7 +3364,7 @@ void Element::RebuildLayoutTree(WhitespaceAttacher& whitespace_attacher) { else RebuildChildrenLayoutTrees(*child_attacher); RebuildPseudoElementLayoutTree(kPseudoIdBefore, *child_attacher); - RebuildPseudoElementLayoutTree(kPseudoIdMarker, *child_attacher); + RebuildMarkerLayoutTree(*child_attacher); RebuildPseudoElementLayoutTree(kPseudoIdBackdrop, *child_attacher); RebuildFirstLetterLayoutTree(); ClearChildNeedsReattachLayoutTree(); @@ -3412,6 +3418,31 @@ void Element::RebuildFirstLetterLayoutTree() { } } +void Element::RebuildMarkerLayoutTree(WhitespaceAttacher& whitespace_attacher) { + if (PseudoElement* marker = GetPseudoElement(kPseudoIdMarker)) { + // In legacy layout, we need to reattach a marker in this case: + // + // <ol><li id="outer"><div id="inner">0</div></li></ol> + // <script>outer.offsetTop; inner.style.display = "inline";</script> + // + // An outside marker must be aligned with the 1st line box in the + // list item, so legacy layout will insert it inside #inner. + // But when #inner becomes inline, the LayoutBlockFlow is destroyed, + // so we need to reinsert it. + // + // TODO: SetNeedsReattachLayoutTree() should not be called at this point. + // The layout tree rebuilding for markers should be done similarly to how + // it is done for ::first-letter. + if (LayoutObject* layout_object = GetLayoutObject()) { + if (layout_object->IsListItem() && !marker->GetLayoutObject()) + marker->SetNeedsReattachLayoutTree(); + } + + if (marker->NeedsRebuildLayoutTree(whitespace_attacher)) + marker->RebuildLayoutTree(whitespace_attacher); + } +} + void Element::UpdateCallbackSelectors(const ComputedStyle* old_style, const ComputedStyle* new_style) { Vector<String> empty_vector; @@ -3452,21 +3483,33 @@ ShadowRoot& Element::CreateAndAttachShadowRoot(ShadowRootType type) { EnsureElementRareData().SetShadowRoot(*shadow_root); shadow_root->SetParentOrShadowHostNode(this); shadow_root->SetParentTreeScope(GetTreeScope()); - if (type == ShadowRootType::V0) { + if (type == ShadowRootType::V0) shadow_root->SetNeedsDistributionRecalc(); - } - shadow_root->InsertedInto(*this); - if (InActiveDocument() && GetComputedStyle()) - SetChildNeedsStyleRecalc(); - SetNeedsStyleRecalc(kSubtreeStyleChange, StyleChangeReasonForTracing::Create( - style_change_reason::kShadow)); probe::DidPushShadowRoot(this, shadow_root); return *shadow_root; } +void Element::AttachDeclarativeShadowRoot(HTMLTemplateElement* template_element, + ShadowRootType type, + FocusDelegation focus_delegation, + SlotAssignmentMode slot_assignment) { + DCHECK(template_element); + DCHECK(type == ShadowRootType::kOpen || type == ShadowRootType::kClosed); + if (!CanAttachShadowRoot()) { + // TODO(masonfreed): Eventually, this should be a DOMException. + LOG(ERROR) << "Invalid shadow root host element"; + return; + } + ShadowRoot* shadow_root = &AttachShadowRootInternal( + type, focus_delegation == FocusDelegation::kDelegateFocus, + slot_assignment == SlotAssignmentMode::kManual); + shadow_root->appendChild(template_element->content()); + template_element->remove(); +} + ShadowRoot* Element::GetShadowRoot() const { return HasRareData() ? GetElementRareData()->GetShadowRoot() : nullptr; } @@ -3512,9 +3555,16 @@ void Element::SetNeedsCompositingUpdate() { if (!layout_object->HasLayer()) return; layout_object->Layer()->SetNeedsCompositingInputsUpdate(); - // Changes in the return value of requiresAcceleratedCompositing change if - // the PaintLayer is self-painting. - layout_object->Layer()->UpdateSelfPaintingLayer(); + + // Changes to RequiresAcceleratedCompositing change if the PaintLayer is + // self-painting (see: LayoutEmbeddedContent::LayerTypeRequired). + if (layout_object->IsLayoutEmbeddedContent()) + layout_object->Layer()->UpdateSelfPaintingLayer(); + + // Changes to AdditionalCompositingReasons can change direct compositing + // reasons which affect paint properties. + if (layout_object->CanHaveAdditionalCompositingReasons()) + layout_object->SetNeedsPaintPropertyUpdate(); } void Element::V0SetCustomElementDefinition( @@ -3666,7 +3716,7 @@ ShadowRoot* Element::attachShadow(const ShadowRootInit* shadow_root_init_dict, DCHECK(!shadow_root_init_dict->hasMode() || !GetShadowRoot()); bool delegates_focus = shadow_root_init_dict->hasDelegatesFocus() && shadow_root_init_dict->delegatesFocus(); - bool manual_slotting = shadow_root_init_dict->slotting() == "manual"; + bool manual_slotting = shadow_root_init_dict->slotAssignment() == "manual"; return &AttachShadowRootInternal(type, delegates_focus, manual_slotting); } @@ -3696,8 +3746,9 @@ ShadowRoot& Element::AttachShadowRootInternal(ShadowRootType type, GetDocument().SetShadowCascadeOrder(ShadowCascadeOrder::kShadowCascadeV1); ShadowRoot& shadow_root = CreateAndAttachShadowRoot(type); shadow_root.SetDelegatesFocus(delegates_focus); - shadow_root.SetSlotting(manual_slotting ? ShadowRootSlotting::kManual - : ShadowRootSlotting::kAuto); + shadow_root.SetSlotAssignmentMode(manual_slotting + ? SlotAssignmentMode::kManual + : SlotAssignmentMode::kAuto); return shadow_root; } @@ -3792,11 +3843,12 @@ void Element::ChildrenChanged(const ChildrenChange& change) { CheckForEmptyStyleChange(change.sibling_before_change, change.sibling_after_change); - if (!change.by_parser && change.IsChildElementChange()) + if (!change.ByParser() && change.IsChildElementChange()) CheckForSiblingStyleChanges( - change.type == kElementRemoved ? kSiblingElementRemoved - : kSiblingElementInserted, - To<Element>(change.sibling_changed.Get()), change.sibling_before_change, + change.type == ChildrenChangeType::kElementRemoved + ? kSiblingElementRemoved + : kSiblingElementInserted, + To<Element>(change.sibling_changed), change.sibling_before_change, change.sibling_after_change); if (ShadowRoot* shadow_root = GetShadowRoot()) @@ -3837,7 +3889,7 @@ Attr* Element::setAttributeNode(Attr* attr_node, return nullptr; } - if (!IsHTMLElement() && attr_node->GetDocument().IsHTMLDocument() && + if (!IsHTMLElement() && IsA<HTMLDocument>(attr_node->GetDocument()) && attr_node->name() != attr_node->name().LowerASCII()) UseCounter::Count( GetDocument(), @@ -3847,10 +3899,9 @@ Attr* Element::setAttributeNode(Attr* attr_node, SynchronizeAllAttributes(); const UniqueElementData& element_data = EnsureUniqueElementData(); - String value = GetStringFromSpecificTrustedType( - attr_node->value(), + String value = TrustedTypesCheckFor( ExpectedTrustedTypeForAttribute(attr_node->GetQualifiedName()), - &GetDocument(), exception_state); + attr_node->value(), GetExecutionContext(), exception_state); if (exception_state.HadException()) return nullptr; @@ -3961,16 +4012,17 @@ bool Element::ParseAttributeName(QualifiedName& out, void Element::setAttributeNS( const AtomicString& namespace_uri, const AtomicString& qualified_name, - const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL& string_or_TT, + const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL& + string_or_trusted, ExceptionState& exception_state) { QualifiedName parsed_name = g_any_name; if (!ParseAttributeName(parsed_name, namespace_uri, qualified_name, exception_state)) return; - String value = GetStringFromSpecificTrustedType( - string_or_TT, ExpectedTrustedTypeForAttribute(parsed_name), - &GetDocument(), exception_state); + String value = TrustedTypesCheckFor( + ExpectedTrustedTypeForAttribute(parsed_name), string_or_trusted, + GetExecutionContext(), exception_state); if (exception_state.HadException()) return; @@ -4025,7 +4077,7 @@ void Element::removeAttribute(const AtomicString& name) { wtf_size_t index = GetElementData()->Attributes().FindIndex(local_name); if (index == kNotFound) { if (UNLIKELY(local_name == html_names::kStyleAttr) && - GetElementData()->style_attribute_is_dirty_ && IsStyledElement()) + GetElementData()->style_attribute_is_dirty() && IsStyledElement()) RemoveAllInlineStyleProperties(); return; } @@ -4098,19 +4150,12 @@ Element* Element::GetFocusableArea() const { return focused_element; // Slide the focus to its inner node. - // TODO(crbug.com/1014094): We should pick the first focusable element in - // the flat tree. - Element* found = - doc.GetPage()->GetFocusController().FindFocusableElementInShadowHost( - *this); - if (found && IsShadowIncludingInclusiveAncestorOf(*found)) - return found; - return nullptr; + return FocusController::FindFocusableElementInShadowHost(*this); } void Element::focus(const FocusOptions* options) { - focus(FocusParams(SelectionBehaviorOnFocus::kRestore, kWebFocusTypeNone, - nullptr, options)); + focus(FocusParams(SelectionBehaviorOnFocus::kRestore, + mojom::blink::FocusType::kNone, nullptr, options)); } void Element::focus(const FocusParams& params) { @@ -4142,8 +4187,8 @@ void Element::focus(const FocusParams& params) { // Unlike the specification, we re-run focus() for new_focus_target // because we can't change |this| in a member function. new_focus_target->focus(FocusParams(SelectionBehaviorOnFocus::kReset, - kWebFocusTypeForward, nullptr, - params.options)); + mojom::blink::FocusType::kForward, + nullptr, params.options)); } // 2. If new focus target is null, then: // 2.1. If no fallback target was specified, then return. @@ -4152,7 +4197,7 @@ void Element::focus(const FocusParams& params) { // If script called focus(), then the type would be none. This means we are // activating because of a script action (kScriptFocus). Otherwise, this is a // user activation (kUserFocus). - ActivateDisplayLockIfNeeded(params.type == kWebFocusTypeNone + ActivateDisplayLockIfNeeded(params.type == mojom::blink::FocusType::kNone ? DisplayLockActivationReason::kScriptFocus : DisplayLockActivationReason::kUserFocus); DispatchActivateInvisibleEventIfNeeded(); @@ -4173,7 +4218,7 @@ void Element::focus(const FocusParams& params) { return; if (GetDocument().FocusedElement() == this && - GetDocument().GetFrame()->HasBeenActivated()) { + GetDocument().GetFrame()->HasStickyUserActivation()) { // Bring up the keyboard in the context of anything triggered by a user // gesture. Since tracking that across arbitrary boundaries (eg. // animations) is difficult, for now we match IE's heuristic and bring @@ -4225,8 +4270,21 @@ void Element::UpdateFocusAppearanceWithOptions( } else if (GetLayoutObject() && !GetLayoutObject()->IsLayoutEmbeddedContent()) { if (!options->preventScroll()) { + auto params = ScrollAlignment::CreateScrollIntoViewParams(); + + // It's common to have menus and list controls that have items slightly + // overflowing horizontally but the control isn't horizontally + // scrollable. Navigating through such a list should make sure items are + // vertically fully visible but avoid horizontal changes. This mostly + // matches behavior in WebKit and Gecko (though, the latter has the + // same behavior vertically) and there's some UA-defined wiggle room in + // the spec for the scrollIntoViewOptions from focus: + // https://html.spec.whatwg.org/#dom-focus. + params->align_x->rect_partial = + mojom::blink::ScrollAlignment::Behavior::kNoScroll; + GetLayoutObject()->ScrollRectToVisible(BoundingBoxForScrollIntoView(), - WebScrollIntoViewParams()); + std::move(params)); } } } @@ -4333,9 +4391,9 @@ bool Element::IsAutofocusable() const { } bool Element::ActivateDisplayLockIfNeeded(DisplayLockActivationReason reason) { - if (!RuntimeEnabledFeatures::DisplayLockingEnabled(GetExecutionContext()) || + if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() || GetDocument().LockedDisplayLockCount() == - GetDocument().ActivationBlockingDisplayLockCount()) + GetDocument().DisplayLockBlockingAllActivationCount()) return false; const_cast<Element*>(this)->UpdateDistributionForFlatTreeTraversal(); @@ -4347,7 +4405,7 @@ bool Element::ActivateDisplayLockIfNeeded(DisplayLockActivationReason reason) { if (auto* context = ancestor_element->GetDisplayLockContext()) { // If any of the ancestors is not activatable for the given reason, we // can't activate. - if (!context->IsActivatable(reason)) + if (context->IsLocked() && !context->IsActivatable(reason)) return false; activatable_targets.push_back(std::make_pair( ancestor_element, &ancestor.GetTreeScope().Retarget(*this))); @@ -4361,7 +4419,7 @@ bool Element::ActivateDisplayLockIfNeeded(DisplayLockActivationReason reason) { if (auto* context = target.first->GetDisplayLockContext()) { if (context->ShouldCommitForActivation(reason)) { activated = true; - context->CommitForActivationWithSignal(target.second); + context->CommitForActivationWithSignal(target.second, reason); } } } @@ -4370,10 +4428,10 @@ bool Element::ActivateDisplayLockIfNeeded(DisplayLockActivationReason reason) { bool Element::DisplayLockPreventsActivation( DisplayLockActivationReason reason) const { - if (!RuntimeEnabledFeatures::DisplayLockingEnabled(GetExecutionContext())) + if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled()) return false; - if (GetDocument().ActivationBlockingDisplayLockCount() == 0) + if (GetDocument().LockedDisplayLockCount() == 0) return false; const_cast<Element*>(this)->UpdateDistributionForFlatTreeTraversal(); @@ -4388,7 +4446,7 @@ bool Element::DisplayLockPreventsActivation( if (!current_element) continue; if (auto* context = current_element->GetDisplayLockContext()) { - if (!context->IsActivatable(reason)) + if (context->IsLocked() && !context->IsActivatable(reason)) return true; } } @@ -4531,7 +4589,7 @@ Element* Element::AdjustedFocusedElementInTreeScope() const { } void Element::DispatchFocusEvent(Element* old_focused_element, - WebFocusType type, + mojom::blink::FocusType type, InputDeviceCapabilities* source_capabilities) { DispatchEvent(*FocusEvent::Create( event_type_names::kFocus, Event::Bubbles::kNo, GetDocument().domWindow(), @@ -4539,7 +4597,7 @@ void Element::DispatchFocusEvent(Element* old_focused_element, } void Element::DispatchBlurEvent(Element* new_focused_element, - WebFocusType type, + mojom::blink::FocusType type, InputDeviceCapabilities* source_capabilities) { DispatchEvent(*FocusEvent::Create( event_type_names::kBlur, Event::Bubbles::kNo, GetDocument().domWindow(), @@ -4549,7 +4607,7 @@ void Element::DispatchBlurEvent(Element* new_focused_element, void Element::DispatchFocusInEvent( const AtomicString& event_type, Element* old_focused_element, - WebFocusType, + mojom::blink::FocusType, InputDeviceCapabilities* source_capabilities) { #if DCHECK_IS_ON() DCHECK(!EventDispatchForbiddenScope::IsEventDispatchForbidden()); @@ -4575,25 +4633,17 @@ void Element::DispatchFocusOutEvent( new_focused_element, source_capabilities)); } -String Element::InnerHTMLAsString() const { +String Element::innerHTML() const { return CreateMarkup(this, kChildrenOnly); } -String Element::OuterHTMLAsString() const { +String Element::outerHTML() const { return CreateMarkup(this); } -void Element::innerHTML(StringOrTrustedHTML& result) const { - result.SetString(InnerHTMLAsString()); -} - -void Element::outerHTML(StringOrTrustedHTML& result) const { - result.SetString(OuterHTMLAsString()); -} - -void Element::SetInnerHTMLFromString(const String& html, - ExceptionState& exception_state) { - probe::BreakableLocation(&GetDocument(), "Element.setInnerHTML"); +void Element::setInnerHTML(const String& html, + ExceptionState& exception_state) { + probe::BreakableLocation(GetExecutionContext(), "Element.setInnerHTML"); if (html.IsEmpty() && !HasNonInBodyInsertionMode()) { setTextContent(html); } else { @@ -4607,25 +4657,14 @@ void Element::SetInnerHTMLFromString(const String& html, } } -void Element::SetInnerHTMLFromString(const String& html) { - SetInnerHTMLFromString(html, ASSERT_NO_EXCEPTION); +String Element::getInnerHTML(bool include_shadow_roots) const { + return CreateMarkup( + this, kChildrenOnly, kDoNotResolveURLs, + include_shadow_roots ? kIncludeShadowRoots : kNoShadowRoots); } -void Element::setInnerHTML(const StringOrTrustedHTML& string_or_html, +void Element::setOuterHTML(const String& html, ExceptionState& exception_state) { - String html = - GetStringFromTrustedHTML(string_or_html, &GetDocument(), exception_state); - if (!exception_state.HadException()) { - SetInnerHTMLFromString(html, exception_state); - } -} - -void Element::setInnerHTML(const StringOrTrustedHTML& string_or_html) { - setInnerHTML(string_or_html, ASSERT_NO_EXCEPTION); -} - -void Element::SetOuterHTMLFromString(const String& html, - ExceptionState& exception_state) { Node* p = parentNode(); if (!p) { exception_state.ThrowDOMException( @@ -4669,41 +4708,32 @@ void Element::SetOuterHTMLFromString(const String& html, } } -void Element::setOuterHTML(const StringOrTrustedHTML& string_or_html, - ExceptionState& exception_state) { - String html = - GetStringFromTrustedHTML(string_or_html, &GetDocument(), exception_state); - if (!exception_state.HadException()) { - SetOuterHTMLFromString(html, exception_state); - } -} - // Step 4 of http://domparsing.spec.whatwg.org/#insertadjacenthtml() Node* Element::InsertAdjacent(const String& where, Node* new_child, ExceptionState& exception_state) { - if (DeprecatedEqualIgnoringCase(where, "beforeBegin")) { + if (EqualIgnoringASCIICase(where, "beforeBegin")) { if (ContainerNode* parent = parentNode()) { - parent->insertBefore(new_child, this, exception_state); + parent->InsertBefore(new_child, this, exception_state); if (!exception_state.HadException()) return new_child; } return nullptr; } - if (DeprecatedEqualIgnoringCase(where, "afterBegin")) { - insertBefore(new_child, firstChild(), exception_state); + if (EqualIgnoringASCIICase(where, "afterBegin")) { + InsertBefore(new_child, firstChild(), exception_state); return exception_state.HadException() ? nullptr : new_child; } - if (DeprecatedEqualIgnoringCase(where, "beforeEnd")) { - appendChild(new_child, exception_state); + if (EqualIgnoringASCIICase(where, "beforeEnd")) { + AppendChild(new_child, exception_state); return exception_state.HadException() ? nullptr : new_child; } - if (DeprecatedEqualIgnoringCase(where, "afterEnd")) { + if (EqualIgnoringASCIICase(where, "afterEnd")) { if (ContainerNode* parent = parentNode()) { - parent->insertBefore(new_child, nextSibling(), exception_state); + parent->InsertBefore(new_child, nextSibling(), exception_state); if (!exception_state.HadException()) return new_child; } @@ -4718,6 +4748,16 @@ Node* Element::InsertAdjacent(const String& where, return nullptr; } +void Element::HideNonce() { + const AtomicString& nonce_value = FastGetAttribute(html_names::kNonceAttr); + if (nonce_value.IsEmpty()) + return; + if (!InActiveDocument()) + return; + if (GetDocument().GetContentSecurityPolicy()->HasHeaderDeliveredPolicy()) + setAttribute(html_names::kNonceAttr, g_empty_atom); +} + ElementIntersectionObserverData* Element::IntersectionObserverData() const { if (HasRareData()) return GetElementRareData()->IntersectionObserverData(); @@ -4728,18 +4768,6 @@ ElementIntersectionObserverData& Element::EnsureIntersectionObserverData() { return EnsureElementRareData().EnsureIntersectionObserverData(); } -bool Element::ComputeIntersectionsForLifecycleUpdate(unsigned flags) { - if (ElementIntersectionObserverData* data = IntersectionObserverData()) - return data->ComputeIntersectionsForLifecycleUpdate(flags); - return false; -} - -bool Element::NeedsOcclusionTracking() const { - if (ElementIntersectionObserverData* data = IntersectionObserverData()) - return data->NeedsOcclusionTracking(); - return false; -} - HeapHashMap<Member<ResizeObserver>, Member<ResizeObservation>>* Element::ResizeObserverData() const { if (HasRareData()) @@ -4752,56 +4780,23 @@ Element::EnsureResizeObserverData() { return EnsureElementRareData().EnsureResizeObserverData(); } -void Element::SetNeedsResizeObserverUpdate() { - if (auto* data = ResizeObserverData()) { - for (auto& observation : data->Values()) - observation->ElementSizeChanged(); - } -} - DisplayLockContext* Element::GetDisplayLockContext() const { - if (!RuntimeEnabledFeatures::DisplayLockingEnabled(GetExecutionContext())) + if (!RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled()) return nullptr; return HasRareData() ? GetElementRareData()->GetDisplayLockContext() : nullptr; } -DisplayLockContext& Element::EnsureDisplayLockContext( - DisplayLockContextCreateMethod method) { - auto& result = *EnsureElementRareData().EnsureDisplayLockContext( - this, GetExecutionContext()); - result.SetMethod(method); - return result; -} - -ScriptPromise Element::updateRendering(ScriptState* script_state) { - auto* context = GetDisplayLockContext(); - if (context) - return context->UpdateRendering(script_state); - auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); - auto promise = resolver->Promise(); - resolver->Resolve(); - return promise; -} - -void Element::resetSubtreeRendered() { - if (auto* context = GetDisplayLockContext()) { - context->ClearActivated(); - // Note that we need to schedule a style invalidation since we may need to - // adjust the lock state, which happens during style recalc for - // CSS-render-subtree. - SetNeedsStyleRecalc( - kLocalStyleChange, - StyleChangeReasonForTracing::Create(style_change_reason::kDisplayLock)); - } +DisplayLockContext& Element::EnsureDisplayLockContext() { + return *EnsureElementRareData().EnsureDisplayLockContext(this); } // Step 1 of http://domparsing.spec.whatwg.org/#insertadjacenthtml() static Node* ContextNodeForInsertion(const String& where, Element* element, ExceptionState& exception_state) { - if (DeprecatedEqualIgnoringCase(where, "beforeBegin") || - DeprecatedEqualIgnoringCase(where, "afterEnd")) { + if (EqualIgnoringASCIICase(where, "beforeBegin") || + EqualIgnoringASCIICase(where, "afterEnd")) { Node* parent = element->parentNode(); if (!parent || IsA<Document>(parent)) { exception_state.ThrowDOMException( @@ -4811,8 +4806,8 @@ static Node* ContextNodeForInsertion(const String& where, } return parent; } - if (DeprecatedEqualIgnoringCase(where, "afterBegin") || - DeprecatedEqualIgnoringCase(where, "beforeEnd")) + if (EqualIgnoringASCIICase(where, "afterBegin") || + EqualIgnoringASCIICase(where, "beforeEnd")) return element; exception_state.ThrowDOMException( DOMExceptionCode::kSyntaxError, @@ -4845,7 +4840,7 @@ void Element::insertAdjacentHTML(const String& where, // Step 2 of http://domparsing.spec.whatwg.org/#insertadjacenthtml() Element* context_element; if (!IsA<Element>(context_node) || - (context_node->GetDocument().IsHTMLDocument() && + (IsA<HTMLDocument>(context_node->GetDocument()) && IsA<HTMLHtmlElement>(context_node))) { context_element = MakeGarbageCollected<HTMLBodyElement>(context_node->GetDocument()); @@ -4862,16 +4857,6 @@ void Element::insertAdjacentHTML(const String& where, InsertAdjacent(where, fragment, exception_state); } -void Element::insertAdjacentHTML(const String& where, - const StringOrTrustedHTML& string_or_html, - ExceptionState& exception_state) { - String markup = - GetStringFromTrustedHTML(string_or_html, &GetDocument(), exception_state); - if (!exception_state.HadException()) { - insertAdjacentHTML(where, markup, exception_state); - } -} - void Element::setPointerCapture(PointerId pointer_id, ExceptionState& exception_state) { if (GetDocument().GetFrame()) { @@ -4947,7 +4932,7 @@ String Element::TextFromChildren() { return g_empty_string; if (first_text_node && !found_multiple_text_nodes) { - first_text_node->MakeParkableOrAtomize(); + first_text_node->MakeParkable(); return first_text_node->data(); } @@ -5212,10 +5197,11 @@ void Element::UpdateFirstLetterPseudoElement(StyleUpdatePhase phase) { DCHECK(!To<FirstLetterPseudoElement>(element)->RemainingTextLayoutObject()); DCHECK(text_node_changed); scoped_refptr<ComputedStyle> pseudo_style = element->StyleForLayoutObject(); - if (PseudoElementLayoutObjectIsNeeded(pseudo_style.get())) + if (PseudoElementLayoutObjectIsNeeded(pseudo_style.get(), this)) element->SetComputedStyle(std::move(pseudo_style)); else GetElementRareData()->SetPseudoElement(kPseudoIdFirstLetter, nullptr); + element->ClearNeedsStyleRecalc(); return; } @@ -5228,7 +5214,7 @@ void Element::UpdateFirstLetterPseudoElement(StyleUpdatePhase phase) { element->RecalcStyle(change); if (element->NeedsReattachLayoutTree() && - !PseudoElementLayoutObjectIsNeeded(element->GetComputedStyle())) { + !PseudoElementLayoutObjectIsNeeded(element->GetComputedStyle(), this)) { GetElementRareData()->SetPseudoElement(kPseudoIdFirstLetter, nullptr); GetDocument().GetStyleEngine().PseudoElementRemoved(*this); } @@ -5238,8 +5224,11 @@ void Element::UpdatePseudoElement(PseudoId pseudo_id, const StyleRecalcChange change) { PseudoElement* element = GetPseudoElement(pseudo_id); if (!element) { - if ((element = CreatePseudoElementIfNeeded(pseudo_id))) + if ((element = CreatePseudoElementIfNeeded(pseudo_id))) { + // ::before and ::after can have a nested ::marker + element->CreatePseudoElementIfNeeded(kPseudoIdMarker); element->SetNeedsReattachLayoutTree(); + } return; } @@ -5248,7 +5237,7 @@ void Element::UpdatePseudoElement(PseudoId pseudo_id, element->RecalcStyle(change.ForPseudoElement()); if (!element->NeedsReattachLayoutTree()) return; - if (PseudoElementLayoutObjectIsNeeded(element->GetComputedStyle())) + if (PseudoElementLayoutObjectIsNeeded(element->GetComputedStyle(), this)) return; } GetElementRareData()->SetPseudoElement(pseudo_id, nullptr); @@ -5257,8 +5246,6 @@ void Element::UpdatePseudoElement(PseudoId pseudo_id, } PseudoElement* Element::CreatePseudoElementIfNeeded(PseudoId pseudo_id) { - if (IsPseudoElement()) - return nullptr; if (!CanGeneratePseudoElement(pseudo_id)) return nullptr; if (pseudo_id == kPseudoIdFirstLetter) { @@ -5272,7 +5259,7 @@ PseudoElement* Element::CreatePseudoElementIfNeeded(PseudoId pseudo_id) { scoped_refptr<ComputedStyle> pseudo_style = pseudo_element->StyleForLayoutObject(); - if (!PseudoElementLayoutObjectIsNeeded(pseudo_style.get())) { + if (!PseudoElementLayoutObjectIsNeeded(pseudo_style.get(), this)) { GetElementRareData()->SetPseudoElement(pseudo_id, nullptr); return nullptr; } @@ -5316,6 +5303,34 @@ LayoutObject* Element::PseudoElementLayoutObject(PseudoId pseudo_id) const { return nullptr; } +bool Element::PseudoElementStylesDependOnFontMetrics() const { + const ComputedStyle* style = GetComputedStyle(); + if (!style) + return false; + if (style->CachedPseudoElementStylesDependOnFontMetrics()) + return true; + + // Note that |HasAnyPseudoElementStyles()| counts public pseudo elements only. + // ::-webkit-scrollbar-* are internal, and hence are not counted. So we must + // perform this check after checking the cached pseudo element styles to avoid + // false negatives. + if (!style->HasAnyPseudoElementStyles()) + return false; + + // If we don't generate a PseudoElement, its style must have been cached on + // the originating element's ComputedStyle. Hence, it remains to check styles + // on the generated PseudoElements. + if (!HasRareData()) + return false; + for (PseudoElement* pseudo_element : + GetElementRareData()->GetPseudoElements()) { + if (pseudo_element->GetComputedStyle()->DependsOnFontMetrics()) + return true; + } + + return false; +} + const ComputedStyle* Element::CachedStyleForPseudoElement( const PseudoElementStyleRequest& request) { const ComputedStyle* style = GetComputedStyle(); @@ -5457,18 +5472,6 @@ KURL Element::GetURLAttribute(const QualifiedName& name) const { StripLeadingAndTrailingHTMLSpaces(getAttribute(name))); } -void Element::GetURLAttribute(const QualifiedName& name, - StringOrTrustedScriptURL& result) const { - KURL url = GetURLAttribute(name); - result.SetString(url.GetString()); -} - -void Element::FastGetAttribute(const QualifiedName& name, - StringOrTrustedHTML& result) const { - String html = FastGetAttribute(name); - result.SetString(html); -} - KURL Element::GetNonEmptyURLAttribute(const QualifiedName& name) const { #if DCHECK_IS_ON() if (GetElementData()) { @@ -5493,6 +5496,12 @@ int Element::GetIntegralAttribute(const QualifiedName& attribute_name, return integral_value; } +unsigned int Element::GetUnsignedIntegralAttribute( + const QualifiedName& attribute_name) const { + return static_cast<unsigned int>( + std::max(0, GetIntegralAttribute(attribute_name))); +} + void Element::SetIntegralAttribute(const QualifiedName& attribute_name, int value) { setAttribute(attribute_name, AtomicString::Number(value)); @@ -5590,21 +5599,50 @@ void Element::SetIsInTopLayer(bool in_top_layer) { SetForceReattachLayoutTree(); } -void Element::requestPointerLock(const PointerLockOptions* options) { +ScriptValue Element::requestPointerLock(ScriptState* script_state, + const PointerLockOptions* options, + ExceptionState& exception_state) { + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); + ScriptPromise promise; if (GetDocument().GetPage()) { - GetDocument().GetPage()->GetPointerLockController().RequestPointerLock( - this, options); + promise = + GetDocument().GetPage()->GetPointerLockController().RequestPointerLock( + resolver, this, exception_state, options); + } else { + promise = resolver->Promise(); + exception_state.ThrowDOMException( + DOMExceptionCode::kWrongDocumentError, + "PointerLock cannot be request when there " + "is no frame or that frame has no page."); + } + + if (RuntimeEnabledFeatures::PointerLockOptionsEnabled( + GetExecutionContext())) { + if (exception_state.HadException()) + resolver->Reject(exception_state); + return promise.GetScriptValue(); } + + // The current spec for PointerLock does not have any language about throwing + // exceptions. Therefore to be spec compliant we must clear all exceptions. + // When behind our experimental flag however, we will throw exceptions which + // should be caught as a promise rejection. + exception_state.ClearException(); + + // Detach the resolver, since we are not using it, to prepare it for garbage + // collection. + resolver->Detach(); + return ScriptValue(); } SpellcheckAttributeState Element::GetSpellcheckAttributeState() const { const AtomicString& value = FastGetAttribute(html_names::kSpellcheckAttr); if (value == g_null_atom) return kSpellcheckAttributeDefault; - if (DeprecatedEqualIgnoringCase(value, "true") || - DeprecatedEqualIgnoringCase(value, "")) + if (EqualIgnoringASCIICase(value, "true") || + EqualIgnoringASCIICase(value, "")) return kSpellcheckAttributeTrue; - if (DeprecatedEqualIgnoringCase(value, "false")) + if (EqualIgnoringASCIICase(value, "false")) return kSpellcheckAttributeFalse; return kSpellcheckAttributeDefault; @@ -5805,23 +5843,23 @@ void Element::DidMoveToNewDocument(Document& old_document) { void Element::UpdateNamedItemRegistration(NamedItemType type, const AtomicString& old_name, const AtomicString& new_name) { - if (!GetDocument().IsHTMLDocument()) + auto* doc = DynamicTo<HTMLDocument>(GetDocument()); + if (!doc) return; - HTMLDocument& doc = ToHTMLDocument(GetDocument()); if (!old_name.IsEmpty()) - doc.RemoveNamedItem(old_name); + doc->RemoveNamedItem(old_name); if (!new_name.IsEmpty()) - doc.AddNamedItem(new_name); + doc->AddNamedItem(new_name); if (type == NamedItemType::kNameOrIdWithName) { const AtomicString id = GetIdAttribute(); if (!id.IsEmpty()) { if (!old_name.IsEmpty() && new_name.IsEmpty()) - doc.RemoveNamedItem(id); + doc->RemoveNamedItem(id); else if (old_name.IsEmpty() && !new_name.IsEmpty()) - doc.AddNamedItem(id); + doc->AddNamedItem(id); } } } @@ -5829,17 +5867,18 @@ void Element::UpdateNamedItemRegistration(NamedItemType type, void Element::UpdateIdNamedItemRegistration(NamedItemType type, const AtomicString& old_id, const AtomicString& new_id) { - if (!GetDocument().IsHTMLDocument()) + auto* doc = DynamicTo<HTMLDocument>(GetDocument()); + if (!doc) return; if (type == NamedItemType::kNameOrIdWithName && GetNameAttribute().IsEmpty()) return; if (!old_id.IsEmpty()) - ToHTMLDocument(GetDocument()).RemoveNamedItem(old_id); + doc->RemoveNamedItem(old_id); if (!new_id.IsEmpty()) - ToHTMLDocument(GetDocument()).AddNamedItem(new_id); + doc->AddNamedItem(new_id); } ScrollOffset Element::SavedLayerScrollOffset() const { @@ -6025,8 +6064,8 @@ void Element::CreateUniqueElementData() { void Element::SynchronizeStyleAttributeInternal() const { DCHECK(IsStyledElement()); DCHECK(GetElementData()); - DCHECK(GetElementData()->style_attribute_is_dirty_); - GetElementData()->style_attribute_is_dirty_ = false; + DCHECK(GetElementData()->style_attribute_is_dirty()); + GetElementData()->SetStyleAttributeIsDirty(false); const CSSPropertyValueSet* inline_style = InlineStyle(); const_cast<Element*>(this)->SetSynchronizedLazyAttribute( html_names::kStyleAttr, @@ -6119,7 +6158,7 @@ void Element::StyleAttributeChanged( SetInlineStyleFromString(new_style_string); } - GetElementData()->style_attribute_is_dirty_ = false; + GetElementData()->SetStyleAttributeIsDirty(false); SetNeedsStyleRecalc(kLocalStyleChange, StyleChangeReasonForTracing::Create( @@ -6129,10 +6168,7 @@ void Element::StyleAttributeChanged( void Element::InlineStyleChanged() { DCHECK(IsStyledElement()); - SetNeedsStyleRecalc(kLocalStyleChange, StyleChangeReasonForTracing::Create( - style_change_reason::kInline)); - DCHECK(GetElementData()); - GetElementData()->style_attribute_is_dirty_ = true; + InvalidateStyleAttribute(); probe::DidInvalidateStyleAttr(this); if (MutationObserverInterestGroup* recipients = @@ -6222,7 +6258,7 @@ void Element::UpdatePresentationAttributeStyle() { // ShareableElementData doesn't store presentation attribute style, so make // sure we have a UniqueElementData. UniqueElementData& element_data = EnsureUniqueElementData(); - element_data.presentation_attribute_style_is_dirty_ = false; + element_data.SetPresentationAttributeStyleIsDirty(false); element_data.presentation_attribute_style_ = ComputePresentationAttributeStyle(*this); } @@ -6331,8 +6367,6 @@ void Element::LogUpdateAttributeIfIsolatedWorldAndInDocument( } void Element::Trace(Visitor* visitor) { - if (HasRareData()) - visitor->Trace(GetElementRareData()); visitor->Trace(element_data_); ContainerNode::Trace(visitor); } @@ -6432,4 +6466,14 @@ void Element::SetActive(bool active) { GetLayoutObject()->InvalidateIfControlStateChanged(kPressedControlState); } +void Element::InvalidateStyleAttribute() { + DCHECK(GetElementData()); + GetElementData()->SetStyleAttributeIsDirty(true); + SetNeedsStyleRecalc(kLocalStyleChange, + StyleChangeReasonForTracing::Create( + style_change_reason::kInlineCSSStyleMutated)); + GetDocument().GetStyleEngine().AttributeChangedForElement( + html_names::kStyleAttr, *this); +} + } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/element.h b/chromium/third_party/blink/renderer/core/dom/element.h index cc135847c83..541b0321bd1 100644 --- a/chromium/third_party/blink/renderer/core/dom/element.h +++ b/chromium/third_party/blink/renderer/core/dom/element.h @@ -25,8 +25,9 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ELEMENT_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ELEMENT_H_ -#include "third_party/blink/public/platform/pointer_id.h" -#include "third_party/blink/public/platform/web_focus_type.h" +#include "third_party/blink/public/common/input/pointer_id.h" +#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_focus_options.h" #include "third_party/blink/renderer/core/animation/animatable.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/css/css_primitive_value.h" @@ -37,7 +38,6 @@ #include "third_party/blink/renderer/core/dom/element_data.h" #include "third_party/blink/renderer/core/dom/names_map.h" #include "third_party/blink/renderer/core/dom/whitespace_attacher.h" -#include "third_party/blink/renderer/core/html/focus_options.h" #include "third_party/blink/renderer/core/html_names.h" #include "third_party/blink/renderer/core/trustedtypes/trusted_types_util.h" #include "third_party/blink/renderer/platform/heap/handle.h" @@ -65,7 +65,7 @@ class ElementRareData; class ExceptionState; class FloatQuad; class FloatSize; -class FocusOptions; +class HTMLTemplateElement; class Image; class InputDeviceCapabilities; class Locale; @@ -77,17 +77,13 @@ class PseudoElement; class PseudoElementStyleRequest; class ResizeObservation; class ResizeObserver; -class ScriptPromise; class ScrollIntoViewOptions; class ScrollIntoViewOptionsOrBoolean; class ScrollToOptions; class ShadowRoot; class ShadowRootInit; class SpaceSplitString; -class StringOrTrustedHTML; class StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL; -class StringOrTrustedScript; -class StringOrTrustedScriptURL; class StylePropertyMap; class StylePropertyMapReadOnly; class V0CustomElementDefinition; @@ -96,7 +92,6 @@ enum class CSSPropertyID; enum class CSSValueID; enum class DisplayLockActivationReason; enum class DisplayLockLifecycleTarget; -enum class DisplayLockContextCreateMethod; using ScrollOffset = FloatSize; @@ -118,6 +113,8 @@ enum class ElementFlags { }; enum class ShadowRootType; +enum class FocusDelegation; +enum class SlotAssignmentMode; enum class SelectionBehaviorOnFocus { kReset, @@ -145,7 +142,7 @@ struct FocusParams { public: FocusParams() : options(FocusOptions::Create()) {} FocusParams(SelectionBehaviorOnFocus selection, - WebFocusType focus_type, + mojom::blink::FocusType focus_type, InputDeviceCapabilities* capabilities, const FocusOptions* focus_options = FocusOptions::Create()) : selection_behavior(selection), @@ -155,9 +152,9 @@ struct FocusParams { SelectionBehaviorOnFocus selection_behavior = SelectionBehaviorOnFocus::kRestore; - WebFocusType type = kWebFocusTypeNone; - Member<InputDeviceCapabilities> source_capabilities = nullptr; - Member<const FocusOptions> options; + mojom::blink::FocusType type = mojom::blink::FocusType::kNone; + InputDeviceCapabilities* source_capabilities = nullptr; + const FocusOptions* options = nullptr; }; typedef HeapVector<Member<Attr>> AttrNodeList; @@ -198,6 +195,8 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { int GetIntegralAttribute(const QualifiedName& attribute_name) const; int GetIntegralAttribute(const QualifiedName& attribute_name, int default_value) const; + unsigned int GetUnsignedIntegralAttribute( + const QualifiedName& attribute_name) const; void SetIntegralAttribute(const QualifiedName& attribute_name, int value); void SetUnsignedIntegralAttribute(const QualifiedName& attribute_name, unsigned value, @@ -208,12 +207,27 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { void SetFloatingPointAttribute(const QualifiedName& attribute_name, double value); + // Returns true if |this| element has attr-associated elements that were set + // via the IDL, rather than computed from the content attribute. + // See + // https://whatpr.org/html/3917/common-dom-interfaces.html#reflecting-content-attributes-in-idl-attributes:element + // for more information. + // This is only exposed as an implementation detail to AXRelationCache, which + // computes aria-owns differently for element reflection. + bool HasExplicitlySetAttrAssociatedElements(const QualifiedName& name); Element* GetElementAttribute(const QualifiedName& name); void SetElementAttribute(const QualifiedName&, Element*); - HeapVector<Member<Element>> GetElementArrayAttribute( + base::Optional<HeapVector<Member<Element>>> GetElementArrayAttribute( + const QualifiedName& name); + // TODO(crbug.com/1060971): Remove |is_null| version. + HeapVector<Member<Element>> GetElementArrayAttribute( // DEPRECATED const QualifiedName& name, bool& is_null); - void SetElementArrayAttribute(const QualifiedName&, + void SetElementArrayAttribute( + const QualifiedName&, + const base::Optional<HeapVector<Member<Element>>>&); + // TODO(crbug.com/1060971): Remove |is_null| version. + void SetElementArrayAttribute(const QualifiedName&, // DEPRECATED HeapVector<Member<Element>>, bool is_null); @@ -243,8 +257,7 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { void setAttribute(const AtomicString& name, const AtomicString& value, - ExceptionState&); - void setAttribute(const AtomicString& name, const AtomicString& value); + ExceptionState& = ASSERT_NO_EXCEPTION); // Trusted Types variant for explicit setAttribute() use. void setAttribute(const AtomicString&, @@ -254,20 +267,7 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { // Returns attributes that should be checked against Trusted Types virtual const AttrNameToTrustedType& GetCheckedAttributeTypes() const; - // Trusted Type HTML variant - void setAttribute(const QualifiedName&, - const StringOrTrustedHTML&, - ExceptionState&); - - // Trusted Type Script variant - void setAttribute(const QualifiedName&, - const StringOrTrustedScript&, - ExceptionState&); - - // Trusted Type ScriptURL variant - void setAttribute(const QualifiedName&, - const StringOrTrustedScriptURL&, - ExceptionState&); + void setAttribute(const QualifiedName&, const String&, ExceptionState&); static bool ParseAttributeName(QualifiedName&, const AtomicString& namespace_uri, @@ -541,6 +541,8 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { void RecalcStyleForTraversalRootAncestor(); void RebuildLayoutTreeForTraversalRootAncestor() { RebuildFirstLetterLayoutTree(); + WhitespaceAttacher whitespace_attacher; + RebuildMarkerLayoutTree(whitespace_attacher); } bool NeedsRebuildLayoutTree( const WhitespaceAttacher& whitespace_attacher) const { @@ -565,6 +567,11 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { ShadowRoot* createShadowRoot(ExceptionState&); ShadowRoot* attachShadow(const ShadowRootInit*, ExceptionState&); + void AttachDeclarativeShadowRoot(HTMLTemplateElement*, + ShadowRootType, + FocusDelegation, + SlotAssignmentMode); + ShadowRoot& CreateV0ShadowRootForTesting() { return CreateShadowRootInternal(); } @@ -613,8 +620,11 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { } bool IsDefined() const { - return !(static_cast<int>(GetCustomElementState()) & - static_cast<int>(CustomElementState::kNotDefinedFlag)); + // An element whose custom element state is "uncustomized" or "custom" + // is said to be defined. + // https://dom.spec.whatwg.org/#concept-element-defined + return GetCustomElementState() == CustomElementState::kUncustomized || + GetCustomElementState() == CustomElementState::kCustom; } bool IsUpgradedV0CustomElement() { return GetV0CustomElementState() == kV0Upgraded; @@ -641,8 +651,6 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { KURL HrefURL() const; KURL GetURLAttribute(const QualifiedName&) const; - void GetURLAttribute(const QualifiedName&, StringOrTrustedScriptURL&) const; - void FastGetAttribute(const QualifiedName&, StringOrTrustedHTML&) const; KURL GetNonEmptyURLAttribute(const QualifiedName&) const; @@ -679,16 +687,16 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { virtual void DispatchFocusEvent( Element* old_focused_element, - WebFocusType, + mojom::blink::FocusType, InputDeviceCapabilities* source_capabilities = nullptr); virtual void DispatchBlurEvent( Element* new_focused_element, - WebFocusType, + mojom::blink::FocusType, InputDeviceCapabilities* source_capabilities = nullptr); virtual void DispatchFocusInEvent( const AtomicString& event_type, Element* old_focused_element, - WebFocusType, + mojom::blink::FocusType, InputDeviceCapabilities* source_capabilities = nullptr); void DispatchFocusOutEvent( const AtomicString& event_type, @@ -698,11 +706,6 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { // The implementation of |innerText()| is found in "element_inner_text.cc". String innerText(); String outerText(); - String InnerHTMLAsString() const; - String OuterHTMLAsString() const; - void SetInnerHTMLFromString(const String& html, ExceptionState&); - void SetInnerHTMLFromString(const String& html); - void SetOuterHTMLFromString(const String& html, ExceptionState&); Element* insertAdjacentElement(const String& where, Element* new_child, @@ -714,16 +717,11 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { const String& html, ExceptionState&); - // TrustedTypes variants of the above. - // TODO(mkwst): Write a spec for these bits. https://crbug.com/739170 - void innerHTML(StringOrTrustedHTML&) const; - void outerHTML(StringOrTrustedHTML&) const; - void setInnerHTML(const StringOrTrustedHTML&, ExceptionState&); - void setInnerHTML(const StringOrTrustedHTML&); - void setOuterHTML(const StringOrTrustedHTML&, ExceptionState&); - void insertAdjacentHTML(const String& where, - const StringOrTrustedHTML&, - ExceptionState&); + String innerHTML() const; + String outerHTML() const; + void setInnerHTML(const String&, ExceptionState& = ASSERT_NO_EXCEPTION); + String getInnerHTML(bool include_shadow_roots) const; + void setOuterHTML(const String&, ExceptionState& = ASSERT_NO_EXCEPTION); void setPointerCapture(PointerId poinetr_id, ExceptionState&); void releasePointerCapture(PointerId pointer_id, ExceptionState&); @@ -758,12 +756,13 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { PseudoElement* GetPseudoElement(PseudoId) const; LayoutObject* PseudoElementLayoutObject(PseudoId) const; + bool PseudoElementStylesDependOnFontMetrics() const; const ComputedStyle* CachedStyleForPseudoElement( const PseudoElementStyleRequest&); scoped_refptr<ComputedStyle> StyleForPseudoElement( const PseudoElementStyleRequest&, const ComputedStyle* parent_style = nullptr); - bool CanGeneratePseudoElement(PseudoId) const; + virtual bool CanGeneratePseudoElement(PseudoId) const; virtual bool MatchesDefaultPseudoClass() const { return false; } virtual bool MatchesEnabledPseudoClass() const { return false; } @@ -860,7 +859,9 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { } void SetIsInTopLayer(bool); - void requestPointerLock(const PointerLockOptions*); + ScriptValue requestPointerLock(ScriptState* script_state, + const PointerLockOptions* options, + ExceptionState& exception_state); bool IsSpellCheckingEnabled() const; @@ -920,23 +921,14 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { ElementIntersectionObserverData* IntersectionObserverData() const; ElementIntersectionObserverData& EnsureIntersectionObserverData(); - bool ComputeIntersectionsForLifecycleUpdate(unsigned flags); - // Returns true if the Element is being observed by an IntersectionObserver - // for which trackVisibility() is true. - bool NeedsOcclusionTracking() const; HeapHashMap<Member<ResizeObserver>, Member<ResizeObservation>>* ResizeObserverData() const; HeapHashMap<Member<ResizeObserver>, Member<ResizeObservation>>& EnsureResizeObserverData(); - void SetNeedsResizeObserverUpdate(); DisplayLockContext* GetDisplayLockContext() const; - DisplayLockContext& EnsureDisplayLockContext(DisplayLockContextCreateMethod); - - // Display locking IDL implementation - ScriptPromise updateRendering(ScriptState*); - void resetSubtreeRendered(); + DisplayLockContext& EnsureDisplayLockContext(); bool StyleRecalcBlockedByDisplayLock(DisplayLockLifecycleTarget) const; @@ -948,6 +940,10 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { virtual void SetActive(bool active); virtual void SetHovered(bool hovered); + // Classes overriding this method can return true when an element has + // been determined to be from an ad. Returns false by default. + virtual bool IsAdRelated() const { return false; } + protected: const ElementData* GetElementData() const { return element_data_.Get(); } UniqueElementData& EnsureUniqueElementData(); @@ -1004,6 +1000,17 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { virtual void ParserDidSetAttributes() {} + // The "nonce" attribute is hidden when: + // 1) The Content-Security-Policy is delivered from the HTTP headers. + // 2) The Element is part of the active document. + // See https://github.com/whatwg/html/pull/2373 + // + // This applies to the element of the HTML and SVG namespaces. + // + // This function clears the "nonce" attribute whenever conditions (1) and (2) + // are met. + void HideNonce(); + private: void ScrollLayoutBoxBy(const ScrollToOptions*); void ScrollLayoutBoxTo(const ScrollToOptions*); @@ -1050,6 +1057,7 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { void RebuildPseudoElementLayoutTree(PseudoId, WhitespaceAttacher&); void RebuildFirstLetterLayoutTree(); + void RebuildMarkerLayoutTree(WhitespaceAttacher&); void RebuildShadowRootLayoutTree(WhitespaceAttacher&); inline void CheckForEmptyStyleChange(const Node* node_before_change, const Node* node_after_change); @@ -1216,7 +1224,6 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { Member<ElementData> element_data_; }; -DEFINE_NODE_TYPE_CASTS(Element, IsElementNode()); template <typename T> bool IsElementOfType(const Node&); template <> @@ -1237,27 +1244,6 @@ struct DowncastTraits<Element> { static bool AllowFrom(const Node& node) { return node.IsElementNode(); } }; -// Type casting. -template <typename T> -inline T& ToElement(Node& node) { - SECURITY_DCHECK(IsElementOfType<const T>(node)); - return static_cast<T&>(node); -} -template <typename T> -inline T* ToElement(Node* node) { - SECURITY_DCHECK(!node || IsElementOfType<const T>(*node)); - return static_cast<T*>(node); -} -template <typename T> -inline const T& ToElement(const Node& node) { - SECURITY_DCHECK(IsElementOfType<const T>(node)); - return static_cast<const T&>(node); -} -template <typename T> -inline const T* ToElement(const Node* node) { - SECURITY_DCHECK(!node || IsElementOfType<const T>(*node)); - return static_cast<const T*>(node); -} inline bool IsDisabledFormControl(const Node* node) { auto* element = DynamicTo<Element>(node); @@ -1356,15 +1342,10 @@ inline UniqueElementData& Element::EnsureUniqueElementData() { return To<UniqueElementData>(*element_data_); } -inline void Element::InvalidateStyleAttribute() { - DCHECK(GetElementData()); - GetElementData()->style_attribute_is_dirty_ = true; -} - inline const CSSPropertyValueSet* Element::PresentationAttributeStyle() { if (!GetElementData()) return nullptr; - if (GetElementData()->presentation_attribute_style_is_dirty_) + if (GetElementData()->presentation_attribute_style_is_dirty()) UpdatePresentationAttributeStyle(); // Need to call elementData() again since updatePresentationAttributeStyle() // might swap it with a UniqueElementData. @@ -1402,23 +1383,6 @@ inline bool IsAtShadowBoundary(const Element* element) { return parent_node && parent_node->IsShadowRoot(); } -// These macros do the same as their NODE equivalents but additionally provide a -// template specialization for isElementOfType<>() so that the Traversal<> API -// works for these Element types. -#define DEFINE_ELEMENT_TYPE_CASTS(thisType, predicate) \ - template <> \ - inline bool IsElementOfType<const thisType>(const Node& node) { \ - return node.predicate; \ - } \ - DEFINE_NODE_TYPE_CASTS(thisType, predicate) - -#define DEFINE_ELEMENT_TYPE_CASTS_WITH_FUNCTION(thisType) \ - template <> \ - inline bool IsElementOfType<const thisType>(const Node& node) { \ - return Is##thisType(node); \ - } \ - DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(thisType) - } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ELEMENT_H_ diff --git a/chromium/third_party/blink/renderer/core/dom/element.idl b/chromium/third_party/blink/renderer/core/dom/element.idl index 2f0674c6038..5ed1c0311d6 100644 --- a/chromium/third_party/blink/renderer/core/dom/element.idl +++ b/chromium/third_party/blink/renderer/core/dom/element.idl @@ -90,13 +90,19 @@ callback ScrollStateCallback = void (ScrollState scrollState); // https://w3c.github.io/DOM-Parsing/#extensions-to-the-element-interface // // TODO(mkwst): Write a spec for the `TrustedHTML` variants. - [Affects=Nothing, CEReactions, CustomElementCallbacks, Custom=Setter, RuntimeCallStatsCounter=ElementInnerHTML] attribute HTMLString innerHTML; - [Affects=Nothing, CEReactions, CustomElementCallbacks, Custom=Setter] attribute HTMLString outerHTML; + // TODO(lyf): Change the type to `[TreatNullAs=xxx] HTMLString` after + // https://crbug.com/1058762 has been fixed. + [Affects=Nothing, CEReactions, CustomElementCallbacks, RuntimeCallStatsCounter=ElementInnerHTML, RaisesException=Setter] attribute [TreatNullAs=EmptyString, StringContext=TrustedHTML] DOMString innerHTML; + [Affects=Nothing, CEReactions, CustomElementCallbacks, RaisesException=Setter] attribute [TreatNullAs=EmptyString, StringContext=TrustedHTML] DOMString outerHTML; [CEReactions, CustomElementCallbacks, RaisesException] void insertAdjacentHTML(DOMString position, HTMLString text); + // Declarative Shadow DOM getInnerHTML() function. + [RuntimeEnabled=DeclarativeShadowDOM, RuntimeCallStatsCounter=ElementGetInnerHTML] HTMLString getInnerHTML(boolean includeShadowRoots); + // Pointer Lock // https://w3c.github.io/pointerlock/#extensions-to-the-element-interface - [MeasureAs=ElementRequestPointerLock] void requestPointerLock(optional PointerLockOptions options); + // This function returns void unless the Runtime Enabled Feature |PointerLockOptions| is enabled then it returns Promise<void>. + [MeasureAs=ElementRequestPointerLock, CallWith=ScriptState, RaisesException] any requestPointerLock(optional PointerLockOptions options = {}); // CSSOM View Module // https://drafts.csswg.org/cssom-view/#extension-to-the-element-interface @@ -105,12 +111,12 @@ callback ScrollStateCallback = void (ScrollState scrollState); // TODO(sunyunjia): Add default value for scrollIntoView() once // crbug.com/734599 is fixed. - void scrollIntoView(optional (ScrollIntoViewOptions or boolean) arg); - [ImplementedAs=scrollTo] void scroll(optional ScrollToOptions options); + void scrollIntoView(optional (ScrollIntoViewOptions or boolean) arg = {}); + [ImplementedAs=scrollTo] void scroll(optional ScrollToOptions options = {}); [ImplementedAs=scrollTo] void scroll(unrestricted double x, unrestricted double y); - void scrollTo(optional ScrollToOptions options); + void scrollTo(optional ScrollToOptions options = {}); void scrollTo(unrestricted double x, unrestricted double y); - void scrollBy(optional ScrollToOptions options); + void scrollBy(optional ScrollToOptions options = {}); void scrollBy(unrestricted double x, unrestricted double y); [Affects=Nothing] attribute unrestricted double scrollTop; [Affects=Nothing] attribute unrestricted double scrollLeft; @@ -145,13 +151,6 @@ callback ScrollStateCallback = void (ScrollState scrollState); attribute EventHandler onbeforepaste; attribute EventHandler onsearch; - // Declarative display locking. - [RuntimeEnabled=DisplayLocking, CEReactions, CustomElementCallbacks, Reflect] attribute DOMString renderSubtree; - [RuntimeEnabled=DisplayLocking, CallWith=ScriptState] Promise<any> updateRendering(); - - // CSS version of display locking. - [RuntimeEnabled=CSSRenderSubtree] void resetSubtreeRendered(); - // Element Timing [Affects=Nothing, CEReactions, Reflect=elementtiming] attribute DOMString elementTiming; }; diff --git a/chromium/third_party/blink/renderer/core/dom/element_data.cc b/chromium/third_party/blink/renderer/core/dom/element_data.cc index 890989ea8f6..cb990d551b0 100644 --- a/chromium/third_party/blink/renderer/core/dom/element_data.cc +++ b/chromium/third_party/blink/renderer/core/dom/element_data.cc @@ -52,27 +52,27 @@ static AdditionalBytes AdditionalBytesForShareableElementDataWithAttributeCount( } ElementData::ElementData() - : is_unique_(true), - array_size_(0), - presentation_attribute_style_is_dirty_(false), - style_attribute_is_dirty_(false), - animated_svg_attributes_are_dirty_(false) {} + : bit_field_(IsUniqueFlag::encode(true) | ArraySize::encode(0) | + PresentationAttributeStyleIsDirty::encode(false) | + StyleAttributeIsDirty::encode(false) | + AnimatedSvgAttributesAreDirty::encode(false)) {} ElementData::ElementData(unsigned array_size) - : is_unique_(false), - array_size_(array_size), - presentation_attribute_style_is_dirty_(false), - style_attribute_is_dirty_(false), - animated_svg_attributes_are_dirty_(false) {} + : bit_field_(IsUniqueFlag::encode(false) | ArraySize::encode(array_size) | + PresentationAttributeStyleIsDirty::encode(false) | + StyleAttributeIsDirty::encode(false) | + AnimatedSvgAttributesAreDirty::encode(false)) {} ElementData::ElementData(const ElementData& other, bool is_unique) - : is_unique_(is_unique), - array_size_(is_unique ? 0 : other.Attributes().size()), - presentation_attribute_style_is_dirty_( - other.presentation_attribute_style_is_dirty_), - style_attribute_is_dirty_(other.style_attribute_is_dirty_), - animated_svg_attributes_are_dirty_( - other.animated_svg_attributes_are_dirty_), + : bit_field_( + IsUniqueFlag::encode(is_unique) | + ArraySize::encode(is_unique ? 0 : other.Attributes().size()) | + PresentationAttributeStyleIsDirty::encode( + other.bit_field_.get<PresentationAttributeStyleIsDirty>()) | + StyleAttributeIsDirty::encode( + other.bit_field_.get<StyleAttributeIsDirty>()) | + AnimatedSvgAttributesAreDirty::encode( + other.bit_field_.get<AnimatedSvgAttributesAreDirty>())), class_names_(other.class_names_), id_for_style_resolution_(other.id_for_style_resolution_) { // NOTE: The inline style is copied by the subclass copy constructor since we @@ -111,24 +111,25 @@ bool ElementData::IsEquivalent(const ElementData* other) const { } void ElementData::Trace(Visitor* visitor) { - if (auto* unique_element_data = DynamicTo<UniqueElementData>(this)) - unique_element_data->TraceAfterDispatch(visitor); - else - To<ShareableElementData>(this)->TraceAfterDispatch(visitor); + if (bit_field_.get_concurrently<IsUniqueFlag>()) { + static_cast<UniqueElementData*>(this)->TraceAfterDispatch(visitor); + } else { + static_cast<ShareableElementData*>(this)->TraceAfterDispatch(visitor); + } } -void ElementData::TraceAfterDispatch(blink::Visitor* visitor) { +void ElementData::TraceAfterDispatch(blink::Visitor* visitor) const { visitor->Trace(inline_style_); } ShareableElementData::ShareableElementData(const Vector<Attribute>& attributes) : ElementData(attributes.size()) { - for (unsigned i = 0; i < array_size_; ++i) + for (unsigned i = 0; i < bit_field_.get<ArraySize>(); ++i) new (&attribute_array_[i]) Attribute(attributes[i]); } ShareableElementData::~ShareableElementData() { - for (unsigned i = 0; i < array_size_; ++i) + for (unsigned i = 0; i < bit_field_.get<ArraySize>(); ++i) attribute_array_[i].~Attribute(); } @@ -140,7 +141,7 @@ ShareableElementData::ShareableElementData(const UniqueElementData& other) inline_style_ = other.inline_style_->ImmutableCopyIfNeeded(); } - for (unsigned i = 0; i < array_size_; ++i) + for (unsigned i = 0; i < bit_field_.get<ArraySize>(); ++i) new (&attribute_array_[i]) Attribute(other.attribute_vector_.at(i)); } @@ -182,7 +183,7 @@ ShareableElementData* UniqueElementData::MakeShareableCopy() const { *this); } -void UniqueElementData::TraceAfterDispatch(blink::Visitor* visitor) { +void UniqueElementData::TraceAfterDispatch(blink::Visitor* visitor) const { visitor->Trace(presentation_attribute_style_); ElementData::TraceAfterDispatch(visitor); } diff --git a/chromium/third_party/blink/renderer/core/dom/element_data.h b/chromium/third_party/blink/renderer/core/dom/element_data.h index a3b87797d0b..bda30301170 100644 --- a/chromium/third_party/blink/renderer/core/dom/element_data.h +++ b/chromium/third_party/blink/renderer/core/dom/element_data.h @@ -37,6 +37,7 @@ #include "third_party/blink/renderer/core/dom/attribute_collection.h" #include "third_party/blink/renderer/core/dom/space_split_string.h" #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/wtf/bit_field.h" #include "third_party/blink/renderer/platform/wtf/casting.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" @@ -78,23 +79,55 @@ class ElementData : public GarbageCollected<ElementData> { bool IsEquivalent(const ElementData* other) const; - bool IsUnique() const { return is_unique_; } + bool IsUnique() const { return bit_field_.get<IsUniqueFlag>(); } - void TraceAfterDispatch(blink::Visitor*); + void TraceAfterDispatch(blink::Visitor*) const; void Trace(Visitor*); protected: + using BitField = WTF::ConcurrentlyReadBitField<uint32_t>; + using IsUniqueFlag = + BitField::DefineFirstValue<bool, 1, WTF::BitFieldValueConstness::kConst>; + using ArraySize = IsUniqueFlag:: + DefineNextValue<uint32_t, 28, WTF::BitFieldValueConstness::kConst>; + using PresentationAttributeStyleIsDirty = ArraySize::DefineNextValue<bool, 1>; + using StyleAttributeIsDirty = + PresentationAttributeStyleIsDirty::DefineNextValue<bool, 1>; + using AnimatedSvgAttributesAreDirty = + StyleAttributeIsDirty::DefineNextValue<bool, 1>; + ElementData(); explicit ElementData(unsigned array_size); ElementData(const ElementData&, bool is_unique); - // Keep the type in a bitfield instead of using virtual destructors to avoid - // adding a vtable. - unsigned is_unique_ : 1; - unsigned array_size_ : 28; - mutable unsigned presentation_attribute_style_is_dirty_ : 1; - mutable unsigned style_attribute_is_dirty_ : 1; - mutable unsigned animated_svg_attributes_are_dirty_ : 1; + bool presentation_attribute_style_is_dirty() const { + return bit_field_.get<PresentationAttributeStyleIsDirty>(); + } + bool style_attribute_is_dirty() const { + return bit_field_.get<StyleAttributeIsDirty>(); + } + bool animated_svg_attributes_are_dirty() const { + return bit_field_.get<AnimatedSvgAttributesAreDirty>(); + } + + // Following 3 fields are meant to be mutable and can change even when const. + void SetPresentationAttributeStyleIsDirty( + bool presentation_attribute_style_is_dirty) const { + const_cast<BitField*>(&bit_field_) + ->set<PresentationAttributeStyleIsDirty>( + presentation_attribute_style_is_dirty); + } + void SetStyleAttributeIsDirty(bool style_attribute_is_dirty) const { + const_cast<BitField*>(&bit_field_) + ->set<StyleAttributeIsDirty>(style_attribute_is_dirty); + } + void SetAnimatedSvgAttributesAreDirty( + bool animated_svg_attributes_are_dirty) const { + const_cast<BitField*>(&bit_field_) + ->set<AnimatedSvgAttributesAreDirty>(animated_svg_attributes_are_dirty); + } + + BitField bit_field_; mutable Member<CSSPropertyValueSet> inline_style_; mutable SpaceSplitString class_names_; @@ -105,6 +138,8 @@ class ElementData : public GarbageCollected<ElementData> { friend class ShareableElementData; friend class UniqueElementData; friend class SVGElement; + friend struct DowncastTraits<UniqueElementData>; + friend struct DowncastTraits<ShareableElementData>; UniqueElementData* MakeUniqueCopy() const; }; @@ -127,7 +162,7 @@ class ShareableElementData final : public ElementData { explicit ShareableElementData(const UniqueElementData&); ~ShareableElementData(); - void TraceAfterDispatch(blink::Visitor* visitor) { + void TraceAfterDispatch(blink::Visitor* visitor) const { ElementData::TraceAfterDispatch(visitor); } @@ -138,7 +173,9 @@ class ShareableElementData final : public ElementData { template <> struct DowncastTraits<ShareableElementData> { - static bool AllowFrom(const ElementData& data) { return !data.IsUnique(); } + static bool AllowFrom(const ElementData& data) { + return !data.bit_field_.get<ElementData::IsUniqueFlag>(); + } }; #if defined(COMPILER_MSVC) @@ -162,7 +199,7 @@ class UniqueElementData final : public ElementData { explicit UniqueElementData(const ShareableElementData&); explicit UniqueElementData(const UniqueElementData&); - void TraceAfterDispatch(blink::Visitor*); + void TraceAfterDispatch(blink::Visitor*) const; // FIXME: We might want to support sharing element data for elements with // presentation attribute style. Lots of table cells likely have the same @@ -174,12 +211,14 @@ class UniqueElementData final : public ElementData { template <> struct DowncastTraits<UniqueElementData> { - static bool AllowFrom(const ElementData& data) { return data.IsUnique(); } + static bool AllowFrom(const ElementData& data) { + return data.bit_field_.get<ElementData::IsUniqueFlag>(); + } }; inline const CSSPropertyValueSet* ElementData::PresentationAttributeStyle() const { - if (!is_unique_) + if (!bit_field_.get<IsUniqueFlag>()) return nullptr; return To<UniqueElementData>(this)->presentation_attribute_style_.Get(); } @@ -191,7 +230,7 @@ inline AttributeCollection ElementData::Attributes() const { } inline AttributeCollection ShareableElementData::Attributes() const { - return AttributeCollection(attribute_array_, array_size_); + return AttributeCollection(attribute_array_, bit_field_.get<ArraySize>()); } inline AttributeCollection UniqueElementData::Attributes() const { diff --git a/chromium/third_party/blink/renderer/core/dom/element_rare_data.cc b/chromium/third_party/blink/renderer/core/dom/element_rare_data.cc index ca9b48e74f8..0f6056b71e0 100644 --- a/chromium/third_party/blink/renderer/core/dom/element_rare_data.cc +++ b/chromium/third_party/blink/renderer/core/dom/element_rare_data.cc @@ -47,9 +47,7 @@ struct SameSizeAsElementRareData : NodeRareData { }; ElementRareData::ElementRareData(NodeRenderingData* node_layout_data) - : NodeRareData(node_layout_data), class_list_(nullptr) { - is_element_rare_data_ = true; -} + : NodeRareData(node_layout_data, true), class_list_(nullptr) {} ElementRareData::~ElementRareData() { DCHECK(!pseudo_element_data_); @@ -95,7 +93,7 @@ ElementInternals& ElementRareData::EnsureElementInternals(HTMLElement& target) { return *element_internals_; } -void ElementRareData::TraceAfterDispatch(blink::Visitor* visitor) { +void ElementRareData::TraceAfterDispatch(blink::Visitor* visitor) const { visitor->Trace(dataset_); visitor->Trace(class_list_); visitor->Trace(part_); diff --git a/chromium/third_party/blink/renderer/core/dom/element_rare_data.h b/chromium/third_party/blink/renderer/core/dom/element_rare_data.h index c105ed22f15..21c5a80acac 100644 --- a/chromium/third_party/blink/renderer/core/dom/element_rare_data.h +++ b/chromium/third_party/blink/renderer/core/dom/element_rare_data.h @@ -58,6 +58,7 @@ class ElementRareData : public NodeRareData { void SetPseudoElement(PseudoId, PseudoElement*); PseudoElement* GetPseudoElement(PseudoId) const; + PseudoElementData::PseudoElementVector GetPseudoElements() const; void SetTabIndexExplicitly() { SetElementFlag(ElementFlags::kTabIndexWasSetExplicitly, true); @@ -191,11 +192,9 @@ class ElementRareData : public NodeRareData { } ResizeObserverDataMap& EnsureResizeObserverData(); - DisplayLockContext* EnsureDisplayLockContext(Element* element, - ExecutionContext* context) { + DisplayLockContext* EnsureDisplayLockContext(Element* element) { if (!display_lock_context_) { - display_lock_context_ = - MakeGarbageCollected<DisplayLockContext>(element, context); + display_lock_context_ = MakeGarbageCollected<DisplayLockContext>(element); } return display_lock_context_.Get(); } @@ -206,7 +205,7 @@ class ElementRareData : public NodeRareData { const AtomicString& GetNonce() const { return nonce_; } void SetNonce(const AtomicString& nonce) { nonce_ = nonce; } - void TraceAfterDispatch(blink::Visitor*); + void TraceAfterDispatch(blink::Visitor*) const; private: ScrollOffset saved_layer_scroll_offset_; @@ -274,6 +273,13 @@ inline PseudoElement* ElementRareData::GetPseudoElement( return pseudo_element_data_->GetPseudoElement(pseudo_id); } +inline PseudoElementData::PseudoElementVector +ElementRareData::GetPseudoElements() const { + if (!pseudo_element_data_) + return {}; + return pseudo_element_data_->GetPseudoElements(); +} + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ELEMENT_RARE_DATA_H_ diff --git a/chromium/third_party/blink/renderer/core/dom/element_test.cc b/chromium/third_party/blink/renderer/core/dom/element_test.cc index 8ab66b130d1..83346d25b0b 100644 --- a/chromium/third_party/blink/renderer/core/dom/element_test.cc +++ b/chromium/third_party/blink/renderer/core/dom/element_test.cc @@ -30,8 +30,7 @@ TEST_F(ElementTest, SupportsFocus) { Document& document = GetDocument(); DCHECK(IsA<HTMLHtmlElement>(document.documentElement())); document.setDesignMode("on"); - document.View()->UpdateAllLifecyclePhases( - DocumentLifecycle::LifecycleUpdateReason::kTest); + document.View()->UpdateAllLifecyclePhases(DocumentUpdateReason::kTest); EXPECT_TRUE(document.documentElement()->SupportsFocus()) << "<html> with designMode=on should be focusable."; } @@ -66,8 +65,7 @@ TEST_F(ElementTest, // Insert a new <div> above the sticky. This will dirty layout and invalidate // the sticky constraints. - writer->SetInnerHTMLFromString( - "<div style='height: 100px; width: 700px;'></div>"); + writer->setInnerHTML("<div style='height: 100px; width: 700px;'></div>"); EXPECT_EQ(DocumentLifecycle::kVisualUpdatePending, document.Lifecycle().GetState()); @@ -111,8 +109,7 @@ TEST_F(ElementTest, OffsetTopAndLeftCorrectForStickyElementsAfterInsertion) { // Insert a new <div> above the sticky. This will dirty layout and invalidate // the sticky constraints. - writer->SetInnerHTMLFromString( - "<div style='height: 100px; width: 700px;'></div>"); + writer->setInnerHTML("<div style='height: 100px; width: 700px;'></div>"); EXPECT_EQ(DocumentLifecycle::kVisualUpdatePending, document.Lifecycle().GetState()); @@ -126,8 +123,7 @@ TEST_F(ElementTest, OffsetTopAndLeftCorrectForStickyElementsAfterInsertion) { ->NeedsCompositingInputsUpdate()); // Dirty layout again, since |OffsetTop| will have cleaned it. - writer->SetInnerHTMLFromString( - "<div style='height: 100px; width: 700px;'></div>"); + writer->setInnerHTML("<div style='height: 100px; width: 700px;'></div>"); EXPECT_EQ(DocumentLifecycle::kVisualUpdatePending, document.Lifecycle().GetState()); @@ -169,8 +165,7 @@ TEST_F(ElementTest, BoundsInViewportCorrectForStickyElementsAfterInsertion) { // Insert a new <div> above the sticky. This will dirty layout and invalidate // the sticky constraints. - writer->SetInnerHTMLFromString( - "<div style='height: 100px; width: 700px;'></div>"); + writer->setInnerHTML("<div style='height: 100px; width: 700px;'></div>"); EXPECT_EQ(DocumentLifecycle::kVisualUpdatePending, document.Lifecycle().GetState()); @@ -224,8 +219,7 @@ TEST_F(ElementTest, StickySubtreesAreTrackedCorrectly) { // ensure that the sticky subtree update behavior survives forking. document.getElementById("child")->SetInlineStyleProperty( CSSPropertyID::kWebkitRubyPosition, CSSValueID::kAfter); - document.View()->UpdateAllLifecyclePhases( - DocumentLifecycle::LifecycleUpdateReason::kTest); + document.View()->UpdateAllLifecyclePhases(DocumentUpdateReason::kTest); EXPECT_EQ(DocumentLifecycle::kPaintClean, document.Lifecycle().GetState()); EXPECT_EQ(RubyPosition::kBefore, outer_sticky->StyleRef().GetRubyPosition()); @@ -247,8 +241,7 @@ TEST_F(ElementTest, StickySubtreesAreTrackedCorrectly) { // fork it's StyleRareInheritedData to maintain the sticky subtree bit. document.getElementById("outerSticky") ->SetInlineStyleProperty(CSSPropertyID::kPosition, CSSValueID::kStatic); - document.View()->UpdateAllLifecyclePhases( - DocumentLifecycle::LifecycleUpdateReason::kTest); + document.View()->UpdateAllLifecyclePhases(DocumentUpdateReason::kTest); EXPECT_EQ(DocumentLifecycle::kPaintClean, document.Lifecycle().GetState()); EXPECT_FALSE(outer_sticky->StyleRef().SubtreeIsSticky()); @@ -469,11 +462,6 @@ TEST_F(ElementTest, OptionElementDisplayNoneComputedStyle) { EXPECT_FALSE(document.getElementById("inner-option")->GetComputedStyle()); } -template <> -struct DowncastTraits<HTMLPlugInElement> { - static bool AllowFrom(const Node& n) { return IsHTMLPlugInElement(n); } -}; - // A fake plugin which will assert that script is allowed in Destroy. class ScriptOnDestroyPlugin : public GarbageCollected<ScriptOnDestroyPlugin>, public WebPlugin { @@ -488,16 +476,16 @@ class ScriptOnDestroyPlugin : public GarbageCollected<ScriptOnDestroyPlugin>, } WebPluginContainer* Container() const override { return container_; } - void UpdateAllLifecyclePhases(WebWidget::LifecycleUpdateReason) override {} + void UpdateAllLifecyclePhases(DocumentUpdateReason) override {} void Paint(cc::PaintCanvas*, const WebRect&) override {} void UpdateGeometry(const WebRect&, const WebRect&, const WebRect&, bool) override {} - void UpdateFocus(bool, WebFocusType) override {} + void UpdateFocus(bool, mojom::blink::FocusType) override {} void UpdateVisibility(bool) override {} WebInputEventResult HandleInputEvent(const WebCoalescedInputEvent&, - WebCursorInfo&) override { + ui::Cursor*) override { return {}; } void DidReceiveResponse(const WebURLResponse&) override {} @@ -505,7 +493,7 @@ class ScriptOnDestroyPlugin : public GarbageCollected<ScriptOnDestroyPlugin>, void DidFinishLoading() override {} void DidFailLoading(const WebURLError&) override {} - void Trace(blink::Visitor*) {} + void Trace(Visitor*) {} bool DestroyCalled() const { return destroy_called_; } diff --git a/chromium/third_party/blink/renderer/core/dom/element_traversal.h b/chromium/third_party/blink/renderer/core/dom/element_traversal.h index 9c203350a96..1754eba2cb2 100644 --- a/chromium/third_party/blink/renderer/core/dom/element_traversal.h +++ b/chromium/third_party/blink/renderer/core/dom/element_traversal.h @@ -131,6 +131,13 @@ class Traversal { } template <typename MatchFunc> static ElementType* FirstWithin(const ContainerNode&, MatchFunc); + + static ElementType* InclusiveFirstWithin(Node& current) { + if (IsElementOfType<const ElementType>(current)) + return To<ElementType>(¤t); + return FirstWithin(current); + } + static ElementType* LastWithin(const ContainerNode& current) { return LastWithinTemplate(current); } @@ -288,7 +295,7 @@ inline ElementType* Traversal<ElementType>::FirstChildTemplate( Node* node = current.firstChild(); while (node && !IsElementOfType<const ElementType>(*node)) node = node->nextSibling(); - return ToElement<ElementType>(node); + return To<ElementType>(node); } template <class ElementType> @@ -307,7 +314,7 @@ inline ElementType* Traversal<ElementType>::FirstAncestor(const Node& current) { ContainerNode* ancestor = current.parentNode(); while (ancestor && !IsElementOfType<const ElementType>(*ancestor)) ancestor = ancestor->parentNode(); - return ToElement<ElementType>(ancestor); + return To<ElementType>(ancestor); } template <class ElementType> @@ -315,7 +322,7 @@ template <class NodeType> inline ElementType* Traversal<ElementType>::FirstAncestorOrSelfTemplate( NodeType& current) { if (IsElementOfType<const ElementType>(current)) - return &ToElement<ElementType>(current); + return &To<ElementType>(current); return FirstAncestor(current); } @@ -326,7 +333,7 @@ inline ElementType* Traversal<ElementType>::LastChildTemplate( Node* node = current.lastChild(); while (node && !IsElementOfType<const ElementType>(*node)) node = node->previousSibling(); - return ToElement<ElementType>(node); + return To<ElementType>(node); } template <class ElementType> @@ -347,7 +354,7 @@ inline ElementType* Traversal<ElementType>::FirstWithinTemplate( Node* node = current.firstChild(); while (node && !IsElementOfType<const ElementType>(*node)) node = NodeTraversal::Next(*node, ¤t); - return ToElement<ElementType>(node); + return To<ElementType>(node); } template <class ElementType> @@ -368,7 +375,7 @@ inline ElementType* Traversal<ElementType>::LastWithinTemplate( Node* node = NodeTraversal::LastWithin(current); while (node && !IsElementOfType<const ElementType>(*node)) node = NodeTraversal::Previous(*node, ¤t); - return ToElement<ElementType>(node); + return To<ElementType>(node); } template <class ElementType> @@ -396,7 +403,7 @@ inline ElementType* Traversal<ElementType>::NextTemplate(NodeType& current) { Node* node = NodeTraversal::Next(current); while (node && !IsElementOfType<const ElementType>(*node)) node = NodeTraversal::Next(*node); - return ToElement<ElementType>(node); + return To<ElementType>(node); } template <class ElementType> @@ -407,7 +414,7 @@ inline ElementType* Traversal<ElementType>::NextTemplate( Node* node = NodeTraversal::Next(current, stay_within); while (node && !IsElementOfType<const ElementType>(*node)) node = NodeTraversal::Next(*node, stay_within); - return ToElement<ElementType>(node); + return To<ElementType>(node); } template <class ElementType> @@ -426,7 +433,7 @@ inline ElementType* Traversal<ElementType>::Previous(const Node& current) { Node* node = NodeTraversal::Previous(current); while (node && !IsElementOfType<const ElementType>(*node)) node = NodeTraversal::Previous(*node); - return ToElement<ElementType>(node); + return To<ElementType>(node); } template <class ElementType> @@ -435,7 +442,7 @@ inline ElementType* Traversal<ElementType>::Previous(const Node& current, Node* node = NodeTraversal::Previous(current, stay_within); while (node && !IsElementOfType<const ElementType>(*node)) node = NodeTraversal::Previous(*node, stay_within); - return ToElement<ElementType>(node); + return To<ElementType>(node); } template <class ElementType> @@ -456,7 +463,7 @@ inline ElementType* Traversal<ElementType>::NextSkippingChildren( Node* node = NodeTraversal::NextSkippingChildren(current); while (node && !IsElementOfType<const ElementType>(*node)) node = NodeTraversal::NextSkippingChildren(*node); - return ToElement<ElementType>(node); + return To<ElementType>(node); } template <class ElementType> @@ -466,7 +473,7 @@ inline ElementType* Traversal<ElementType>::NextSkippingChildren( Node* node = NodeTraversal::NextSkippingChildren(current, stay_within); while (node && !IsElementOfType<const ElementType>(*node)) node = NodeTraversal::NextSkippingChildren(*node, stay_within); - return ToElement<ElementType>(node); + return To<ElementType>(node); } template <class ElementType> @@ -476,7 +483,7 @@ inline ElementType* Traversal<ElementType>::PreviousIncludingPseudo( Node* node = NodeTraversal::PreviousIncludingPseudo(current, stay_within); while (node && !IsElementOfType<const ElementType>(*node)) node = NodeTraversal::PreviousIncludingPseudo(*node, stay_within); - return ToElement<ElementType>(node); + return To<ElementType>(node); } template <class ElementType> @@ -486,7 +493,7 @@ inline ElementType* Traversal<ElementType>::NextIncludingPseudo( Node* node = NodeTraversal::NextIncludingPseudo(current, stay_within); while (node && !IsElementOfType<const ElementType>(*node)) node = NodeTraversal::NextIncludingPseudo(*node, stay_within); - return ToElement<ElementType>(node); + return To<ElementType>(node); } template <class ElementType> @@ -498,7 +505,7 @@ inline ElementType* Traversal<ElementType>::NextIncludingPseudoSkippingChildren( while (node && !IsElementOfType<const ElementType>(*node)) node = NodeTraversal::NextIncludingPseudoSkippingChildren(*node, stay_within); - return ToElement<ElementType>(node); + return To<ElementType>(node); } template <class ElementType> @@ -507,7 +514,7 @@ inline ElementType* Traversal<ElementType>::PseudoAwarePreviousSibling( Node* node = current.PseudoAwarePreviousSibling(); while (node && !IsElementOfType<const ElementType>(*node)) node = node->PseudoAwarePreviousSibling(); - return ToElement<ElementType>(node); + return To<ElementType>(node); } template <class ElementType> @@ -516,7 +523,7 @@ inline ElementType* Traversal<ElementType>::PreviousSibling( Node* node = current.previousSibling(); while (node && !IsElementOfType<const ElementType>(*node)) node = node->previousSibling(); - return ToElement<ElementType>(node); + return To<ElementType>(node); } template <class ElementType> @@ -535,7 +542,7 @@ inline ElementType* Traversal<ElementType>::NextSibling(const Node& current) { Node* node = current.nextSibling(); while (node && !IsElementOfType<const ElementType>(*node)) node = node->nextSibling(); - return ToElement<ElementType>(node); + return To<ElementType>(node); } template <class ElementType> diff --git a/chromium/third_party/blink/renderer/core/dom/events/add_event_listener_options_resolved.h b/chromium/third_party/blink/renderer/core/dom/events/add_event_listener_options_resolved.h index 321db436341..1eb95afb2c8 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/add_event_listener_options_resolved.h +++ b/chromium/third_party/blink/renderer/core/dom/events/add_event_listener_options_resolved.h @@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_ADD_EVENT_LISTENER_OPTIONS_RESOLVED_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_ADD_EVENT_LISTENER_OPTIONS_RESOLVED_H_ -#include "third_party/blink/renderer/core/dom/events/add_event_listener_options.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_add_event_listener_options.h" namespace blink { diff --git a/chromium/third_party/blink/renderer/core/dom/events/custom_event.cc b/chromium/third_party/blink/renderer/core/dom/events/custom_event.cc index 447a53e79f4..95b79fbcd94 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/custom_event.cc +++ b/chromium/third_party/blink/renderer/core/dom/events/custom_event.cc @@ -25,6 +25,7 @@ #include "third_party/blink/renderer/core/dom/events/custom_event.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_custom_event_init.h" #include "third_party/blink/renderer/core/event_interface_names.h" namespace blink { diff --git a/chromium/third_party/blink/renderer/core/dom/events/custom_event.h b/chromium/third_party/blink/renderer/core/dom/events/custom_event.h index 3cce5f21cd8..f456e3d543f 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/custom_event.h +++ b/chromium/third_party/blink/renderer/core/dom/events/custom_event.h @@ -28,11 +28,12 @@ #include "third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.h" #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/dom/events/custom_event_init.h" #include "third_party/blink/renderer/core/dom/events/event.h" namespace blink { +class CustomEventInit; + class CORE_EXPORT CustomEvent final : public Event { DEFINE_WRAPPERTYPEINFO(); diff --git a/chromium/third_party/blink/renderer/core/dom/events/custom_event.idl b/chromium/third_party/blink/renderer/core/dom/events/custom_event.idl index 2ae3973b317..0bb00fd08d1 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/custom_event.idl +++ b/chromium/third_party/blink/renderer/core/dom/events/custom_event.idl @@ -26,10 +26,9 @@ // https://dom.spec.whatwg.org/#interface-customevent [ - Constructor(DOMString type, optional CustomEventInit eventInitDict), - ConstructorCallWith=ScriptState, Exposed=(Window,Worker) ] interface CustomEvent : Event { + [CallWith=ScriptState] constructor(DOMString type, optional CustomEventInit eventInitDict = {}); [CallWith=ScriptState] readonly attribute any detail; [Measure, CallWith=ScriptState] void initCustomEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false, optional any detail = null); diff --git a/chromium/third_party/blink/renderer/core/dom/events/event.cc b/chromium/third_party/blink/renderer/core/dom/events/event.cc index 47ee4071da3..1e5f4e14e3c 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/event.cc +++ b/chromium/third_party/blink/renderer/core/dom/events/event.cc @@ -32,7 +32,6 @@ #include "third_party/blink/renderer/core/events/mouse_event.h" #include "third_party/blink/renderer/core/events/pointer_event.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" -#include "third_party/blink/renderer/core/frame/hosts_using_features.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/web_feature.h" #include "third_party/blink/renderer/core/svg/svg_element.h" @@ -273,20 +272,20 @@ void Event::SetTarget(EventTarget* target) { } void Event::SetRelatedTargetIfExists(EventTarget* related_target) { - if (IsMouseEvent()) { - ToMouseEvent(this)->SetRelatedTarget(related_target); - } else if (IsPointerEvent()) { - ToPointerEvent(this)->SetRelatedTarget(related_target); - } else if (IsFocusEvent()) { - ToFocusEvent(this)->SetRelatedTarget(related_target); + if (auto* mouse_event = DynamicTo<MouseEvent>(this)) { + mouse_event->SetRelatedTarget(related_target); + } else if (auto* pointer_event = DynamicTo<PointerEvent>(this)) { + pointer_event->SetRelatedTarget(related_target); + } else if (auto* focus_event = DynamicTo<FocusEvent>(this)) { + focus_event->SetRelatedTarget(related_target); } } void Event::ReceivedTarget() {} -void Event::SetUnderlyingEvent(Event* ue) { +void Event::SetUnderlyingEvent(const Event* ue) { // Prohibit creation of a cycle -- just do nothing in that case. - for (Event* e = ue; e; e = e->UnderlyingEvent()) + for (const Event* e = ue; e; e = e->UnderlyingEvent()) if (e == this) return; underlying_event_ = ue; diff --git a/chromium/third_party/blink/renderer/core/dom/events/event.h b/chromium/third_party/blink/renderer/core/dom/events/event.h index 650e935ca96..d261a7f2252 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/event.h +++ b/chromium/third_party/blink/renderer/core/dom/events/event.h @@ -249,11 +249,11 @@ class CORE_EXPORT Event : public ScriptWrappable { } void setCancelBubble(ScriptState*, bool); - Event* UnderlyingEvent() const { return underlying_event_.Get(); } - void SetUnderlyingEvent(Event*); + const Event* UnderlyingEvent() const { return underlying_event_.Get(); } + void SetUnderlyingEvent(const Event*); bool HasEventPath() { return event_path_; } - EventPath& GetEventPath() { + EventPath& GetEventPath() const { DCHECK(event_path_); return *event_path_; } @@ -355,7 +355,7 @@ class CORE_EXPORT Event : public ScriptWrappable { Member<EventTarget> current_target_; Member<EventTarget> target_; - Member<Event> underlying_event_; + Member<const Event> underlying_event_; Member<EventPath> event_path_; // The monotonic platform time in seconds, for input events it is the // event timestamp provided by the host OS and reported in the original @@ -363,10 +363,6 @@ class CORE_EXPORT Event : public ScriptWrappable { base::TimeTicks platform_time_stamp_; }; -#define DEFINE_EVENT_TYPE_CASTS(typeName) \ - DEFINE_TYPE_CASTS(typeName, Event, event, event->Is##typeName(), \ - event.Is##typeName()) - } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_H_ diff --git a/chromium/third_party/blink/renderer/core/dom/events/event.idl b/chromium/third_party/blink/renderer/core/dom/events/event.idl index 85e3cab97e0..88b05a48924 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/event.idl +++ b/chromium/third_party/blink/renderer/core/dom/events/event.idl @@ -21,9 +21,9 @@ // https://dom.spec.whatwg.org/#interface-event [ - Constructor(DOMString type, optional EventInit eventInitDict), Exposed=(Window,Worker,AudioWorklet) ] interface Event { + constructor(DOMString type, optional EventInit eventInitDict = {}); readonly attribute DOMString type; readonly attribute EventTarget? target; readonly attribute EventTarget? currentTarget; diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc b/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc index 67441a59665..dc55e6a462a 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc +++ b/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc @@ -64,7 +64,7 @@ DispatchEventResult EventDispatcher::DispatchEvent(Node& node, Event& event) { } EventDispatcher::EventDispatcher(Node& node, Event& event) - : node_(node), event_(event) { + : node_(&node), event_(&event) { view_ = node.GetDocument().View(); event_->InitEventPath(*node_); } @@ -78,7 +78,7 @@ void EventDispatcher::DispatchScopedEvent(Node& node, Event& event) { void EventDispatcher::DispatchSimulatedClick( Node& node, - Event* underlying_event, + const Event* underlying_event, SimulatedClickMouseEventOptions mouse_event_options, SimulatedClickCreationScope creation_scope) { // This persistent vector doesn't cause leaks, because added Nodes are removed @@ -140,8 +140,8 @@ DispatchEventResult EventDispatcher::Dispatch() { event_dispatched_ = true; #endif if (GetEvent().GetEventPath().IsEmpty()) { - // eventPath() can be empty if event path is shrinked by relataedTarget - // retargeting. + // eventPath() can be empty if relatedTarget retargeting has shrunk the + // path. return DispatchEventResult::kNotCanceled; } std::unique_ptr<EventTiming> eventTiming; @@ -159,7 +159,8 @@ DispatchEventResult EventDispatcher::Dispatch() { // A genuine mouse click cannot be triggered by script so we don't expect // there are any script in the stack. DCHECK(!frame->GetAdTracker() || - !frame->GetAdTracker()->IsAdScriptInStack()); + !frame->GetAdTracker()->IsAdScriptInStack( + AdTracker::StackType::kBottomAndTop)); if (frame->IsAdSubframe()) { UseCounter::Count(document, WebFeature::kAdClick); } @@ -202,9 +203,6 @@ DispatchEventResult EventDispatcher::Dispatch() { pre_dispatch_event_handler_result) == kContinueDispatching) { if (DispatchEventAtCapturing() == kContinueDispatching) { - // TODO(crbug/882574): Remove these. - CHECK(event_->HasEventPath()); - CHECK(!event_->GetEventPath().IsEmpty()); if (DispatchEventAtTarget() == kContinueDispatching) DispatchEventAtBubbling(); } @@ -309,8 +307,9 @@ inline void EventDispatcher::DispatchEventPostProcess( // 17. Set event’s currentTarget attribute to null. event_->SetCurrentTarget(nullptr); - bool is_click = event_->IsMouseEvent() && - ToMouseEvent(*event_).type() == event_type_names::kClick; + auto* mouse_event = DynamicTo<MouseEvent>(event_); + bool is_click = + mouse_event && mouse_event->type() == event_type_names::kClick; if (is_click) { // Fire an accessibility event indicating a node was clicked on. This is // safe if event_->target()->ToNode() returns null. @@ -347,10 +346,8 @@ inline void EventDispatcher::DispatchEventPostProcess( // Call default event handlers. While the DOM does have a concept of // preventing default handling, the detail of which handlers are called is an // internal implementation detail and not part of the DOM. - if (event_->defaultPrevented()) { - if (activation_target) - activation_target->DidPreventDefault(*event_); - } else if (!event_->DefaultHandled() && is_trusted_or_click) { + if (!event_->defaultPrevented() && !event_->DefaultHandled() && + is_trusted_or_click) { // Non-bubbling events call only one default event handler, the one for the // target. node_->DefaultEventHandler(*event_); @@ -368,10 +365,11 @@ inline void EventDispatcher::DispatchEventPostProcess( } } + auto* keyboard_event = DynamicTo<KeyboardEvent>(event_); if (Page* page = node_->GetDocument().GetPage()) { if (page->GetSettings().GetSpatialNavigationEnabled() && - is_trusted_or_click && event_->IsKeyboardEvent() && - ToKeyboardEvent(*event_).key() == "Enter" && + is_trusted_or_click && keyboard_event && + keyboard_event->key() == "Enter" && event_->type() == event_type_names::kKeyup) { page->GetSpatialNavigationController().ResetEnterKeyState(); } diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.h b/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.h index 59eba27ca46..048327a6a80 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.h +++ b/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.h @@ -56,7 +56,7 @@ class EventDispatcher { static void DispatchScopedEvent(Node&, Event&); static void DispatchSimulatedClick(Node&, - Event* underlying_event, + const Event* underlying_event, SimulatedClickMouseEventOptions, SimulatedClickCreationScope); @@ -76,9 +76,9 @@ class EventDispatcher { void DispatchEventPostProcess(Node* activation_target, EventDispatchHandlingState*); - Member<Node> node_; - Member<Event> event_; - Member<LocalFrameView> view_; + Node* node_; + Event* event_; + LocalFrameView* view_; #if DCHECK_IS_ON() bool event_dispatched_ = false; #endif diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.cc b/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.cc index b3137fcb85e..1d59550227a 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.cc +++ b/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.cc @@ -32,6 +32,8 @@ #include "third_party/blink/renderer/core/dom/events/event_listener_map.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_event_listener_options.h" +#include "third_party/blink/renderer/core/dom/events/add_event_listener_options_resolved.h" #include "third_party/blink/renderer/core/dom/events/event_listener.h" #include "third_party/blink/renderer/core/dom/events/event_target.h" #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.h b/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.h index 7121c9f06af..ae83fe10ce2 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.h +++ b/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.h @@ -35,13 +35,12 @@ #include "base/macros.h" #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/dom/events/add_event_listener_options_resolved.h" -#include "third_party/blink/renderer/core/dom/events/event_listener_options.h" #include "third_party/blink/renderer/core/dom/events/registered_event_listener.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h" namespace blink { +class EventListenerOptions; class EventTarget; using EventListenerVector = HeapVector<RegisteredEventListener, 1>; diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_queue.cc b/chromium/third_party/blink/renderer/core/dom/events/event_queue.cc index a0a24e1025f..419938ad5e9 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/event_queue.cc +++ b/chromium/third_party/blink/renderer/core/dom/events/event_queue.cc @@ -36,7 +36,7 @@ namespace blink { EventQueue::EventQueue(ExecutionContext* context, TaskType task_type) - : ContextLifecycleObserver(context), + : ExecutionContextLifecycleObserver(context), task_type_(task_type), is_closed_(false) { if (!GetExecutionContext() || GetExecutionContext()->IsContextDestroyed()) @@ -47,7 +47,7 @@ EventQueue::~EventQueue() = default; void EventQueue::Trace(Visitor* visitor) { visitor->Trace(queued_events_); - ContextLifecycleObserver::Trace(visitor); + ExecutionContextLifecycleObserver::Trace(visitor); } bool EventQueue::EnqueueEvent(const base::Location& from_here, Event& event) { @@ -105,8 +105,8 @@ void EventQueue::DispatchEvent(Event* event) { target->DispatchEvent(*event); } -void EventQueue::ContextDestroyed(ExecutionContext* context) { - Close(context); +void EventQueue::ContextDestroyed() { + Close(GetExecutionContext()); } void EventQueue::Close(ExecutionContext* context) { diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_queue.h b/chromium/third_party/blink/renderer/core/dom/events/event_queue.h index c0d12674570..4c0f2995b2d 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/event_queue.h +++ b/chromium/third_party/blink/renderer/core/dom/events/event_queue.h @@ -28,7 +28,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_QUEUE_H_ #include "third_party/blink/public/platform/task_type.h" -#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h" +#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" #include "third_party/blink/renderer/platform/wtf/linked_hash_set.h" namespace blink { @@ -37,7 +37,7 @@ class Event; class ExecutionContext; class CORE_EXPORT EventQueue final : public GarbageCollected<EventQueue>, - public ContextLifecycleObserver { + public ExecutionContextLifecycleObserver { USING_GARBAGE_COLLECTED_MIXIN(EventQueue); public: @@ -53,7 +53,7 @@ class CORE_EXPORT EventQueue final : public GarbageCollected<EventQueue>, bool RemoveEvent(Event&); void DispatchEvent(Event*); - void ContextDestroyed(ExecutionContext*) override; + void ContextDestroyed() override; void Close(ExecutionContext*); void DoCancelAllEvents(ExecutionContext*); diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_target.cc b/chromium/third_party/blink/renderer/core/dom/events/event_target.cc index 5d6f05dc435..2c506ac3266 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/event_target.cc +++ b/chromium/third_party/blink/renderer/core/dom/events/event_target.cc @@ -40,6 +40,7 @@ #include "third_party/blink/renderer/bindings/core/v8/js_based_event_listener.h" #include "third_party/blink/renderer/bindings/core/v8/js_event_listener.h" #include "third_party/blink/renderer/bindings/core/v8/source_location.h" +#include "third_party/blink/renderer/core/dom/events/add_event_listener_options_resolved.h" #include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h" #include "third_party/blink/renderer/core/dom/events/event_target_impl.h" @@ -179,7 +180,7 @@ void CountFiringEventListeners(const Event& event, } if (CheckTypeThenUseCount(event, event_type_names::kPointerdown, WebFeature::kPointerDownFired, document)) { - if (event.IsPointerEvent() && + if (IsA<PointerEvent>(event) && static_cast<const PointerEvent&>(event).pointerType() == "touch") { UseCounter::Count(document, WebFeature::kPointerDownFiredForTouch); } @@ -212,24 +213,11 @@ void CountFiringEventListeners(const Event& event, counted_event.feature, document)) return; } - - if (event.eventPhase() == Event::kCapturingPhase || - event.eventPhase() == Event::kBubblingPhase) { - if (CheckTypeThenUseCount( - event, event_type_names::kDOMNodeRemoved, - WebFeature::kDOMNodeRemovedEventListenedAtNonTarget, document)) - return; - if (CheckTypeThenUseCount( - event, event_type_names::kDOMNodeRemovedFromDocument, - WebFeature::kDOMNodeRemovedFromDocumentEventListenedAtNonTarget, - document)) - return; - } } void RegisterWithScheduler(ExecutionContext* execution_context, const AtomicString& event_type) { - if (!execution_context) + if (!execution_context || !execution_context->GetScheduler()) return; // TODO(altimin): Ideally we would also support tracking unregistration of // event listeners, but we don't do this for performance reasons. @@ -410,7 +398,7 @@ void EventTarget::SetDefaultAddEventListenerOptions( WebFeature::kSmoothScrollJSInterventionActivated); executing_window->GetFrame()->Console().AddMessage( - ConsoleMessage::Create( + MakeGarbageCollected<ConsoleMessage>( mojom::ConsoleMessageSource::kIntervention, mojom::ConsoleMessageLevel::kWarning, "Registering mousewheel event as passive due to " diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_target.h b/chromium/third_party/blink/renderer/core/dom/events/event_target.h index 9c3f2d35018..0963aaaab0a 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/event_target.h +++ b/chromium/third_party/blink/renderer/core/dom/events/event_target.h @@ -37,7 +37,6 @@ #include "base/macros.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/dom/events/add_event_listener_options_resolved.h" #include "third_party/blink/renderer/core/dom/events/event_dispatch_result.h" #include "third_party/blink/renderer/core/dom/events/event_listener_map.h" #include "third_party/blink/renderer/core/event_target_names.h" @@ -50,6 +49,7 @@ namespace blink { class AddEventListenerOptionsOrBoolean; +class AddEventListenerOptionsResolved; class DOMWindow; class Event; class EventListenerOptionsOrBoolean; @@ -58,10 +58,10 @@ class ExecutionContext; class LocalDOMWindow; class MessagePort; class Node; +class PortalHost; class ScriptState; class ServiceWorker; class V8EventListener; -class PortalHost; struct FiringEventIterator { DISALLOW_NEW(); @@ -109,8 +109,8 @@ class CORE_EXPORT EventTargetData final // file. // - Override EventTarget::interfaceName() and getExecutionContext(). The former // will typically return EventTargetNames::YourClassName. The latter will -// return ContextLifecycleObserver::executionContext (if you are an -// ContextLifecycleObserver) +// return ExecutionContextLifecycleObserver::executionContext (if you are an +// ExecutionContextLifecycleObserver) // or the document you're in. // - Your trace() method will need to call EventTargetWithInlineData::trace // depending on the base class of your class. diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_target.idl b/chromium/third_party/blink/renderer/core/dom/events/event_target.idl index 9446764ac88..f80e0071488 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/event_target.idl +++ b/chromium/third_party/blink/renderer/core/dom/events/event_target.idl @@ -22,12 +22,11 @@ [ CheckSecurity=Receiver, - Constructor(), - ConstructorCallWith=ScriptState, Exposed=(Window,Worker,AudioWorklet), ImmutablePrototype ] interface EventTarget { - [Custom=CallPrologue] void addEventListener(DOMString type, EventListener? listener, optional (AddEventListenerOptions or boolean) options); - [Custom=CallPrologue] void removeEventListener(DOMString type, EventListener? listener, optional (EventListenerOptions or boolean) options); + [CallWith=ScriptState] constructor(); + void addEventListener(DOMString type, EventListener? listener, optional (AddEventListenerOptions or boolean) options); + void removeEventListener(DOMString type, EventListener? listener, optional (EventListenerOptions or boolean) options); [ImplementedAs=dispatchEventForBindings, RaisesException, RuntimeCallStatsCounter=EventTargetDispatchEvent] boolean dispatchEvent(Event event); }; diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_target_impl.cc b/chromium/third_party/blink/renderer/core/dom/events/event_target_impl.cc index 005b8cd2a46..83a530add58 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/event_target_impl.cc +++ b/chromium/third_party/blink/renderer/core/dom/events/event_target_impl.cc @@ -4,6 +4,8 @@ #include "third_party/blink/renderer/core/dom/events/event_target_impl.h" +#include "third_party/blink/renderer/core/execution_context/execution_context.h" + namespace blink { const AtomicString& EventTargetImpl::InterfaceName() const { @@ -11,15 +13,15 @@ const AtomicString& EventTargetImpl::InterfaceName() const { } ExecutionContext* EventTargetImpl::GetExecutionContext() const { - return ContextLifecycleObserver::GetExecutionContext(); + return ExecutionContextClient::GetExecutionContext(); } void EventTargetImpl::Trace(Visitor* visitor) { EventTargetWithInlineData::Trace(visitor); - ContextLifecycleObserver::Trace(visitor); + ExecutionContextClient::Trace(visitor); } EventTargetImpl::EventTargetImpl(ScriptState* script_state) - : ContextLifecycleObserver(ExecutionContext::From(script_state)) {} + : ExecutionContextClient(ExecutionContext::From(script_state)) {} } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_target_impl.h b/chromium/third_party/blink/renderer/core/dom/events/event_target_impl.h index d817811a70a..df9434937be 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/event_target_impl.h +++ b/chromium/third_party/blink/renderer/core/dom/events/event_target_impl.h @@ -6,7 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_TARGET_IMPL_H_ #include "third_party/blink/renderer/core/dom/events/event_target.h" -#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h" +#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" class ScriptState; @@ -21,7 +21,7 @@ namespace blink { // that are mostly unnecessary for them, resulting in a performance // decrease. class CORE_EXPORT EventTargetImpl final : public EventTargetWithInlineData, - public ContextLifecycleObserver { + public ExecutionContextClient { USING_GARBAGE_COLLECTED_MIXIN(EventTargetImpl); public: diff --git a/chromium/third_party/blink/renderer/core/dom/events/tree_scope_event_context.cc b/chromium/third_party/blink/renderer/core/dom/events/tree_scope_event_context.cc index 28fbb1ae8e2..8d0dd9bf75e 100644 --- a/chromium/third_party/blink/renderer/core/dom/events/tree_scope_event_context.cc +++ b/chromium/third_party/blink/renderer/core/dom/events/tree_scope_event_context.cc @@ -32,6 +32,7 @@ #include "third_party/blink/renderer/core/dom/static_node_list.h" #include "third_party/blink/renderer/core/events/touch_event_context.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -82,7 +83,7 @@ HeapVector<Member<EventTarget>>& TreeScopeEventContext::EnsureEventPath( TouchEventContext& TreeScopeEventContext::EnsureTouchEventContext() { if (!touch_event_context_) - touch_event_context_ = TouchEventContext::Create(); + touch_event_context_ = MakeGarbageCollected<TouchEventContext>(); return *touch_event_context_; } diff --git a/chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc b/chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc index d2571c6ee9a..219f5212afe 100644 --- a/chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc +++ b/chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc @@ -143,7 +143,7 @@ LayoutText* FirstLetterPseudoElement::FirstLetterTextLayoutObject( first_letter_text_layout_object = first_letter_text_layout_object->NextSibling(); } else if (first_letter_text_layout_object - ->IsListMarkerIncludingNGInside()) { + ->IsListMarkerIncludingNGOutsideAndInside()) { // The list item marker may have out-of-flow siblings inside an anonymous // block. Skip them to make sure we leave the anonymous block before // continuing looking for the first letter text. @@ -166,7 +166,7 @@ LayoutText* FirstLetterPseudoElement::FirstLetterTextLayoutObject( first_letter_text_layout_object->NextSibling(); } else if (first_letter_text_layout_object->IsAtomicInlineLevel() || first_letter_text_layout_object->IsLayoutButton() || - first_letter_text_layout_object->IsMenuList()) { + IsMenuList(first_letter_text_layout_object)) { return nullptr; } else if (first_letter_text_layout_object ->IsFlexibleBoxIncludingDeprecatedAndNG() || @@ -232,7 +232,7 @@ void FirstLetterPseudoElement::UpdateTextFragments() { // Make sure the first-letter layoutObject is set to require a layout as it // needs to re-create the line boxes. The remaining text layoutObject // will be marked by the LayoutText::setText. - child_fragment->SetNeedsLayoutAndPrefWidthsRecalc( + child_fragment->SetNeedsLayoutAndIntrinsicWidthsRecalc( layout_invalidation_reason::kTextChanged); break; } diff --git a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_test.cc b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_test.cc index 718f61219e3..e880c282988 100644 --- a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_test.cc +++ b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_test.cc @@ -48,22 +48,22 @@ void FlatTreeTraversalTest::SetupSampleHTML(const char* main_html, const char* shadow_html, unsigned index) { Element* body = GetDocument().body(); - body->SetInnerHTMLFromString(String::FromUTF8(main_html)); + body->setInnerHTML(String::FromUTF8(main_html)); auto* shadow_host = To<Element>(NodeTraversal::ChildAt(*body, index)); ShadowRoot& shadow_root = shadow_host->CreateV0ShadowRootForTesting(); - shadow_root.SetInnerHTMLFromString(String::FromUTF8(shadow_html)); + shadow_root.setInnerHTML(String::FromUTF8(shadow_html)); body->UpdateDistributionForFlatTreeTraversal(); } void FlatTreeTraversalTest::SetupDocumentTree(const char* main_html) { Element* body = GetDocument().body(); - body->SetInnerHTMLFromString(String::FromUTF8(main_html)); + body->setInnerHTML(String::FromUTF8(main_html)); } void FlatTreeTraversalTest::AttachV0ShadowRoot(Element& shadow_host, const char* shadow_inner_html) { ShadowRoot& shadow_root = shadow_host.CreateV0ShadowRootForTesting(); - shadow_root.SetInnerHTMLFromString(String::FromUTF8(shadow_inner_html)); + shadow_root.setInnerHTML(String::FromUTF8(shadow_inner_html)); GetDocument().body()->UpdateDistributionForFlatTreeTraversal(); } @@ -72,7 +72,7 @@ void FlatTreeTraversalTest::AttachOpenShadowRoot( const char* shadow_inner_html) { ShadowRoot& shadow_root = shadow_host.AttachShadowRootInternal(ShadowRootType::kOpen); - shadow_root.SetInnerHTMLFromString(String::FromUTF8(shadow_inner_html)); + shadow_root.setInnerHTML(String::FromUTF8(shadow_inner_html)); GetDocument().body()->UpdateDistributionForFlatTreeTraversal(); } diff --git a/chromium/third_party/blink/renderer/core/dom/global_event_handlers.h b/chromium/third_party/blink/renderer/core/dom/global_event_handlers.h index e18c39445b1..c92b4ed1cd6 100644 --- a/chromium/third_party/blink/renderer/core/dom/global_event_handlers.h +++ b/chromium/third_party/blink/renderer/core/dom/global_event_handlers.h @@ -127,6 +127,14 @@ class GlobalEventHandlers { DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(touchstart, kTouchstart) DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(volumechange, kVolumechange) DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(waiting, kWaiting) + DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(webkitanimationend, + kWebkitAnimationEnd) + DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(webkitanimationiteration, + kWebkitAnimationIteration) + DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(webkitanimationstart, + kWebkitAnimationStart) + DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(webkittransitionend, + kWebkitTransitionEnd) DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(wheel, kWheel) }; diff --git a/chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl b/chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl index d4480cf6d8f..e5ea3133cd1 100644 --- a/chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl +++ b/chromium/third_party/blink/renderer/core/dom/global_event_handlers.idl @@ -82,7 +82,7 @@ attribute EventHandler onplaying; attribute EventHandler onprogress; attribute EventHandler onratechange; - [RuntimeEnabled=DisplayLocking] attribute EventHandler onrendersubtreeactivation; + [RuntimeEnabled=CSSSubtreeVisibilityActivationEvent] attribute EventHandler onrendersubtreeactivation; attribute EventHandler onreset; attribute EventHandler onresize; attribute EventHandler onscroll; @@ -98,6 +98,10 @@ attribute EventHandler ontoggle; attribute EventHandler onvolumechange; attribute EventHandler onwaiting; + attribute EventHandler onwebkitanimationend; + attribute EventHandler onwebkitanimationiteration; + attribute EventHandler onwebkitanimationstart; + attribute EventHandler onwebkittransitionend; attribute EventHandler onwheel; // auxclick diff --git a/chromium/third_party/blink/renderer/core/dom/icon_url.cc b/chromium/third_party/blink/renderer/core/dom/icon_url.cc index 38b41d01827..4b1476afcef 100644 --- a/chromium/third_party/blink/renderer/core/dom/icon_url.cc +++ b/chromium/third_party/blink/renderer/core/dom/icon_url.cc @@ -28,7 +28,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "third_party/blink/public/web/web_icon_url.h" #include "third_party/blink/renderer/core/dom/icon_url.h" #include "third_party/blink/renderer/platform/wtf/assertions.h" @@ -44,7 +43,8 @@ IconURL IconURL::DefaultFavicon(const KURL& document_url) { url.SetPort(document_url.Port()); url.SetPath("/favicon.ico"); - IconURL result(url, Vector<IntSize>(), g_empty_string, kFavicon); + IconURL result(url, {}, g_empty_string, + mojom::blink::FaviconIconType::kFavicon); result.is_default_icon_ = true; return result; } @@ -56,9 +56,4 @@ bool operator==(const IconURL& lhs, const IconURL& rhs) { lhs.mime_type_ == rhs.mime_type_; } -STATIC_ASSERT_ENUM(WebIconURL::kTypeInvalid, kInvalidIcon); -STATIC_ASSERT_ENUM(WebIconURL::kTypeFavicon, kFavicon); -STATIC_ASSERT_ENUM(WebIconURL::kTypeTouch, kTouchIcon); -STATIC_ASSERT_ENUM(WebIconURL::kTypeTouchPrecomposed, kTouchPrecomposedIcon); - } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/icon_url.h b/chromium/third_party/blink/renderer/core/dom/icon_url.h index 04f45144db5..9aa68b47662 100644 --- a/chromium/third_party/blink/renderer/core/dom/icon_url.h +++ b/chromium/third_party/blink/renderer/core/dom/icon_url.h @@ -31,33 +31,29 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ICON_URL_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ICON_URL_H_ -#include "third_party/blink/renderer/platform/geometry/int_size.h" +#include "third_party/blink/public/mojom/favicon/favicon_url.mojom-blink.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" +#include "ui/gfx/geometry/size.h" namespace blink { -enum IconType { - kInvalidIcon = 0, - kFavicon = 1, - kTouchIcon = 1 << 1, - kTouchPrecomposedIcon = 1 << 2, -}; - struct IconURL { DISALLOW_NEW(); - IconType icon_type_; - Vector<IntSize> sizes_; + mojom::blink::FaviconIconType icon_type_; + Vector<gfx::Size> sizes_; String mime_type_; KURL icon_url_; bool is_default_icon_; - IconURL() : icon_type_(kInvalidIcon), is_default_icon_(false) {} + IconURL() + : icon_type_(mojom::blink::FaviconIconType::kInvalid), + is_default_icon_(false) {} IconURL(const KURL& url, - const Vector<IntSize>& sizes, + const Vector<gfx::Size>& sizes, const String& mime_type, - IconType type) + mojom::blink::FaviconIconType type) : icon_type_(type), sizes_(sizes), mime_type_(mime_type), diff --git a/chromium/third_party/blink/renderer/core/dom/idle_deadline_test.cc b/chromium/third_party/blink/renderer/core/dom/idle_deadline_test.cc index 8116102c65a..71dc4d7e458 100644 --- a/chromium/third_party/blink/renderer/core/dom/idle_deadline_test.cc +++ b/chromium/third_party/blink/renderer/core/dom/idle_deadline_test.cc @@ -42,6 +42,9 @@ class MockIdleDeadlineScheduler final : public ThreadScheduler { scoped_refptr<base::SingleThreadTaskRunner> IPCTaskRunner() override { return nullptr; } + scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override { + return nullptr; + } scoped_refptr<base::SingleThreadTaskRunner> DeprecatedDefaultTaskRunner() override { return nullptr; diff --git a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.h b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.h index 97047f10db2..ecbfb41c6dd 100644 --- a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.h +++ b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.h @@ -61,7 +61,7 @@ class LayoutTreeBuilder { LayoutTreeBuilder(NodeType& node, Node::AttachContext& context, const ComputedStyle* style) - : node_(node), context_(context), style_(style) { + : node_(&node), context_(context), style_(style) { DCHECK(!node.GetLayoutObject()); DCHECK(node.GetDocument().InStyleRecalc()); DCHECK(node.InActiveDocument()); @@ -87,7 +87,7 @@ class LayoutTreeBuilder { return next; } - Member<NodeType> node_; + NodeType* node_; Node::AttachContext& context_; const ComputedStyle* style_; }; diff --git a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc index 031c54abae3..c023f6557b3 100644 --- a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc +++ b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc @@ -30,6 +30,7 @@ #include "third_party/blink/renderer/core/dom/pseudo_element.h" #include "third_party/blink/renderer/core/html_names.h" #include "third_party/blink/renderer/core/layout/layout_object.h" +#include "third_party/blink/renderer/core/layout/layout_view.h" namespace blink { @@ -344,7 +345,7 @@ LayoutObject* LayoutTreeBuilderTraversal::NextInTopLayer( // If top_layer_elements[i] is not a LayoutView child, its LayoutObject is // not re-attached and not in the top layer yet, thus we can not use it as a // sibling LayoutObject. - if (layout_object && layout_object->Parent()->IsLayoutView()) + if (layout_object && IsA<LayoutView>(layout_object->Parent())) return layout_object; } return nullptr; diff --git a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h index 300be78ef8e..106020b85a9 100644 --- a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h +++ b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h @@ -59,7 +59,7 @@ class CORE_EXPORT LayoutTreeBuilderTraversal { } private: - Member<const V0InsertionPoint> insertion_point_; + const V0InsertionPoint* insertion_point_; }; static ContainerNode* Parent(const Node&, ParentDetails* = nullptr); diff --git a/chromium/third_party/blink/renderer/core/dom/live_node_list.cc b/chromium/third_party/blink/renderer/core/dom/live_node_list.cc index 291c4d10e5a..13c0cdb2861 100644 --- a/chromium/third_party/blink/renderer/core/dom/live_node_list.cc +++ b/chromium/third_party/blink/renderer/core/dom/live_node_list.cc @@ -22,8 +22,6 @@ #include "third_party/blink/renderer/core/dom/live_node_list.h" -#include "third_party/blink/renderer/core/dom/node_child_removal_tracker.h" - namespace blink { namespace { @@ -39,7 +37,7 @@ class IsMatch { } private: - Member<const LiveNodeList> list_; + const LiveNodeList* list_; }; } // namespace @@ -57,12 +55,7 @@ unsigned LiveNodeList::length() const { } Element* LiveNodeList::item(unsigned offset) const { - Element* element = collection_items_cache_.NodeAt(*this, offset); - if (element && element->GetDocument().InDOMNodeRemovedHandler()) { - if (NodeChildRemovalTracker::IsBeingRemoved(*element)) - GetDocument().CountDetachingNodeAccessInDOMNodeRemovedHandler(); - } - return element; + return collection_items_cache_.NodeAt(*this, offset); } Element* LiveNodeList::TraverseToFirst() const { diff --git a/chromium/third_party/blink/renderer/core/dom/live_node_list.h b/chromium/third_party/blink/renderer/core/dom/live_node_list.h index 37f27fe048d..af5bcea9f72 100644 --- a/chromium/third_party/blink/renderer/core/dom/live_node_list.h +++ b/chromium/third_party/blink/renderer/core/dom/live_node_list.h @@ -79,11 +79,12 @@ class CORE_EXPORT LiveNodeList : public NodeList, public LiveNodeListBase { mutable CollectionItemsCache<LiveNodeList, Element> collection_items_cache_; }; -DEFINE_TYPE_CASTS(LiveNodeList, - LiveNodeListBase, - list, - IsLiveNodeListType(list->GetType()), - IsLiveNodeListType(list.GetType())); +template <> +struct DowncastTraits<LiveNodeList> { + static bool AllowFrom(const LiveNodeListBase& list) { + return IsLiveNodeListType(list.GetType()); + } +}; inline void LiveNodeList::InvalidateCacheForAttribute( const QualifiedName* attr_name) const { diff --git a/chromium/third_party/blink/renderer/core/dom/live_node_list_base.cc b/chromium/third_party/blink/renderer/core/dom/live_node_list_base.cc index 36c48183ddd..d60ec265eaf 100644 --- a/chromium/third_party/blink/renderer/core/dom/live_node_list_base.cc +++ b/chromium/third_party/blink/renderer/core/dom/live_node_list_base.cc @@ -31,9 +31,9 @@ namespace blink { void LiveNodeListBase::InvalidateCacheForAttribute( const QualifiedName* attr_name) const { if (IsLiveNodeListType(GetType())) - ToLiveNodeList(this)->InvalidateCacheForAttribute(attr_name); + To<LiveNodeList>(this)->InvalidateCacheForAttribute(attr_name); else - ToHTMLCollection(this)->InvalidateCacheForAttribute(attr_name); + To<HTMLCollection>(this)->InvalidateCacheForAttribute(attr_name); } ContainerNode& LiveNodeListBase::RootNode() const { diff --git a/chromium/third_party/blink/renderer/core/dom/mutation_observer.cc b/chromium/third_party/blink/renderer/core/dom/mutation_observer.cc index bc2775726de..24a4c117fe8 100644 --- a/chromium/third_party/blink/renderer/core/dom/mutation_observer.cc +++ b/chromium/third_party/blink/renderer/core/dom/mutation_observer.cc @@ -34,8 +34,8 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/v8_mutation_callback.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_mutation_observer_init.h" #include "third_party/blink/renderer/core/dom/document.h" -#include "third_party/blink/renderer/core/dom/mutation_observer_init.h" #include "third_party/blink/renderer/core/dom/mutation_observer_registration.h" #include "third_party/blink/renderer/core/dom/mutation_record.h" #include "third_party/blink/renderer/core/dom/node.h" @@ -50,7 +50,7 @@ namespace blink { class MutationObserver::V8DelegateImpl final : public MutationObserver::Delegate, - public ContextClient { + public ExecutionContextClient { USING_GARBAGE_COLLECTED_MIXIN(V8DelegateImpl); public: @@ -61,10 +61,10 @@ class MutationObserver::V8DelegateImpl final V8DelegateImpl(V8MutationCallback* callback, ExecutionContext* execution_context) - : ContextClient(execution_context), callback_(callback) {} + : ExecutionContextClient(execution_context), callback_(callback) {} ExecutionContext* GetExecutionContext() const override { - return ContextClient::GetExecutionContext(); + return ExecutionContextClient::GetExecutionContext(); } void Deliver(const MutationRecordVector& records, @@ -77,7 +77,7 @@ class MutationObserver::V8DelegateImpl final void Trace(Visitor* visitor) override { visitor->Trace(callback_); MutationObserver::Delegate::Trace(visitor); - ContextClient::Trace(visitor); + ExecutionContextClient::Trace(visitor); } private: @@ -108,7 +108,8 @@ MutationObserver* MutationObserver::Create(ScriptState* script_state, MutationObserver::MutationObserver(ExecutionContext* execution_context, Delegate* delegate) - : ContextLifecycleStateObserver(execution_context), delegate_(delegate) { + : ExecutionContextLifecycleStateObserver(execution_context), + delegate_(delegate) { priority_ = g_observer_priority++; UpdateStateIfNeeded(); } @@ -346,7 +347,7 @@ void MutationObserver::Trace(Visitor* visitor) { visitor->Trace(records_); visitor->Trace(registrations_); ScriptWrappable::Trace(visitor); - ContextLifecycleStateObserver::Trace(visitor); + ExecutionContextLifecycleStateObserver::Trace(visitor); } } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/mutation_observer.h b/chromium/third_party/blink/renderer/core/dom/mutation_observer.h index 2b77b0b7b6c..060b575349a 100644 --- a/chromium/third_party/blink/renderer/core/dom/mutation_observer.h +++ b/chromium/third_party/blink/renderer/core/dom/mutation_observer.h @@ -35,8 +35,8 @@ #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/mutation_observer_options.h" -#include "third_party/blink/renderer/core/execution_context/context_lifecycle_state_observer.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h" #include "third_party/blink/renderer/platform/bindings/name_client.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/heap/handle.h" @@ -65,7 +65,7 @@ using MutationRecordVector = HeapVector<Member<MutationRecord>>; class CORE_EXPORT MutationObserver final : public ScriptWrappable, public ActiveScriptWrappable<MutationObserver>, - public ContextLifecycleStateObserver { + public ExecutionContextLifecycleStateObserver { DEFINE_WRAPPERTYPEINFO(); USING_GARBAGE_COLLECTED_MIXIN(MutationObserver); // Using CancelInspectorAsyncTasks as pre-finalizer to cancel async tasks. @@ -116,6 +116,7 @@ class CORE_EXPORT MutationObserver final bool HasPendingActivity() const override { return !records_.IsEmpty(); } void ContextLifecycleStateChanged(mojom::FrameLifecycleState) final; + void ContextDestroyed() final {} void Trace(Visitor*) override; diff --git a/chromium/third_party/blink/renderer/core/dom/mutation_observer.idl b/chromium/third_party/blink/renderer/core/dom/mutation_observer.idl index 370a5a07868..b0402dc46ff 100644 --- a/chromium/third_party/blink/renderer/core/dom/mutation_observer.idl +++ b/chromium/third_party/blink/renderer/core/dom/mutation_observer.idl @@ -34,12 +34,13 @@ callback MutationCallback = void (sequence<MutationRecord> mutations, MutationObserver observer); [ - ConstructorCallWith=ScriptState, - Constructor(MutationCallback callback), ActiveScriptWrappable, - Exposed=Window + Exposed=Window, + LegacyWindowAlias=WebKitMutationObserver, + LegacyWindowAlias_Measure=PrefixedMutationObserverConstructor ] interface MutationObserver { - [RaisesException] void observe(Node target, optional MutationObserverInit options); + [CallWith=ScriptState] constructor(MutationCallback callback); + [RaisesException] void observe(Node target, optional MutationObserverInit options = {}); void disconnect(); sequence<MutationRecord> takeRecords(); }; diff --git a/chromium/third_party/blink/renderer/core/dom/mutation_observer_interest_group.cc b/chromium/third_party/blink/renderer/core/dom/mutation_observer_interest_group.cc index 42c73cfa883..a9773f16e62 100644 --- a/chromium/third_party/blink/renderer/core/dom/mutation_observer_interest_group.cc +++ b/chromium/third_party/blink/renderer/core/dom/mutation_observer_interest_group.cc @@ -72,10 +72,6 @@ void MutationObserverInterestGroup::EnqueueMutationRecord( MutationRecord* mutation) { MutationRecord* mutation_with_null_old_value = nullptr; - // For investigation of crbug.com/1003733. - // If the crashes stop it means there is a GC related issue. - ThreadState::GCForbiddenScope gc_forbidden(ThreadState::Current()); - for (auto& iter : observers_) { MutationObserver* observer = iter.key.Get(); if (HasOldValue(iter.value)) { diff --git a/chromium/third_party/blink/renderer/core/dom/mutation_observer_test.cc b/chromium/third_party/blink/renderer/core/dom/mutation_observer_test.cc index 6268b17c7a4..9ee4b3d8ea6 100644 --- a/chromium/third_party/blink/renderer/core/dom/mutation_observer_test.cc +++ b/chromium/third_party/blink/renderer/core/dom/mutation_observer_test.cc @@ -5,7 +5,7 @@ #include "third_party/blink/renderer/core/dom/mutation_observer.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/renderer/core/dom/mutation_observer_init.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_mutation_observer_init.h" #include "third_party/blink/renderer/core/dom/mutation_observer_registration.h" #include "third_party/blink/renderer/core/html/html_document.h" #include "third_party/blink/renderer/core/html/html_element.h" @@ -19,7 +19,9 @@ class EmptyMutationCallback : public MutationObserver::Delegate { public: explicit EmptyMutationCallback(Document& document) : document_(document) {} - ExecutionContext* GetExecutionContext() const override { return document_; } + ExecutionContext* GetExecutionContext() const override { + return document_->GetExecutionContext(); + } void Deliver(const MutationRecordVector&, MutationObserver&) override {} @@ -39,7 +41,7 @@ TEST(MutationObserverTest, DisconnectCrash) { auto* root = To<HTMLElement>(document->CreateRawElement(html_names::kHTMLTag)); document->AppendChild(root); - root->SetInnerHTMLFromString("<head><title>\n</title></head><body></body>"); + root->setInnerHTML("<head><title>\n</title></head><body></body>"); Node* head = root->firstChild()->firstChild(); DCHECK(head); Persistent<MutationObserver> observer = MutationObserver::Create( diff --git a/chromium/third_party/blink/renderer/core/dom/mutation_record.h b/chromium/third_party/blink/renderer/core/dom/mutation_record.h index c8e5cce7dac..246e76b098d 100644 --- a/chromium/third_party/blink/renderer/core/dom/mutation_record.h +++ b/chromium/third_party/blink/renderer/core/dom/mutation_record.h @@ -32,6 +32,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_MUTATION_RECORD_H_ #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/dom/static_node_list.h" #include "third_party/blink/renderer/core/probe/async_task_id.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/heap/handle.h" @@ -41,8 +42,7 @@ namespace blink { class Node; class QualifiedName; -template <typename NodeType> -class StaticNodeTypeList; + using StaticNodeList = StaticNodeTypeList<Node>; class CORE_EXPORT MutationRecord : public ScriptWrappable { diff --git a/chromium/third_party/blink/renderer/core/dom/named_node_map.cc b/chromium/third_party/blink/renderer/core/dom/named_node_map.cc index af97e374a74..e1120392bec 100644 --- a/chromium/third_party/blink/renderer/core/dom/named_node_map.cc +++ b/chromium/third_party/blink/renderer/core/dom/named_node_map.cc @@ -28,6 +28,7 @@ #include "third_party/blink/renderer/core/dom/attr.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/element.h" +#include "third_party/blink/renderer/core/html/html_document.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/wtf/vector.h" @@ -105,7 +106,7 @@ void NamedNodeMap::NamedPropertyEnumerator(Vector<String>& names, // 3. Return names. const AttributeCollection attributes = element_->Attributes(); names.ReserveInitialCapacity(attributes.size()); - if (element_->IsHTMLElement() && element_->GetDocument().IsHTMLDocument()) { + if (element_->IsHTMLElement() && IsA<HTMLDocument>(element_->GetDocument())) { for (const Attribute& attribute : attributes) { if ((attribute.Prefix() == attribute.Prefix().LowerASCII()) && (attribute.LocalName() == attribute.LocalName().LowerASCII())) { diff --git a/chromium/third_party/blink/renderer/core/dom/node.cc b/chromium/third_party/blink/renderer/core/dom/node.cc index 1442bac4064..371f39cbed5 100644 --- a/chromium/third_party/blink/renderer/core/dom/node.cc +++ b/chromium/third_party/blink/renderer/core/dom/node.cc @@ -28,8 +28,10 @@ #include <algorithm> +#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/node_or_string_or_trusted_script.h" #include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_script.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_get_root_node_options.h" #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h" #include "third_party/blink/renderer/core/css/css_selector.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver.h" @@ -47,6 +49,7 @@ #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/element_rare_data.h" #include "third_party/blink/renderer/core/dom/element_traversal.h" +#include "third_party/blink/renderer/core/dom/events/add_event_listener_options_resolved.h" #include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h" #include "third_party/blink/renderer/core/dom/events/event_dispatcher.h" @@ -54,7 +57,6 @@ #include "third_party/blink/renderer/core/dom/events/event_path.h" #include "third_party/blink/renderer/core/dom/flat_tree_node_data.h" #include "third_party/blink/renderer/core/dom/flat_tree_traversal.h" -#include "third_party/blink/renderer/core/dom/get_root_node_options.h" #include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h" #include "third_party/blink/renderer/core/dom/mutation_observer_registration.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h" @@ -102,6 +104,7 @@ #include "third_party/blink/renderer/core/input/input_device_capabilities.h" #include "third_party/blink/renderer/core/layout/layout_box.h" #include "third_party/blink/renderer/core/layout/layout_embedded_content.h" +#include "third_party/blink/renderer/core/layout/layout_shift_tracker.h" #include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/mathml_names.h" #include "third_party/blink/renderer/core/page/context_menu_controller.h" @@ -165,32 +168,18 @@ void AppendUnsafe(StringBuilder& builder, const String& off_thread_string) { } // namespace +using ReattachHook = LayoutShiftTracker::ReattachHook; + struct SameSizeAsNode : EventTarget { uint32_t node_flags_; Member<void*> willbe_member_[4]; - void* pointer_; + Member<NodeData> member_; +#if !DCHECK_IS_ON() + static_assert(sizeof(Member<NodeData>) == sizeof(void*), + "Increasing size of Member increases size of Node"); +#endif // !DCHECK_IS_ON() }; -NodeRenderingData::NodeRenderingData( - LayoutObject* layout_object, - scoped_refptr<const ComputedStyle> computed_style) - : layout_object_(layout_object), computed_style_(computed_style) {} - -NodeRenderingData::~NodeRenderingData() { - CHECK(!layout_object_); -} - -void NodeRenderingData::SetComputedStyle( - scoped_refptr<const ComputedStyle> computed_style) { - DCHECK_NE(&SharedEmptyData(), this); - computed_style_ = computed_style; -} - -NodeRenderingData& NodeRenderingData::SharedEmptyData() { - DEFINE_STATIC_LOCAL(NodeRenderingData, shared_empty_data, (nullptr, nullptr)); - return shared_empty_data; -} - static_assert(sizeof(Node) <= sizeof(SameSizeAsNode), "Node should stay small"); #if DUMP_NODE_STATISTICS @@ -341,7 +330,8 @@ Node::Node(TreeScope* tree_scope, ConstructionType type) parent_or_shadow_host_node_(nullptr), tree_scope_(tree_scope), previous_(nullptr), - next_(nullptr) { + next_(nullptr), + data_(&NodeRenderingData::SharedEmptyData()) { DCHECK(tree_scope_ || type == kCreateDocument || type == kCreateShadowRoot); #if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS) TrackForDebugging(); @@ -353,23 +343,18 @@ Node::Node(TreeScope* tree_scope, ConstructionType type) } Node::~Node() { - if (!HasRareData() && !data_.node_layout_data_->IsSharedEmptyData()) - delete data_.node_layout_data_; InstanceCounters::DecrementCounter(InstanceCounters::kNodeCounter); } NodeRareData& Node::CreateRareData() { if (IsElementNode()) { - data_.rare_data_ = - MakeGarbageCollected<ElementRareData>(data_.node_layout_data_); + data_ = MakeGarbageCollected<ElementRareData>(DataAsNodeRenderingData()); } else { - data_.rare_data_ = - MakeGarbageCollected<NodeRareData>(data_.node_layout_data_); + data_ = MakeGarbageCollected<NodeRareData>(DataAsNodeRenderingData()); } - DCHECK(data_.rare_data_); + DCHECK(data_); SetFlag(kHasRareDataFlag); - MarkingVisitor::WriteBarrier(RareData()); return *RareData(); } @@ -389,14 +374,7 @@ ContainerNode* Node::parentNode() const { return IsShadowRoot() ? nullptr : ParentOrShadowHostNode(); } -ContainerNode* Node::ParentNodeWithCounting() const { - if (GetFlag(kInDOMNodeRemovedHandler)) - GetDocument().CountDetachingNodeAccessInDOMNodeRemovedHandler(); - return IsShadowRoot() ? nullptr : ParentOrShadowHostNode(); -} - NodeList* Node::childNodes() { - ThreadState::MainThreadGCForbiddenScope gc_forbidden; auto* this_node = DynamicTo<ContainerNode>(this); if (this_node) return EnsureRareData().EnsureNodeLists().EnsureChildNodeList(*this_node); @@ -404,36 +382,64 @@ NodeList* Node::childNodes() { } Node* Node::PseudoAwarePreviousSibling() const { - if (parentElement() && !previousSibling()) { - Element* parent = parentElement(); - if (IsAfterPseudoElement() && parent->lastChild()) - return parent->lastChild(); - if (!IsBeforePseudoElement()) - return parent->GetPseudoElement(kPseudoIdBefore); + Element* parent = parentElement(); + if (!parent || previousSibling()) + return previousSibling(); + switch (GetPseudoId()) { + case kPseudoIdAfter: + if (Node* previous = parent->lastChild()) + return previous; + FALLTHROUGH; + case kPseudoIdNone: + if (Node* previous = parent->GetPseudoElement(kPseudoIdBefore)) + return previous; + FALLTHROUGH; + case kPseudoIdBefore: + if (Node* previous = parent->GetPseudoElement(kPseudoIdMarker)) + return previous; + FALLTHROUGH; + case kPseudoIdMarker: + break; + default: + NOTREACHED(); } - return previousSibling(); + return nullptr; } Node* Node::PseudoAwareNextSibling() const { - if (parentElement() && !nextSibling()) { - Element* parent = parentElement(); - if (IsBeforePseudoElement() && parent->HasChildren()) - return parent->firstChild(); - if (!IsAfterPseudoElement()) - return parent->GetPseudoElement(kPseudoIdAfter); + Element* parent = parentElement(); + if (!parent || nextSibling()) + return nextSibling(); + switch (GetPseudoId()) { + case kPseudoIdMarker: + if (Node* next = parent->GetPseudoElement(kPseudoIdBefore)) + return next; + FALLTHROUGH; + case kPseudoIdBefore: + if (parent->HasChildren()) + return parent->firstChild(); + FALLTHROUGH; + case kPseudoIdNone: + if (Node* next = parent->GetPseudoElement(kPseudoIdAfter)) + return next; + FALLTHROUGH; + case kPseudoIdAfter: + break; + default: + NOTREACHED(); } - return nextSibling(); + return nullptr; } Node* Node::PseudoAwareFirstChild() const { if (const auto* current_element = DynamicTo<Element>(this)) { - Node* first = current_element->GetPseudoElement(kPseudoIdBefore); - if (first) + if (Node* first = current_element->GetPseudoElement(kPseudoIdMarker)) + return first; + if (Node* first = current_element->GetPseudoElement(kPseudoIdBefore)) + return first; + if (Node* first = current_element->firstChild()) return first; - first = current_element->firstChild(); - if (!first) - first = current_element->GetPseudoElement(kPseudoIdAfter); - return first; + return current_element->GetPseudoElement(kPseudoIdAfter); } return firstChild(); @@ -441,13 +447,13 @@ Node* Node::PseudoAwareFirstChild() const { Node* Node::PseudoAwareLastChild() const { if (const auto* current_element = DynamicTo<Element>(this)) { - Node* last = current_element->GetPseudoElement(kPseudoIdAfter); - if (last) + if (Node* last = current_element->GetPseudoElement(kPseudoIdAfter)) + return last; + if (Node* last = current_element->lastChild()) + return last; + if (Node* last = current_element->GetPseudoElement(kPseudoIdBefore)) return last; - last = current_element->lastChild(); - if (!last) - last = current_element->GetPseudoElement(kPseudoIdBefore); - return last; + return current_element->GetPseudoElement(kPseudoIdMarker); } return lastChild(); @@ -536,9 +542,8 @@ void Node::NativeApplyScroll(ScrollState& scroll_state) { if (delta.IsZero()) return; - // TODO(esprehn): This should use - // updateStyleAndLayoutForNode. - GetDocument().UpdateStyleAndLayout(); + // TODO: This should use updateStyleAndLayoutForNode. + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kScroll); LayoutBox* box_to_scroll = ToLayoutBox(GetLayoutObject()); @@ -556,7 +561,7 @@ void Node::NativeApplyScroll(ScrollState& scroll_state) { // behavior in CC. bool also_scroll_visual_viewport = GetDocument().GetFrame() && GetDocument().GetFrame()->IsMainFrame() && - box_to_scroll->IsLayoutView(); + IsA<LayoutView>(box_to_scroll); DCHECK(!also_scroll_visual_viewport || !box_to_scroll->IsGlobalRootScroller()); @@ -566,16 +571,16 @@ void Node::NativeApplyScroll(ScrollState& scroll_state) { return; } - ScrollResult result = scrollable_area->UserScroll( - ScrollGranularity(static_cast<int>(scroll_state.deltaGranularity())), - delta, ScrollableArea::ScrollCallback()); + ScrollResult result = + scrollable_area->UserScroll(scroll_state.delta_granularity(), delta, + ScrollableArea::ScrollCallback()); // Also try scrolling the visual viewport if we're at the end of the scroll // chain. if (!result.DidScroll() && also_scroll_visual_viewport) { result = GetDocument().GetPage()->GetVisualViewport().UserScroll( - ScrollGranularity(static_cast<int>(scroll_state.deltaGranularity())), - delta, ScrollableArea::ScrollCallback()); + scroll_state.delta_granularity(), delta, + ScrollableArea::ScrollCallback()); } if (!result.DidScroll()) @@ -697,10 +702,6 @@ void Node::DidEndCustomizedScrollPhase() { Node* Node::insertBefore(Node* new_child, Node* ref_child, ExceptionState& exception_state) { - new_child = TrustedTypesCheckForScriptNode(new_child, exception_state); - if (!new_child) - return nullptr; - auto* this_node = DynamicTo<ContainerNode>(this); if (this_node) return this_node->InsertBefore(new_child, ref_child, exception_state); @@ -718,10 +719,6 @@ Node* Node::insertBefore(Node* new_child, Node* ref_child) { Node* Node::replaceChild(Node* new_child, Node* old_child, ExceptionState& exception_state) { - new_child = TrustedTypesCheckForScriptNode(new_child, exception_state); - if (!new_child) - return nullptr; - auto* this_node = DynamicTo<ContainerNode>(this); if (this_node) return this_node->ReplaceChild(new_child, old_child, exception_state); @@ -752,10 +749,6 @@ Node* Node::removeChild(Node* old_child) { } Node* Node::appendChild(Node* new_child, ExceptionState& exception_state) { - new_child = TrustedTypesCheckForScriptNode(new_child, exception_state); - if (!new_child) - return nullptr; - auto* this_node = DynamicTo<ContainerNode>(this); if (this_node) return this_node->AppendChild(new_child, exception_state); @@ -833,8 +826,8 @@ static Node* NodeOrStringToNode( ? node_or_string.GetAsString() : node_or_string.GetAsNode()->textContent(); - string_value = - GetStringFromTrustedScript(string_value, &document, exception_state); + string_value = TrustedTypesCheckForScript( + string_value, document.GetExecutionContext(), exception_state); if (exception_state.HadException()) return nullptr; return Text::Create(document, string_value); @@ -1019,8 +1012,8 @@ LayoutBox* Node::GetLayoutBox() const { void Node::SetLayoutObject(LayoutObject* layout_object) { NodeRenderingData* node_layout_data = - HasRareData() ? data_.rare_data_->GetNodeRenderingData() - : data_.node_layout_data_; + HasRareData() ? DataAsNodeRareData()->GetNodeRenderingData() + : DataAsNodeRenderingData(); // Already pointing to a non empty NodeRenderingData so just set the pointer // to the new LayoutObject. @@ -1035,11 +1028,13 @@ void Node::SetLayoutObject(LayoutObject* layout_object) { // Swap the NodeRenderingData to point to a new NodeRenderingData instead of // the static SharedEmptyData instance. DCHECK(!node_layout_data->GetComputedStyle()); - node_layout_data = new NodeRenderingData(layout_object, nullptr); - if (HasRareData()) - data_.rare_data_->SetNodeRenderingData(node_layout_data); - else - data_.node_layout_data_ = node_layout_data; + node_layout_data = + MakeGarbageCollected<NodeRenderingData>(layout_object, nullptr); + if (HasRareData()) { + DataAsNodeRareData()->SetNodeRenderingData(node_layout_data); + } else { + data_ = node_layout_data; + } } void Node::SetComputedStyle(scoped_refptr<const ComputedStyle> computed_style) { @@ -1047,8 +1042,8 @@ void Node::SetComputedStyle(scoped_refptr<const ComputedStyle> computed_style) { DCHECK(IsElementNode()); NodeRenderingData* node_layout_data = - HasRareData() ? data_.rare_data_->GetNodeRenderingData() - : data_.node_layout_data_; + HasRareData() ? DataAsNodeRareData()->GetNodeRenderingData() + : DataAsNodeRenderingData(); // Already pointing to a non empty NodeRenderingData so just set the pointer // to the new LayoutObject. @@ -1068,11 +1063,13 @@ void Node::SetComputedStyle(scoped_refptr<const ComputedStyle> computed_style) { // Swap the NodeRenderingData to point to a new NodeRenderingData instead of // the static SharedEmptyData instance. DCHECK(!node_layout_data->GetLayoutObject()); - node_layout_data = new NodeRenderingData(nullptr, computed_style); - if (HasRareData()) - data_.rare_data_->SetNodeRenderingData(node_layout_data); - else - data_.node_layout_data_ = node_layout_data; + node_layout_data = + MakeGarbageCollected<NodeRenderingData>(nullptr, computed_style); + if (HasRareData()) { + DataAsNodeRareData()->SetNodeRenderingData(node_layout_data); + } else { + data_ = node_layout_data; + } } LayoutBoxModelObject* Node::GetLayoutBoxModelObject() const { @@ -1229,6 +1226,35 @@ void Node::MarkAncestorsWithChildNeedsDistributionRecalc() { GetDocument().ScheduleLayoutTreeUpdateIfNeeded(); } +void Node::MarkSubtreeNeedsStyleRecalcForFontUpdates() { + if (GetStyleChangeType() == kSubtreeStyleChange) + return; + + if (IsElementNode()) { + const ComputedStyle* style = GetComputedStyle(); + if (!style) + return; + + // We require font-specific metrics to resolve length units 'ex' and 'ch', + // and to compute the adjusted font size when 'font-size-adjust' is set. All + // other style computations are unaffected by font loading. + if (!NeedsStyleRecalc()) { + if (style->DependsOnFontMetrics() || + To<Element>(this)->PseudoElementStylesDependOnFontMetrics()) { + SetNeedsStyleRecalc( + kLocalStyleChange, + StyleChangeReasonForTracing::Create(style_change_reason::kFonts)); + } + } + + if (Node* shadow_root = GetShadowRoot()) + shadow_root->MarkSubtreeNeedsStyleRecalcForFontUpdates(); + } + + for (Node* child = firstChild(); child; child = child->nextSibling()) + child->MarkSubtreeNeedsStyleRecalcForFontUpdates(); +} + #if DCHECK_IS_ON() namespace { class AllowDirtyShadowV0TraversalScope { @@ -1245,7 +1271,7 @@ class AllowDirtyShadowV0TraversalScope { } private: - Member<Document> document_; + Document* document_; bool old_value_; }; } // namespace @@ -1292,7 +1318,7 @@ void Node::MarkAncestorsWithChildNeedsStyleRecalc() { break; // If we reach a locked ancestor, we should abort since the ancestor marking // will be done when the lock is committed. - if (RuntimeEnabledFeatures::DisplayLockingEnabled(GetExecutionContext())) { + if (RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled()) { auto* ancestor_element = DynamicTo<Element>(ancestor); if (ancestor_element && ancestor_element->StyleRecalcBlockedByDisplayLock( DisplayLockLifecycleTarget::kChildren)) { @@ -1328,7 +1354,7 @@ void Node::MarkAncestorsWithChildNeedsStyleRecalc() { // roots. These would be updated when we commit the lock. If we have locked // display locks somewhere in the document, we iterate up the ancestor chain // to check if we're in one such subtree. - if (RuntimeEnabledFeatures::DisplayLockingEnabled(GetExecutionContext()) && + if (RuntimeEnabledFeatures::CSSSubtreeVisibilityEnabled() && GetDocument().LockedDisplayLockCount() > 0) { for (auto* ancestor_copy = ancestor; ancestor_copy; ancestor_copy = ancestor_copy->GetStyleRecalcParent()) { @@ -1359,6 +1385,7 @@ Element* Node::FlatTreeParentForChildDirty() const { const_cast<V0InsertionPoint*>(ResolveReprojection(this))) { return insertion_point; } + return nullptr; } } return ParentOrShadowHostElement(); @@ -1416,7 +1443,8 @@ void Node::SetNeedsStyleRecalc(StyleChangeType change_type, TRACE_EVENT_INSTANT1( TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking"), "StyleRecalcInvalidationTracking", TRACE_EVENT_SCOPE_THREAD, "data", - inspector_style_recalc_invalidation_tracking_event::Data(this, reason)); + inspector_style_recalc_invalidation_tracking_event::Data( + this, change_type, reason)); StyleChangeType existing_change_type = GetStyleChangeType(); if (change_type > existing_change_type) @@ -1528,6 +1556,8 @@ void Node::ClearFlatTreeNodeDataIfHostChanged(const ContainerNode& parent) { } bool Node::IsDescendantOf(const Node* other) const { + DCHECK(this); // Necessary for clusterfuzz tooling to get a useful backtrace + // Return true if other is an ancestor of this, otherwise false if (!other || isConnected() != other->isConnected()) return false; @@ -1631,6 +1661,7 @@ Node* Node::CommonAncestor(const Node& other, void Node::ReattachLayoutTree(AttachContext& context) { context.performing_reattach = true; + ReattachHook::Scope reattach_scope(*this); DetachLayoutTree(context.performing_reattach); AttachLayoutTree(context); @@ -1646,12 +1677,15 @@ void Node::AttachLayoutTree(AttachContext& context) { LayoutObject* layout_object = GetLayoutObject(); DCHECK(!layout_object || (layout_object->Style() && - (layout_object->Parent() || layout_object->IsLayoutView()))); + (layout_object->Parent() || IsA<LayoutView>(layout_object)))); ClearNeedsReattachLayoutTree(); if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache()) cache->UpdateCacheAfterNodeIsAttached(this); + + if (context.performing_reattach) + ReattachHook::NotifyAttach(*this); } void Node::DetachLayoutTree(bool performing_reattach) { @@ -1659,6 +1693,10 @@ void Node::DetachLayoutTree(bool performing_reattach) { DCHECK(!performing_reattach || GetDocument().GetStyleEngine().InRebuildLayoutTree()); DocumentLifecycle::DetachScope will_detach(GetDocument().Lifecycle()); + + if (performing_reattach) + ReattachHook::NotifyDetach(*this); + if (GetLayoutObject()) GetLayoutObject()->DestroyAndCleanupAnonymousWrappers(); SetLayoutObject(nullptr); @@ -1844,6 +1882,16 @@ ContainerNode* Node::ParentOrShadowHostOrTemplateHostNode() const { return ParentOrShadowHostNode(); } +TreeScope& Node::OriginatingTreeScope() const { + if (const SVGElement* svg_element = DynamicTo<SVGElement>(this)) { + if (const SVGElement* corr_element = svg_element->CorrespondingElement()) { + DCHECK(!corr_element->CorrespondingElement()); + return corr_element->GetTreeScope(); + } + } + return GetTreeScope(); +} + Document* Node::ownerDocument() const { Document* doc = &GetDocument(); return doc == this ? nullptr : doc; @@ -2418,6 +2466,10 @@ static void AppendMarkedTree(const String& base_indent, indent.Append('\t'); if (const auto* element = DynamicTo<Element>(node)) { + if (Element* pseudo = element->GetPseudoElement(kPseudoIdMarker)) { + AppendMarkedTree(indent.ToString(), pseudo, marked_node1, marked_label1, + marked_node2, marked_label2, builder); + } if (Element* pseudo = element->GetPseudoElement(kPseudoIdBefore)) AppendMarkedTree(indent.ToString(), pseudo, marked_node1, marked_label1, marked_node2, marked_label2, builder); @@ -2560,7 +2612,9 @@ const AtomicString& Node::InterfaceName() const { } ExecutionContext* Node::GetExecutionContext() const { - return GetDocument().ContextDocument(); + if (auto* document = GetDocument().ContextDocument()) + return document->domWindow(); + return nullptr; } void Node::WillMoveToNewDocument(Document& old_document, @@ -2823,7 +2877,7 @@ void Node::HandleLocalEvents(Event& event) { if (!HasEventTargetData()) return; - if (IsDisabledFormControl(this) && event.IsMouseEvent() && + if (IsDisabledFormControl(this) && IsA<MouseEvent>(event) && !RuntimeEnabledFeatures::SendMouseEventsDisabledFormControlsEnabled()) { if (HasEventListeners(event.type())) { UseCounter::Count(GetDocument(), @@ -2884,10 +2938,10 @@ DispatchEventResult Node::DispatchDOMActivateEvent(int detail, return EventTarget::GetDispatchEventResult(event); } -void Node::DispatchSimulatedClick(Event* underlying_event, +void Node::DispatchSimulatedClick(const Event* underlying_event, SimulatedClickMouseEventOptions event_options, SimulatedClickCreationScope scope) { - if (auto* element = IsElementNode() ? ToElement(this) : parentElement()) { + if (auto* element = IsElementNode() ? To<Element>(this) : parentElement()) { element->ActivateDisplayLockIfNeeded( DisplayLockActivationReason::kSimulatedClick); } @@ -2895,13 +2949,6 @@ void Node::DispatchSimulatedClick(Event* underlying_event, event_options, scope); } -void Node::DispatchInputEvent() { - // Legacy 'input' event for forms set value and checked. - Event* event = Event::CreateBubble(event_type_names::kInput); - event->SetComposed(true); - DispatchScopedEvent(*event); -} - void Node::DefaultEventHandler(Event& event) { if (event.target() != this) return; @@ -2909,22 +2956,22 @@ void Node::DefaultEventHandler(Event& event) { if (event_type == event_type_names::kKeydown || event_type == event_type_names::kKeypress || event_type == event_type_names::kKeyup) { - if (event.IsKeyboardEvent()) { + if (auto* keyboard_event = DynamicTo<KeyboardEvent>(&event)) { if (LocalFrame* frame = GetDocument().GetFrame()) { - frame->GetEventHandler().DefaultKeyboardEventHandler( - ToKeyboardEvent(&event)); + frame->GetEventHandler().DefaultKeyboardEventHandler(keyboard_event); } } } else if (event_type == event_type_names::kClick) { - int detail = event.IsUIEvent() ? ToUIEvent(event).detail() : 0; + auto* ui_event = DynamicTo<UIEvent>(event); + int detail = ui_event ? ui_event->detail() : 0; if (DispatchDOMActivateEvent(detail, event) != DispatchEventResult::kNotCanceled) event.SetDefaultHandled(); } else if (event_type == event_type_names::kContextmenu && - event.IsMouseEvent()) { + IsA<MouseEvent>(event)) { if (Page* page = GetDocument().GetPage()) { page->GetContextMenuController().HandleContextMenuEvent( - ToMouseEvent(&event)); + To<MouseEvent>(&event)); } } else if (event_type == event_type_names::kTextInput) { if (event.HasInterface(event_interface_names::kTextEvent)) { @@ -2935,8 +2982,8 @@ void Node::DefaultEventHandler(Event& event) { } } else if (RuntimeEnabledFeatures::MiddleClickAutoscrollEnabled() && event_type == event_type_names::kMousedown && - event.IsMouseEvent()) { - auto& mouse_event = ToMouseEvent(event); + IsA<MouseEvent>(event)) { + auto& mouse_event = To<MouseEvent>(event); if (mouse_event.button() == static_cast<int16_t>(WebPointerProperties::Button::kMiddle)) { if (EnclosingLinkEventParentOrSelf()) @@ -2947,7 +2994,7 @@ void Node::DefaultEventHandler(Event& event) { // FIXME: We should avoid synchronous layout if possible. We can // remove this synchronous layout if we avoid synchronous layout in // LayoutTextControlSingleLine::scrollHeight - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kInput); LayoutObject* layout_object = GetLayoutObject(); while ( layout_object && @@ -3082,8 +3129,8 @@ HTMLSlotElement* Node::assignedSlotForBinding() { return nullptr; } -void Node::SetFocused(bool flag, WebFocusType focus_type) { - if (focus_type == kWebFocusTypeMouse) +void Node::SetFocused(bool flag, mojom::blink::FocusType focus_type) { + if (focus_type == mojom::blink::FocusType::kMouse) GetDocument().SetHadKeyboardEvent(false); GetDocument().UserActionElements().SetFocused(this, flag); } @@ -3139,7 +3186,8 @@ void Node::SetCustomElementState(CustomElementState new_state) { break; case CustomElementState::kCustom: - DCHECK_EQ(CustomElementState::kUndefined, old_state); + DCHECK(old_state == CustomElementState::kUndefined || + old_state == CustomElementState::kFailed); break; case CustomElementState::kFailed: @@ -3235,6 +3283,12 @@ bool Node::IsEffectiveRootScroller() const { : false; } +LayoutBox* Node::AutoscrollBox() { + return nullptr; +} + +void Node::StopAutoscroll() {} + WebPluginContainerImpl* Node::GetWebPluginContainer() const { if (!IsA<HTMLObjectElement>(this) && !IsA<HTMLEmbedElement>(this)) { return nullptr; @@ -3273,6 +3327,14 @@ void Node::FlatTreeParentChanged() { DCHECK(GetDocument().MayContainV0Shadow()); return; } + if (const ComputedStyle* style = GetComputedStyle()) { + // We are moving a node with ensured computed style into the flat tree. + // Clear ensured styles so that we can use IsEnsuredOutsideFlatTree() to + // determine that we are outside the flat tree before updating the style + // recalc root in MarkAncestorsWithChildNeedsStyleRecalc(). + if (style->IsEnsuredOutsideFlatTree()) + DetachLayoutTree(); + } // The node changed the flat tree position by being slotted to a new slot or // slotted for the first time. We need to recalc style since the inheritance // parent may have changed. @@ -3300,29 +3362,11 @@ void Node::RemovedFromFlatTree() { GetDocument().GetStyleEngine().RemovedFromFlatTree(*this); } -Node* Node::TrustedTypesCheckForScriptNode( - Node* child, - ExceptionState& exception_state) const { - DCHECK(child); - bool needs_check = IsA<HTMLScriptElement>(this) && child->IsTextNode() && - GetDocument().IsTrustedTypesEnabledForDoc(); - if (!needs_check) - return child; - - child = TrustedTypesCheckForHTMLScriptElement(child, &GetDocument(), - exception_state); - DCHECK_EQ(!child, exception_state.HadException()); - return child; -} - void Node::Trace(Visitor* visitor) { visitor->Trace(parent_or_shadow_host_node_); visitor->Trace(previous_); visitor->Trace(next_); - // rareData() and data_.node_layout_data_ share their storage. We have to - // trace only one of them. - if (HasRareData()) - visitor->Trace(RareData()); + visitor->Trace(data_); visitor->Trace(tree_scope_); EventTarget::Trace(visitor); } diff --git a/chromium/third_party/blink/renderer/core/dom/node.h b/chromium/third_party/blink/renderer/core/dom/node.h index e2a2045833d..767e551efc4 100644 --- a/chromium/third_party/blink/renderer/core/dom/node.h +++ b/chromium/third_party/blink/renderer/core/dom/node.h @@ -27,7 +27,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NODE_H_ #include "base/macros.h" -#include "third_party/blink/public/platform/web_focus_type.h" +#include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/events/event_target.h" #include "third_party/blink/renderer/core/dom/events/simulated_click_options.h" @@ -80,12 +80,14 @@ class V8ScrollStateCallback; class WebPluginContainerImpl; struct PhysicalRect; -const int kNodeStyleChangeShift = 19; -const int kNodeCustomElementShift = 21; +const int kDOMNodeTypeShift = 2; +const int kElementNamespaceTypeShift = 4; +const int kNodeStyleChangeShift = 17; +const int kNodeCustomElementShift = 19; // Values for kChildNeedsStyleRecalcFlag, controlling whether a node gets its // style recalculated. -enum StyleChangeType { +enum StyleChangeType : uint32_t { // This node does not need style recalculation. kNoStyleChange = 0, // This node needs style recalculation. @@ -94,14 +96,12 @@ enum StyleChangeType { kSubtreeStyleChange = 2 << kNodeStyleChangeShift, }; -enum class CustomElementState { +enum class CustomElementState : uint32_t { // https://dom.spec.whatwg.org/#concept-element-custom-element-state kUncustomized = 0, kCustom = 1 << kNodeCustomElementShift, kUndefined = 2 << kNodeCustomElementShift, kFailed = 3 << kNodeCustomElementShift, - - kNotDefinedFlag = 2 << kNodeCustomElementShift, }; enum class SlotChangeType { @@ -260,7 +260,7 @@ class CORE_EXPORT Node : public EventTarget { const AtomicString& lookupNamespaceURI(const String& prefix) const; String textContent(bool convert_brs_to_newlines = false) const; - void setTextContent(const String&); + virtual void setTextContent(const String&); void textContent(StringOrTrustedScript& result); virtual void setTextContent(const StringOrTrustedScript&, ExceptionState&); @@ -269,13 +269,28 @@ class CORE_EXPORT Node : public EventTarget { void SetComputedStyle(scoped_refptr<const ComputedStyle> computed_style); // Other methods (not part of DOM) + ALWAYS_INLINE bool IsTextNode() const { + return GetDOMNodeType() == DOMNodeType::kText; + } + ALWAYS_INLINE bool IsContainerNode() const { + return GetFlag(kIsContainerFlag); + } + ALWAYS_INLINE bool IsElementNode() const { + return GetDOMNodeType() == DOMNodeType::kElement; + } + ALWAYS_INLINE bool IsDocumentFragment() const { + return GetDOMNodeType() == DOMNodeType::kDocumentFragment; + } - bool IsElementNode() const { return GetFlag(kIsElementFlag); } - bool IsContainerNode() const { return GetFlag(kIsContainerFlag); } - bool IsTextNode() const { return GetFlag(kIsTextFlag); } - bool IsHTMLElement() const { return GetFlag(kIsHTMLFlag); } - bool IsMathMLElement() const { return GetFlag(kIsMathMLFlag); } - bool IsSVGElement() const { return GetFlag(kIsSVGFlag); } + ALWAYS_INLINE bool IsHTMLElement() const { + return GetElementNamespaceType() == ElementNamespaceType::kHTML; + } + ALWAYS_INLINE bool IsMathMLElement() const { + return GetElementNamespaceType() == ElementNamespaceType::kMathML; + } + ALWAYS_INLINE bool IsSVGElement() const { + return GetElementNamespaceType() == ElementNamespaceType::kSVG; + } DISABLE_CFI_PERF bool IsPseudoElement() const { return GetPseudoId() != kPseudoIdNone; @@ -335,7 +350,6 @@ class CORE_EXPORT Node : public EventTarget { bool IsDocumentNode() const; bool IsTreeScope() const; - bool IsDocumentFragment() const { return GetFlag(kIsDocumentFragmentFlag); } bool IsShadowRoot() const { return IsDocumentFragment() && IsTreeScope(); } bool IsV0InsertionPoint() const { return GetFlag(kIsV0InsertionPointFlag); } @@ -463,6 +477,10 @@ class CORE_EXPORT Node : public EventTarget { // Propagates a dirty bit breadcrumb for this element up the ancestor chain. void MarkAncestorsWithChildNeedsStyleRecalc(); + // Traverses subtree (include pseudo elements and shadow trees) and + // invalidates nodes whose styles depend on font metrics (e.g., 'ex' unit). + void MarkSubtreeNeedsStyleRecalcForFontUpdates(); + // Nodes which are not connected are style clean. Mark them for style recalc // when inserting them into a document. This method was added as a light- // weight alternative to SetNeedsStyleRecalc because using that method caused @@ -574,7 +592,7 @@ class CORE_EXPORT Node : public EventTarget { SetFlag(flag, kHasEventTargetDataFlag); } - virtual void SetFocused(bool flag, WebFocusType); + virtual void SetFocused(bool flag, mojom::blink::FocusType); void SetHasFocusWithin(bool flag); virtual void SetDragged(bool flag); @@ -617,6 +635,11 @@ class CORE_EXPORT Node : public EventTarget { return *tree_scope_; } + // Returns the tree scope where this element originated. + // Use this when resolving element references for (CSS url(...)s and #id). + // This differs from GetTreeScope for shadow clones inside <svg:use/>. + TreeScope& OriginatingTreeScope() const; + bool InActiveDocument() const; // Returns true if this node is connected to a document, false otherwise. @@ -666,8 +689,8 @@ class CORE_EXPORT Node : public EventTarget { // have one as well. LayoutObject* GetLayoutObject() const { return HasRareData() - ? data_.rare_data_->GetNodeRenderingData()->GetLayoutObject() - : data_.node_layout_data_->GetLayoutObject(); + ? DataAsNodeRareData()->GetNodeRenderingData()->GetLayoutObject() + : DataAsNodeRenderingData()->GetLayoutObject(); } void SetLayoutObject(LayoutObject*); // Use these two methods with caution. @@ -744,16 +767,20 @@ class CORE_EXPORT Node : public EventTarget { // // Blink notifies this callback regardless if the subtree of the node is a // document tree or a floating subtree. Implementation can determine the type - // of subtree by seeing insertionPoint->isConnected(). For a performance + // of subtree by seeing insertion_point->isConnected(). For a performance // reason, notifications are delivered only to ContainerNode subclasses if the - // insertionPoint is out of document. + // insertion_point is out of document. // - // There are another callback named didNotifySubtreeInsertionsToDocument(), + // There are another callback named DidNotifySubtreeInsertionsToDocument(), // which is called after all the descendant is notified, if this node was // inserted into the document tree. Only a few subclasses actually need // this. To utilize this, the node should return - // InsertionShouldCallDidNotifySubtreeInsertions from insertedInto(). + // kInsertionShouldCallDidNotifySubtreeInsertions from InsertedInto(). // + // InsertedInto() implementations must not modify the DOM tree, and must not + // dispatch synchronous events. On the other hand, + // DidNotifySubtreeInsertionsToDocument() may modify the DOM tree, and may + // dispatch synchronous events. enum InsertionNotificationRequest { kInsertionDone, kInsertionShouldCallDidNotifySubtreeInsertions @@ -765,10 +792,12 @@ class CORE_EXPORT Node : public EventTarget { // Notifies the node that it is no longer part of the tree. // - // This is a dual of insertedInto(), and is similar to the + // This is a dual of InsertedInto(), and is similar to the // DOMNodeRemovedFromDocument DOM event, but does not require the overhead of // event dispatching, and is called _after_ the node is removed from the tree. // + // RemovedFrom() implementations must not modify the DOM tree, and must not + // dispatch synchronous events. virtual void RemovedFrom(ContainerNode& insertion_point); // FIXME(dominicc): This method is not debug-only--it is used by @@ -826,10 +855,6 @@ class CORE_EXPORT Node : public EventTarget { } virtual void PostDispatchEventHandler(Event&, EventDispatchHandlingState*) {} - // TODO(crbug.com/1013385): Remove DidPreventDefault. It is here as a - // temporary fix for form double-submit. - virtual void DidPreventDefault(const Event&) {} - void DispatchScopedEvent(Event&); virtual void HandleLocalEvents(Event&); @@ -838,13 +863,11 @@ class CORE_EXPORT Node : public EventTarget { DispatchEventResult DispatchDOMActivateEvent(int detail, Event& underlying_event); - void DispatchSimulatedClick(Event* underlying_event, + void DispatchSimulatedClick(const Event* underlying_event, SimulatedClickMouseEventOptions = kSendNoEvents, SimulatedClickCreationScope = SimulatedClickCreationScope::kFromUserAgent); - void DispatchInputEvent(); - // Perform the default action for an event. virtual void DefaultEventHandler(Event&); void UpdateHadKeyboardEvent(const Event&); @@ -895,100 +918,128 @@ class CORE_EXPORT Node : public EventTarget { return GetFlag(kHasDuplicateAttributes); } - void SetInDOMNodeRemovedHandler(bool flag) { - SetFlag(flag, kInDOMNodeRemovedHandler); - } - bool InDOMNodeRemovedHandler() const { - return GetFlag(kInDOMNodeRemovedHandler); - } - bool IsEffectiveRootScroller() const; + virtual LayoutBox* AutoscrollBox(); + virtual void StopAutoscroll(); + // If the node is a plugin, then this returns its WebPluginContainer. WebPluginContainerImpl* GetWebPluginContainer() const; void Trace(Visitor*) override; private: - enum NodeFlags { + enum NodeFlags : uint32_t { kHasRareDataFlag = 1, // Node type flags. These never change once created. - kIsTextFlag = 1 << 1, - kIsContainerFlag = 1 << 2, - kIsElementFlag = 1 << 3, - kIsHTMLFlag = 1 << 4, - kIsMathMLFlag = 1 << 5, - kIsSVGFlag = 1 << 6, - kIsDocumentFragmentFlag = 1 << 7, - kIsV0InsertionPointFlag = 1 << 8, + kIsContainerFlag = 1 << 1, + kDOMNodeTypeMask = 0x3 << kDOMNodeTypeShift, + kElementNamespaceTypeMask = 0x3 << kElementNamespaceTypeShift, + kIsV0InsertionPointFlag = 1 << 6, // Changes based on if the element should be treated like a link, // ex. When setting the href attribute on an <a>. - kIsLinkFlag = 1 << 9, + kIsLinkFlag = 1 << 7, // Changes based on :hover, :active and :focus state. - kIsUserActionElementFlag = 1 << 10, + kIsUserActionElementFlag = 1 << 8, // Tree state flags. These change when the element is added/removed // from a DOM tree. - kIsConnectedFlag = 1 << 11, - kIsInShadowTreeFlag = 1 << 12, + kIsConnectedFlag = 1 << 9, + kIsInShadowTreeFlag = 1 << 10, // Set by the parser when the children are done parsing. - kIsFinishedParsingChildrenFlag = 1 << 13, + kIsFinishedParsingChildrenFlag = 1 << 11, // Flags related to recalcStyle. - kHasCustomStyleCallbacksFlag = 1 << 14, - kChildNeedsStyleInvalidationFlag = 1 << 15, - kNeedsStyleInvalidationFlag = 1 << 16, - kChildNeedsDistributionRecalcFlag = 1 << 17, - kChildNeedsStyleRecalcFlag = 1 << 18, - kStyleChangeMask = - 1 << kNodeStyleChangeShift | 1 << (kNodeStyleChangeShift + 1), + kHasCustomStyleCallbacksFlag = 1 << 12, + kChildNeedsStyleInvalidationFlag = 1 << 13, + kNeedsStyleInvalidationFlag = 1 << 14, + kChildNeedsDistributionRecalcFlag = 1 << 15, + kChildNeedsStyleRecalcFlag = 1 << 16, + kStyleChangeMask = 0x3 << kNodeStyleChangeShift, kCustomElementStateMask = 0x3 << kNodeCustomElementShift, - kHasNameOrIsEditingTextFlag = 1 << 23, - kHasEventTargetDataFlag = 1 << 24, - - kV0CustomElementFlag = 1 << 25, - kV0CustomElementUpgradedFlag = 1 << 26, + kHasNameOrIsEditingTextFlag = 1 << 21, + kHasEventTargetDataFlag = 1 << 22, - kNeedsReattachLayoutTree = 1 << 27, - kChildNeedsReattachLayoutTree = 1 << 28, + kV0CustomElementFlag = 1 << 23, + kV0CustomElementUpgradedFlag = 1 << 24, - kHasDuplicateAttributes = 1 << 29, + kNeedsReattachLayoutTree = 1 << 25, + kChildNeedsReattachLayoutTree = 1 << 26, - // Temporary flag for some UseCounter items. crbug.com/859391. - kInDOMNodeRemovedHandler = 1 << 30, + kHasDuplicateAttributes = 1 << 27, - kForceReattachLayoutTree = 1 << 31, + kForceReattachLayoutTree = 1 << 28, kDefaultNodeFlags = kIsFinishedParsingChildrenFlag, - }; - // 0 bits remaining. + // 4 bits remaining. + }; - bool GetFlag(NodeFlags mask) const { return node_flags_ & mask; } + ALWAYS_INLINE bool GetFlag(NodeFlags mask) const { + return node_flags_ & mask; + } void SetFlag(bool f, NodeFlags mask) { node_flags_ = (node_flags_ & ~mask) | (-(int32_t)f & mask); } void SetFlag(NodeFlags mask) { node_flags_ |= mask; } void ClearFlag(NodeFlags mask) { node_flags_ &= ~mask; } + enum class DOMNodeType : uint32_t { + kElement = 0, + kText = 1 << kDOMNodeTypeShift, + kDocumentFragment = 2 << kDOMNodeTypeShift, + kOther = 3 << kDOMNodeTypeShift, + }; + ALWAYS_INLINE DOMNodeType GetDOMNodeType() const { + return static_cast<DOMNodeType>(node_flags_ & kDOMNodeTypeMask); + } + + enum class ElementNamespaceType : uint32_t { + kHTML = 0, + kMathML = 1 << kElementNamespaceTypeShift, + kSVG = 2 << kElementNamespaceTypeShift, + kOther = 3 << kElementNamespaceTypeShift, + }; + ALWAYS_INLINE ElementNamespaceType GetElementNamespaceType() const { + return static_cast<ElementNamespaceType>(node_flags_ & + kElementNamespaceTypeMask); + } + protected: enum ConstructionType { - kCreateOther = kIsFinishedParsingChildrenFlag, - kCreateText = kDefaultNodeFlags | kIsTextFlag, - kCreateContainer = kDefaultNodeFlags | kIsContainerFlag, - kCreateElement = kCreateContainer | kIsElementFlag, - kCreateShadowRoot = - kCreateContainer | kIsDocumentFragmentFlag | kIsInShadowTreeFlag, - kCreateDocumentFragment = kCreateContainer | kIsDocumentFragmentFlag, - kCreateHTMLElement = kCreateElement | kIsHTMLFlag, - kCreateMathMLElement = kCreateElement | kIsMathMLFlag, - kCreateSVGElement = kCreateElement | kIsSVGFlag, + kCreateOther = kDefaultNodeFlags | + static_cast<NodeFlags>(DOMNodeType::kOther) | + static_cast<NodeFlags>(ElementNamespaceType::kOther), + kCreateText = kDefaultNodeFlags | + static_cast<NodeFlags>(DOMNodeType::kText) | + static_cast<NodeFlags>(ElementNamespaceType::kOther), + kCreateContainer = kDefaultNodeFlags | kIsContainerFlag | + static_cast<NodeFlags>(DOMNodeType::kOther) | + static_cast<NodeFlags>(ElementNamespaceType::kOther), + kCreateElement = kDefaultNodeFlags | kIsContainerFlag | + static_cast<NodeFlags>(DOMNodeType::kElement) | + static_cast<NodeFlags>(ElementNamespaceType::kOther), + kCreateDocumentFragment = + kDefaultNodeFlags | kIsContainerFlag | + static_cast<NodeFlags>(DOMNodeType::kDocumentFragment) | + static_cast<NodeFlags>(ElementNamespaceType::kOther), + kCreateShadowRoot = kCreateDocumentFragment | kIsInShadowTreeFlag, + kCreateHTMLElement = kDefaultNodeFlags | kIsContainerFlag | + static_cast<NodeFlags>(DOMNodeType::kElement) | + static_cast<NodeFlags>(ElementNamespaceType::kHTML), + kCreateMathMLElement = + kDefaultNodeFlags | kIsContainerFlag | + static_cast<NodeFlags>(DOMNodeType::kElement) | + static_cast<NodeFlags>(ElementNamespaceType::kMathML), + kCreateSVGElement = kDefaultNodeFlags | kIsContainerFlag | + static_cast<NodeFlags>(DOMNodeType::kElement) | + static_cast<NodeFlags>(ElementNamespaceType::kSVG), kCreateDocument = kCreateContainer | kIsConnectedFlag, kCreateV0InsertionPoint = kCreateHTMLElement | kIsV0InsertionPointFlag, kCreateEditingText = kCreateText | kHasNameOrIsEditingTextFlag, @@ -1009,7 +1060,7 @@ class CORE_EXPORT Node : public EventTarget { NodeRareData* RareData() const { SECURITY_DCHECK(HasRareData()); - return static_cast<NodeRareData*>(data_.rare_data_); + return DataAsNodeRareData(); } NodeRareData& EnsureRareData() { if (HasRareData()) @@ -1063,8 +1114,14 @@ class CORE_EXPORT Node : public EventTarget { const HeapHashSet<Member<MutationObserverRegistration>>* TransientMutationObserverRegistry(); - inline Node* TrustedTypesCheckForScriptNode(Node* child, - ExceptionState&) const; + NodeRareData* DataAsNodeRareData() const { + DCHECK(HasRareData()); + return reinterpret_cast<NodeRareData*>(data_.Get()); + } + NodeRenderingData* DataAsNodeRenderingData() const { + DCHECK(!HasRareData()); + return reinterpret_cast<NodeRenderingData*>(data_.Get()); + } uint32_t node_flags_; Member<Node> parent_or_shadow_host_node_; @@ -1072,13 +1129,7 @@ class CORE_EXPORT Node : public EventTarget { Member<Node> previous_; Member<Node> next_; // When a node has rare data we move the layoutObject into the rare data. - union DataUnion { - DataUnion() : node_layout_data_(&NodeRenderingData::SharedEmptyData()) {} - // LayoutObjects are fully owned by their DOM node. See LayoutObject's - // LIFETIME documentation section. - NodeRenderingData* node_layout_data_; - NodeRareDataBase* rare_data_; - } data_; + Member<NodeData> data_; }; inline void Node::SetParentOrShadowHostNode(ContainerNode* parent) { @@ -1094,14 +1145,6 @@ inline ContainerNode* Node::ParentOrShadowHostNode() const { // Allow equality comparisons of Nodes by reference or pointer, interchangeably. DEFINE_COMPARISON_OPERATORS_WITH_REFERENCES(Node) -#define DEFINE_NODE_TYPE_CASTS(thisType, predicate) \ - DEFINE_TYPE_CASTS(thisType, Node, node, node->predicate, node.predicate) - -// This requires isClassName(const Node&). -#define DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(thisType) \ - DEFINE_TYPE_CASTS(thisType, Node, node, Is##thisType(*node), \ - Is##thisType(node)) - CORE_EXPORT std::ostream& operator<<(std::ostream&, const Node&); CORE_EXPORT std::ostream& operator<<(std::ostream&, const Node*); diff --git a/chromium/third_party/blink/renderer/core/dom/node.idl b/chromium/third_party/blink/renderer/core/dom/node.idl index 758feb3d188..f3e793fdb01 100644 --- a/chromium/third_party/blink/renderer/core/dom/node.idl +++ b/chromium/third_party/blink/renderer/core/dom/node.idl @@ -46,7 +46,7 @@ [Affects=Nothing, Measure] readonly attribute boolean isConnected; [Affects=Nothing, PerWorldBindings] readonly attribute Document? ownerDocument; - [Affects=Nothing, PerWorldBindings, ImplementedAs=ParentNodeWithCounting] readonly attribute Node? parentNode; + [Affects=Nothing, PerWorldBindings] readonly attribute Node? parentNode; [Affects=Nothing, PerWorldBindings] readonly attribute Element? parentElement; [Affects=Nothing, ImplementedAs=hasChildren] boolean hasChildNodes(); [Affects=Nothing, SameObject, PerWorldBindings] readonly attribute NodeList childNodes; @@ -54,11 +54,11 @@ [Affects=Nothing, PerWorldBindings] readonly attribute Node? lastChild; [Affects=Nothing, PerWorldBindings] readonly attribute Node? previousSibling; [Affects=Nothing, PerWorldBindings] readonly attribute Node? nextSibling; - [MeasureAs=NodeGetRootNode] Node getRootNode(optional GetRootNodeOptions options); + [MeasureAs=NodeGetRootNode] Node getRootNode(optional GetRootNodeOptions options = {}); [Affects=Nothing, CEReactions, CustomElementCallbacks] attribute DOMString? nodeValue; - [Affects=Nothing, CEReactions, CustomElementCallbacks, RaisesException=Setter] attribute ScriptString? textContent; + [Affects=Nothing, CEReactions, CustomElementCallbacks, RaisesException=Setter] attribute (DOMString or TrustedScript)? textContent; [CEReactions, CustomElementCallbacks] void normalize(); [NewObject, DoNotTestNewObject, CEReactions, CustomElementCallbacks, RaisesException] Node cloneNode(optional boolean deep = false); diff --git a/chromium/third_party/blink/renderer/core/dom/node_child_removal_tracker.h b/chromium/third_party/blink/renderer/core/dom/node_child_removal_tracker.h index afb769a183d..8e8df211f22 100644 --- a/chromium/third_party/blink/renderer/core/dom/node_child_removal_tracker.h +++ b/chromium/third_party/blink/renderer/core/dom/node_child_removal_tracker.h @@ -27,7 +27,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NODE_CHILD_REMOVAL_TRACKER_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NODE_CHILD_REMOVAL_TRACKER_H_ -#include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/node.h" #include "third_party/blink/renderer/platform/heap/handle.h" @@ -46,15 +45,15 @@ class NodeChildRemovalTracker { const Node& GetNode() const { return *node_; } NodeChildRemovalTracker* Previous() { return previous_; } - Member<const Node> node_; + const Node* node_; // Using raw pointers are safe because these NodeChildRemovalTrackers are // guaranteed to be on a stack. NodeChildRemovalTracker* previous_; - CORE_EXPORT static NodeChildRemovalTracker* last_; + static NodeChildRemovalTracker* last_; }; inline NodeChildRemovalTracker::NodeChildRemovalTracker(const Node& node) - : node_(node), previous_(last_) { + : node_(&node), previous_(last_) { last_ = this; } diff --git a/chromium/third_party/blink/renderer/core/dom/node_computed_style.h b/chromium/third_party/blink/renderer/core/dom/node_computed_style.h index a870a3d2610..3d28403ddc9 100644 --- a/chromium/third_party/blink/renderer/core/dom/node_computed_style.h +++ b/chromium/third_party/blink/renderer/core/dom/node_computed_style.h @@ -39,9 +39,10 @@ inline ComputedStyle* Node::MutableComputedStyleForEditingDeprecated() const { inline const ComputedStyle* Node::GetComputedStyle() const { if (IsElementNode()) { - return HasRareData() - ? data_.rare_data_->GetNodeRenderingData()->GetComputedStyle() - : data_.node_layout_data_->GetComputedStyle(); + return HasRareData() ? DataAsNodeRareData() + ->GetNodeRenderingData() + ->GetComputedStyle() + : DataAsNodeRenderingData()->GetComputedStyle(); } // Text nodes and Document. if (LayoutObject* layout_object = GetLayoutObject()) diff --git a/chromium/third_party/blink/renderer/core/dom/node_lists_node_data.h b/chromium/third_party/blink/renderer/core/dom/node_lists_node_data.h index 09cb934340b..375ba7f6d5c 100644 --- a/chromium/third_party/blink/renderer/core/dom/node_lists_node_data.h +++ b/chromium/third_party/blink/renderer/core/dom/node_lists_node_data.h @@ -39,20 +39,18 @@ class NodeListsNodeData final : public GarbageCollected<NodeListsNodeData> { public: ChildNodeList* GetChildNodeList(ContainerNode& node) { DCHECK(!child_node_list_ || node == child_node_list_->VirtualOwnerNode()); - return ToChildNodeList(child_node_list_); + return To<ChildNodeList>(child_node_list_.Get()); } ChildNodeList* EnsureChildNodeList(ContainerNode& node) { - DCHECK(ThreadState::Current()->IsGCForbidden()); if (child_node_list_) - return ToChildNodeList(child_node_list_); + return To<ChildNodeList>(child_node_list_.Get()); auto* list = MakeGarbageCollected<ChildNodeList>(node); child_node_list_ = list; return list; } EmptyNodeList* EnsureEmptyChildNodeList(Node& node) { - DCHECK(ThreadState::Current()->IsGCForbidden()); if (child_node_list_) return To<EmptyNodeList>(child_node_list_.Get()); auto* list = MakeGarbageCollected<EmptyNodeList>(node); @@ -88,7 +86,6 @@ class NodeListsNodeData final : public GarbageCollected<NodeListsNodeData> { T* AddCache(ContainerNode& node, CollectionType collection_type, const AtomicString& name) { - DCHECK(ThreadState::Current()->IsGCForbidden()); NodeListAtomicNameCacheMap::AddResult result = atomic_name_caches_.insert( std::make_pair(collection_type, name), nullptr); if (!result.is_new_entry) { @@ -102,7 +99,6 @@ class NodeListsNodeData final : public GarbageCollected<NodeListsNodeData> { template <typename T> T* AddCache(ContainerNode& node, CollectionType collection_type) { - DCHECK(ThreadState::Current()->IsGCForbidden()); NodeListAtomicNameCacheMap::AddResult result = atomic_name_caches_.insert( NamedNodeListKey(collection_type, CSSSelector::UniversalSelectorAtom()), nullptr); @@ -124,15 +120,14 @@ class NodeListsNodeData final : public GarbageCollected<NodeListsNodeData> { TagCollectionNS* AddCache(ContainerNode& node, const AtomicString& namespace_uri, const AtomicString& local_name) { - DCHECK(ThreadState::Current()->IsGCForbidden()); QualifiedName name(g_null_atom, local_name, namespace_uri); TagCollectionNSCache::AddResult result = tag_collection_ns_caches_.insert(name, nullptr); if (!result.is_new_entry) return result.stored_value->value; - TagCollectionNS* list = - TagCollectionNS::Create(node, namespace_uri, local_name); + auto* list = MakeGarbageCollected<TagCollectionNS>( + node, kTagCollectionNSType, namespace_uri, local_name); result.stored_value->value = list; return list; } @@ -183,7 +178,6 @@ class NodeListsNodeData final : public GarbageCollected<NodeListsNodeData> { template <typename Collection> inline Collection* ContainerNode::EnsureCachedCollection(CollectionType type) { - ThreadState::MainThreadGCForbiddenScope gc_forbidden; return EnsureNodeLists().AddCache<Collection>(*this, type); } @@ -191,7 +185,6 @@ template <typename Collection> inline Collection* ContainerNode::EnsureCachedCollection( CollectionType type, const AtomicString& name) { - ThreadState::MainThreadGCForbiddenScope gc_forbidden; return EnsureNodeLists().AddCache<Collection>(*this, type, name); } @@ -201,7 +194,6 @@ inline Collection* ContainerNode::EnsureCachedCollection( const AtomicString& namespace_uri, const AtomicString& local_name) { DCHECK_EQ(type, kTagCollectionNSType); - ThreadState::MainThreadGCForbiddenScope gc_forbidden; return EnsureNodeLists().AddCache(*this, namespace_uri, local_name); } diff --git a/chromium/third_party/blink/renderer/core/dom/node_rare_data.cc b/chromium/third_party/blink/renderer/core/dom/node_rare_data.cc index 8b4d8a63bd0..50a72f9dee0 100644 --- a/chromium/third_party/blink/renderer/core/dom/node_rare_data.cc +++ b/chromium/third_party/blink/renderer/core/dom/node_rare_data.cc @@ -37,13 +37,13 @@ #include "third_party/blink/renderer/core/dom/mutation_observer_registration.h" #include "third_party/blink/renderer/core/dom/node_lists_node_data.h" #include "third_party/blink/renderer/core/page/page.h" +#include "third_party/blink/renderer/core/style/computed_style.h" #include "third_party/blink/renderer/platform/heap/handle.h" namespace blink { struct SameSizeAsNodeRareData { - void* pointer_; - Member<void*> willbe_member_[3]; + Member<void*> willbe_member_[4]; unsigned bitfields_; }; @@ -77,25 +77,47 @@ void NodeMutationObserverData::RemoveRegistration( registry_.EraseAt(registry_.Find(registration)); } -void NodeRareData::TraceAfterDispatch(blink::Visitor* visitor) { - visitor->Trace(mutation_observer_data_); - visitor->Trace(flat_tree_node_data_); - // Do not keep empty NodeListsNodeData objects around. - if (node_lists_ && node_lists_->IsEmpty()) - node_lists_.Clear(); - else - visitor->Trace(node_lists_); +void NodeData::Trace(Visitor* visitor) { + if (bit_field_.get_concurrently<IsRareData>()) { + if (bit_field_.get_concurrently<IsElementRareData>()) + static_cast<ElementRareData*>(this)->TraceAfterDispatch(visitor); + else + static_cast<NodeRareData*>(this)->TraceAfterDispatch(visitor); + } else { + static_cast<NodeRenderingData*>(this)->TraceAfterDispatch(visitor); + } } -void NodeRareData::Trace(Visitor* visitor) { - if (is_element_rare_data_) - static_cast<ElementRareData*>(this)->TraceAfterDispatch(visitor); - else - TraceAfterDispatch(visitor); +NodeRenderingData::NodeRenderingData( + LayoutObject* layout_object, + scoped_refptr<const ComputedStyle> computed_style) + : NodeData(false, false), + layout_object_(layout_object), + computed_style_(computed_style) {} + +void NodeRenderingData::SetComputedStyle( + scoped_refptr<const ComputedStyle> computed_style) { + DCHECK_NE(&SharedEmptyData(), this); + computed_style_ = computed_style; +} + +NodeRenderingData& NodeRenderingData::SharedEmptyData() { + DEFINE_STATIC_LOCAL( + Persistent<NodeRenderingData>, shared_empty_data, + (MakeGarbageCollected<NodeRenderingData>(nullptr, nullptr))); + return *shared_empty_data; +} + +void NodeRareData::TraceAfterDispatch(blink::Visitor* visitor) const { + visitor->Trace(mutation_observer_data_); + visitor->Trace(flat_tree_node_data_); + visitor->Trace(node_layout_data_); + visitor->Trace(node_lists_); + NodeData::TraceAfterDispatch(visitor); } void NodeRareData::FinalizeGarbageCollectedObject() { - if (is_element_rare_data_) + if (bit_field_.get<IsElementRareData>()) static_cast<ElementRareData*>(this)->~ElementRareData(); else this->~NodeRareData(); diff --git a/chromium/third_party/blink/renderer/core/dom/node_rare_data.h b/chromium/third_party/blink/renderer/core/dom/node_rare_data.h index 6daa78adc8b..f38a3374e33 100644 --- a/chromium/third_party/blink/renderer/core/dom/node_rare_data.h +++ b/chromium/third_party/blink/renderer/core/dom/node_rare_data.h @@ -25,6 +25,7 @@ #include "base/macros.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/heap/heap.h" +#include "third_party/blink/renderer/platform/wtf/bit_field.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h" namespace blink { @@ -63,13 +64,48 @@ class NodeMutationObserverData final DISALLOW_COPY_AND_ASSIGN(NodeMutationObserverData); }; -class NodeRenderingData { - USING_FAST_MALLOC(NodeRenderingData); +class GC_PLUGIN_IGNORE( + "GC plugin reports that TraceAfterDispatch is not called but it is called " + "by both NodeRareDate::TraceAfterDispatch and " + "NodeRenderingData::TraceAfterDispatch.") NodeData + : public GarbageCollected<NodeData> { + public: + NodeData(bool is_rare_data, bool is_element_rare_data) + : connected_frame_count_(0), + element_flags_(0), + bit_field_(RestyleFlags::encode(0) | + IsElementRareData::encode(is_element_rare_data) | + IsRareData::encode(is_rare_data)) { + DCHECK(!is_element_rare_data || is_rare_data); + } + void Trace(Visitor*); + void TraceAfterDispatch(blink::Visitor*) const {} + + enum { + kConnectedFrameCountBits = 10, // Must fit Page::maxNumberOfFrames. + kNumberOfElementFlags = 6, + kNumberOfDynamicRestyleFlags = 14 + }; + + protected: + using BitField = WTF::ConcurrentlyReadBitField<uint16_t>; + using RestyleFlags = + BitField::DefineFirstValue<uint16_t, kNumberOfDynamicRestyleFlags>; + using IsElementRareData = RestyleFlags:: + DefineNextValue<bool, 1, WTF::BitFieldValueConstness::kConst>; + using IsRareData = IsElementRareData:: + DefineNextValue<bool, 1, WTF::BitFieldValueConstness::kConst>; + + uint16_t connected_frame_count_ : kConnectedFrameCountBits; + uint16_t element_flags_ : kNumberOfElementFlags; + BitField bit_field_; +}; +class GC_PLUGIN_IGNORE("Manual dispatch implemented in NodeData.") + NodeRenderingData final : public NodeData { public: NodeRenderingData(LayoutObject*, scoped_refptr<const ComputedStyle> computed_style); - ~NodeRenderingData(); LayoutObject* GetLayoutObject() const { return layout_object_; } void SetLayoutObject(LayoutObject* layout_object) { @@ -85,51 +121,34 @@ class NodeRenderingData { static NodeRenderingData& SharedEmptyData(); bool IsSharedEmptyData() { return this == &SharedEmptyData(); } + void TraceAfterDispatch(Visitor* visitor) const { + NodeData::TraceAfterDispatch(visitor); + } + private: LayoutObject* layout_object_; scoped_refptr<const ComputedStyle> computed_style_; DISALLOW_COPY_AND_ASSIGN(NodeRenderingData); }; -class NodeRareDataBase { +class GC_PLUGIN_IGNORE("Manual dispatch implemented in NodeData.") NodeRareData + : public NodeData { public: + explicit NodeRareData(NodeRenderingData* node_layout_data) + : NodeRareData(node_layout_data, false) {} + NodeRenderingData* GetNodeRenderingData() const { return node_layout_data_; } void SetNodeRenderingData(NodeRenderingData* node_layout_data) { DCHECK(node_layout_data); node_layout_data_ = node_layout_data; } - protected: - explicit NodeRareDataBase(NodeRenderingData* node_layout_data) - : node_layout_data_(node_layout_data) {} - ~NodeRareDataBase() { - if (node_layout_data_ && !node_layout_data_->IsSharedEmptyData()) - delete node_layout_data_; - } - - protected: - NodeRenderingData* node_layout_data_; -}; - -class NodeRareData : public GarbageCollected<NodeRareData>, - public NodeRareDataBase { - public: - explicit NodeRareData(NodeRenderingData* node_layout_data) - : NodeRareDataBase(node_layout_data), - connected_frame_count_(0), - element_flags_(0), - restyle_flags_(0), - is_element_rare_data_(false) { - CHECK_NE(node_layout_data, nullptr); - } - void ClearNodeLists() { node_lists_.Clear(); } NodeListsNodeData* NodeLists() const { return node_lists_.Get(); } // EnsureNodeLists() and a following NodeListsNodeData functions must be // wrapped with a ThreadState::GCForbiddenScope in order to avoid an // initialized node_lists_ is cleared by NodeRareData::TraceAfterDispatch(). NodeListsNodeData& EnsureNodeLists() { - DCHECK(ThreadState::Current()->IsGCForbidden()); if (!node_lists_) return CreateNodeLists(); return *node_lists_; @@ -149,7 +168,7 @@ class NodeRareData : public GarbageCollected<NodeRareData>, return *mutation_observer_data_; } - unsigned ConnectedSubframeCount() const { return connected_frame_count_; } + uint16_t ConnectedSubframeCount() const { return connected_frame_count_; } void IncrementConnectedSubframeCount(); void DecrementConnectedSubframeCount() { DCHECK(connected_frame_count_); @@ -157,36 +176,41 @@ class NodeRareData : public GarbageCollected<NodeRareData>, } bool HasElementFlag(ElementFlags mask) const { - return element_flags_ & static_cast<unsigned>(mask); + return element_flags_ & static_cast<uint16_t>(mask); } void SetElementFlag(ElementFlags mask, bool value) { - element_flags_ = (element_flags_ & ~static_cast<unsigned>(mask)) | - (-(int32_t)value & static_cast<unsigned>(mask)); + element_flags_ = + (element_flags_ & ~static_cast<uint16_t>(mask)) | + (-static_cast<uint16_t>(value) & static_cast<uint16_t>(mask)); } void ClearElementFlag(ElementFlags mask) { - element_flags_ &= ~static_cast<unsigned>(mask); + element_flags_ &= ~static_cast<uint16_t>(mask); } bool HasRestyleFlag(DynamicRestyleFlags mask) const { - return restyle_flags_ & static_cast<unsigned>(mask); + return bit_field_.get<RestyleFlags>() & static_cast<uint16_t>(mask); } void SetRestyleFlag(DynamicRestyleFlags mask) { - restyle_flags_ |= static_cast<unsigned>(mask); - CHECK(restyle_flags_); + bit_field_.set<RestyleFlags>(bit_field_.get<RestyleFlags>() | + static_cast<uint16_t>(mask)); + CHECK(bit_field_.get<RestyleFlags>()); } - bool HasRestyleFlags() const { return restyle_flags_; } - void ClearRestyleFlags() { restyle_flags_ = 0; } + bool HasRestyleFlags() const { return bit_field_.get<RestyleFlags>(); } + void ClearRestyleFlags() { bit_field_.set<RestyleFlags>(0); } - enum { - kConnectedFrameCountBits = 10, // Must fit Page::maxNumberOfFrames. - kNumberOfElementFlags = 6, - kNumberOfDynamicRestyleFlags = 14 - }; - - void Trace(Visitor*); - void TraceAfterDispatch(blink::Visitor*); + void TraceAfterDispatch(blink::Visitor*) const; void FinalizeGarbageCollectedObject(); + protected: + explicit NodeRareData(NodeRenderingData* node_layout_data, + bool is_element_rare_data) + : NodeData(true, is_element_rare_data), + node_layout_data_(node_layout_data) { + CHECK_NE(node_layout_data, nullptr); + } + + Member<NodeRenderingData> node_layout_data_; + private: NodeListsNodeData& CreateNodeLists(); @@ -194,12 +218,6 @@ class NodeRareData : public GarbageCollected<NodeRareData>, Member<NodeMutationObserverData> mutation_observer_data_; Member<FlatTreeNodeData> flat_tree_node_data_; - unsigned connected_frame_count_ : kConnectedFrameCountBits; - unsigned element_flags_ : kNumberOfElementFlags; - unsigned restyle_flags_ : kNumberOfDynamicRestyleFlags; - - protected: - unsigned is_element_rare_data_ : 1; DISALLOW_COPY_AND_ASSIGN(NodeRareData); }; diff --git a/chromium/third_party/blink/renderer/core/dom/node_test.cc b/chromium/third_party/blink/renderer/core/dom/node_test.cc index 4156ce2f7d8..96d805be445 100644 --- a/chromium/third_party/blink/renderer/core/dom/node_test.cc +++ b/chromium/third_party/blink/renderer/core/dom/node_test.cc @@ -5,6 +5,7 @@ #include "third_party/blink/renderer/core/dom/node.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_shadow_root_init.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver.h" #include "third_party/blink/renderer/core/css/style_engine.h" #include "third_party/blink/renderer/core/dom/comment.h" @@ -14,7 +15,6 @@ #include "third_party/blink/renderer/core/dom/processing_instruction.h" #include "third_party/blink/renderer/core/dom/pseudo_element.h" #include "third_party/blink/renderer/core/dom/shadow_root.h" -#include "third_party/blink/renderer/core/dom/shadow_root_init.h" #include "third_party/blink/renderer/core/dom/slot_assignment_engine.h" #include "third_party/blink/renderer/core/editing/testing/editing_test_base.h" #include "third_party/blink/renderer/core/html/html_div_element.h" @@ -269,7 +269,7 @@ TEST_F(NodeTest, AttachContext_PreviousInFlow_Slotted) { ShadowRoot& shadow_root = GetDocument().getElementById("host")->AttachShadowRootInternal( ShadowRootType::kOpen); - shadow_root.SetInnerHTMLFromString( + shadow_root.setInnerHTML( "<div id=root style='display:contents'><span></span><slot></slot></div>"); UpdateAllLifecyclePhasesForTest(); @@ -352,8 +352,7 @@ TEST_F(NodeTest, SkipStyleDirtyHostChild) { Element* host = GetDocument().getElementById("host"); ShadowRoot& shadow_root = host->AttachShadowRootInternal(ShadowRootType::kOpen); - shadow_root.SetInnerHTMLFromString( - "<div style='display:none'><slot></slot></div>"); + shadow_root.setInnerHTML("<div style='display:none'><slot></slot></div>"); UpdateAllLifecyclePhasesForTest(); EXPECT_FALSE(GetDocument().NeedsLayoutTreeUpdate()); @@ -392,7 +391,7 @@ TEST_F(NodeTest, SkipForceReattachDisplayNone) { Element* host = GetDocument().getElementById("host"); ShadowRoot& shadow_root = host->AttachShadowRootInternal(ShadowRootType::kOpen); - shadow_root.SetInnerHTMLFromString("<slot name='target'></slot>"); + shadow_root.setInnerHTML("<slot name='target'></slot>"); UpdateAllLifecyclePhasesForTest(); Element* span = To<Element>(host->firstChild()); @@ -413,7 +412,7 @@ TEST_F(NodeTest, UpdateChildDirtyAncestorsOnSlotAssignment) { Element* host = GetDocument().getElementById("host"); ShadowRoot& shadow_root = host->AttachShadowRootInternal(ShadowRootType::kOpen); - shadow_root.SetInnerHTMLFromString( + shadow_root.setInnerHTML( "<div><slot></slot></div><div id='child-dirty'><slot " "name='target'></slot></div>"); UpdateAllLifecyclePhasesForTest(); @@ -439,7 +438,7 @@ TEST_F(NodeTest, UpdateChildDirtySlotAfterRemoval) { Element* host = GetDocument().getElementById("host"); ShadowRoot& shadow_root = host->AttachShadowRootInternal(ShadowRootType::kOpen); - shadow_root.SetInnerHTMLFromString("<slot></slot>"); + shadow_root.setInnerHTML("<slot></slot>"); UpdateAllLifecyclePhasesForTest(); auto* span = To<Element>(host->firstChild()); @@ -471,7 +470,7 @@ TEST_F(NodeTest, UpdateChildDirtyAfterSlotRemoval) { Element* host = GetDocument().getElementById("host"); ShadowRoot& shadow_root = host->AttachShadowRootInternal(ShadowRootType::kOpen); - shadow_root.SetInnerHTMLFromString("<div><slot></slot></div>"); + shadow_root.setInnerHTML("<div><slot></slot></div>"); UpdateAllLifecyclePhasesForTest(); auto* span = To<Element>(host->firstChild()); @@ -513,7 +512,7 @@ TEST_F(NodeTest, UpdateChildDirtyAfterSlottingDirtyNode) { ShadowRoot& shadow_root = host->AttachShadowRootInternal(ShadowRootType::kOpen); - shadow_root.SetInnerHTMLFromString("<div><slot name=x></slot></div>"); + shadow_root.setInnerHTML("<div><slot name=x></slot></div>"); UpdateAllLifecyclePhasesForTest(); // Make sure the span is style dirty. diff --git a/chromium/third_party/blink/renderer/core/dom/node_with_index.h b/chromium/third_party/blink/renderer/core/dom/node_with_index.h index fbbb90d5157..ac401632f6a 100644 --- a/chromium/third_party/blink/renderer/core/dom/node_with_index.h +++ b/chromium/third_party/blink/renderer/core/dom/node_with_index.h @@ -37,7 +37,7 @@ class NodeWithIndex { STACK_ALLOCATED(); public: - explicit NodeWithIndex(Node& node) : node_(node), index_(-1) {} + explicit NodeWithIndex(Node& node) : node_(&node), index_(-1) {} Node& GetNode() const { return *node_; } @@ -53,7 +53,7 @@ class NodeWithIndex { private: bool HasIndex() const { return index_ >= 0; } - Member<Node> node_; + Node* node_; mutable int index_; }; diff --git a/chromium/third_party/blink/renderer/core/dom/nth_index_cache.h b/chromium/third_party/blink/renderer/core/dom/nth_index_cache.h index b2aa37a7b9b..002e8c3f808 100644 --- a/chromium/third_party/blink/renderer/core/dom/nth_index_cache.h +++ b/chromium/third_party/blink/renderer/core/dom/nth_index_cache.h @@ -55,9 +55,9 @@ class CORE_EXPORT NthIndexCache final { IndexByType& EnsureTypeIndexMap(ContainerNode&); NthIndexData* NthTypeIndexDataForParent(Element&) const; - Member<Document> document_; - Member<ParentMap> parent_map_; - Member<ParentMapForType> parent_map_for_type_; + Document* document_ = nullptr; + ParentMap* parent_map_ = nullptr; + ParentMapForType* parent_map_for_type_ = nullptr; #if DCHECK_IS_ON() uint64_t dom_tree_version_; diff --git a/chromium/third_party/blink/renderer/core/dom/nth_index_cache_test.cc b/chromium/third_party/blink/renderer/core/dom/nth_index_cache_test.cc index 128459bb123..942d9b4f3d5 100644 --- a/chromium/third_party/blink/renderer/core/dom/nth_index_cache_test.cc +++ b/chromium/third_party/blink/renderer/core/dom/nth_index_cache_test.cc @@ -15,7 +15,7 @@ namespace blink { class NthIndexCacheTest : public PageTestBase {}; TEST_F(NthIndexCacheTest, NthIndex) { - GetDocument().documentElement()->SetInnerHTMLFromString(R"HTML( + GetDocument().documentElement()->setInnerHTML(R"HTML( <body> <span id=first></span><span></span><span></span><span></span><span></span> diff --git a/chromium/third_party/blink/renderer/core/dom/processing_instruction.cc b/chromium/third_party/blink/renderer/core/dom/processing_instruction.cc index c7e29ddcf5c..be5780126f8 100644 --- a/chromium/third_party/blink/renderer/core/dom/processing_instruction.cc +++ b/chromium/third_party/blink/renderer/core/dom/processing_instruction.cc @@ -138,7 +138,8 @@ void ProcessingInstruction::Process(const String& href, const String& charset) { // can hang off some parent sheet. if (is_xsl_ && RuntimeEnabledFeatures::XSLTEnabled()) { KURL final_url(local_href_); - sheet_ = XSLStyleSheet::CreateEmbedded(this, final_url); + sheet_ = MakeGarbageCollected<XSLStyleSheet>(this, final_url.GetString(), + final_url, true); loading_ = false; } return; @@ -195,9 +196,9 @@ void ProcessingInstruction::NotifyFinished(Resource* resource) { is_xsl_ ? std::make_unique<IncrementLoadEventDelayCount>(GetDocument()) : nullptr; if (is_xsl_) { - sheet_ = XSLStyleSheet::Create(this, resource->Url(), - resource->GetResponse().ResponseUrl()); - ToXSLStyleSheet(sheet_.Get()) + sheet_ = MakeGarbageCollected<XSLStyleSheet>( + this, resource->Url(), resource->GetResponse().ResponseUrl(), false); + To<XSLStyleSheet>(sheet_.Get()) ->ParseString(ToXSLStyleSheetResource(resource)->Sheet()); } else { DCHECK(is_css_); @@ -217,7 +218,8 @@ void ProcessingInstruction::NotifyFinished(Resource* resource) { GetDocument().GetStyleEngine().SetPreferredStylesheetSetNameIfNotSet( title_); } - css_sheet->SetMediaQueries(MediaQuerySet::Create(media_)); + css_sheet->SetMediaQueries( + MediaQuerySet::Create(media_, GetExecutionContext())); sheet_ = css_sheet; // We don't need the cross-origin security check here because we are // getting the sheet text in "strict" mode. This enforces a valid CSS MIME @@ -232,7 +234,7 @@ void ProcessingInstruction::NotifyFinished(Resource* resource) { if (is_css_) To<CSSStyleSheet>(sheet_.Get())->Contents()->CheckLoaded(); else if (is_xsl_) - ToXSLStyleSheet(sheet_.Get())->CheckLoaded(); + To<XSLStyleSheet>(sheet_.Get())->CheckLoaded(); } Node::InsertionNotificationRequest ProcessingInstruction::InsertedInto( @@ -282,6 +284,8 @@ void ProcessingInstruction::ClearSheet() { } void ProcessingInstruction::RemovePendingSheet() { + if (is_xsl_) + return; GetDocument().GetStyleEngine().RemovePendingSheet(*this, style_engine_context_); } diff --git a/chromium/third_party/blink/renderer/core/dom/pseudo_element.cc b/chromium/third_party/blink/renderer/core/dom/pseudo_element.cc index 146cefae08d..2f7c2899e92 100644 --- a/chromium/third_party/blink/renderer/core/dom/pseudo_element.cc +++ b/chromium/third_party/blink/renderer/core/dom/pseudo_element.cc @@ -35,6 +35,7 @@ #include "third_party/blink/renderer/core/layout/generated_children.h" #include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/layout/layout_quote.h" +#include "third_party/blink/renderer/core/layout/ng/list/list_marker.h" #include "third_party/blink/renderer/core/probe/core_probes.h" #include "third_party/blink/renderer/core/style/computed_style.h" #include "third_party/blink/renderer/core/style/content_data.h" @@ -160,6 +161,17 @@ PseudoElement::AttachLayoutTreeScope::~AttachLayoutTreeScope() { void PseudoElement::AttachLayoutTree(AttachContext& context) { DCHECK(!GetLayoutObject()); + + // Some elements may have 'display: list-item' but not be list items. + // Do not create a layout object for the ::marker in that case. + if (pseudo_id_ == kPseudoIdMarker) { + LayoutObject* originating_layout = parentNode()->GetLayoutObject(); + if (!originating_layout || !originating_layout->IsListItemIncludingNG()) { + Node::AttachLayoutTree(context); + return; + } + } + { AttachLayoutTreeScope scope(this); Element::AttachLayoutTree(context); @@ -176,12 +188,28 @@ void PseudoElement::AttachLayoutTree(AttachContext& context) { DCHECK(CanHaveGeneratedChildren(*layout_object->Parent())); const ComputedStyle& style = layout_object->StyleRef(); - if (style.StyleType() != kPseudoIdBefore && - style.StyleType() != kPseudoIdAfter && - style.StyleType() != kPseudoIdMarker) - return; - DCHECK(style.GetContentData()); + switch (pseudo_id_) { + case kPseudoIdMarker: { + if (ListMarker* marker = ListMarker::Get(layout_object)) { + marker->UpdateMarkerContentIfNeeded(*layout_object); + } else { + DCHECK(layout_object->IsListMarker()); + // TODO(obrufau): support non-normal content in legacy markers. + return; + } + if (style.ContentBehavesAsNormal()) + return; + break; + } + case kPseudoIdBefore: + case kPseudoIdAfter: + break; + default: + return; + } + DCHECK(!style.ContentBehavesAsNormal()); + DCHECK(!style.ContentPreventsBoxGeneration()); for (const ContentData* content = style.GetContentData(); content; content = content->Next()) { LegacyLayout legacy = context.force_legacy_layout ? LegacyLayout::kForce @@ -200,22 +228,55 @@ void PseudoElement::AttachLayoutTree(AttachContext& context) { } bool PseudoElement::LayoutObjectIsNeeded(const ComputedStyle& style) const { - return PseudoElementLayoutObjectIsNeeded(&style); + return PseudoElementLayoutObjectIsNeeded(&style, this->parentElement()); +} + +bool PseudoElement::CanGeneratePseudoElement(PseudoId pseudo_id) const { + switch (pseudo_id_) { + case kPseudoIdBefore: + case kPseudoIdAfter: + if (pseudo_id != kPseudoIdMarker) + return false; + break; + default: + return false; + } + return Element::CanGeneratePseudoElement(pseudo_id); } Node* PseudoElement::InnerNodeForHitTesting() const { - return ParentOrShadowHostNode(); + Node* parent = ParentOrShadowHostNode(); + if (parent && parent->IsPseudoElement()) + return To<PseudoElement>(parent)->InnerNodeForHitTesting(); + return parent; } -bool PseudoElementLayoutObjectIsNeeded(const ComputedStyle* style) { - if (!style) +bool PseudoElementLayoutObjectIsNeeded(const ComputedStyle* pseudo_style, + const Element* originating_element) { + if (!pseudo_style) return false; - if (style->Display() == EDisplay::kNone) + if (pseudo_style->Display() == EDisplay::kNone) return false; - if (style->StyleType() == kPseudoIdFirstLetter || - style->StyleType() == kPseudoIdBackdrop) - return true; - return style->GetContentData(); + switch (pseudo_style->StyleType()) { + case kPseudoIdFirstLetter: + case kPseudoIdBackdrop: + return true; + case kPseudoIdBefore: + case kPseudoIdAfter: + return !pseudo_style->ContentPreventsBoxGeneration(); + case kPseudoIdMarker: { + if (!pseudo_style->ContentBehavesAsNormal()) + return !pseudo_style->ContentPreventsBoxGeneration(); + const ComputedStyle* parent_style = + originating_element->GetComputedStyle(); + return parent_style && + (parent_style->ListStyleType() != EListStyleType::kNone || + parent_style->GeneratesMarkerImage()); + } + default: + NOTREACHED(); + return false; + } } } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/pseudo_element.h b/chromium/third_party/blink/renderer/core/dom/pseudo_element.h index 951fc21bc7a..2f38fb6a975 100644 --- a/chromium/third_party/blink/renderer/core/dom/pseudo_element.h +++ b/chromium/third_party/blink/renderer/core/dom/pseudo_element.h @@ -44,6 +44,7 @@ class CORE_EXPORT PseudoElement : public Element { scoped_refptr<ComputedStyle> CustomStyleForLayoutObject() override; void AttachLayoutTree(AttachContext&) override; bool LayoutObjectIsNeeded(const ComputedStyle&) const override; + bool CanGeneratePseudoElement(PseudoId) const override; bool CanStartSelection() const override { return false; } bool CanContainRangeEndPoint() const override { return false; } @@ -68,7 +69,7 @@ class CORE_EXPORT PseudoElement : public Element { ~AttachLayoutTreeScope(); private: - Member<PseudoElement> element_; + PseudoElement* element_; scoped_refptr<const ComputedStyle> original_style_; }; @@ -77,7 +78,8 @@ class CORE_EXPORT PseudoElement : public Element { const QualifiedName& PseudoElementTagName(PseudoId); -bool PseudoElementLayoutObjectIsNeeded(const ComputedStyle*); +bool PseudoElementLayoutObjectIsNeeded(const ComputedStyle* pseudo_style, + const Element* originating_element); template <> struct DowncastTraits<PseudoElement> { diff --git a/chromium/third_party/blink/renderer/core/dom/pseudo_element_data.h b/chromium/third_party/blink/renderer/core/dom/pseudo_element_data.h index a94702a0564..23af73fd418 100644 --- a/chromium/third_party/blink/renderer/core/dom/pseudo_element_data.h +++ b/chromium/third_party/blink/renderer/core/dom/pseudo_element_data.h @@ -17,6 +17,10 @@ class PseudoElementData final : public GarbageCollected<PseudoElementData> { void SetPseudoElement(PseudoId, PseudoElement*); PseudoElement* GetPseudoElement(PseudoId) const; + + using PseudoElementVector = HeapVector<Member<PseudoElement>, 2>; + PseudoElementVector GetPseudoElements() const; + bool HasPseudoElements() const; void ClearPseudoElements(); void Trace(Visitor* visitor) { @@ -102,6 +106,22 @@ inline PseudoElement* PseudoElementData::GetPseudoElement( return nullptr; } +inline PseudoElementData::PseudoElementVector +PseudoElementData::GetPseudoElements() const { + PseudoElementData::PseudoElementVector result; + if (generated_before_) + result.push_back(generated_before_); + if (generated_after_) + result.push_back(generated_after_); + if (generated_marker_) + result.push_back(generated_marker_); + if (generated_first_letter_) + result.push_back(generated_first_letter_); + if (backdrop_) + result.push_back(backdrop_); + return result; +} + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_PSEUDO_ELEMENT_DATA_H_ diff --git a/chromium/third_party/blink/renderer/core/dom/range.cc b/chromium/third_party/blink/renderer/core/dom/range.cc index 44c86ad3893..71bad3d8be8 100644 --- a/chromium/third_party/blink/renderer/core/dom/range.cc +++ b/chromium/third_party/blink/renderer/core/dom/range.cc @@ -25,7 +25,6 @@ #include "third_party/blink/renderer/core/dom/range.h" -#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html.h" #include "third_party/blink/renderer/core/dom/character_data.h" #include "third_party/blink/renderer/core/dom/container_node.h" #include "third_party/blink/renderer/core/dom/document_fragment.h" @@ -72,7 +71,7 @@ class RangeUpdateScope { DCHECK(range); if (++scope_count_ == 1) { range_ = range; - old_document_ = range->OwnerDocument(); + old_document_ = &range->OwnerDocument(); #if DCHECK_IS_ON() current_range_ = range; } else { @@ -107,8 +106,8 @@ class RangeUpdateScope { // - RangeUpdateScope is used only in Range member functions. static Range* current_range_; #endif - Member<Range> range_; - Member<Document> old_document_; + Range* range_ = nullptr; + Document* old_document_ = nullptr; DISALLOW_COPY_AND_ASSIGN(RangeUpdateScope); }; @@ -963,29 +962,13 @@ String Range::GetText() const { } DocumentFragment* Range::createContextualFragment( - const StringOrTrustedHTML& string_or_html, - ExceptionState& exception_state) { - // Algorithm: - // http://domparsing.spec.whatwg.org/#extensions-to-the-range-interface - - DCHECK(!string_or_html.IsNull()); - - Document& document = start_.Container().GetDocument(); - - String markup = - GetStringFromTrustedHTML(string_or_html, &document, exception_state); - if (!exception_state.HadException()) { - return createContextualFragmentFromString(markup, exception_state); - } - return nullptr; -} - -DocumentFragment* Range::createContextualFragmentFromString( const String& markup, ExceptionState& exception_state) { // Algorithm: // http://domparsing.spec.whatwg.org/#extensions-to-the-range-interface + DCHECK(!markup.IsNull()); + Node* node = &start_.Container(); // Step 1. @@ -1599,7 +1582,7 @@ void Range::DidSplitTextNode(const Text& old_node) { void Range::expand(const String& unit, ExceptionState& exception_state) { if (!StartPosition().IsConnected() || !EndPosition().IsConnected()) return; - owner_document_->UpdateStyleAndLayout(); + owner_document_->UpdateStyleAndLayout(DocumentUpdateReason::kJavaScript); VisiblePosition start = CreateVisiblePosition(StartPosition()); VisiblePosition end = CreateVisiblePosition(EndPosition()); if (unit == "word") { @@ -1626,12 +1609,12 @@ void Range::expand(const String& unit, ExceptionState& exception_state) { } DOMRectList* Range::getClientRects() const { - owner_document_->UpdateStyleAndLayout(); + owner_document_->UpdateStyleAndLayout(DocumentUpdateReason::kJavaScript); Vector<FloatQuad> quads; GetBorderAndTextQuads(quads); - return DOMRectList::Create(quads); + return MakeGarbageCollected<DOMRectList>(quads); } DOMRect* Range::getBoundingClientRect() const { @@ -1747,7 +1730,7 @@ void Range::GetBorderAndTextQuads(Vector<FloatQuad>& quads) const { } FloatRect Range::BoundingRect() const { - owner_document_->UpdateStyleAndLayout(); + owner_document_->UpdateStyleAndLayout(DocumentUpdateReason::kJavaScript); Vector<FloatQuad> quads; GetBorderAndTextQuads(quads); diff --git a/chromium/third_party/blink/renderer/core/dom/range.h b/chromium/third_party/blink/renderer/core/dom/range.h index 98d708375ac..e3d643b525d 100644 --- a/chromium/third_party/blink/renderer/core/dom/range.h +++ b/chromium/third_party/blink/renderer/core/dom/range.h @@ -46,7 +46,6 @@ class ExceptionState; class FloatQuad; class Node; class NodeWithIndex; -class StringOrTrustedHTML; class Text; class CORE_EXPORT Range final : public ScriptWrappable { @@ -117,7 +116,7 @@ class CORE_EXPORT Range final : public ScriptWrappable { String GetText() const; - DocumentFragment* createContextualFragment(const StringOrTrustedHTML& html, + DocumentFragment* createContextualFragment(const String& html, ExceptionState&); void detach(); @@ -206,9 +205,6 @@ class CORE_EXPORT Range final : public ScriptWrappable { void UpdateSelectionIfAddedToSelection(); void RemoveFromSelectionIfInDifferentRoot(Document& old_document); - DocumentFragment* createContextualFragmentFromString(const String& html, - ExceptionState&); - Member<Document> owner_document_; // Cannot be null. RangeBoundaryPoint start_; RangeBoundaryPoint end_; diff --git a/chromium/third_party/blink/renderer/core/dom/range.idl b/chromium/third_party/blink/renderer/core/dom/range.idl index c2ee325331f..499e5b55452 100644 --- a/chromium/third_party/blink/renderer/core/dom/range.idl +++ b/chromium/third_party/blink/renderer/core/dom/range.idl @@ -20,10 +20,9 @@ // https://dom.spec.whatwg.org/#interface-range [ - Constructor, - ConstructorCallWith=Document, Exposed=Window ] interface Range { + [CallWith=Document] constructor(); readonly attribute Node startContainer; readonly attribute unsigned long startOffset; readonly attribute Node endContainer; @@ -73,5 +72,5 @@ [NewObject, RaisesException, CEReactions, CustomElementCallbacks] DocumentFragment createContextualFragment(HTMLString fragment); // Non-standard API - [RaisesException, DeprecateAs=RangeExpand] void expand([DefaultValue=Undefined] optional DOMString unit); + [RaisesException, DeprecateAs=RangeExpand] void expand(optional DOMString unit = ""); }; diff --git a/chromium/third_party/blink/renderer/core/dom/range_test.cc b/chromium/third_party/blink/renderer/core/dom/range_test.cc index b9a5b8be767..173d2e2e524 100644 --- a/chromium/third_party/blink/renderer/core/dom/range_test.cc +++ b/chromium/third_party/blink/renderer/core/dom/range_test.cc @@ -8,7 +8,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/bindings/core/v8/string_or_array_buffer_or_array_buffer_view.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" -#include "third_party/blink/renderer/core/css/font_face_descriptors.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_font_face_descriptors.h" #include "third_party/blink/renderer/core/css/font_face_set_document.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/node_list.h" @@ -37,7 +37,7 @@ namespace blink { class RangeTest : public EditingTestBase {}; TEST_F(RangeTest, extractContentsWithDOMMutationEvent) { - GetDocument().body()->SetInnerHTMLFromString("<span><b>abc</b>def</span>"); + GetDocument().body()->setInnerHTML("<span><b>abc</b>def</span>"); GetDocument().GetSettings()->SetScriptEnabled(true); Element* const script_element = GetDocument().CreateRawElement(html_names::kScriptTag); @@ -57,9 +57,9 @@ TEST_F(RangeTest, extractContentsWithDOMMutationEvent) { Element* const result = GetDocument().CreateRawElement(html_names::kDivTag); result->AppendChild(range->extractContents(ASSERT_NO_EXCEPTION)); - EXPECT_EQ("<b>abc</b>", result->InnerHTMLAsString()) + EXPECT_EQ("<b>abc</b>", result->innerHTML()) << "DOM mutation event handler should not affect result."; - EXPECT_EQ("<span>DEF</span>", span_element->OuterHTMLAsString()) + EXPECT_EQ("<span>DEF</span>", span_element->outerHTML()) << "DOM mutation event handler should be executed."; } @@ -102,7 +102,7 @@ TEST_F(RangeTest, IntersectsNode) { TEST_F(RangeTest, SplitTextNodeRangeWithinText) { V8TestingScope scope; - GetDocument().body()->SetInnerHTMLFromString("1234"); + GetDocument().body()->setInnerHTML("1234"); auto* old_text = To<Text>(GetDocument().body()->firstChild()); auto* range04 = @@ -147,7 +147,7 @@ TEST_F(RangeTest, SplitTextNodeRangeWithinText) { TEST_F(RangeTest, SplitTextNodeRangeOutsideText) { V8TestingScope scope; - GetDocument().body()->SetInnerHTMLFromString( + GetDocument().body()->setInnerHTML( "<span id=\"outer\">0<span id=\"inner-left\">1</span>SPLITME<span " "id=\"inner-right\">2</span>3</span>"); @@ -233,7 +233,7 @@ TEST_F(RangeTest, updateOwnerDocumentIfNeeded) { // Regression test for crbug.com/639184 TEST_F(RangeTest, NotMarkedValidByIrrelevantTextInsert) { - GetDocument().body()->SetInnerHTMLFromString( + GetDocument().body()->setInnerHTML( "<div><span id=span1>foo</span>bar<span id=span2>baz</span></div>"); Element* div = GetDocument().QuerySelector("div"); @@ -255,7 +255,7 @@ TEST_F(RangeTest, NotMarkedValidByIrrelevantTextInsert) { // Regression test for crbug.com/639184 TEST_F(RangeTest, NotMarkedValidByIrrelevantTextRemove) { - GetDocument().body()->SetInnerHTMLFromString( + GetDocument().body()->setInnerHTML( "<div><span id=span1>foofoo</span>bar<span id=span2>baz</span></div>"); Element* div = GetDocument().QuerySelector("div"); @@ -294,7 +294,7 @@ TEST_F(RangeTest, ToPosition) { TEST_F(RangeTest, BoundingRectMustIndependentFromSelection) { LoadAhem(); - GetDocument().body()->SetInnerHTMLFromString( + GetDocument().body()->setInnerHTML( "<div style='font: Ahem; width: 2em;letter-spacing: 5px;'>xx xx </div>"); Node* const div = GetDocument().QuerySelector("div"); // "x^x @@ -316,9 +316,8 @@ TEST_F(RangeTest, BoundingRectMustIndependentFromSelection) { // Regression test for crbug.com/681536 TEST_F(RangeTest, BorderAndTextQuadsWithInputInBetween) { - GetDocument().body()->SetInnerHTMLFromString( - "<div>foo <u><input> bar</u></div>"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().body()->setInnerHTML("<div>foo <u><input> bar</u></div>"); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Node* foo = GetDocument().QuerySelector("div")->firstChild(); Node* bar = GetDocument().QuerySelector("u")->lastChild(); @@ -349,7 +348,7 @@ static Vector<IntSize> ComputeSizesOfQuads(const Vector<FloatQuad>& quads) { } TEST_F(RangeTest, GetBorderAndTextQuadsWithFirstLetterOne) { - GetDocument().body()->SetInnerHTMLFromString(R"HTML( + GetDocument().body()->setInnerHTML(R"HTML( <style> body { font-size: 20px; } #sample::first-letter { font-size: 500%; } @@ -357,7 +356,7 @@ TEST_F(RangeTest, GetBorderAndTextQuadsWithFirstLetterOne) { <p id=sample>abc</p> <p id=expected><span style='font-size: 500%'>a</span>bc</p> )HTML"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Element* const expected = GetDocument().getElementById("expected"); Element* const sample = GetDocument().getElementById("sample"); @@ -394,7 +393,7 @@ TEST_F(RangeTest, GetBorderAndTextQuadsWithFirstLetterOne) { } TEST_F(RangeTest, GetBorderAndTextQuadsWithFirstLetterThree) { - GetDocument().body()->SetInnerHTMLFromString(R"HTML( + GetDocument().body()->setInnerHTML(R"HTML( <style> body { font-size: 20px; } #sample::first-letter { font-size: 500%; } @@ -402,7 +401,7 @@ TEST_F(RangeTest, GetBorderAndTextQuadsWithFirstLetterThree) { <p id=sample>(a)bc</p> <p id=expected><span style='font-size: 500%'>(a)</span>bc</p> )HTML"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Element* const expected = GetDocument().getElementById("expected"); Element* const sample = GetDocument().getElementById("sample"); @@ -455,7 +454,7 @@ TEST_F(RangeTest, GetBorderAndTextQuadsWithFirstLetterThree) { } TEST_F(RangeTest, CollapsedRangeGetBorderAndTextQuadsWithFirstLetter) { - GetDocument().body()->SetInnerHTMLFromString(R"HTML( + GetDocument().body()->setInnerHTML(R"HTML( <style> body { font-size: 20px; } #sample::first-letter { font-size: 500%; } @@ -463,7 +462,7 @@ TEST_F(RangeTest, CollapsedRangeGetBorderAndTextQuadsWithFirstLetter) { <p id=sample>abc</p> <p id=expected><span style='font-size: 500%'>a</span>bc</p> )HTML"); - GetDocument().UpdateStyleAndLayout(); + GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest); Element* const expected = GetDocument().getElementById("expected"); Element* const sample = GetDocument().getElementById("sample"); diff --git a/chromium/third_party/blink/renderer/core/dom/scriptable_document_parser.h b/chromium/third_party/blink/renderer/core/dom/scriptable_document_parser.h index 61ac0c87702..64afdc19a08 100644 --- a/chromium/third_party/blink/renderer/core/dom/scriptable_document_parser.h +++ b/chromium/third_party/blink/renderer/core/dom/scriptable_document_parser.h @@ -43,13 +43,11 @@ class CORE_EXPORT ScriptableDocumentParser : public DecodedDataDocumentParser { // JavaScript document.open() call right now, or it should be ignored. virtual bool IsExecutingScript() const { return false; } - // FIXME: Only the HTMLDocumentParser ever blocks script execution on - // stylesheet load, which is likely a bug in the XMLDocumentParser. - virtual void ExecuteScriptsWaitingForResources() {} + virtual void ExecuteScriptsWaitingForResources() = 0; virtual bool IsWaitingForScripts() const = 0; - virtual void DidAddPendingParserBlockingStylesheet() {} - virtual void DidLoadAllPendingParserBlockingStylesheets() {} + virtual void DidAddPendingParserBlockingStylesheet() = 0; + virtual void DidLoadAllPendingParserBlockingStylesheets() = 0; // These are used to expose the current line/column to the scripting system. virtual bool IsParsingAtLineNumber() const; diff --git a/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.cc b/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.cc index 934615945bf..7e54b479fe7 100644 --- a/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.cc +++ b/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.cc @@ -38,32 +38,44 @@ namespace blink { -std::pair<EventTarget*, StringImpl*> EventTargetKey(const Event* event) { - return std::make_pair(event->target(), event->type().Impl()); +bool ScriptedAnimationController::InsertToPerFrameEventsMap( + const Event* event) { + HashSet<const StringImpl*>& set = + per_frame_events_.insert(event->target(), HashSet<const StringImpl*>()) + .stored_value->value; + return set.insert(event->type().Impl()).is_new_entry; } -ScriptedAnimationController::ScriptedAnimationController(Document* document) - : document_(document), callback_collection_(document), suspend_count_(0) {} +void ScriptedAnimationController::EraseFromPerFrameEventsMap( + const Event* event) { + EventTarget* target = event->target(); + PerFrameEventsMap::iterator it = per_frame_events_.find(target); + if (it != per_frame_events_.end()) { + HashSet<const StringImpl*>& set = it->value; + set.erase(event->type().Impl()); + if (set.IsEmpty()) + per_frame_events_.erase(target); + } +} + +ScriptedAnimationController::ScriptedAnimationController(LocalDOMWindow* window) + : ExecutionContextLifecycleStateObserver(window), + callback_collection_(window) { + UpdateStateIfNeeded(); +} void ScriptedAnimationController::Trace(Visitor* visitor) { - visitor->Trace(document_); + ExecutionContextLifecycleStateObserver::Trace(visitor); visitor->Trace(callback_collection_); visitor->Trace(event_queue_); visitor->Trace(media_query_list_listeners_); visitor->Trace(per_frame_events_); } -void ScriptedAnimationController::Pause() { - ++suspend_count_; -} - -void ScriptedAnimationController::Unpause() { - // It would be nice to put an DCHECK_GT(suspend_count_, 0) here, but in WK1 - // resume() can be called even when suspend hasn't (if a tab was created in - // the background). - if (suspend_count_ > 0) - --suspend_count_; - ScheduleAnimationIfNeeded(); +void ScriptedAnimationController::ContextLifecycleStateChanged( + mojom::FrameLifecycleState state) { + if (state == mojom::FrameLifecycleState::kRunning) + ScheduleAnimationIfNeeded(); } void ScriptedAnimationController::DispatchEventsAndCallbacksForPrinting() { @@ -71,6 +83,13 @@ void ScriptedAnimationController::DispatchEventsAndCallbacksForPrinting() { CallMediaQueryListListeners(); } +void ScriptedAnimationController::ScheduleVideoFrameCallbacksExecution( + ExecuteVfcCallback execute_vfc_callback) { + DCHECK(RuntimeEnabledFeatures::RequestVideoFrameCallbackEnabled()); + vfc_execution_queue_.push_back(std::move(execute_vfc_callback)); + ScheduleAnimationIfNeeded(); +} + ScriptedAnimationController::CallbackId ScriptedAnimationController::RegisterFrameCallback( FrameRequestCallbackCollection::FrameCallback* callback) { @@ -84,7 +103,8 @@ void ScriptedAnimationController::CancelFrameCallback(CallbackId id) { } bool ScriptedAnimationController::HasFrameCallback() const { - return callback_collection_.HasFrameCallback(); + return callback_collection_.HasFrameCallback() || + !vfc_execution_queue_.IsEmpty(); } ScriptedAnimationController::CallbackId @@ -116,7 +136,7 @@ void ScriptedAnimationController::DispatchEvents( HeapVector<Member<Event>> remaining; for (auto& event : event_queue_) { if (event && event->InterfaceName() == event_interface_filter) { - per_frame_events_.erase(EventTargetKey(event.Get())); + EraseFromPerFrameEventsMap(event.Get()); events.push_back(event.Release()); } else { remaining.push_back(event.Release()); @@ -140,9 +160,20 @@ void ScriptedAnimationController::DispatchEvents( } } +void ScriptedAnimationController::ExecuteVideoFrameCallbacks() { + // dispatchEvents() runs script which can cause the context to be destroyed. + if (!GetExecutionContext()) + return; + + Vector<ExecuteVfcCallback> execute_vfc_callbacks; + vfc_execution_queue_.swap(execute_vfc_callbacks); + for (auto& callback : execute_vfc_callbacks) + std::move(callback).Run(current_frame_time_ms_); +} + void ScriptedAnimationController::ExecuteFrameCallbacks() { - // dispatchEvents() runs script which can cause the document to be destroyed. - if (!document_) + // dispatchEvents() runs script which can cause the context to be destroyed. + if (!GetExecutionContext()) return; callback_collection_.ExecuteFrameCallbacks(current_frame_time_ms_, @@ -159,28 +190,28 @@ void ScriptedAnimationController::CallMediaQueryListListeners() { } bool ScriptedAnimationController::HasScheduledFrameTasks() const { - if (suspend_count_) - return false; - return callback_collection_.HasFrameCallback() || !task_queue_.IsEmpty() || !event_queue_.IsEmpty() || !media_query_list_listeners_.IsEmpty() || - (document_ && document_->HasAutofocusCandidates()); + GetWindow()->document()->HasAutofocusCandidates() || + !vfc_execution_queue_.IsEmpty(); } void ScriptedAnimationController::ServiceScriptedAnimations( base::TimeTicks monotonic_time_now) { - if (document_ && document_->Loader()) { - current_frame_time_ms_ = - document_->Loader() - ->GetTiming() - .MonotonicTimeToZeroBasedDocumentTime(monotonic_time_now) - .InMillisecondsF(); - current_frame_legacy_time_ms_ = - document_->Loader() - ->GetTiming() - .MonotonicTimeToPseudoWallTime(monotonic_time_now) - .InMillisecondsF(); - } + if (!GetExecutionContext() || GetExecutionContext()->IsContextPaused()) + return; + auto* loader = GetWindow()->document()->Loader(); + if (!loader) + return; + + current_frame_time_ms_ = + loader->GetTiming() + .MonotonicTimeToZeroBasedDocumentTime(monotonic_time_now) + .InMillisecondsF(); + current_frame_legacy_time_ms_ = + loader->GetTiming() + .MonotonicTimeToPseudoWallTime(monotonic_time_now) + .InMillisecondsF(); current_frame_had_raf_ = HasFrameCallback(); if (!HasScheduledFrameTasks()) @@ -191,8 +222,7 @@ void ScriptedAnimationController::ServiceScriptedAnimations( // 10.5. For each fully active Document in docs, flush autofocus // candidates for that Document if its browsing context is a top-level // browsing context. - if (document_) - document_->FlushAutofocusCandidates(); + GetWindow()->document()->FlushAutofocusCandidates(); // 10.8. For each fully active Document in docs, evaluate media // queries and report changes for that Document, passing in now as the @@ -213,6 +243,12 @@ void ScriptedAnimationController::ServiceScriptedAnimations( // steps for that Document, passing in now as the timestamp. RunTasks(); + if (RuntimeEnabledFeatures::RequestVideoFrameCallbackEnabled()) { + // Run the fulfilled HTMLVideoELement.requestVideoFrameCallback() callbacks. + // See https://wicg.github.io/video-raf/. + ExecuteVideoFrameCallbacks(); + } + // 10.11. For each fully active Document in docs, run the animation // frame callbacks for that Document, passing in now as the timestamp. ExecuteFrameCallbacks(); @@ -245,7 +281,7 @@ void ScriptedAnimationController::EnqueueEvent(Event* event) { } void ScriptedAnimationController::EnqueuePerFrameEvent(Event* event) { - if (!per_frame_events_.insert(EventTargetKey(event)).is_new_entry) + if (!InsertToPerFrameEventsMap(event)) return; EnqueueEvent(event); } @@ -259,16 +295,17 @@ void ScriptedAnimationController::EnqueueMediaQueryChangeListeners( } void ScriptedAnimationController::ScheduleAnimationIfNeeded() { - if (suspend_count_ || !document_) + if (!GetExecutionContext() || GetExecutionContext()->IsContextPaused()) return; - LocalFrameView* frame_view = document_->View(); - if (!frame_view) + + auto* frame = GetWindow()->GetFrame(); + if (!frame) return; // If there is any pre-frame work to do, schedule an animation // unconditionally. if (HasScheduledFrameTasks()) { - frame_view->ScheduleAnimation(); + frame->View()->ScheduleAnimation(); return; } @@ -276,12 +313,14 @@ void ScriptedAnimationController::ScheduleAnimationIfNeeded() { // currently running one -- if we're currently running an animation, then any // scheduled post-frame tasks will get run at the end of the current frame, so // no need to schedule another one. - if (!callback_collection_.HasPostFrameCallback()) - return; - if (Page* page = document_->GetPage()) { - if (!page->Animator().IsServicingAnimations()) - frame_view->ScheduleAnimation(); + if (callback_collection_.HasPostFrameCallback() && + !frame->GetPage()->Animator().IsServicingAnimations()) { + frame->View()->ScheduleAnimation(); } } +LocalDOMWindow* ScriptedAnimationController::GetWindow() const { + return To<LocalDOMWindow>(GetExecutionContext()); +} + } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.h b/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.h index 430fe011dac..d3ac68f2b31 100644 --- a/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.h +++ b/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.h @@ -28,31 +28,42 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/frame_request_callback_collection.h" +#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h" #include "third_party/blink/renderer/platform/bindings/name_client.h" #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" +#include "third_party/blink/renderer/platform/wtf/functional.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" #include "third_party/blink/renderer/platform/wtf/text/string_impl.h" #include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink { -class Document; class Event; class EventTarget; +class LocalDOMWindow; class MediaQueryListListener; class CORE_EXPORT ScriptedAnimationController : public GarbageCollected<ScriptedAnimationController>, + public ExecutionContextLifecycleStateObserver, public NameClient { + USING_GARBAGE_COLLECTED_MIXIN(ScriptedAnimationController); + public: - explicit ScriptedAnimationController(Document*); - virtual ~ScriptedAnimationController() = default; + explicit ScriptedAnimationController(LocalDOMWindow*); + ~ScriptedAnimationController() override = default; - void Trace(Visitor*); + void Trace(Visitor*) override; const char* NameInHeapSnapshot() const override { return "ScriptedAnimationController"; } - void ClearDocumentPointer() { document_ = nullptr; } + + // Runs all the video.requestVideoFrameCallback() callbacks associated with + // one HTMLVideoElement. |double| is the current frame time in milliseconds + // (e.g. |current_frame_time_ms_|), to be passed as the "now" parameter + // when running the callbacks. + using ExecuteVfcCallback = base::OnceCallback<void(double)>; // Animation frame callbacks are used for requestAnimationFrame(). typedef int CallbackId; @@ -66,6 +77,10 @@ class CORE_EXPORT ScriptedAnimationController FrameRequestCallbackCollection::FrameCallback*); void CancelPostFrameCallback(CallbackId); + // Queues up the execution of video.requestVideoFrameCallback() callbacks for + // a specific HTMLVideoELement, as part of the next rendering steps. + void ScheduleVideoFrameCallbacksExecution(ExecuteVfcCallback); + // Animation frame events are used for resize events, scroll events, etc. void EnqueueEvent(Event*); void EnqueuePerFrameEvent(Event*); @@ -82,8 +97,8 @@ class CORE_EXPORT ScriptedAnimationController void ServiceScriptedAnimations(base::TimeTicks monotonic_time_now); void RunPostFrameCallbacks(); - void Pause(); - void Unpause(); + void ContextLifecycleStateChanged(mojom::FrameLifecycleState) final; + void ContextDestroyed() final {} void DispatchEventsAndCallbacksForPrinting(); @@ -97,17 +112,23 @@ class CORE_EXPORT ScriptedAnimationController void DispatchEvents( const AtomicString& event_interface_filter = AtomicString()); void ExecuteFrameCallbacks(); + void ExecuteVideoFrameCallbacks(); void CallMediaQueryListListeners(); bool HasScheduledFrameTasks() const; - Member<Document> document_; + LocalDOMWindow* GetWindow() const; + + ALWAYS_INLINE bool InsertToPerFrameEventsMap(const Event* event); + ALWAYS_INLINE void EraseFromPerFrameEventsMap(const Event* event); + FrameRequestCallbackCollection callback_collection_; - int suspend_count_; Vector<base::OnceClosure> task_queue_; + Vector<ExecuteVfcCallback> vfc_execution_queue_; HeapVector<Member<Event>> event_queue_; - HeapListHashSet<std::pair<Member<const EventTarget>, const StringImpl*>> - per_frame_events_; + using PerFrameEventsMap = + HeapHashMap<Member<const EventTarget>, HashSet<const StringImpl*>>; + PerFrameEventsMap per_frame_events_; using MediaQueryListListeners = HeapListHashSet<Member<MediaQueryListListener>>; MediaQueryListListeners media_query_list_listeners_; diff --git a/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller_test.cc b/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller_test.cc index 72057a2e44f..e757b3d8ea2 100644 --- a/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller_test.cc +++ b/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller_test.cc @@ -36,10 +36,10 @@ void ScriptedAnimationControllerTest::SetUp() { dummy_page_holder_ = std::make_unique<DummyPageHolder>(IntSize(800, 600)); // Note: The document doesn't know about this ScriptedAnimationController - // instance, and will create another if - // Document::ensureScriptedAnimationController is called. - controller_ = WrapPersistent( - MakeGarbageCollected<ScriptedAnimationController>(&GetDocument())); + // instance. + controller_ = + WrapPersistent(MakeGarbageCollected<ScriptedAnimationController>( + dummy_page_holder_->GetFrame().DomWindow())); } namespace { diff --git a/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc b/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc index cb844a1fdbc..760c696f452 100644 --- a/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc +++ b/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc @@ -7,7 +7,7 @@ #include "base/location.h" #include "base/metrics/histogram_macros.h" #include "third_party/blink/public/platform/platform.h" -#include "third_party/blink/renderer/core/dom/idle_request_options.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_idle_request_options.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/inspector/inspector_trace_events.h" #include "third_party/blink/renderer/core/probe/core_probes.h" @@ -90,7 +90,7 @@ void ScriptedIdleTaskController::V8IdleTask::invoke(IdleDeadline* deadline) { ScriptedIdleTaskController::ScriptedIdleTaskController( ExecutionContext* context) - : ContextLifecycleStateObserver(context), + : ExecutionContextLifecycleStateObserver(context), scheduler_(ThreadScheduler::Current()), next_callback_id_(0), paused_(false) {} @@ -99,7 +99,7 @@ ScriptedIdleTaskController::~ScriptedIdleTaskController() = default; void ScriptedIdleTaskController::Trace(Visitor* visitor) { visitor->Trace(idle_tasks_); - ContextLifecycleStateObserver::Trace(visitor); + ExecutionContextLifecycleStateObserver::Trace(visitor); } int ScriptedIdleTaskController::NextCallbackId() { @@ -228,7 +228,7 @@ void ScriptedIdleTaskController::RunCallback( idle_tasks_.erase(id); } -void ScriptedIdleTaskController::ContextDestroyed(ExecutionContext*) { +void ScriptedIdleTaskController::ContextDestroyed() { idle_tasks_.clear(); } diff --git a/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h b/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h index 6bcc6b19bbc..c13fe650ed9 100644 --- a/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h +++ b/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h @@ -7,7 +7,7 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_idle_request_callback.h" #include "third_party/blink/renderer/core/dom/idle_deadline.h" -#include "third_party/blink/renderer/core/execution_context/context_lifecycle_state_observer.h" +#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h" #include "third_party/blink/renderer/core/probe/async_task_id.h" #include "third_party/blink/renderer/platform/bindings/name_client.h" #include "third_party/blink/renderer/platform/heap/handle.h" @@ -25,7 +25,7 @@ class ThreadScheduler; class CORE_EXPORT ScriptedIdleTaskController : public GarbageCollected<ScriptedIdleTaskController>, - public ContextLifecycleStateObserver, + public ExecutionContextLifecycleStateObserver, public NameClient { USING_GARBAGE_COLLECTED_MIXIN(ScriptedIdleTaskController); @@ -82,8 +82,8 @@ class CORE_EXPORT ScriptedIdleTaskController int RegisterCallback(IdleTask*, const IdleRequestOptions*); void CancelCallback(CallbackId); - // ContextLifecycleStateObserver interface. - void ContextDestroyed(ExecutionContext*) override; + // ExecutionContextLifecycleStateObserver interface. + void ContextDestroyed() override; void ContextLifecycleStateChanged(mojom::FrameLifecycleState) override; void CallbackFired(CallbackId, diff --git a/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc b/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc index 55f08d66335..911c7e2cf0d 100644 --- a/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc +++ b/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc @@ -7,7 +7,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/bindings/core/v8/v8_idle_request_callback.h" -#include "third_party/blink/renderer/core/dom/idle_request_options.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_idle_request_options.h" #include "third_party/blink/renderer/core/testing/null_execution_context.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" #include "third_party/blink/renderer/platform/testing/scoped_scheduler_overrider.h" @@ -33,6 +33,9 @@ class MockScriptedIdleTaskControllerScheduler final : public ThreadScheduler { scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() override { return nullptr; } + scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override { + return nullptr; + } scoped_refptr<base::SingleThreadTaskRunner> DeprecatedDefaultTaskRunner() override { return nullptr; diff --git a/chromium/third_party/blink/renderer/core/dom/shadow_dom_v0_test.cc b/chromium/third_party/blink/renderer/core/dom/shadow_dom_v0_test.cc index df99e4679f3..c20d7e70dd2 100644 --- a/chromium/third_party/blink/renderer/core/dom/shadow_dom_v0_test.cc +++ b/chromium/third_party/blink/renderer/core/dom/shadow_dom_v0_test.cc @@ -111,7 +111,7 @@ TEST_F(ShadowDOMV0Test, FeatureSetMultipleSelectors) { TEST_F(ShadowDOMV0Test, FeatureSetSubtree) { LoadURL("about:blank"); auto* host = GetDocument().CreateRawElement(html_names::kDivTag); - host->CreateV0ShadowRootForTesting().SetInnerHTMLFromString(R"HTML( + host->CreateV0ShadowRootForTesting().setInnerHTML(R"HTML( <div> <div></div> <content select='*'></content> @@ -130,7 +130,7 @@ TEST_F(ShadowDOMV0Test, FeatureSetMultipleShadowRoots) { LoadURL("about:blank"); auto* host = GetDocument().CreateRawElement(html_names::kDivTag); auto& host_shadow = host->CreateV0ShadowRootForTesting(); - host_shadow.SetInnerHTMLFromString("<content select='#foo'></content>"); + host_shadow.setInnerHTML("<content select='#foo'></content>"); auto* child = GetDocument().CreateRawElement(html_names::kDivTag); auto& child_root = child->CreateV0ShadowRootForTesting(); auto* child_content = GetDocument().CreateRawElement(html_names::kContentTag); @@ -157,8 +157,7 @@ TEST_F(ShadowDOMV0Test, ReattachNonDistributedElements) { host->appendChild(inner_host); inner_host->appendChild(span); - GetDocument().View()->UpdateAllLifecyclePhases( - DocumentLifecycle::LifecycleUpdateReason::kTest); + GetDocument().View()->UpdateAllLifecyclePhases(DocumentUpdateReason::kTest); host->CreateV0ShadowRootForTesting(); inner_host->CreateV0ShadowRootForTesting(); @@ -166,8 +165,7 @@ TEST_F(ShadowDOMV0Test, ReattachNonDistributedElements) { CSSValueID::kInlineBlock); span->SetInlineStyleProperty(CSSPropertyID::kDisplay, CSSValueID::kBlock); - GetDocument().View()->UpdateAllLifecyclePhases( - DocumentLifecycle::LifecycleUpdateReason::kTest); + GetDocument().View()->UpdateAllLifecyclePhases(DocumentUpdateReason::kTest); EXPECT_FALSE(span->NeedsReattachLayoutTree()); } @@ -180,8 +178,7 @@ TEST_F(ShadowDOMV0Test, DetachLayoutTreeOnShadowRootCreation) { auto* span = GetDocument().CreateRawElement(html_names::kSpanTag); host->appendChild(span); GetDocument().body()->appendChild(host); - GetDocument().View()->UpdateAllLifecyclePhases( - DocumentLifecycle::LifecycleUpdateReason::kTest); + GetDocument().View()->UpdateAllLifecyclePhases(DocumentUpdateReason::kTest); EXPECT_TRUE(span->GetLayoutObject()); diff --git a/chromium/third_party/blink/renderer/core/dom/shadow_root.cc b/chromium/third_party/blink/renderer/core/dom/shadow_root.cc index 155f4e28ad9..215a8af0e76 100644 --- a/chromium/third_party/blink/renderer/core/dom/shadow_root.cc +++ b/chromium/third_party/blink/renderer/core/dom/shadow_root.cc @@ -27,7 +27,6 @@ #include "third_party/blink/renderer/core/dom/shadow_root.h" #include "third_party/blink/public/platform/platform.h" -#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver.h" #include "third_party/blink/renderer/core/css/style_change_reason.h" #include "third_party/blink/renderer/core/css/style_engine.h" @@ -71,7 +70,7 @@ ShadowRoot::ShadowRoot(Document& document, ShadowRootType type) type_(static_cast<unsigned>(type)), registered_with_parent_shadow_root_(false), delegates_focus_(false), - slotting_(static_cast<unsigned>(ShadowRootSlotting::kAuto)), + slot_assignment_mode_(static_cast<unsigned>(SlotAssignmentMode::kAuto)), needs_distribution_recalc_(false), unused_(0) { if (IsV0()) @@ -109,35 +108,22 @@ Node* ShadowRoot::Clone(Document&, CloneChildrenFlag) const { return nullptr; } -void ShadowRoot::SetSlotting(ShadowRootSlotting slotting) { - slotting_ = static_cast<unsigned>(slotting); +void ShadowRoot::SetSlotAssignmentMode(SlotAssignmentMode assignment_mode) { + slot_assignment_mode_ = static_cast<unsigned>(assignment_mode); } -String ShadowRoot::InnerHTMLAsString() const { +String ShadowRoot::innerHTML() const { return CreateMarkup(this, kChildrenOnly); } -void ShadowRoot::innerHTML(StringOrTrustedHTML& result) const { - result.SetString(InnerHTMLAsString()); -} - -void ShadowRoot::SetInnerHTMLFromString(const String& markup, - ExceptionState& exception_state) { +void ShadowRoot::setInnerHTML(const String& markup, + ExceptionState& exception_state) { if (DocumentFragment* fragment = CreateFragmentForInnerOuterHTML( markup, &host(), kAllowScriptingContent, "innerHTML", exception_state)) ReplaceChildrenWithFragment(this, fragment, exception_state); } -void ShadowRoot::setInnerHTML(const StringOrTrustedHTML& stringOrHtml, - ExceptionState& exception_state) { - String html = - GetStringFromTrustedHTML(stringOrHtml, &GetDocument(), exception_state); - if (!exception_state.HadException()) { - SetInnerHTMLFromString(html, exception_state); - } -} - void ShadowRoot::RecalcStyle(const StyleRecalcChange change) { // ShadowRoot doesn't support custom callbacks. DCHECK(!HasCustomStyleCallbacks()); @@ -222,9 +208,10 @@ void ShadowRoot::ChildrenChanged(const ChildrenChange& change) { if (change.IsChildElementChange()) { CheckForSiblingStyleChanges( - change.type == kElementRemoved ? kSiblingElementRemoved - : kSiblingElementInserted, - To<Element>(change.sibling_changed.Get()), change.sibling_before_change, + change.type == ChildrenChangeType::kElementRemoved + ? kSiblingElementRemoved + : kSiblingElementInserted, + To<Element>(change.sibling_changed), change.sibling_before_change, change.sibling_after_change); } } diff --git a/chromium/third_party/blink/renderer/core/dom/shadow_root.h b/chromium/third_party/blink/renderer/core/dom/shadow_root.h index 5cce67184ee..7a0290d0790 100644 --- a/chromium/third_party/blink/renderer/core/dom/shadow_root.h +++ b/chromium/third_party/blink/renderer/core/dom/shadow_root.h @@ -42,12 +42,13 @@ class Document; class ExceptionState; class ShadowRootV0; class SlotAssignment; -class StringOrTrustedHTML; class WhitespaceAttacher; enum class ShadowRootType { V0, kOpen, kClosed, kUserAgent }; -enum class ShadowRootSlotting { kManual, kAuto }; +enum class SlotAssignmentMode { kManual, kAuto }; + +enum class FocusDelegation { kNone, kDelegateFocus }; class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope { DEFINE_WRAPPERTYPEINFO(); @@ -139,23 +140,24 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope { Element* ActiveElement() const; - String InnerHTMLAsString() const; - void SetInnerHTMLFromString(const String&, - ExceptionState& = ASSERT_NO_EXCEPTION); - - // TrustedTypes variants of the above. - // TODO(mkwst): Write a spec for these bits. https://crbug.com/739170 - void innerHTML(StringOrTrustedHTML&) const; - void setInnerHTML(const StringOrTrustedHTML&, ExceptionState&); + String innerHTML() const; + void setInnerHTML(const String&, ExceptionState& = ASSERT_NO_EXCEPTION); Node* Clone(Document&, CloneChildrenFlag) const override; void SetDelegatesFocus(bool flag) { delegates_focus_ = flag; } bool delegatesFocus() const { return delegates_focus_; } - void SetSlotting(ShadowRootSlotting slotting); - bool IsManualSlotting() { - return slotting_ == static_cast<unsigned>(ShadowRootSlotting::kManual); + void SetSlotAssignmentMode(SlotAssignmentMode assignment); + bool IsManualSlotting() const { + return slot_assignment_mode_ == + static_cast<unsigned>(SlotAssignmentMode::kManual); + } + SlotAssignmentMode GetSlotAssignmentMode() const { + return static_cast<SlotAssignmentMode>(slot_assignment_mode_); + } + String slotAssignment() const { + return IsManualSlotting() ? "manual" : "auto"; } bool ContainsShadowRoots() const { return child_shadow_root_count_; } @@ -188,7 +190,7 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope { unsigned type_ : 2; unsigned registered_with_parent_shadow_root_ : 1; unsigned delegates_focus_ : 1; - unsigned slotting_ : 1; + unsigned slot_assignment_mode_ : 1; unsigned needs_distribution_recalc_ : 1; unsigned unused_ : 10; diff --git a/chromium/third_party/blink/renderer/core/dom/shadow_root.idl b/chromium/third_party/blink/renderer/core/dom/shadow_root.idl index ec004dfb701..0080770117d 100644 --- a/chromium/third_party/blink/renderer/core/dom/shadow_root.idl +++ b/chromium/third_party/blink/renderer/core/dom/shadow_root.idl @@ -30,8 +30,11 @@ interface ShadowRoot : DocumentFragment { readonly attribute ShadowRootMode mode; readonly attribute Element host; - [CEReactions, CustomElementCallbacks, Custom=Setter] attribute HTMLString innerHTML; + // TODO(lyf): Change the type to `[TreatNullAs=xxx] HTMLString` after + // https://crbug.com/1058762 has been fixed. + [CEReactions, CustomElementCallbacks, RaisesException=Setter] attribute [TreatNullAs=EmptyString, StringContext=TrustedHTML] DOMString innerHTML; readonly attribute boolean delegatesFocus; + [RuntimeEnabled=ManualSlotting] readonly attribute SlotAssignmentMode slotAssignment; }; ShadowRoot includes DocumentOrShadowRoot; diff --git a/chromium/third_party/blink/renderer/core/dom/shadow_root_init.idl b/chromium/third_party/blink/renderer/core/dom/shadow_root_init.idl index 0857f2ae500..ed464209c97 100644 --- a/chromium/third_party/blink/renderer/core/dom/shadow_root_init.idl +++ b/chromium/third_party/blink/renderer/core/dom/shadow_root_init.idl @@ -5,10 +5,10 @@ // Spec: https://w3c.github.io/webcomponents/spec/shadow/#shadowrootinit-dictionary enum ShadowRootMode { "open", "closed" }; -enum ShadowRootSlottingMode { "manual", "auto" }; +enum SlotAssignmentMode { "manual", "auto" }; dictionary ShadowRootInit { required ShadowRootMode mode; boolean delegatesFocus; - [RuntimeEnabled=ManualSlotting] ShadowRootSlottingMode slotting; + [RuntimeEnabled=ManualSlotting] SlotAssignmentMode slotAssignment; }; diff --git a/chromium/third_party/blink/renderer/core/dom/slot_assignment_test.cc b/chromium/third_party/blink/renderer/core/dom/slot_assignment_test.cc index db21a594ec7..ec0505a065c 100644 --- a/chromium/third_party/blink/renderer/core/dom/slot_assignment_test.cc +++ b/chromium/third_party/blink/renderer/core/dom/slot_assignment_test.cc @@ -103,7 +103,7 @@ void SlotAssignmentTest::SetUp() { void SlotAssignmentTest::SetBody(const char* html) { Element* body = GetDocument().body(); - body->SetInnerHTMLFromString(String::FromUTF8(html)); + body->setInnerHTML(String::FromUTF8(html)); ConvertDeclarativeShadowDOMToShadowRoot(*body); RemoveWhiteSpaceOnlyTextNode(*body); } diff --git a/chromium/third_party/blink/renderer/core/dom/static_node_list.h b/chromium/third_party/blink/renderer/core/dom/static_node_list.h index c40af665aff..ec11d4c1c20 100644 --- a/chromium/third_party/blink/renderer/core/dom/static_node_list.h +++ b/chromium/third_party/blink/renderer/core/dom/static_node_list.h @@ -29,8 +29,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_STATIC_NODE_LIST_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_STATIC_NODE_LIST_H_ -#include "third_party/blink/renderer/core/dom/document.h" -#include "third_party/blink/renderer/core/dom/node_child_removal_tracker.h" #include "third_party/blink/renderer/core/dom/node_list.h" #include "third_party/blink/renderer/platform/wtf/vector.h" @@ -75,13 +73,8 @@ unsigned StaticNodeTypeList<NodeType>::length() const { template <typename NodeType> NodeType* StaticNodeTypeList<NodeType>::item(unsigned index) const { - if (index < nodes_.size()) { - auto* node = nodes_[index].Get(); - if (node->GetDocument().InDOMNodeRemovedHandler() && - NodeChildRemovalTracker::IsBeingRemoved(*node)) - node->GetDocument().CountDetachingNodeAccessInDOMNodeRemovedHandler(); - return node; - } + if (index < nodes_.size()) + return nodes_[index].Get(); return nullptr; } diff --git a/chromium/third_party/blink/renderer/core/dom/static_range_test.cc b/chromium/third_party/blink/renderer/core/dom/static_range_test.cc index bbab5fd4e89..c46da517509 100644 --- a/chromium/third_party/blink/renderer/core/dom/static_range_test.cc +++ b/chromium/third_party/blink/renderer/core/dom/static_range_test.cc @@ -45,7 +45,7 @@ HTMLDocument& StaticRangeTest::GetDocument() const { TEST_F(StaticRangeTest, SplitTextNodeRangeWithinText) { V8TestingScope scope; - GetDocument().body()->SetInnerHTMLFromString("1234"); + GetDocument().body()->setInnerHTML("1234"); auto* old_text = To<Text>(GetDocument().body()->firstChild()); auto* static_range04 = MakeGarbageCollected<StaticRange>( @@ -116,7 +116,7 @@ TEST_F(StaticRangeTest, SplitTextNodeRangeWithinText) { TEST_F(StaticRangeTest, SplitTextNodeRangeOutsideText) { V8TestingScope scope; - GetDocument().body()->SetInnerHTMLFromString( + GetDocument().body()->setInnerHTML( "<span id=\"outer\">0<span id=\"inner-left\">1</span>SPLITME<span " "id=\"inner-right\">2</span>3</span>"); @@ -231,7 +231,7 @@ TEST_F(StaticRangeTest, SplitTextNodeRangeOutsideText) { TEST_F(StaticRangeTest, InvalidToRange) { V8TestingScope scope; - GetDocument().body()->SetInnerHTMLFromString("1234"); + GetDocument().body()->setInnerHTML("1234"); auto* old_text = To<Text>(GetDocument().body()->firstChild()); auto* static_range04 = MakeGarbageCollected<StaticRange>( diff --git a/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.cc b/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.cc deleted file mode 100644 index c2c719883ce..00000000000 --- a/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.cc +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/core/dom/synchronous_mutation_notifier.h" - -#include "third_party/blink/renderer/core/dom/document.h" -#include "third_party/blink/renderer/core/dom/synchronous_mutation_observer.h" - -namespace blink { - -SynchronousMutationNotifier::SynchronousMutationNotifier() = default; - -void SynchronousMutationNotifier::NotifyChangeChildren( - const ContainerNode& container) { - ForEachObserver([&](SynchronousMutationObserver* observer) { - observer->DidChangeChildren(container); - }); -} - -void SynchronousMutationNotifier::NotifyMergeTextNodes( - const Text& node, - const NodeWithIndex& node_to_be_removed_with_index, - unsigned old_length) { - ForEachObserver([&](SynchronousMutationObserver* observer) { - observer->DidMergeTextNodes(node, node_to_be_removed_with_index, - old_length); - }); -} - -void SynchronousMutationNotifier::NotifyMoveTreeToNewDocument( - const Node& root) { - ForEachObserver([&](SynchronousMutationObserver* observer) { - observer->DidMoveTreeToNewDocument(root); - }); -} - -void SynchronousMutationNotifier::NotifySplitTextNode(const Text& node) { - ForEachObserver([&](SynchronousMutationObserver* observer) { - observer->DidSplitTextNode(node); - }); -} - -void SynchronousMutationNotifier::NotifyUpdateCharacterData( - CharacterData* character_data, - unsigned offset, - unsigned old_length, - unsigned new_length) { - ForEachObserver([&](SynchronousMutationObserver* observer) { - observer->DidUpdateCharacterData(character_data, offset, old_length, - new_length); - }); -} - -void SynchronousMutationNotifier::NotifyNodeChildrenWillBeRemoved( - ContainerNode& container) { - ForEachObserver([&](SynchronousMutationObserver* observer) { - observer->NodeChildrenWillBeRemoved(container); - }); -} - -void SynchronousMutationNotifier::NotifyNodeWillBeRemoved(Node& node) { - ForEachObserver([&](SynchronousMutationObserver* observer) { - observer->NodeWillBeRemoved(node); - }); -} - -} // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.h b/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.h deleted file mode 100644 index dd2a04a94e8..00000000000 --- a/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SYNCHRONOUS_MUTATION_NOTIFIER_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SYNCHRONOUS_MUTATION_NOTIFIER_H_ - -#include "base/macros.h" -#include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/platform/lifecycle_notifier.h" - -namespace blink { - -class CharacterData; -class ContainerNode; -class Document; -class Node; -class NodeWithIndex; -class SynchronousMutationObserver; -class Text; - -class CORE_EXPORT SynchronousMutationNotifier - : public LifecycleNotifier<Document, SynchronousMutationObserver> { - public: - // TODO(yosin): We will have |notifyXXX()| functions defined in - // |SynchronousMutationObserver|. - void NotifyChangeChildren(const ContainerNode&); - void NotifyMergeTextNodes(const Text& merged_node, - const NodeWithIndex& node_to_be_removed_with_index, - unsigned old_length); - void NotifyMoveTreeToNewDocument(const Node&); - void NotifySplitTextNode(const Text&); - void NotifyUpdateCharacterData(CharacterData*, - unsigned offset, - unsigned old_length, - unsigned new_length); - void NotifyNodeChildrenWillBeRemoved(ContainerNode&); - void NotifyNodeWillBeRemoved(Node&); - - protected: - SynchronousMutationNotifier(); - - private: - DISALLOW_COPY_AND_ASSIGN(SynchronousMutationNotifier); -}; - -} // namespace dom - -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SYNCHRONOUS_MUTATION_NOTIFIER_H_ diff --git a/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_observer.cc b/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_observer.cc index f3eac687ac3..ce72d1f7c2c 100644 --- a/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_observer.cc +++ b/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_observer.cc @@ -5,24 +5,28 @@ #include "third_party/blink/renderer/core/dom/synchronous_mutation_observer.h" #include "third_party/blink/renderer/core/dom/document.h" -#include "third_party/blink/renderer/core/dom/synchronous_mutation_notifier.h" namespace blink { -SynchronousMutationObserver::SynchronousMutationObserver() - : LifecycleObserver(nullptr) {} - -void SynchronousMutationObserver::DidChangeChildren(const ContainerNode&) {} -void SynchronousMutationObserver::DidMergeTextNodes(const Text&, - const NodeWithIndex&, - unsigned) {} -void SynchronousMutationObserver::DidMoveTreeToNewDocument(const Node&) {} -void SynchronousMutationObserver::DidSplitTextNode(const Text&) {} -void SynchronousMutationObserver::DidUpdateCharacterData(CharacterData*, - unsigned, - unsigned, - unsigned) {} -void SynchronousMutationObserver::NodeChildrenWillBeRemoved(ContainerNode&) {} -void SynchronousMutationObserver::NodeWillBeRemoved(Node&) {} +void SynchronousMutationObserver::ObserverListWillBeCleared() { + document_ = nullptr; +} + +void SynchronousMutationObserver::SetDocument(Document* document) { + if (document == document_) + return; + + if (document_) + document_->SynchronousMutationObserverList().RemoveObserver(this); + + document_ = document; + + if (document_) + document_->SynchronousMutationObserverList().AddObserver(this); +} + +void SynchronousMutationObserver::Trace(Visitor* visitor) { + visitor->Trace(document_); +} } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_observer.h b/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_observer.h index 1ef62cea242..6999e725ad8 100644 --- a/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_observer.h +++ b/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_observer.h @@ -5,9 +5,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SYNCHRONOUS_MUTATION_OBSERVER_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SYNCHRONOUS_MUTATION_OBSERVER_H_ -#include "base/macros.h" #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/platform/lifecycle_observer.h" +#include "third_party/blink/renderer/platform/heap/handle.h" namespace blink { @@ -21,8 +20,8 @@ class Text; // synchronously. If you want to observe DOM tree mutation asynchronously see // MutationObserver Web API. // Note: if you only need to observe Document shutdown, -// DocumentShutdownObserver provides this same functionality more efficiently -// (since it doesn't observe the other events). +// ExecutionContextLifecycleObserver::ContextDestroyed provides this same +// functionality more efficiently (since it doesn't observe the other events). // // TODO(yosin): Following classes should be derived from this class to // simplify Document class. @@ -34,8 +33,7 @@ class Text; // - SelectionController // - Range set // - NodeIterator set -class CORE_EXPORT SynchronousMutationObserver - : public LifecycleObserver<Document, SynchronousMutationObserver> { +class CORE_EXPORT SynchronousMutationObserver : public GarbageCollectedMixin { public: // TODO(yosin): We will have following member functions: // - dataWillBeChanged(const CharacterData&); @@ -44,21 +42,21 @@ class CORE_EXPORT SynchronousMutationObserver // - didRemoveText(Node*, unsigned offset, unsigned length); // Called after child nodes changed. - virtual void DidChangeChildren(const ContainerNode&); + virtual void DidChangeChildren(const ContainerNode&) {} // Called after characters in |nodeToBeRemoved| is appended into |mergedNode|. // |oldLength| holds length of |mergedNode| before merge. virtual void DidMergeTextNodes( const Text& merged_node, const NodeWithIndex& node_to_be_removed_with_index, - unsigned old_length); + unsigned old_length) {} // Called just after node tree |root| is moved to new document. - virtual void DidMoveTreeToNewDocument(const Node& root); + virtual void DidMoveTreeToNewDocument(const Node& root) {} // Called when |Text| node is split, next sibling |oldNode| contains // characters after split point. - virtual void DidSplitTextNode(const Text& old_node); + virtual void DidSplitTextNode(const Text& old_node) {} // Called when |CharacterData| is updated at |offset|, |oldLength| is a // number of deleted character and |newLength| is a number of added @@ -66,22 +64,30 @@ class CORE_EXPORT SynchronousMutationObserver virtual void DidUpdateCharacterData(CharacterData*, unsigned offset, unsigned old_length, - unsigned new_length); + unsigned new_length) {} // Called before removing container node. - virtual void NodeChildrenWillBeRemoved(ContainerNode&); + virtual void NodeChildrenWillBeRemoved(ContainerNode&) {} // Called before removing node. - virtual void NodeWillBeRemoved(Node&); + virtual void NodeWillBeRemoved(Node&) {} // Called when detaching document. - virtual void ContextDestroyed(Document*) {} + virtual void ContextDestroyed() {} + + // Call before clearing an observer list. + void ObserverListWillBeCleared(); + + Document* GetDocument() const { return document_; } + void SetDocument(Document*); + + void Trace(Visitor*) override; protected: - SynchronousMutationObserver(); + SynchronousMutationObserver() = default; private: - DISALLOW_COPY_AND_ASSIGN(SynchronousMutationObserver); + WeakMember<Document> document_; }; } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/tag_collection.h b/chromium/third_party/blink/renderer/core/dom/tag_collection.h index d9842209221..40cbb9c1019 100644 --- a/chromium/third_party/blink/renderer/core/dom/tag_collection.h +++ b/chromium/third_party/blink/renderer/core/dom/tag_collection.h @@ -32,14 +32,6 @@ namespace blink { // Collection that limits to a particular tag. class TagCollection : public HTMLCollection { public: - static TagCollection* Create(ContainerNode& root_node, - CollectionType type, - const AtomicString& qualified_name) { - DCHECK_EQ(type, kTagCollectionType); - return MakeGarbageCollected<TagCollection>(root_node, kTagCollectionType, - qualified_name); - } - TagCollection(ContainerNode& root_node, CollectionType, const AtomicString& qualified_name); @@ -53,13 +45,6 @@ class TagCollection : public HTMLCollection { class TagCollectionNS : public HTMLCollection { public: - static TagCollectionNS* Create(ContainerNode& root_node, - const AtomicString& namespace_uri, - const AtomicString& local_name) { - return MakeGarbageCollected<TagCollectionNS>( - root_node, kTagCollectionNSType, namespace_uri, local_name); - } - TagCollectionNS(ContainerNode& root_node, CollectionType, const AtomicString& namespace_uri, @@ -73,17 +58,19 @@ class TagCollectionNS : public HTMLCollection { AtomicString local_name_; }; -DEFINE_TYPE_CASTS(TagCollection, - LiveNodeListBase, - collection, - collection->GetType() == kTagCollectionType, - collection.GetType() == kTagCollectionType); +template <> +struct DowncastTraits<TagCollection> { + static bool AllowFrom(const LiveNodeListBase& collection) { + return collection.GetType() == kTagCollectionType; + } +}; -DEFINE_TYPE_CASTS(TagCollectionNS, - LiveNodeListBase, - collection, - collection->GetType() == kTagCollectionNSType, - collection.GetType() == kTagCollectionNSType); +template <> +struct DowncastTraits<TagCollectionNS> { + static bool AllowFrom(const LiveNodeListBase& collection) { + return collection.GetType() == kTagCollectionNSType; + } +}; } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/text.idl b/chromium/third_party/blink/renderer/core/dom/text.idl index d199fd7adf7..7a10043d266 100644 --- a/chromium/third_party/blink/renderer/core/dom/text.idl +++ b/chromium/third_party/blink/renderer/core/dom/text.idl @@ -20,10 +20,9 @@ // https://dom.spec.whatwg.org/#interface-text [ - Constructor(optional DOMString data = ""), - ConstructorCallWith=Document, Exposed=Window ] interface Text : CharacterData { + [CallWith=Document] constructor(optional DOMString data = ""); [NewObject, DoNotTestNewObject, RaisesException] Text splitText(unsigned long offset); [MeasureAs=TextWholeText] readonly attribute DOMString wholeText; diff --git a/chromium/third_party/blink/renderer/core/dom/text_link_colors.cc b/chromium/third_party/blink/renderer/core/dom/text_link_colors.cc index 6c38ddaa4db..df6d9db255c 100644 --- a/chromium/third_party/blink/renderer/core/dom/text_link_colors.cc +++ b/chromium/third_party/blink/renderer/core/dom/text_link_colors.cc @@ -85,8 +85,6 @@ Color TextLinkColors::ColorFromCSSValue(const CSSValue& value, return LayoutTheme::GetTheme().FocusRingColor(); case CSSValueID::kCurrentcolor: return current_color; - case CSSValueID::kInternalRootColor: - return LayoutTheme::GetTheme().RootElementColor(color_scheme); default: return StyleColor::ColorFromKeyword(value_id, color_scheme); } diff --git a/chromium/third_party/blink/renderer/core/dom/traversal_range.h b/chromium/third_party/blink/renderer/core/dom/traversal_range.h index 38939a61e34..cd8d349e2a9 100644 --- a/chromium/third_party/blink/renderer/core/dom/traversal_range.h +++ b/chromium/third_party/blink/renderer/core/dom/traversal_range.h @@ -22,7 +22,7 @@ class TraversalRange { Iterator end() { return Iterator::End(); } private: - Member<const StartNodeType> start_; + const StartNodeType* start_; }; template <class Traversal> @@ -39,7 +39,7 @@ class TraversalIteratorBase { protected: explicit TraversalIteratorBase(NodeType* current) : current_(current) {} - Member<NodeType> current_; + NodeType* current_; }; template <class Traversal> @@ -81,7 +81,7 @@ class TraversalDescendantIterator : public TraversalIteratorBase<Traversal> { private: TraversalDescendantIterator() : TraversalIteratorBase<Traversal>(nullptr) {} - Member<const StartNodeType> root_; + const StartNodeType* root_ = nullptr; }; template <class Traversal> @@ -102,7 +102,7 @@ class TraversalInclusiveDescendantIterator } private: - Member<const StartNodeType> root_; + const StartNodeType* root_; }; template <class Traversal> diff --git a/chromium/third_party/blink/renderer/core/dom/tree_scope.cc b/chromium/third_party/blink/renderer/core/dom/tree_scope.cc index 6a30fd0ce23..f1aef848635 100644 --- a/chromium/third_party/blink/renderer/core/dom/tree_scope.cc +++ b/chromium/third_party/blink/renderer/core/dom/tree_scope.cc @@ -34,7 +34,6 @@ #include "third_party/blink/renderer/core/dom/element_traversal.h" #include "third_party/blink/renderer/core/dom/events/event_path.h" #include "third_party/blink/renderer/core/dom/id_target_observer_registry.h" -#include "third_party/blink/renderer/core/dom/node_child_removal_tracker.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h" #include "third_party/blink/renderer/core/dom/shadow_root.h" #include "third_party/blink/renderer/core/dom/tree_scope_adopter.h" @@ -115,13 +114,7 @@ Element* TreeScope::getElementById(const AtomicString& element_id) const { return nullptr; if (!elements_by_id_) return nullptr; - Element* element = elements_by_id_->GetElementById(element_id, *this); - if (element && &RootNode() == &GetDocument() && - GetDocument().InDOMNodeRemovedHandler()) { - if (NodeChildRemovalTracker::IsBeingRemoved(*element)) - GetDocument().CountDetachingNodeAccessInDOMNodeRemovedHandler(); - } - return element; + return elements_by_id_->GetElementById(element_id, *this); } const HeapVector<Member<Element>>& TreeScope::GetAllElementsById( @@ -207,7 +200,7 @@ static bool PointInFrameContentIfVisible(Document& document, return false; // The VisibleContentRect check below requires that scrollbars are up-to-date. - document.UpdateStyleAndLayout(); + document.UpdateStyleAndLayout(DocumentUpdateReason::kHitTest); auto* scrollable_area = frame_view->LayoutViewport(); IntRect visible_frame_rect(IntPoint(), @@ -289,7 +282,7 @@ HeapVector<Member<Element>> TreeScope::ElementsFromHitTestResult( HitTestResult& result) const { HeapVector<Member<Element>> elements; Node* last_node = nullptr; - for (const auto rect_based_node : result.ListBasedTestResult()) { + for (const auto& rect_based_node : result.ListBasedTestResult()) { Node* node = rect_based_node.Get(); if (!node->IsElementNode() && !ShouldAcceptNonElementNode(*node)) continue; diff --git a/chromium/third_party/blink/renderer/core/dom/tree_scope_adopter.h b/chromium/third_party/blink/renderer/core/dom/tree_scope_adopter.h index db59f06c363..0644c27164f 100644 --- a/chromium/third_party/blink/renderer/core/dom/tree_scope_adopter.h +++ b/chromium/third_party/blink/renderer/core/dom/tree_scope_adopter.h @@ -63,15 +63,15 @@ class CORE_EXPORT TreeScopeAdopter { TreeScope& OldScope() const { return *old_scope_; } TreeScope& NewScope() const { return *new_scope_; } - Member<Node> to_adopt_; - Member<TreeScope> new_scope_; - Member<TreeScope> old_scope_; + Node* to_adopt_; + TreeScope* new_scope_; + TreeScope* old_scope_; }; inline TreeScopeAdopter::TreeScopeAdopter(Node& to_adopt, TreeScope& new_scope) - : to_adopt_(to_adopt), - new_scope_(new_scope), - old_scope_(to_adopt.GetTreeScope()) {} + : to_adopt_(&to_adopt), + new_scope_(&new_scope), + old_scope_(&to_adopt.GetTreeScope()) {} } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/dom/user_action_element_set.cc b/chromium/third_party/blink/renderer/core/dom/user_action_element_set.cc index b2985558174..1f19a82a2ef 100644 --- a/chromium/third_party/blink/renderer/core/dom/user_action_element_set.cc +++ b/chromium/third_party/blink/renderer/core/dom/user_action_element_set.cc @@ -33,8 +33,6 @@ namespace blink { UserActionElementSet::UserActionElementSet() = default; -UserActionElementSet::~UserActionElementSet() = default; - void UserActionElementSet::DidDetach(Element& element) { DCHECK(element.IsUserActionElement()); ClearFlags(&element, kIsActiveFlag | kInActiveChainFlag | kIsHoveredFlag | diff --git a/chromium/third_party/blink/renderer/core/dom/user_action_element_set.h b/chromium/third_party/blink/renderer/core/dom/user_action_element_set.h index 408825e8507..23181dacb0f 100644 --- a/chromium/third_party/blink/renderer/core/dom/user_action_element_set.h +++ b/chromium/third_party/blink/renderer/core/dom/user_action_element_set.h @@ -69,7 +69,6 @@ class UserActionElementSet final { } UserActionElementSet(); - ~UserActionElementSet(); void DidDetach(Element&); diff --git a/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc b/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc index 0aff714f64b..b0a904af877 100644 --- a/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc +++ b/chromium/third_party/blink/renderer/core/dom/v0_insertion_point.cc @@ -72,8 +72,8 @@ void V0InsertionPoint::SetDistributedNodes( for (; i < distributed_nodes_.size() && j < distributed_nodes.size(); ++i, ++j) { if (distributed_nodes_.size() < distributed_nodes.size()) { - // If the new distribution is larger than the old one, reattach all nodes - // in the new distribution that were inserted. + // If the new distribution is larger than the old one, notify all nodes in + // the new distribution that were inserted. for (; j < distributed_nodes.size() && distributed_nodes_.at(i) != distributed_nodes.at(j); ++j) @@ -81,26 +81,21 @@ void V0InsertionPoint::SetDistributedNodes( if (j == distributed_nodes.size()) break; } else if (distributed_nodes_.size() > distributed_nodes.size()) { - // If the old distribution is larger than the new one, reattach all nodes - // in the old distribution that were removed. - for (; i < distributed_nodes_.size() && - distributed_nodes_.at(i) != distributed_nodes.at(j); - ++i) - distributed_nodes_.at(i)->FlatTreeParentChanged(); + // If the old distribution is larger than the new one, skip all nodes in + // the old distribution that were removed. + while (i < distributed_nodes_.size() && + distributed_nodes_.at(i) != distributed_nodes.at(j)) + ++i; if (i == distributed_nodes_.size()) break; } else if (distributed_nodes_.at(i) != distributed_nodes.at(j)) { - // If both distributions are the same length reattach both old and new. - distributed_nodes_.at(i)->FlatTreeParentChanged(); + // If both distributions are the same length notify the new. distributed_nodes.at(j)->FlatTreeParentChanged(); } } - // If we hit the end of either list above we need to reattach all remaining - // nodes. - - for (; i < distributed_nodes_.size(); ++i) - distributed_nodes_.at(i)->FlatTreeParentChanged(); + // If we hit the end of either list above we need to notify all remaining + // nodes in the new distribution. for (; j < distributed_nodes.size(); ++j) distributed_nodes.at(j)->FlatTreeParentChanged(); diff --git a/chromium/third_party/blink/renderer/core/dom/whitespace_attacher.cc b/chromium/third_party/blink/renderer/core/dom/whitespace_attacher.cc index a4dbdb24af0..b03567ba2fa 100644 --- a/chromium/third_party/blink/renderer/core/dom/whitespace_attacher.cc +++ b/chromium/third_party/blink/renderer/core/dom/whitespace_attacher.cc @@ -34,7 +34,7 @@ void WhitespaceAttacher::DidReattach(Node* node, LayoutObject* prev_in_flow) { layout_object = prev_in_flow; // Only in-flow boxes affect subsequent whitespace. - if (layout_object && !layout_object->IsFloatingOrOutOfFlowPositioned()) + if (layout_object && layout_object->AffectsWhitespaceSiblings()) ReattachWhitespaceSiblings(layout_object); } @@ -102,7 +102,7 @@ void WhitespaceAttacher::DidVisitElement(Element* element) { SetLastTextNode(nullptr); return; } - if (layout_object->IsFloatingOrOutOfFlowPositioned()) + if (!layout_object->AffectsWhitespaceSiblings()) return; ReattachWhitespaceSiblings(layout_object); } @@ -136,7 +136,7 @@ void WhitespaceAttacher::ReattachWhitespaceSiblings( if (sibling_layout_object) context.previous_in_flow = sibling_layout_object; } else if (sibling_layout_object && - !sibling_layout_object->IsFloatingOrOutOfFlowPositioned()) { + sibling_layout_object->AffectsWhitespaceSiblings()) { break; } context.next_sibling_valid = false; @@ -160,7 +160,8 @@ void WhitespaceAttacher::ForceLastTextNodeNeedsReattach() { void WhitespaceAttacher::UpdateLastTextNodeFromDisplayContents() { DCHECK(last_display_contents_); DCHECK(last_display_contents_->HasDisplayContentsStyle()); - Element* contents_element = last_display_contents_.Release(); + Element* contents_element = last_display_contents_; + last_display_contents_ = nullptr; Node* sibling = LayoutTreeBuilderTraversal::FirstLayoutChild(*contents_element); @@ -183,7 +184,7 @@ void WhitespaceAttacher::UpdateLastTextNodeFromDisplayContents() { last_text_node_ = text; return; } - if (layout_object && !layout_object->IsFloatingOrOutOfFlowPositioned()) { + if (layout_object && layout_object->AffectsWhitespaceSiblings()) { last_text_node_ = nullptr; break; } diff --git a/chromium/third_party/blink/renderer/core/dom/whitespace_attacher.h b/chromium/third_party/blink/renderer/core/dom/whitespace_attacher.h index 2c2b427c1b8..15563dee305 100644 --- a/chromium/third_party/blink/renderer/core/dom/whitespace_attacher.h +++ b/chromium/third_party/blink/renderer/core/dom/whitespace_attacher.h @@ -77,10 +77,10 @@ class CORE_EXPORT WhitespaceAttacher { // Invariants: // DCHECK(!last_display_contents_ || !last_text_node_needs_reattach_) // DCHECK(last_text_node_ || !last_text_node_needs_reattach_) - Member<Element> last_display_contents_ = nullptr; + Element* last_display_contents_ = nullptr; // The last text node we've visited during rebuild for this attacher. - Member<Text> last_text_node_ = nullptr; + Text* last_text_node_ = nullptr; // Set to true if we need to re-attach last_text_node_ when: // 1. We visiting a previous in-flow sibling, or diff --git a/chromium/third_party/blink/renderer/core/dom/whitespace_attacher_test.cc b/chromium/third_party/blink/renderer/core/dom/whitespace_attacher_test.cc index da281640af4..f4ffb1b13a5 100644 --- a/chromium/third_party/blink/renderer/core/dom/whitespace_attacher_test.cc +++ b/chromium/third_party/blink/renderer/core/dom/whitespace_attacher_test.cc @@ -6,10 +6,10 @@ #include <gtest/gtest.h> #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_shadow_root_init.h" #include "third_party/blink/renderer/core/css/style_engine.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h" #include "third_party/blink/renderer/core/dom/shadow_root.h" -#include "third_party/blink/renderer/core/dom/shadow_root_init.h" #include "third_party/blink/renderer/core/layout/layout_text.h" #include "third_party/blink/renderer/core/testing/page_test_base.h" @@ -24,7 +24,7 @@ class WhitespaceAttacherTest : public PageTestBase { }; TEST_F(WhitespaceAttacherTest, WhitespaceAfterReattachedBlock) { - GetDocument().body()->SetInnerHTMLFromString("<div id=block></div> "); + GetDocument().body()->setInnerHTML("<div id=block></div> "); UpdateAllLifecyclePhasesForTest(); Element* div = GetDocument().getElementById("block"); @@ -44,7 +44,7 @@ TEST_F(WhitespaceAttacherTest, WhitespaceAfterReattachedBlock) { } TEST_F(WhitespaceAttacherTest, WhitespaceAfterReattachedInline) { - GetDocument().body()->SetInnerHTMLFromString("<span id=inline></span> "); + GetDocument().body()->setInnerHTML("<span id=inline></span> "); UpdateAllLifecyclePhasesForTest(); Element* span = GetDocument().getElementById("inline"); @@ -63,8 +63,7 @@ TEST_F(WhitespaceAttacherTest, WhitespaceAfterReattachedInline) { } TEST_F(WhitespaceAttacherTest, WhitespaceAfterReattachedWhitespace) { - GetDocument().body()->SetInnerHTMLFromString( - "<span id=inline></span> <!-- --> "); + GetDocument().body()->setInnerHTML("<span id=inline></span> <!-- --> "); UpdateAllLifecyclePhasesForTest(); Element* span = GetDocument().getElementById("inline"); @@ -90,7 +89,7 @@ TEST_F(WhitespaceAttacherTest, WhitespaceAfterReattachedWhitespace) { } TEST_F(WhitespaceAttacherTest, VisitBlockAfterReattachedWhitespace) { - GetDocument().body()->SetInnerHTMLFromString("<div id=block></div> "); + GetDocument().body()->setInnerHTML("<div id=block></div> "); UpdateAllLifecyclePhasesForTest(); Element* div = GetDocument().getElementById("block"); @@ -108,7 +107,7 @@ TEST_F(WhitespaceAttacherTest, VisitBlockAfterReattachedWhitespace) { } TEST_F(WhitespaceAttacherTest, VisitInlineAfterReattachedWhitespace) { - GetDocument().body()->SetInnerHTMLFromString("<span id=inline></span> "); + GetDocument().body()->setInnerHTML("<span id=inline></span> "); UpdateAllLifecyclePhasesForTest(); Element* span = GetDocument().getElementById("inline"); @@ -129,7 +128,7 @@ TEST_F(WhitespaceAttacherTest, VisitInlineAfterReattachedWhitespace) { } TEST_F(WhitespaceAttacherTest, VisitTextAfterReattachedWhitespace) { - GetDocument().body()->SetInnerHTMLFromString("Text<!-- --> "); + GetDocument().body()->setInnerHTML("Text<!-- --> "); UpdateAllLifecyclePhasesForTest(); auto* text = To<Text>(GetDocument().body()->firstChild()); @@ -152,7 +151,7 @@ TEST_F(WhitespaceAttacherTest, VisitTextAfterReattachedWhitespace) { } TEST_F(WhitespaceAttacherTest, ReattachWhitespaceInsideBlockExitingScope) { - GetDocument().body()->SetInnerHTMLFromString("<div id=block> </div>"); + GetDocument().body()->setInnerHTML("<div id=block> </div>"); UpdateAllLifecyclePhasesForTest(); Element* div = GetDocument().getElementById("block"); @@ -174,7 +173,7 @@ TEST_F(WhitespaceAttacherTest, ReattachWhitespaceInsideBlockExitingScope) { } TEST_F(WhitespaceAttacherTest, ReattachWhitespaceInsideInlineExitingScope) { - GetDocument().body()->SetInnerHTMLFromString("<span id=inline> </span>"); + GetDocument().body()->setInnerHTML("<span id=inline> </span>"); UpdateAllLifecyclePhasesForTest(); Element* span = GetDocument().getElementById("inline"); @@ -195,13 +194,13 @@ TEST_F(WhitespaceAttacherTest, ReattachWhitespaceInsideInlineExitingScope) { } TEST_F(WhitespaceAttacherTest, SlottedWhitespaceAfterReattachedBlock) { - GetDocument().body()->SetInnerHTMLFromString("<div id=host> </div>"); + GetDocument().body()->setInnerHTML("<div id=host> </div>"); Element* host = GetDocument().getElementById("host"); ASSERT_TRUE(host); ShadowRoot& shadow_root = host->AttachShadowRootInternal(ShadowRootType::kOpen); - shadow_root.SetInnerHTMLFromString("<div id=block></div><slot></slot>"); + shadow_root.setInnerHTML("<div id=block></div><slot></slot>"); UpdateAllLifecyclePhasesForTest(); Element* div = shadow_root.getElementById("block"); @@ -223,13 +222,13 @@ TEST_F(WhitespaceAttacherTest, SlottedWhitespaceAfterReattachedBlock) { } TEST_F(WhitespaceAttacherTest, SlottedWhitespaceAfterReattachedInline) { - GetDocument().body()->SetInnerHTMLFromString("<div id=host> </div>"); + GetDocument().body()->setInnerHTML("<div id=host> </div>"); Element* host = GetDocument().getElementById("host"); ASSERT_TRUE(host); ShadowRoot& shadow_root = host->AttachShadowRootInternal(ShadowRootType::kOpen); - shadow_root.SetInnerHTMLFromString("<span id=inline></span><slot></slot>"); + shadow_root.setInnerHTML("<span id=inline></span><slot></slot>"); UpdateAllLifecyclePhasesForTest(); Element* span = shadow_root.getElementById("inline"); @@ -251,7 +250,7 @@ TEST_F(WhitespaceAttacherTest, SlottedWhitespaceAfterReattachedInline) { TEST_F(WhitespaceAttacherTest, WhitespaceInDisplayContentsAfterReattachedBlock) { - GetDocument().body()->SetInnerHTMLFromString( + GetDocument().body()->setInnerHTML( "<div id=block></div><span style='display:contents'> </span>"); UpdateAllLifecyclePhasesForTest(); @@ -277,7 +276,7 @@ TEST_F(WhitespaceAttacherTest, TEST_F(WhitespaceAttacherTest, WhitespaceInDisplayContentsAfterReattachedInline) { - GetDocument().body()->SetInnerHTMLFromString( + GetDocument().body()->setInnerHTML( "<span id=inline></span><span style='display:contents'> </span>"); UpdateAllLifecyclePhasesForTest(); @@ -302,7 +301,7 @@ TEST_F(WhitespaceAttacherTest, TEST_F(WhitespaceAttacherTest, WhitespaceAfterEmptyDisplayContentsAfterReattachedBlock) { - GetDocument().body()->SetInnerHTMLFromString( + GetDocument().body()->setInnerHTML( "<div id=block></div><span style='display:contents'></span> "); UpdateAllLifecyclePhasesForTest(); @@ -329,7 +328,7 @@ TEST_F(WhitespaceAttacherTest, TEST_F(WhitespaceAttacherTest, WhitespaceAfterDisplayContentsWithDisplayNoneChildAfterReattachedBlock) { - GetDocument().body()->SetInnerHTMLFromString( + GetDocument().body()->setInnerHTML( "<div id=block></div><span style='display:contents'>" "<span style='display:none'></span></span> "); UpdateAllLifecyclePhasesForTest(); @@ -356,7 +355,7 @@ TEST_F(WhitespaceAttacherTest, } TEST_F(WhitespaceAttacherTest, WhitespaceDeepInsideDisplayContents) { - GetDocument().body()->SetInnerHTMLFromString( + GetDocument().body()->setInnerHTML( "<span id=inline></span><span style='display:contents'>" "<span style='display:none'></span>" "<span id=inner style='display:contents'> </span></span>"); @@ -381,7 +380,7 @@ TEST_F(WhitespaceAttacherTest, WhitespaceDeepInsideDisplayContents) { } TEST_F(WhitespaceAttacherTest, MultipleDisplayContents) { - GetDocument().body()->SetInnerHTMLFromString( + GetDocument().body()->setInnerHTML( "<span id=inline></span>" "<span style='display:contents'></span>" "<span style='display:contents'></span>" @@ -411,13 +410,13 @@ TEST_F(WhitespaceAttacherTest, MultipleDisplayContents) { } TEST_F(WhitespaceAttacherTest, SlottedWhitespaceInsideDisplayContents) { - GetDocument().body()->SetInnerHTMLFromString("<div id=host> </div>"); + GetDocument().body()->setInnerHTML("<div id=host> </div>"); Element* host = GetDocument().getElementById("host"); ASSERT_TRUE(host); ShadowRoot& shadow_root = host->AttachShadowRootInternal(ShadowRootType::kOpen); - shadow_root.SetInnerHTMLFromString( + shadow_root.setInnerHTML( "<span id=inline></span>" "<div style='display:contents'><slot></slot></div>"); UpdateAllLifecyclePhasesForTest(); @@ -441,7 +440,7 @@ TEST_F(WhitespaceAttacherTest, SlottedWhitespaceInsideDisplayContents) { } TEST_F(WhitespaceAttacherTest, RemoveInlineBeforeSpace) { - GetDocument().body()->SetInnerHTMLFromString("<span id=inline></span> "); + GetDocument().body()->setInnerHTML("<span id=inline></span> "); UpdateAllLifecyclePhasesForTest(); Element* span = GetDocument().getElementById("inline"); @@ -463,7 +462,7 @@ TEST_F(WhitespaceAttacherTest, RemoveInlineBeforeSpace) { } TEST_F(WhitespaceAttacherTest, RemoveInlineBeforeOutOfFlowBeforeSpace) { - GetDocument().body()->SetInnerHTMLFromString( + GetDocument().body()->setInnerHTML( "<span id=inline></span><div id=float style='float:right'></div> "); UpdateAllLifecyclePhasesForTest(); @@ -489,7 +488,7 @@ TEST_F(WhitespaceAttacherTest, RemoveInlineBeforeOutOfFlowBeforeSpace) { } TEST_F(WhitespaceAttacherTest, RemoveSpaceBeforeSpace) { - GetDocument().body()->SetInnerHTMLFromString("<span> <!-- --> </span>"); + GetDocument().body()->setInnerHTML("<span> <!-- --> </span>"); UpdateAllLifecyclePhasesForTest(); Node* span = GetDocument().body()->firstChild(); @@ -512,7 +511,7 @@ TEST_F(WhitespaceAttacherTest, RemoveSpaceBeforeSpace) { } TEST_F(WhitespaceAttacherTest, RemoveInlineBeforeDisplayContentsWithSpace) { - GetDocument().body()->SetInnerHTMLFromString( + GetDocument().body()->setInnerHTML( "<style>div { display: contents }</style>" "<div><span id=inline></span></div>" "<div><div><div id=innerdiv> </div></div></div>text"); @@ -533,8 +532,7 @@ TEST_F(WhitespaceAttacherTest, RemoveInlineBeforeDisplayContentsWithSpace) { } TEST_F(WhitespaceAttacherTest, RemoveBlockBeforeSpace) { - GetDocument().body()->SetInnerHTMLFromString( - "A<div id=block></div> <span>B</span>"); + GetDocument().body()->setInnerHTML("A<div id=block></div> <span>B</span>"); UpdateAllLifecyclePhasesForTest(); Node* div = GetDocument().getElementById("block"); diff --git a/chromium/third_party/blink/renderer/core/dom/xml_document.h b/chromium/third_party/blink/renderer/core/dom/xml_document.h index 95828e80e86..858e7f68c79 100644 --- a/chromium/third_party/blink/renderer/core/dom/xml_document.h +++ b/chromium/third_party/blink/renderer/core/dom/xml_document.h @@ -50,7 +50,12 @@ class XMLDocument final : public Document { DocumentClassFlags document_classes = kXMLDocumentClass); }; -DEFINE_DOCUMENT_TYPE_CASTS(XMLDocument); +template <> +struct DowncastTraits<XMLDocument> { + static bool AllowFrom(const Document& document) { + return document.IsXMLDocument(); + } +}; } // namespace blink |