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 9bb50569b93..e769150081e 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 d6761bd28c1..dbdf05c6664 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 ab6bc2c5d5b..810729ca1d2 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 fb848b61bfb..a6ddd2d869c 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 ef59d118e2f..dc456c70a93 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 5626867051c..b6497202522 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 745e9e7e0b9..c65d96e3cfb 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 585ead84173..ddb78da3185 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 99fe3246a18..0c172c250f3 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 5286351d515..071dbf64748 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 a46e9abb279..d99e36e734e 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 c1a02c04cf7..fc722ba013d 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 00000000000..5e5d89d9532 --- /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 73304f8246e..1a1b104f7d5 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 d1e29347d9b..379c02a26c1 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 0080770117d..61cfe03df10 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 4ce1fcedd10..67e212282bc 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 62a552ab400..af1d518ceca 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 2838ebf353a..a73b30f1965 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 a06215f687b..a36767291bc 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 8eb7549c466..870c7f51762 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 7b673c946d2..faff875c9c1 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 a4fc7d9b24c..3a26bd51713 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 afc0067ce96..77abc99de36 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 cb6630daaa7..ee8ff98b952 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 4c0f973f666..340f1bbd87b 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 bf1ec424277..d5dd8dcd69d 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 9283952a058..c5179f1e5cd 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 00000000000..9b033332c43 --- /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 57e236052ab..72054a48a15 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 e25c1b8eeb3..e75442e579e 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 a87b5c0adc2..8ff21db2d0f 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 99a79bb2eb2..96136b348f6 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 73b43829f1a..99a255bfa21 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 @@