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

Side by Side Diff: third_party/WebKit/Source/web/WebFrameSerializer.cpp

Issue 2912213002: Support serializing shadow DOM to MHTML (Closed)
Patch Set: Address feedback Created 3 years, 6 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2009 Google Inc. All rights reserved. 2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 16 matching lines...) Expand all
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "public/web/WebFrameSerializer.h" 31 #include "public/web/WebFrameSerializer.h"
32 32
33 #include "core/HTMLNames.h" 33 #include "core/HTMLNames.h"
34 #include "core/InputTypeNames.h" 34 #include "core/InputTypeNames.h"
35 #include "core/dom/Document.h" 35 #include "core/dom/Document.h"
36 #include "core/dom/Element.h" 36 #include "core/dom/Element.h"
37 #include "core/dom/shadow/ElementShadow.h"
37 #include "core/frame/Frame.h" 38 #include "core/frame/Frame.h"
38 #include "core/frame/FrameSerializer.h" 39 #include "core/frame/FrameSerializer.h"
39 #include "core/frame/LocalFrame.h" 40 #include "core/frame/LocalFrame.h"
40 #include "core/frame/RemoteFrame.h" 41 #include "core/frame/RemoteFrame.h"
41 #include "core/frame/WebLocalFrameBase.h" 42 #include "core/frame/WebLocalFrameBase.h"
42 #include "core/html/HTMLAllCollection.h" 43 #include "core/html/HTMLAllCollection.h"
43 #include "core/html/HTMLFrameElementBase.h" 44 #include "core/html/HTMLFrameElementBase.h"
44 #include "core/html/HTMLFrameOwnerElement.h" 45 #include "core/html/HTMLFrameOwnerElement.h"
45 #include "core/html/HTMLImageElement.h" 46 #include "core/html/HTMLImageElement.h"
46 #include "core/html/HTMLInputElement.h" 47 #include "core/html/HTMLInputElement.h"
(...skipping 26 matching lines...) Expand all
73 #include "public/web/WebFrameSerializerCacheControlPolicy.h" 74 #include "public/web/WebFrameSerializerCacheControlPolicy.h"
74 #include "public/web/WebFrameSerializerClient.h" 75 #include "public/web/WebFrameSerializerClient.h"
75 #include "web/WebFrameSerializerImpl.h" 76 #include "web/WebFrameSerializerImpl.h"
76 #include "web/WebRemoteFrameImpl.h" 77 #include "web/WebRemoteFrameImpl.h"
77 78
78 namespace blink { 79 namespace blink {
79 80
80 namespace { 81 namespace {
81 82
82 const int kPopupOverlayZIndexThreshold = 50; 83 const int kPopupOverlayZIndexThreshold = 50;
84 const char kShadowModeAttributeName[] = "shadowmode";
85 const char kShadowDelegatesFocusAttributeName[] = "shadowdelegatesfocus";
83 86
84 class MHTMLFrameSerializerDelegate final : public FrameSerializer::Delegate { 87 class MHTMLFrameSerializerDelegate final : public FrameSerializer::Delegate {
88 STACK_ALLOCATED()
85 WTF_MAKE_NONCOPYABLE(MHTMLFrameSerializerDelegate); 89 WTF_MAKE_NONCOPYABLE(MHTMLFrameSerializerDelegate);
86 90
87 public: 91 public:
88 explicit MHTMLFrameSerializerDelegate( 92 MHTMLFrameSerializerDelegate(
89 WebFrameSerializer::MHTMLPartsGenerationDelegate&); 93 WebFrameSerializer::MHTMLPartsGenerationDelegate&,
94 HeapHashSet<WeakMember<const Element>>&);
90 ~MHTMLFrameSerializerDelegate() override; 95 ~MHTMLFrameSerializerDelegate() override;
91 bool ShouldIgnoreElement(const Element&) override; 96 bool ShouldIgnoreElement(const Element&) override;
92 bool ShouldIgnoreAttribute(const Element&, const Attribute&) override; 97 bool ShouldIgnoreAttribute(const Element&, const Attribute&) override;
93 bool RewriteLink(const Element&, String& rewritten_link) override; 98 bool RewriteLink(const Element&, String& rewritten_link) override;
94 bool ShouldSkipResourceWithURL(const KURL&) override; 99 bool ShouldSkipResourceWithURL(const KURL&) override;
95 bool ShouldSkipResource( 100 bool ShouldSkipResource(
96 FrameSerializer::ResourceHasCacheControlNoStoreHeader) override; 101 FrameSerializer::ResourceHasCacheControlNoStoreHeader) override;
97 Vector<Attribute> GetCustomAttributes(const Element&) override; 102 Vector<Attribute> GetCustomAttributes(const Element&) override;
103 std::pair<Node*, Element*> GetAuxiliaryDOMTree(const Element&) const override;
98 104
99 private: 105 private:
100 bool ShouldIgnoreHiddenElement(const Element&); 106 bool ShouldIgnoreHiddenElement(const Element&);
101 bool ShouldIgnoreMetaElement(const Element&); 107 bool ShouldIgnoreMetaElement(const Element&);
102 bool ShouldIgnorePopupOverlayElement(const Element&); 108 bool ShouldIgnorePopupOverlayElement(const Element&);
103 void GetCustomAttributesForImageElement(const HTMLImageElement&, 109 void GetCustomAttributesForImageElement(const HTMLImageElement&,
104 Vector<Attribute>*); 110 Vector<Attribute>*);
105 void GetCustomAttributesForFormControlElement(const Element&, 111 void GetCustomAttributesForFormControlElement(const Element&,
106 Vector<Attribute>*); 112 Vector<Attribute>*);
107 113
108 WebFrameSerializer::MHTMLPartsGenerationDelegate& web_delegate_; 114 WebFrameSerializer::MHTMLPartsGenerationDelegate& web_delegate_;
115 HeapHashSet<WeakMember<const Element>>& shadow_template_elements_;
109 bool popup_overlays_skipped_; 116 bool popup_overlays_skipped_;
110 }; 117 };
111 118
112 MHTMLFrameSerializerDelegate::MHTMLFrameSerializerDelegate( 119 MHTMLFrameSerializerDelegate::MHTMLFrameSerializerDelegate(
113 WebFrameSerializer::MHTMLPartsGenerationDelegate& web_delegate) 120 WebFrameSerializer::MHTMLPartsGenerationDelegate& web_delegate,
114 : web_delegate_(web_delegate), popup_overlays_skipped_(false) {} 121 HeapHashSet<WeakMember<const Element>>& shadow_template_elements)
122 : web_delegate_(web_delegate),
123 shadow_template_elements_(shadow_template_elements),
124 popup_overlays_skipped_(false) {}
115 125
116 MHTMLFrameSerializerDelegate::~MHTMLFrameSerializerDelegate() { 126 MHTMLFrameSerializerDelegate::~MHTMLFrameSerializerDelegate() {
117 if (web_delegate_.RemovePopupOverlay()) { 127 if (web_delegate_.RemovePopupOverlay()) {
118 UMA_HISTOGRAM_BOOLEAN( 128 UMA_HISTOGRAM_BOOLEAN(
119 "PageSerialization.MhtmlGeneration.PopupOverlaySkipped", 129 "PageSerialization.MhtmlGeneration.PopupOverlaySkipped",
120 popup_overlays_skipped_); 130 popup_overlays_skipped_);
121 } 131 }
122 } 132 }
123 133
124 bool MHTMLFrameSerializerDelegate::ShouldIgnoreElement(const Element& element) { 134 bool MHTMLFrameSerializerDelegate::ShouldIgnoreElement(const Element& element) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 if (attribute.LocalName() == HTMLNames::srcsetAttr) 205 if (attribute.LocalName() == HTMLNames::srcsetAttr)
196 return true; 206 return true;
197 207
198 // Do not save ping attribute since anyway the ping will be blocked from 208 // Do not save ping attribute since anyway the ping will be blocked from
199 // MHTML. 209 // MHTML.
200 if (isHTMLAnchorElement(element) && 210 if (isHTMLAnchorElement(element) &&
201 attribute.LocalName() == HTMLNames::pingAttr) { 211 attribute.LocalName() == HTMLNames::pingAttr) {
202 return true; 212 return true;
203 } 213 }
204 214
215 // The special attribute in a template element to denote the shadow DOM
216 // should only be generated from MHTML serialization. If it is found in the
217 // original page, it should be ignored.
218 if (isHTMLTemplateElement(element) &&
219 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
220 !shadow_template_elements_.Contains(&element)) {
221 return true;
222 }
223
205 // If srcdoc attribute for frame elements will be rewritten as src attribute 224 // If srcdoc attribute for frame elements will be rewritten as src attribute
206 // containing link instead of html contents, don't ignore the attribute. 225 // containing link instead of html contents, don't ignore the attribute.
207 // Bail out now to avoid the check in Element::isScriptingAttribute. 226 // Bail out now to avoid the check in Element::isScriptingAttribute.
208 bool is_src_doc_attribute = IsHTMLFrameElementBase(element) && 227 bool is_src_doc_attribute = IsHTMLFrameElementBase(element) &&
209 attribute.GetName() == HTMLNames::srcdocAttr; 228 attribute.GetName() == HTMLNames::srcdocAttr;
210 String new_link_for_the_element; 229 String new_link_for_the_element;
211 if (is_src_doc_attribute && RewriteLink(element, new_link_for_the_element)) 230 if (is_src_doc_attribute && RewriteLink(element, new_link_for_the_element))
212 return false; 231 return false;
213 232
214 // Do not include attributes that contain javascript. This is because the 233 // Do not include attributes that contain javascript. This is because the
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 Vector<Attribute>* attributes) { 341 Vector<Attribute>* attributes) {
323 // Disable all form elements in MTHML to tell the user that the form cannot be 342 // Disable all form elements in MTHML to tell the user that the form cannot be
324 // worked on. MHTML is loaded in full sandboxing mode which disable the form 343 // worked on. MHTML is loaded in full sandboxing mode which disable the form
325 // submission and script execution. 344 // submission and script execution.
326 if (element.FastHasAttribute(HTMLNames::disabledAttr)) 345 if (element.FastHasAttribute(HTMLNames::disabledAttr))
327 return; 346 return;
328 Attribute disabled_attribute(HTMLNames::disabledAttr, ""); 347 Attribute disabled_attribute(HTMLNames::disabledAttr, "");
329 attributes->push_back(disabled_attribute); 348 attributes->push_back(disabled_attribute);
330 } 349 }
331 350
351 std::pair<Node*, Element*> MHTMLFrameSerializerDelegate::GetAuxiliaryDOMTree(
352 const Element& element) const {
353 const ElementShadow* shadow = element.Shadow();
354 if (!shadow)
355 return std::pair<Node*, Element*>();
356 ShadowRoot& shadow_root = shadow->OldestShadowRoot();
357
358 String shadow_mode;
359 switch (shadow_root.GetType()) {
360 case ShadowRootType::kUserAgent:
361 // No need to serialize.
362 return std::pair<Node*, Element*>();
363 case ShadowRootType::V0:
364 shadow_mode = "v0";
365 break;
366 case ShadowRootType::kOpen:
367 shadow_mode = "open";
368 break;
369 case ShadowRootType::kClosed:
370 shadow_mode = "closed";
371 break;
372 }
373
374 // Put the shadow DOM content inside a template element. A special attribute
375 // is set to tell the mode of the shadow DOM.
376 Element* template_element =
377 Element::Create(HTMLNames::templateTag, &(element.GetDocument()));
378 template_element->setAttribute(
379 QualifiedName(g_null_atom, kShadowModeAttributeName, g_null_atom),
380 AtomicString(shadow_mode));
381 if (shadow_root.GetType() != ShadowRootType::V0 &&
382 shadow_root.delegatesFocus()) {
383 template_element->setAttribute(
384 QualifiedName(g_null_atom, kShadowDelegatesFocusAttributeName,
385 g_null_atom),
386 g_empty_atom);
387 }
388 shadow_template_elements_.insert(template_element);
389
390 return std::pair<Node*, Element*>(&shadow_root, template_element);
391 }
392
332 bool CacheControlNoStoreHeaderPresent( 393 bool CacheControlNoStoreHeaderPresent(
333 const WebLocalFrameBase& web_local_frame) { 394 const WebLocalFrameBase& web_local_frame) {
334 const ResourceResponse& response = 395 const ResourceResponse& response =
335 web_local_frame.DataSource()->GetResponse().ToResourceResponse(); 396 web_local_frame.DataSource()->GetResponse().ToResourceResponse();
336 if (response.CacheControlContainsNoStore()) 397 if (response.CacheControlContainsNoStore())
337 return true; 398 return true;
338 399
339 const ResourceRequest& request = 400 const ResourceRequest& request =
340 web_local_frame.DataSource()->GetRequest().ToResourceRequest(); 401 web_local_frame.DataSource()->GetRequest().ToResourceRequest();
341 return request.CacheControlContainsNoStore(); 402 return request.CacheControlContainsNoStore();
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 ? MHTMLArchive::EncodingPolicy::kUseBinaryEncoding 468 ? MHTMLArchive::EncodingPolicy::kUseBinaryEncoding
408 : MHTMLArchive::EncodingPolicy::kUseDefaultEncoding; 469 : MHTMLArchive::EncodingPolicy::kUseDefaultEncoding;
409 470
410 // Serialize. 471 // Serialize.
411 TRACE_EVENT_BEGIN0("page-serialization", 472 TRACE_EVENT_BEGIN0("page-serialization",
412 "WebFrameSerializer::generateMHTMLParts serializing"); 473 "WebFrameSerializer::generateMHTMLParts serializing");
413 Deque<SerializedResource> resources; 474 Deque<SerializedResource> resources;
414 { 475 {
415 SCOPED_BLINK_UMA_HISTOGRAM_TIMER( 476 SCOPED_BLINK_UMA_HISTOGRAM_TIMER(
416 "PageSerialization.MhtmlGeneration.SerializationTime.SingleFrame"); 477 "PageSerialization.MhtmlGeneration.SerializationTime.SingleFrame");
417 MHTMLFrameSerializerDelegate core_delegate(*web_delegate); 478 HeapHashSet<WeakMember<const Element>> shadow_template_elements;
479 MHTMLFrameSerializerDelegate core_delegate(*web_delegate,
480 shadow_template_elements);
418 FrameSerializer serializer(resources, core_delegate); 481 FrameSerializer serializer(resources, core_delegate);
419 serializer.SerializeFrame(*frame); 482 serializer.SerializeFrame(*frame);
420 } 483 }
421 484
422 TRACE_EVENT_END1("page-serialization", 485 TRACE_EVENT_END1("page-serialization",
423 "WebFrameSerializer::generateMHTMLParts serializing", 486 "WebFrameSerializer::generateMHTMLParts serializing",
424 "resource count", 487 "resource count",
425 static_cast<unsigned long long>(resources.size())); 488 static_cast<unsigned long long>(resources.size()));
426 489
427 // There was an error serializing the frame (e.g. of an image resource). 490 // There was an error serializing the frame (e.g. of an image resource).
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 const WebString& base_target) { 542 const WebString& base_target) {
480 // TODO(yosin) We should call |FrameSerializer::baseTagDeclarationOf()|. 543 // TODO(yosin) We should call |FrameSerializer::baseTagDeclarationOf()|.
481 if (base_target.IsEmpty()) 544 if (base_target.IsEmpty())
482 return String("<base href=\".\">"); 545 return String("<base href=\".\">");
483 String base_string = "<base href=\".\" target=\"" + 546 String base_string = "<base href=\".\" target=\"" +
484 static_cast<const String&>(base_target) + "\">"; 547 static_cast<const String&>(base_target) + "\">";
485 return base_string; 548 return base_string;
486 } 549 }
487 550
488 } // namespace blink 551 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/web/LocalFrameClientImpl.cpp ('k') | third_party/WebKit/Source/web/tests/MHTMLTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698