Chromium Code Reviews| Index: third_party/WebKit/Source/web/WebFrameSerializer.cpp |
| diff --git a/third_party/WebKit/Source/web/WebFrameSerializer.cpp b/third_party/WebKit/Source/web/WebFrameSerializer.cpp |
| index 5ae9b75c24659cbfe022424e8fb66b0041688498..4a6820d50240e9778a626576283ce6bf6c36b5f2 100644 |
| --- a/third_party/WebKit/Source/web/WebFrameSerializer.cpp |
| +++ b/third_party/WebKit/Source/web/WebFrameSerializer.cpp |
| @@ -34,6 +34,7 @@ |
| #include "core/InputTypeNames.h" |
| #include "core/dom/Document.h" |
| #include "core/dom/Element.h" |
| +#include "core/dom/shadow/ElementShadow.h" |
| #include "core/frame/Frame.h" |
| #include "core/frame/FrameSerializer.h" |
| #include "core/frame/LocalFrame.h" |
| @@ -80,13 +81,17 @@ namespace blink { |
| namespace { |
| const int kPopupOverlayZIndexThreshold = 50; |
| +const char kShadowModeAttributeName[] = "shadowmode"; |
| +const char kShadowDelegatesFocusAttributeName[] = "shadowdelegatesfocus"; |
| class MHTMLFrameSerializerDelegate final : public FrameSerializer::Delegate { |
| + STACK_ALLOCATED() |
| WTF_MAKE_NONCOPYABLE(MHTMLFrameSerializerDelegate); |
| public: |
| - explicit MHTMLFrameSerializerDelegate( |
| - WebFrameSerializer::MHTMLPartsGenerationDelegate&); |
| + MHTMLFrameSerializerDelegate( |
| + WebFrameSerializer::MHTMLPartsGenerationDelegate&, |
| + HeapHashSet<WeakMember<const Element>>&); |
| ~MHTMLFrameSerializerDelegate() override; |
| bool ShouldIgnoreElement(const Element&) override; |
| bool ShouldIgnoreAttribute(const Element&, const Attribute&) override; |
| @@ -95,6 +100,7 @@ class MHTMLFrameSerializerDelegate final : public FrameSerializer::Delegate { |
| bool ShouldSkipResource( |
| FrameSerializer::ResourceHasCacheControlNoStoreHeader) override; |
| Vector<Attribute> GetCustomAttributes(const Element&) override; |
| + std::pair<Node*, Element*> GetAuxiliaryDOMTree(const Element&) const override; |
| private: |
| bool ShouldIgnoreHiddenElement(const Element&); |
| @@ -106,12 +112,16 @@ class MHTMLFrameSerializerDelegate final : public FrameSerializer::Delegate { |
| Vector<Attribute>*); |
| WebFrameSerializer::MHTMLPartsGenerationDelegate& web_delegate_; |
| + HeapHashSet<WeakMember<const Element>>& shadow_template_elements_; |
| bool popup_overlays_skipped_; |
| }; |
| MHTMLFrameSerializerDelegate::MHTMLFrameSerializerDelegate( |
| - WebFrameSerializer::MHTMLPartsGenerationDelegate& web_delegate) |
| - : web_delegate_(web_delegate), popup_overlays_skipped_(false) {} |
| + WebFrameSerializer::MHTMLPartsGenerationDelegate& web_delegate, |
| + HeapHashSet<WeakMember<const Element>>& shadow_template_elements) |
| + : web_delegate_(web_delegate), |
| + shadow_template_elements_(shadow_template_elements), |
| + popup_overlays_skipped_(false) {} |
| MHTMLFrameSerializerDelegate::~MHTMLFrameSerializerDelegate() { |
| if (web_delegate_.RemovePopupOverlay()) { |
| @@ -202,6 +212,15 @@ bool MHTMLFrameSerializerDelegate::ShouldIgnoreAttribute( |
| return true; |
| } |
| + // The special attribute in a template element to denote the shadow DOM |
| + // should only be generated from MHTML serialization. If it is found in the |
| + // original page, it should be ignored. |
| + if (isHTMLTemplateElement(element) && |
| + attribute.LocalName() == kShadowModeAttributeName && |
|
Mike West
2017/06/14 07:03:59
Should we be stripping `kShadowDelegatesFocusAttri
jianli
2017/06/14 19:06:08
kShadowDelegatesFocusAttributeName can't take any
Dmitry Titov
2017/06/14 19:33:10
Hm, stripping all attributes that feature adds mig
jianli
2017/06/14 21:48:06
Sounds reasonable. I am going to remove this attri
|
| + !shadow_template_elements_.Contains(&element)) { |
| + return true; |
| + } |
| + |
| // If srcdoc attribute for frame elements will be rewritten as src attribute |
| // containing link instead of html contents, don't ignore the attribute. |
| // Bail out now to avoid the check in Element::isScriptingAttribute. |
| @@ -329,6 +348,48 @@ void MHTMLFrameSerializerDelegate::GetCustomAttributesForFormControlElement( |
| attributes->push_back(disabled_attribute); |
| } |
| +std::pair<Node*, Element*> MHTMLFrameSerializerDelegate::GetAuxiliaryDOMTree( |
| + const Element& element) const { |
| + const ElementShadow* shadow = element.Shadow(); |
| + if (!shadow) |
| + return std::pair<Node*, Element*>(); |
| + ShadowRoot& shadow_root = shadow->OldestShadowRoot(); |
| + |
| + String shadow_mode; |
| + switch (shadow_root.GetType()) { |
| + case ShadowRootType::kUserAgent: |
| + // No need to serialize. |
| + return std::pair<Node*, Element*>(); |
| + case ShadowRootType::V0: |
| + shadow_mode = "v0"; |
| + break; |
| + case ShadowRootType::kOpen: |
| + shadow_mode = "open"; |
| + break; |
| + case ShadowRootType::kClosed: |
| + shadow_mode = "closed"; |
| + break; |
| + } |
| + |
| + // Put the shadow DOM content inside a template element. A special attribute |
| + // is set to tell the mode of the shadow DOM. |
| + Element* template_element = |
| + Element::Create(HTMLNames::templateTag, &(element.GetDocument())); |
| + template_element->setAttribute( |
| + QualifiedName(g_null_atom, kShadowModeAttributeName, g_null_atom), |
| + AtomicString(shadow_mode)); |
| + if (shadow_root.GetType() != ShadowRootType::V0 && |
| + shadow_root.delegatesFocus()) { |
| + template_element->setAttribute( |
| + QualifiedName(g_null_atom, kShadowDelegatesFocusAttributeName, |
| + g_null_atom), |
| + g_empty_atom); |
| + } |
| + shadow_template_elements_.insert(template_element); |
| + |
| + return std::pair<Node*, Element*>(&shadow_root, template_element); |
| +} |
| + |
| bool CacheControlNoStoreHeaderPresent( |
| const WebLocalFrameBase& web_local_frame) { |
| const ResourceResponse& response = |
| @@ -414,7 +475,9 @@ WebThreadSafeData WebFrameSerializer::GenerateMHTMLParts( |
| { |
| SCOPED_BLINK_UMA_HISTOGRAM_TIMER( |
| "PageSerialization.MhtmlGeneration.SerializationTime.SingleFrame"); |
| - MHTMLFrameSerializerDelegate core_delegate(*web_delegate); |
| + HeapHashSet<WeakMember<const Element>> shadow_template_elements; |
| + MHTMLFrameSerializerDelegate core_delegate(*web_delegate, |
| + shadow_template_elements); |
| FrameSerializer serializer(resources, core_delegate); |
| serializer.SerializeFrame(*frame); |
| } |