From 8e7a96f644d510631bb09cda15b0e37afd46105a Mon Sep 17 00:00:00 2001 From: Mason Freed Date: Thu, 12 Nov 2020 04:05:03 +0000 Subject: [PATCH] Update declarative Shadow DOM opt-in mechanics The issue thread [1] has had more discussion, after the initial draft of declarative Shadow DOM opt-in landed [2]. This CL implements those bits of feedback. In particular: - There is no public allowDeclarativeShadowDom state available on Document or DocumentFragment. - All APIs use call parameters to avoid state, with the exception of DOMParser. - innerHTML no longer supports Declarative Shadow DOM. - A new setInnerHTML() function allows opt-in access to DSD. - Several of the more obscure APIs do not have an opt-in for declarative Shadow DOM, such as XHR, createContextualFragment, and document.write. - The sandbox flag has been removed from iframes completely. The new plan is to use DocumentPolicy to enable declarative Shadow DOM for iframes. For now, iframes always support declarative Shadow DOM. - 'allowDeclarativeShadowDOM' has become 'allowShadowRoot'. [1] https://github.com/whatwg/dom/issues/912#issuecomment-723188817 [2] https://chromium-review.googlesource.com/c/chromium/src/+/2513525 Bug: 1042130 Change-Id: I3a2becf2a113cc8647b29077d2efea1c990d4547 Cq-Do-Not-Cancel-Tryjobs: true Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2530222 Auto-Submit: Mason Freed Reviewed-by: Kouhei Ueno Reviewed-by: Kinuko Yasuda Commit-Queue: Mason Freed Cr-Commit-Position: refs/heads/master@{#826643} GitOrigin-RevId: d5bf4401a47f04cbfbcca5d7fb4be5f99fa41e19 --- blink/common/feature_policy/feature_policy.cc | 1 - blink/renderer/bindings/generated_in_core.gni | 4 + blink/renderer/bindings/idl_in_core.gni | 2 + blink/renderer/core/core_idl_files.gni | 2 + blink/renderer/core/dom/document.cc | 14 +- blink/renderer/core/dom/document.h | 11 +- blink/renderer/core/dom/document.idl | 3 - blink/renderer/core/dom/document_fragment.idl | 2 - blink/renderer/core/dom/dom_implementation.cc | 1 + blink/renderer/core/dom/element.cc | 32 +++- blink/renderer/core/dom/element.h | 8 + blink/renderer/core/dom/element.idl | 5 +- .../core/dom/set_inner_html_options.idl | 7 + blink/renderer/core/dom/shadow_root.cc | 27 +++- blink/renderer/core/dom/shadow_root.h | 8 + blink/renderer/core/dom/shadow_root.idl | 4 + .../renderer/core/dom/slot_assignment_test.cc | 10 +- .../core/editing/serializers/serialization.cc | 8 +- .../core/editing/serializers/serialization.h | 1 + .../renderer/core/html/html_iframe_element.cc | 10 +- .../html/parser/html_construction_site.cc | 7 +- .../core/html/parser/html_construction_site.h | 4 +- .../core/html/parser/html_document_parser.cc | 35 ++--- .../core/html/parser/html_tree_builder.cc | 13 +- .../core/html/parser/html_tree_builder.h | 6 +- blink/renderer/core/xml/dom_parser.cc | 9 +- blink/renderer/core/xml/dom_parser.h | 17 +-- blink/renderer/core/xml/dom_parser.idl | 3 +- blink/renderer/core/xml/dom_parser_init.idl | 7 + .../core/xmlhttprequest/xml_http_request.cc | 7 +- .../core/xmlhttprequest/xml_http_request.h | 9 -- .../core/xmlhttprequest/xml_http_request.idl | 2 - .../platform/bindings/runtime_call_stats.h | 1 + ...ative-shadow-dom-attachment.tentative.html | 4 +- ...eclarative-shadow-dom-basic.tentative.html | 32 ++-- ...clarative-shadow-dom-opt-in.tentative.html | 144 +++++++----------- .../declarative/getinnerhtml.tentative.html | 2 +- .../declarative/setinnerhtml.tentative.html | 39 +++++ ...ve-shadow-dom-origin-trial-interfaces.html | 18 +-- .../resources/declarative-child-frame.html | 17 --- ...w-dom-origin-trial-interfaces-expected.txt | 5 - ...ent-instance-property-listing-expected.txt | 2 + ...face-listing-dedicated-worker-expected.txt | 2 - .../global-interface-listing-expected.txt | 10 +- ...terface-listing-shared-worker-expected.txt | 2 - 45 files changed, 277 insertions(+), 280 deletions(-) create mode 100644 blink/renderer/core/dom/set_inner_html_options.idl create mode 100644 blink/renderer/core/xml/dom_parser_init.idl create mode 100644 blink/web_tests/external/wpt/shadow-dom/declarative/setinnerhtml.tentative.html delete mode 100644 blink/web_tests/http/tests/origin_trials/webexposed/resources/declarative-child-frame.html delete mode 100644 blink/web_tests/virtual/origin-trials-runtimeflags-disabled/http/tests/origin_trials/webexposed/declarative-shadow-dom-origin-trial-interfaces-expected.txt diff --git a/blink/common/feature_policy/feature_policy.cc b/blink/common/feature_policy/feature_policy.cc index 9bb50569b936..e769150081ec 100644 --- a/blink/common/feature_policy/feature_policy.cc +++ b/blink/common/feature_policy/feature_policy.cc @@ -314,7 +314,6 @@ mojom::FeaturePolicyFeature FeaturePolicy::FeatureForSandboxFlag( kPropagatesToAuxiliaryBrowsingContexts: case network::mojom::WebSandboxFlags::kTopNavigationByUserActivation: case network::mojom::WebSandboxFlags::kStorageAccessByUserActivation: - case network::mojom::WebSandboxFlags::kDeclarativeShadowDom: break; } return mojom::FeaturePolicyFeature::kNotFound; diff --git a/blink/renderer/bindings/generated_in_core.gni b/blink/renderer/bindings/generated_in_core.gni index d6761bd28c15..dbdf05c66645 100644 --- a/blink/renderer/bindings/generated_in_core.gni +++ b/blink/renderer/bindings/generated_in_core.gni @@ -111,6 +111,8 @@ generated_dictionary_sources_in_core = [ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_dom_matrix_2d_init.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_dom_matrix_init.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_dom_matrix_init.h", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_dom_parser_init.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_dom_parser_init.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_dom_point_init.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_dom_point_init.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_dom_quad_init.cc", @@ -299,6 +301,8 @@ generated_dictionary_sources_in_core = [ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_scroll_to_options.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_security_policy_violation_event_init.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_security_policy_violation_event_init.h", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_set_inner_html_options.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_set_inner_html_options.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_shadow_root_init.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_shadow_root_init.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_stream_pipe_options.h", diff --git a/blink/renderer/bindings/idl_in_core.gni b/blink/renderer/bindings/idl_in_core.gni index ab6bc2c5d5b4..810729ca1d2f 100644 --- a/blink/renderer/bindings/idl_in_core.gni +++ b/blink/renderer/bindings/idl_in_core.gni @@ -162,6 +162,7 @@ static_idl_files_in_core = get_path_info( "//third_party/blink/renderer/core/dom/pointer_lock_options.idl", "//third_party/blink/renderer/core/dom/processing_instruction.idl", "//third_party/blink/renderer/core/dom/range.idl", + "//third_party/blink/renderer/core/dom/set_inner_html_options.idl", "//third_party/blink/renderer/core/dom/shadow_root.idl", "//third_party/blink/renderer/core/dom/shadow_root_init.idl", "//third_party/blink/renderer/core/dom/static_range.idl", @@ -664,6 +665,7 @@ static_idl_files_in_core = get_path_info( "//third_party/blink/renderer/core/workers/worklet_options.idl", "//third_party/blink/renderer/core/xml/document_xpath_evaluator.idl", "//third_party/blink/renderer/core/xml/dom_parser.idl", + "//third_party/blink/renderer/core/xml/dom_parser_init.idl", "//third_party/blink/renderer/core/xml/xml_serializer.idl", "//third_party/blink/renderer/core/xml/xpath_evaluator.idl", "//third_party/blink/renderer/core/xml/xpath_expression.idl", diff --git a/blink/renderer/core/core_idl_files.gni b/blink/renderer/core/core_idl_files.gni index fb848b61bfb9..a6ddd2d869cc 100644 --- a/blink/renderer/core/core_idl_files.gni +++ b/blink/renderer/core/core_idl_files.gni @@ -652,6 +652,7 @@ core_dictionary_idl_files = "dom/idle_request_options.idl", "dom/mutation_observer_init.idl", "dom/pointer_lock_options.idl", + "dom/set_inner_html_options.idl", "dom/shadow_root_init.idl", "dom/events/add_event_listener_options.idl", "dom/events/custom_event_init.idl", @@ -758,6 +759,7 @@ core_dictionary_idl_files = "trustedtypes/trusted_type_policy_options.idl", "workers/worker_options.idl", "workers/worklet_options.idl", + "xml/dom_parser_init.idl", ], "abspath") diff --git a/blink/renderer/core/dom/document.cc b/blink/renderer/core/dom/document.cc index ef59d118e2f6..dc456c70a933 100644 --- a/blink/renderer/core/dom/document.cc +++ b/blink/renderer/core/dom/document.cc @@ -6962,20 +6962,16 @@ void Document::MarkFirstPaint() { MaybeExecuteDelayedAsyncScripts(); } -using AllowState = blink::Document::DeclarativeShadowDomAllowState; -AllowState Document::GetDeclarativeShadowDomAllowState() const { - return declarative_shadow_dom_allow_state_; +using AllowState = blink::Document::DeclarativeShadowRootAllowState; +AllowState Document::GetDeclarativeShadowRootAllowState() const { + return declarative_shadow_root_allow_state_; } -void Document::setAllowDeclarativeShadowDom(bool val) { - declarative_shadow_dom_allow_state_ = +void Document::setAllowDeclarativeShadowRoot(bool val) { + declarative_shadow_root_allow_state_ = val ? AllowState::kAllow : AllowState::kDeny; } -bool Document::allowDeclarativeShadowDom() const { - return declarative_shadow_dom_allow_state_ == AllowState::kAllow; -} - void Document::FinishedParsing() { DCHECK(!GetScriptableDocumentParser() || !parser_->IsParsing()); DCHECK(!GetScriptableDocumentParser() || ready_state_ != kLoading); diff --git a/blink/renderer/core/dom/document.h b/blink/renderer/core/dom/document.h index 5626867051c9..b64972025224 100644 --- a/blink/renderer/core/dom/document.h +++ b/blink/renderer/core/dom/document.h @@ -1662,14 +1662,13 @@ class CORE_EXPORT Document : public ContainerNode, void MarkFirstPaint(); void MaybeExecuteDelayedAsyncScripts(); - enum class DeclarativeShadowDomAllowState : uint8_t { + enum class DeclarativeShadowRootAllowState : uint8_t { kNotSet, kAllow, kDeny }; - DeclarativeShadowDomAllowState GetDeclarativeShadowDomAllowState() const; - void setAllowDeclarativeShadowDom(bool val); - bool allowDeclarativeShadowDom() const; + DeclarativeShadowRootAllowState GetDeclarativeShadowRootAllowState() const; + void setAllowDeclarativeShadowRoot(bool val); void SetFindInPageActiveMatchNode(Node*); const Node* GetFindInPageActiveMatchNode() const; @@ -2212,8 +2211,8 @@ class CORE_EXPORT Document : public ContainerNode, int async_script_count_ = 0; bool first_paint_recorded_ = false; - DeclarativeShadowDomAllowState declarative_shadow_dom_allow_state_ = - DeclarativeShadowDomAllowState::kNotSet; + DeclarativeShadowRootAllowState declarative_shadow_root_allow_state_ = + DeclarativeShadowRootAllowState::kNotSet; WeakMember find_in_page_active_match_node_; diff --git a/blink/renderer/core/dom/document.idl b/blink/renderer/core/dom/document.idl index 745e9e7e0b99..c65d96e3cfb1 100644 --- a/blink/renderer/core/dom/document.idl +++ b/blink/renderer/core/dom/document.idl @@ -197,9 +197,6 @@ typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement; // https://w3c.github.io/webappsec-feature-policy/#the-policy-object readonly attribute FeaturePolicy featurePolicy; - // Declarative Shadow DOM API - [RuntimeEnabled=DeclarativeShadowDOM] attribute boolean allowDeclarativeShadowDom; - // Deprecated prefixed page visibility API. // TODO(davidben): This is a property so attaching a deprecation warning results in false positives when outputting // document in the console. It's possible https://crbug.com/43394 will resolve this. diff --git a/blink/renderer/core/dom/document_fragment.idl b/blink/renderer/core/dom/document_fragment.idl index 585ead841737..ddb78da31852 100644 --- a/blink/renderer/core/dom/document_fragment.idl +++ b/blink/renderer/core/dom/document_fragment.idl @@ -23,8 +23,6 @@ Exposed=Window ] interface DocumentFragment : Node { [CallWith=Document] constructor(); - - [RuntimeEnabled=DeclarativeShadowDOM] attribute boolean allowDeclarativeShadowDom; }; DocumentFragment includes ParentNode; diff --git a/blink/renderer/core/dom/dom_implementation.cc b/blink/renderer/core/dom/dom_implementation.cc index 99fe3246a18f..0c172c250f3f 100644 --- a/blink/renderer/core/dom/dom_implementation.cc +++ b/blink/renderer/core/dom/dom_implementation.cc @@ -109,6 +109,7 @@ Document* DOMImplementation::createHTMLDocument(const String& title) { .WithExecutionContext(document_->GetExecutionContext()) .WithRegistrationContext(document_->RegistrationContext()); auto* d = MakeGarbageCollected(init); + d->setAllowDeclarativeShadowRoot(false); d->open(); d->write(""); if (!title.IsNull()) { diff --git a/blink/renderer/core/dom/element.cc b/blink/renderer/core/dom/element.cc index 5286351d515b..071dbf647483 100644 --- a/blink/renderer/core/dom/element.cc +++ b/blink/renderer/core/dom/element.cc @@ -44,6 +44,7 @@ #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_set_inner_html_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" @@ -4462,14 +4463,17 @@ String Element::outerHTML() const { return CreateMarkup(this); } -void Element::setInnerHTML(const String& html, - ExceptionState& exception_state) { - probe::BreakableLocation(GetExecutionContext(), "Element.setInnerHTML"); +void Element::SetInnerHTMLInternal(const String& html, + const SetInnerHTMLOptions* options, + ExceptionState& exception_state) { if (html.IsEmpty() && !HasNonInBodyInsertionMode()) { setTextContent(html); } else { + bool allow_shadow_root = + options->hasAllowShadowRoot() && options->allowShadowRoot(); if (DocumentFragment* fragment = CreateFragmentForInnerOuterHTML( - html, this, kAllowScriptingContent, "innerHTML", exception_state)) { + html, this, kAllowScriptingContent, "innerHTML", allow_shadow_root, + exception_state)) { ContainerNode* container = this; if (auto* template_element = DynamicTo(*this)) { // Allow replacing innerHTML on declarative shadow templates, prior to @@ -4483,6 +4487,21 @@ void Element::setInnerHTML(const String& html, } } +void Element::setInnerHTML(const String& html, + ExceptionState& exception_state) { + probe::BreakableLocation(GetExecutionContext(), "Element.setInnerHTML"); + const SetInnerHTMLOptions options; + SetInnerHTMLInternal(html, &options, exception_state); +} + +void Element::setInnerHTMLWithOptions(const String& html, + const SetInnerHTMLOptions* options, + ExceptionState& exception_state) { + DCHECK(RuntimeEnabledFeatures::DeclarativeShadowDOMEnabled( + GetExecutionContext())); + SetInnerHTMLInternal(html, options, exception_state); +} + String Element::getInnerHTML(const GetInnerHTMLOptions* options) const { DCHECK(RuntimeEnabledFeatures::DeclarativeShadowDOMEnabled( GetExecutionContext())); @@ -4521,7 +4540,8 @@ void Element::setOuterHTML(const String& html, Node* next = nextSibling(); DocumentFragment* fragment = CreateFragmentForInnerOuterHTML( - html, parent, kAllowScriptingContent, "outerHTML", exception_state); + html, parent, kAllowScriptingContent, "outerHTML", + /*allow_shadow_root=*/false, exception_state); if (exception_state.HadException()) return; @@ -4703,7 +4723,7 @@ void Element::insertAdjacentHTML(const String& where, // Step 3 of http://domparsing.spec.whatwg.org/#insertadjacenthtml() DocumentFragment* fragment = CreateFragmentForInnerOuterHTML( markup, context_element, kAllowScriptingContent, "insertAdjacentHTML", - exception_state); + /*allow_shadow_root=*/false, exception_state); if (!fragment) return; InsertAdjacent(where, fragment, exception_state); diff --git a/blink/renderer/core/dom/element.h b/blink/renderer/core/dom/element.h index a46e9abb2795..d99e36e734ed 100644 --- a/blink/renderer/core/dom/element.h +++ b/blink/renderer/core/dom/element.h @@ -66,6 +66,7 @@ class ExceptionState; class FloatQuad; class FloatSize; class FocusOptions; +class SetInnerHTMLOptions; class GetInnerHTMLOptions; class HTMLTemplateElement; class Image; @@ -697,6 +698,9 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { String innerHTML() const; String outerHTML() const; void setInnerHTML(const String&, ExceptionState& = ASSERT_NO_EXCEPTION); + void setInnerHTMLWithOptions(const String&, + const SetInnerHTMLOptions*, + ExceptionState& = ASSERT_NO_EXCEPTION); String getInnerHTML(const GetInnerHTMLOptions* options) const; void setOuterHTML(const String&, ExceptionState& = ASSERT_NO_EXCEPTION); @@ -1185,6 +1189,10 @@ class CORE_EXPORT Element : public ContainerNode, public Animatable { const QualifiedName&, const AtomicString&); + void SetInnerHTMLInternal(const String&, + const SetInnerHTMLOptions*, + ExceptionState&); + ElementRareData* GetElementRareData() const; ElementRareData& EnsureElementRareData(); diff --git a/blink/renderer/core/dom/element.idl b/blink/renderer/core/dom/element.idl index c1a02c04cf78..fc722ba013d0 100644 --- a/blink/renderer/core/dom/element.idl +++ b/blink/renderer/core/dom/element.idl @@ -96,8 +96,9 @@ callback ScrollStateCallback = void (ScrollState scrollState); [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(optional GetInnerHTMLOptions options = {}); + // Declarative Shadow DOM setInnerHTML/getInnerHTML() functions. + [Affects=Nothing, RuntimeEnabled=DeclarativeShadowDOM, RuntimeCallStatsCounter=ElementSetInnerHTML, RaisesException, ImplementedAs=setInnerHTMLWithOptions] void setInnerHTML(DOMString html, optional SetInnerHTMLOptions options = {}); + [Affects=Nothing, RuntimeEnabled=DeclarativeShadowDOM, RuntimeCallStatsCounter=ElementGetInnerHTML] HTMLString getInnerHTML(optional GetInnerHTMLOptions options = {}); // Pointer Lock // https://w3c.github.io/pointerlock/#extensions-to-the-element-interface diff --git a/blink/renderer/core/dom/set_inner_html_options.idl b/blink/renderer/core/dom/set_inner_html_options.idl new file mode 100644 index 000000000000..5e5d89d95326 --- /dev/null +++ b/blink/renderer/core/dom/set_inner_html_options.idl @@ -0,0 +1,7 @@ +// Copyright 2020 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. + +dictionary SetInnerHTMLOptions { + boolean allowShadowRoot = false; +}; diff --git a/blink/renderer/core/dom/shadow_root.cc b/blink/renderer/core/dom/shadow_root.cc index 73304f8246e0..1a1b104f7d56 100644 --- a/blink/renderer/core/dom/shadow_root.cc +++ b/blink/renderer/core/dom/shadow_root.cc @@ -27,6 +27,7 @@ #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/v8_set_inner_html_options.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" @@ -116,12 +117,30 @@ String ShadowRoot::innerHTML() const { return CreateMarkup(this, kChildrenOnly); } -void ShadowRoot::setInnerHTML(const String& markup, - ExceptionState& exception_state) { +void ShadowRoot::SetInnerHTMLInternal(const String& html, + const SetInnerHTMLOptions* options, + ExceptionState& exception_state) { + bool allow_shadow_root = + options->hasAllowShadowRoot() && options->allowShadowRoot(); if (DocumentFragment* fragment = CreateFragmentForInnerOuterHTML( - markup, &host(), kAllowScriptingContent, "innerHTML", - exception_state)) + html, &host(), kAllowScriptingContent, "innerHTML", allow_shadow_root, + exception_state)) { ReplaceChildrenWithFragment(this, fragment, exception_state); + } +} + +void ShadowRoot::setInnerHTML(const String& html, + ExceptionState& exception_state) { + const SetInnerHTMLOptions options; + SetInnerHTMLInternal(html, &options, exception_state); +} + +void ShadowRoot::setInnerHTMLWithOptions(const String& html, + const SetInnerHTMLOptions* options, + ExceptionState& exception_state) { + DCHECK(RuntimeEnabledFeatures::DeclarativeShadowDOMEnabled( + GetExecutionContext())); + SetInnerHTMLInternal(html, options, exception_state); } void ShadowRoot::RebuildLayoutTree(WhitespaceAttacher& whitespace_attacher) { diff --git a/blink/renderer/core/dom/shadow_root.h b/blink/renderer/core/dom/shadow_root.h index d1e29347d9b5..379c02a26c19 100644 --- a/blink/renderer/core/dom/shadow_root.h +++ b/blink/renderer/core/dom/shadow_root.h @@ -40,6 +40,7 @@ namespace blink { class Document; class ExceptionState; +class SetInnerHTMLOptions; class ShadowRootV0; class SlotAssignment; class WhitespaceAttacher; @@ -138,6 +139,9 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope { String innerHTML() const; void setInnerHTML(const String&, ExceptionState& = ASSERT_NO_EXCEPTION); + void setInnerHTMLWithOptions(const String&, + const SetInnerHTMLOptions*, + ExceptionState& = ASSERT_NO_EXCEPTION); Node* Clone(Document&, CloneChildrenFlag) const override; @@ -188,6 +192,10 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope { SlotAssignment& EnsureSlotAssignment(); + void SetInnerHTMLInternal(const String&, + const SetInnerHTMLOptions*, + ExceptionState&); + void AddChildShadowRoot() { ++child_shadow_root_count_; } void RemoveChildShadowRoot() { DCHECK_GT(child_shadow_root_count_, 0u); diff --git a/blink/renderer/core/dom/shadow_root.idl b/blink/renderer/core/dom/shadow_root.idl index 0080770117d0..61cfe03df10e 100644 --- a/blink/renderer/core/dom/shadow_root.idl +++ b/blink/renderer/core/dom/shadow_root.idl @@ -35,6 +35,10 @@ interface ShadowRoot : DocumentFragment { [CEReactions, CustomElementCallbacks, RaisesException=Setter] attribute [TreatNullAs=EmptyString, StringContext=TrustedHTML] DOMString innerHTML; readonly attribute boolean delegatesFocus; [RuntimeEnabled=ManualSlotting] readonly attribute SlotAssignmentMode slotAssignment; + + // Declarative Shadow DOM setInnerHTML function. + // TODO(crbug.com/1147752): Add getInnerHTML() here also. + [Affects=Nothing, RuntimeEnabled=DeclarativeShadowDOM, RaisesException, ImplementedAs=setInnerHTMLWithOptions] void setInnerHTML(DOMString html, optional SetInnerHTMLOptions options = {}); }; ShadowRoot includes DocumentOrShadowRoot; diff --git a/blink/renderer/core/dom/slot_assignment_test.cc b/blink/renderer/core/dom/slot_assignment_test.cc index 4ce1fcedd106..67e212282bc9 100644 --- a/blink/renderer/core/dom/slot_assignment_test.cc +++ b/blink/renderer/core/dom/slot_assignment_test.cc @@ -5,6 +5,7 @@ #include "third_party/blink/renderer/core/dom/flat_tree_traversal.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_set_inner_html_options.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.h" @@ -64,13 +65,14 @@ class SlotAssignmentTest : public testing::Test { void SlotAssignmentTest::SetUp() { dummy_page_holder_ = std::make_unique(IntSize(800, 600)); document_ = &dummy_page_holder_->GetDocument(); - document_->setAllowDeclarativeShadowDom(true); DCHECK(document_); } void SlotAssignmentTest::SetBody(const char* html) { Element* body = GetDocument().body(); - body->setInnerHTML(String::FromUTF8(html)); + SetInnerHTMLOptions options; + options.setAllowShadowRoot(true); + body->setInnerHTMLWithOptions(String::FromUTF8(html), &options); RemoveWhiteSpaceOnlyTextNode(*body); } @@ -133,9 +135,9 @@ TEST_F(SlotAssignmentTest, AssignedNodesAreSet) { TEST_F(SlotAssignmentTest, ScheduleVisualUpdate) { SetBody(R"HTML(
- +
)HTML"); diff --git a/blink/renderer/core/editing/serializers/serialization.cc b/blink/renderer/core/editing/serializers/serialization.cc index 62a552ab4005..af1d518cecad 100644 --- a/blink/renderer/core/editing/serializers/serialization.cc +++ b/blink/renderer/core/editing/serializers/serialization.cc @@ -609,6 +609,7 @@ DocumentFragment* CreateFragmentForInnerOuterHTML( Element* context_element, ParserContentPolicy parser_content_policy, const char* method, + bool allow_shadow_root, ExceptionState& exception_state) { DCHECK(context_element); const HTMLTemplateElement* template_element = @@ -622,10 +623,7 @@ DocumentFragment* CreateFragmentForInnerOuterHTML( ? context_element->GetDocument().EnsureTemplateDocument() : context_element->GetDocument(); DocumentFragment* fragment = DocumentFragment::Create(document); - fragment->setAllowDeclarativeShadowDom( - context_element->GetDocument().allowDeclarativeShadowDom() || - (template_element && template_element->content() && - template_element->content()->allowDeclarativeShadowDom())); + document.setAllowDeclarativeShadowRoot(allow_shadow_root); if (IsA(document)) { fragment->ParseHTML(markup, context_element, parser_content_policy); @@ -693,7 +691,7 @@ DocumentFragment* CreateContextualFragment( DocumentFragment* fragment = CreateFragmentForInnerOuterHTML( markup, element, parser_content_policy, "createContextualFragment", - exception_state); + /*allow_shadow_root=*/false, exception_state); if (!fragment) return nullptr; diff --git a/blink/renderer/core/editing/serializers/serialization.h b/blink/renderer/core/editing/serializers/serialization.h index 2838ebf353a6..a73b30f1965f 100644 --- a/blink/renderer/core/editing/serializers/serialization.h +++ b/blink/renderer/core/editing/serializers/serialization.h @@ -66,6 +66,7 @@ DocumentFragment* CreateFragmentForInnerOuterHTML(const String&, Element*, ParserContentPolicy, const char* method, + bool allow_shadow_root, ExceptionState&); DocumentFragment* CreateFragmentForTransformToFragment( const String&, diff --git a/blink/renderer/core/html/html_iframe_element.cc b/blink/renderer/core/html/html_iframe_element.cc index a06215f687b5..a36767291bcd 100644 --- a/blink/renderer/core/html/html_iframe_element.cc +++ b/blink/renderer/core/html/html_iframe_element.cc @@ -161,12 +161,10 @@ void HTMLIFrameElement::ParseAttribute( network::mojom::blink::WebSandboxFlags::kNone; if (!value.IsNull()) { using network::mojom::blink::WebSandboxFlags; - WebSandboxFlags ignored_flags = WebSandboxFlags::kNone; - if (!RuntimeEnabledFeatures::StorageAccessAPIEnabled()) - ignored_flags |= WebSandboxFlags::kStorageAccessByUserActivation; - if (!RuntimeEnabledFeatures::DeclarativeShadowDOMEnabled( - GetExecutionContext())) - ignored_flags |= WebSandboxFlags::kDeclarativeShadowDom; + WebSandboxFlags ignored_flags = + !RuntimeEnabledFeatures::StorageAccessAPIEnabled() + ? WebSandboxFlags::kStorageAccessByUserActivation + : WebSandboxFlags::kNone; auto parsed = network::ParseWebSandboxPolicy(sandbox_->value().Utf8(), ignored_flags); diff --git a/blink/renderer/core/html/parser/html_construction_site.cc b/blink/renderer/core/html/parser/html_construction_site.cc index 8eb7549c4665..870c7f517624 100644 --- a/blink/renderer/core/html/parser/html_construction_site.cc +++ b/blink/renderer/core/html/parser/html_construction_site.cc @@ -713,15 +713,10 @@ void HTMLConstructionSite::InsertHTMLFormElement(AtomicHTMLToken* token, void HTMLConstructionSite::InsertHTMLTemplateElement( AtomicHTMLToken* token, - DeclarativeShadowRootType declarative_shadow_root_type, - bool allow_declarative_shadow_dom) { + DeclarativeShadowRootType declarative_shadow_root_type) { auto* template_element = To( CreateElement(token, html_names::xhtmlNamespaceURI)); template_element->SetDeclarativeShadowRootType(declarative_shadow_root_type); - if (DocumentFragment* content = - template_element->TemplateContentForHTMLConstructionSite()) { - content->setAllowDeclarativeShadowDom(allow_declarative_shadow_dom); - } AttachLater(CurrentNode(), template_element); open_elements_.Push( MakeGarbageCollected(template_element, token)); diff --git a/blink/renderer/core/html/parser/html_construction_site.h b/blink/renderer/core/html/parser/html_construction_site.h index 7b673c946d21..faff875c9c14 100644 --- a/blink/renderer/core/html/parser/html_construction_site.h +++ b/blink/renderer/core/html/parser/html_construction_site.h @@ -149,9 +149,7 @@ class HTMLConstructionSite final { void InsertCommentOnDocument(AtomicHTMLToken*); void InsertCommentOnHTMLHtmlElement(AtomicHTMLToken*); void InsertHTMLElement(AtomicHTMLToken*); - void InsertHTMLTemplateElement(AtomicHTMLToken*, - DeclarativeShadowRootType, - bool allow_declarative_shadow_dom); + void InsertHTMLTemplateElement(AtomicHTMLToken*, DeclarativeShadowRootType); void InsertSelfClosingHTMLElementDestroyingToken(AtomicHTMLToken*); void InsertFormattingElement(AtomicHTMLToken*); void InsertHTMLHeadElement(AtomicHTMLToken*); diff --git a/blink/renderer/core/html/parser/html_document_parser.cc b/blink/renderer/core/html/parser/html_document_parser.cc index a4fc7d9b24c7..3a26bd517137 100644 --- a/blink/renderer/core/html/parser/html_document_parser.cc +++ b/blink/renderer/core/html/parser/html_document_parser.cc @@ -288,29 +288,12 @@ HTMLDocumentParser::HTMLDocumentParser(HTMLDocument& document, script_runner_ = HTMLParserScriptRunner::Create(ReentryPermit(), &document, this); - // Deny declarative Shadow DOM if explicitly denied. - // Allow declarative shadow DOM: - // 1. For the main frame (non-fragment) document, or - // 2. When explicitly enabled by the allowDeclarativeShadowDom flag, or - // 3. For sub-frames that do not have this feature sandboxed. - bool allow_declarative_shadow_dom = false; - if (document.GetDeclarativeShadowDomAllowState() != - Document::DeclarativeShadowDomAllowState::kDeny) { - bool is_main_frame = - document.GetFrame() && document.GetFrame()->IsMainFrame(); - const auto* context = document.GetExecutionContext(); - allow_declarative_shadow_dom = - is_main_frame || - (document.GetDeclarativeShadowDomAllowState() == - Document::DeclarativeShadowDomAllowState::kAllow) || - (!is_main_frame && context && - !context->IsSandboxed( - network::mojom::blink::WebSandboxFlags::kDeclarativeShadowDom)); - } - + // Allow declarative shadow DOM for the document parser, if not explicitly + // disabled. + bool allow_shadow_root = document.GetDeclarativeShadowRootAllowState() != + Document::DeclarativeShadowRootAllowState::kDeny; tree_builder_ = MakeGarbageCollected( - this, document, kAllowScriptingContent, options_, - allow_declarative_shadow_dom); + this, document, kAllowScriptingContent, options_, allow_shadow_root); } HTMLDocumentParser::HTMLDocumentParser( @@ -320,10 +303,16 @@ HTMLDocumentParser::HTMLDocumentParser( : HTMLDocumentParser(fragment->GetDocument(), parser_content_policy, kForceSynchronousParsing) { + // Allow declarative shadow DOM for the fragment parser only if explicitly + // enabled. + bool allow_shadow_root = + fragment->GetDocument().GetDeclarativeShadowRootAllowState() == + Document::DeclarativeShadowRootAllowState::kAllow; + // No script_runner_ in fragment parser. tree_builder_ = MakeGarbageCollected( this, fragment, context_element, parser_content_policy, options_, - fragment->allowDeclarativeShadowDom()); + allow_shadow_root); // For now document fragment parsing never reports errors. bool report_errors = false; diff --git a/blink/renderer/core/html/parser/html_tree_builder.cc b/blink/renderer/core/html/parser/html_tree_builder.cc index afc0067ce960..77abc99de368 100644 --- a/blink/renderer/core/html/parser/html_tree_builder.cc +++ b/blink/renderer/core/html/parser/html_tree_builder.cc @@ -233,13 +233,13 @@ HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser* parser, Document& document, ParserContentPolicy parser_content_policy, const HTMLParserOptions& options, - bool allow_declarative_shadow_dom) + bool allow_shadow_root) : frameset_ok_(true), tree_(parser->ReentryPermit(), document, parser_content_policy), insertion_mode_(kInitialMode), original_insertion_mode_(kInitialMode), should_skip_leading_newline_(false), - allow_declarative_shadow_dom_(allow_declarative_shadow_dom), + allow_shadow_root_(allow_shadow_root), parser_(parser), script_to_process_start_position_(UninitializedPositionValue1()), options_(options) {} @@ -249,12 +249,12 @@ HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser* parser, Element* context_element, ParserContentPolicy parser_content_policy, const HTMLParserOptions& options, - bool allow_declarative_shadow_dom) + bool allow_shadow_root) : HTMLTreeBuilder(parser, fragment->GetDocument(), parser_content_policy, options, - allow_declarative_shadow_dom) { + allow_shadow_root) { DCHECK(IsMainThread()); DCHECK(context_element); tree_.InitFragmentParsing(fragment, context_element); @@ -905,7 +905,7 @@ void HTMLTreeBuilder::ProcessTemplateStartTag(AtomicHTMLToken* token) { DeclarativeShadowRootType::kNone); if (RuntimeEnabledFeatures::DeclarativeShadowDOMEnabled( tree_.CurrentNode()->GetExecutionContext()) && - allow_declarative_shadow_dom_) { + allow_shadow_root_) { if (Attribute* type_attribute = token->GetAttributeItem(html_names::kShadowrootAttr)) { String shadow_mode = type_attribute->Value(); @@ -924,8 +924,7 @@ void HTMLTreeBuilder::ProcessTemplateStartTag(AtomicHTMLToken* token) { } } } - tree_.InsertHTMLTemplateElement(token, declarative_shadow_root_type, - allow_declarative_shadow_dom_); + tree_.InsertHTMLTemplateElement(token, declarative_shadow_root_type); frameset_ok_ = false; template_insertion_modes_.push_back(kTemplateContentsMode); SetInsertionMode(kTemplateContentsMode); diff --git a/blink/renderer/core/html/parser/html_tree_builder.h b/blink/renderer/core/html/parser/html_tree_builder.h index cb6630daaa7c..ee8ff98b9523 100644 --- a/blink/renderer/core/html/parser/html_tree_builder.h +++ b/blink/renderer/core/html/parser/html_tree_builder.h @@ -55,13 +55,13 @@ class HTMLTreeBuilder final : public GarbageCollected { Document&, ParserContentPolicy, const HTMLParserOptions&, - bool allow_declarative_shadow_dom); + bool allow_shadow_root); HTMLTreeBuilder(HTMLDocumentParser*, DocumentFragment*, Element* context_element, ParserContentPolicy, const HTMLParserOptions&, - bool allow_declarative_shadow_dom); + bool allow_shadow_root); ~HTMLTreeBuilder(); void Trace(Visitor*) const; @@ -248,7 +248,7 @@ class HTMLTreeBuilder final : public GarbageCollected { bool should_skip_leading_newline_; - const bool allow_declarative_shadow_dom_; + const bool allow_shadow_root_; // We access parser because HTML5 spec requires that we be able to change the // state of the tokenizer from within parser actions. We also need it to track diff --git a/blink/renderer/core/xml/dom_parser.cc b/blink/renderer/core/xml/dom_parser.cc index 4c0f973f6667..340f1bbd87bc 100644 --- a/blink/renderer/core/xml/dom_parser.cc +++ b/blink/renderer/core/xml/dom_parser.cc @@ -18,9 +18,11 @@ */ #include "third_party/blink/renderer/core/xml/dom_parser.h" + #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/document_init.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" +#include "third_party/blink/renderer/core/xml/dom_parser_init.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/weborigin/security_origin.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -33,14 +35,15 @@ Document* DOMParser::parseFromString(const String& str, const String& type) { .WithTypeFrom(type) .WithExecutionContext(window_) .CreateDocument(); - doc->setAllowDeclarativeShadowDom(allow_declarative_shadow_dom_); + doc->setAllowDeclarativeShadowRoot(allow_shadow_root_); doc->SetContent(str); doc->SetMimeType(AtomicString(type)); return doc; } -DOMParser::DOMParser(ScriptState* script_state) - : window_(LocalDOMWindow::From(script_state)) {} +DOMParser::DOMParser(ScriptState* script_state, const DOMParserInit* init) + : allow_shadow_root_(init->hasAllowShadowRoot() && init->allowShadowRoot()), + window_(LocalDOMWindow::From(script_state)) {} void DOMParser::Trace(Visitor* visitor) const { visitor->Trace(window_); diff --git a/blink/renderer/core/xml/dom_parser.h b/blink/renderer/core/xml/dom_parser.h index bf1ec424277f..d5dd8dcd69d4 100644 --- a/blink/renderer/core/xml/dom_parser.h +++ b/blink/renderer/core/xml/dom_parser.h @@ -27,6 +27,7 @@ namespace blink { class Document; +class DOMParserInit; class LocalDOMWindow; class ScriptState; @@ -34,27 +35,21 @@ class DOMParser final : public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); public: - static DOMParser* Create(ScriptState* script_state) { - return MakeGarbageCollected(script_state); + static DOMParser* Create(ScriptState* script_state, + const DOMParserInit* dict) { + return MakeGarbageCollected(script_state, dict); } - explicit DOMParser(ScriptState*); + explicit DOMParser(ScriptState*, const DOMParserInit*); Document* parseFromString(const String&, const String& type); - bool allowDeclarativeShadowDom() const { - return allow_declarative_shadow_dom_; - } - void setAllowDeclarativeShadowDom(bool value) { - allow_declarative_shadow_dom_ = value; - } - void Trace(Visitor*) const override; LocalDOMWindow* GetWindow() const { return window_.Get(); } private: - bool allow_declarative_shadow_dom_{false}; + const bool allow_shadow_root_; WeakMember window_; }; diff --git a/blink/renderer/core/xml/dom_parser.idl b/blink/renderer/core/xml/dom_parser.idl index 9283952a0589..c5179f1e5cda 100644 --- a/blink/renderer/core/xml/dom_parser.idl +++ b/blink/renderer/core/xml/dom_parser.idl @@ -30,7 +30,6 @@ enum SupportedType { [ Exposed=Window ] interface DOMParser { - [CallWith=ScriptState] constructor(); + [CallWith=ScriptState] constructor(optional DOMParserInit options = {}); [NewObject] Document parseFromString(HTMLString str, SupportedType type); - [RuntimeEnabled=DeclarativeShadowDOM] attribute boolean allowDeclarativeShadowDom; }; diff --git a/blink/renderer/core/xml/dom_parser_init.idl b/blink/renderer/core/xml/dom_parser_init.idl new file mode 100644 index 000000000000..9b033332c43f --- /dev/null +++ b/blink/renderer/core/xml/dom_parser_init.idl @@ -0,0 +1,7 @@ +// Copyright 2020 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. + +dictionary DOMParserInit { + boolean allowShadowRoot = false; +}; diff --git a/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/blink/renderer/core/xmlhttprequest/xml_http_request.cc index 57e236052ab1..72054a48a152 100644 --- a/blink/renderer/core/xmlhttprequest/xml_http_request.cc +++ b/blink/renderer/core/xmlhttprequest/xml_http_request.cc @@ -347,16 +347,15 @@ void XMLHttpRequest::InitResponseDocument() { DocumentInit init = DocumentInit::Create() .WithExecutionContext(GetExecutionContext()) .WithURL(response_.ResponseUrl()); - if (is_html) + if (is_html) { response_document_ = MakeGarbageCollected(init); - else + response_document_->setAllowDeclarativeShadowRoot(false); + } else response_document_ = MakeGarbageCollected(init); // FIXME: Set Last-Modified. response_document_->SetContextFeatures(document->GetContextFeatures()); response_document_->SetMimeType(FinalResponseMIMETypeWithFallback()); - response_document_->setAllowDeclarativeShadowDom( - allow_declarative_shadow_dom_); } Document* XMLHttpRequest::responseXML(ExceptionState& exception_state) { diff --git a/blink/renderer/core/xmlhttprequest/xml_http_request.h b/blink/renderer/core/xmlhttprequest/xml_http_request.h index e25c1b8eeb39..e75442e579ed 100644 --- a/blink/renderer/core/xmlhttprequest/xml_http_request.h +++ b/blink/renderer/core/xmlhttprequest/xml_http_request.h @@ -163,13 +163,6 @@ class XMLHttpRequest final : public XMLHttpRequestEventTarget, return trust_token_operation_error_; } - bool allowDeclarativeShadowDom() const { - return allow_declarative_shadow_dom_; - } - void setAllowDeclarativeShadowDom(bool value) { - allow_declarative_shadow_dom_ = value; - } - // For Inspector. void SendForInspectorXHRReplay(scoped_refptr, ExceptionState&); @@ -387,8 +380,6 @@ class XMLHttpRequest final : public XMLHttpRequestEventTarget, bool send_flag_ = false; bool response_array_buffer_failure_ = false; - bool allow_declarative_shadow_dom_{false}; - probe::AsyncTaskId async_task_id_; }; diff --git a/blink/renderer/core/xmlhttprequest/xml_http_request.idl b/blink/renderer/core/xmlhttprequest/xml_http_request.idl index a87b5c0adc21..8ff21db2d0fb 100644 --- a/blink/renderer/core/xmlhttprequest/xml_http_request.idl +++ b/blink/renderer/core/xmlhttprequest/xml_http_request.idl @@ -56,8 +56,6 @@ typedef (Blob or BufferSource or FormData or URLSearchParams or USVString) XMLHt const unsigned short DONE = 4; readonly attribute unsigned short readyState; - [RuntimeEnabled=DeclarativeShadowDOM] attribute boolean allowDeclarativeShadowDom; - // request [RaisesException] void open(ByteString method, USVString url); [RaisesException] void open(ByteString method, USVString url, boolean async, optional USVString? username = null, optional USVString? password = null); diff --git a/blink/renderer/platform/bindings/runtime_call_stats.h b/blink/renderer/platform/bindings/runtime_call_stats.h index 99a79bb2eb23..96136b348f6d 100644 --- a/blink/renderer/platform/bindings/runtime_call_stats.h +++ b/blink/renderer/platform/bindings/runtime_call_stats.h @@ -250,6 +250,7 @@ class PLATFORM_EXPORT RuntimeCallStats { #define CALLBACK_COUNTERS(V) \ BINDINGS_METHOD(V, ElementGetBoundingClientRect) \ BINDINGS_METHOD(V, ElementGetInnerHTML) \ + BINDINGS_METHOD(V, ElementSetInnerHTML) \ BINDINGS_METHOD(V, EventTargetDispatchEvent) \ BINDINGS_METHOD(V, HTMLElementClick) \ BINDINGS_METHOD(V, NodeAppendChild) \ diff --git a/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-shadow-dom-attachment.tentative.html b/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-shadow-dom-attachment.tentative.html index 73b43829f1a0..99a255bfa218 100644 --- a/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-shadow-dom-attachment.tentative.html +++ b/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-shadow-dom-attachment.tentative.html @@ -7,8 +7,6 @@