Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(655)

Unified Diff: third_party/WebKit/Source/web/WebFrameSerializer.cpp

Issue 2912213002: Support serializing shadow DOM to MHTML (Closed)
Patch Set: Add .gitattributes Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..617dc042f62533923c43949939d4e0a137935756 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;
+ Node* GetAuxiliaryDOMTree(const Element&, 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 &&
+ !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,52 @@ void MHTMLFrameSerializerDelegate::GetCustomAttributesForFormControlElement(
attributes->push_back(disabled_attribute);
}
+Node* MHTMLFrameSerializerDelegate::GetAuxiliaryDOMTree(
+ const Element& element,
+ Element** enclosing_element) const {
+ DCHECK(enclosing_element);
+
+ const ElementShadow* shadow = element.Shadow();
+ if (!shadow)
+ return nullptr;
+ ShadowRoot& shadow_root = shadow->OldestShadowRoot();
+
+ String shadow_mode;
+ switch (shadow_root.GetType()) {
+ case ShadowRootType::kUserAgent:
+ // No need to serialize.
+ return nullptr;
+ 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);
+
+ *enclosing_element = template_element;
+ return &shadow_root;
+}
+
bool CacheControlNoStoreHeaderPresent(
const WebLocalFrameBase& web_local_frame) {
const ResourceResponse& response =
@@ -414,7 +479,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);
}

Powered by Google App Engine
This is Rietveld 408576698