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

Side by Side Diff: telemetry/third_party/snap-it/HTMLSerializer.js

Issue 3017573002: Make sure snap_page combined iframe serialized dom
Patch Set: . Created 3 years, 3 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 * HTML Serializer that takes a document and synchronously stores it as an array 2 * HTML Serializer that takes a document and synchronously stores it as an array
3 * of strings, then asynchronously retrieves data URLs for same-origin images. 3 * of strings, then asynchronously retrieves data URLs for same-origin images.
4 * It stores enough state to later be converted to an html text file. 4 * It stores enough state to later be converted to an html text file.
5 */ 5 */
6 var HTMLSerializer = class { 6 var HTMLSerializer = class {
7 constructor() { 7 constructor() {
8 8
9 /** 9 /**
10 * @private {Set<string>} Contains the tag names that should be 10 * @private {Set<string>} Contains the tag names that should be
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 * text. 63 * text.
64 * @const 64 * @const
65 */ 65 */
66 this.INPUT_TEXT_TYPE = { 66 this.INPUT_TEXT_TYPE = {
67 HTML : 0, 67 HTML : 0,
68 CSS : 1 68 CSS : 1
69 }; 69 };
70 70
71 /** 71 /**
72 * @public {Array<string>} This array represents the serialized html that 72 * @public {Array<string>} This array represents the serialized html that
73 * makes up a node or document. 73 * makes up a node or document.
74 */ 74 */
75 this.html = []; 75 this.html = [];
76 76
77 /** 77 /**
78 * @public {Object<number, string>} The keys represent an index in 78 * @public {Object<number, string>} The keys represent an index in
79 * |this.html|. The value is a url at which the resource that belongs at 79 * |this.html|. The value is a url at which the resource that belongs at
80 * that index can be retrieved. The resource will eventually be 80 * that index can be retrieved. The resource will eventually be
81 * converted to a data url. 81 * converted to a data url.
82 */ 82 */
83 this.srcHoles = {}; 83 this.srcHoles = {};
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 * @private {string} The assigned id of the html element. 180 * @private {string} The assigned id of the html element.
181 */ 181 */
182 this.rootId; 182 this.rootId;
183 } 183 }
184 184
185 /** 185 /**
186 * Takes an html document, and populates this objects fields such that it can 186 * Takes an html document, and populates this objects fields such that it can
187 * eventually be converted into an html file. 187 * eventually be converted into an html file.
188 * 188 *
189 * @param {Document} doc The Document to serialize. 189 * @param {Document} doc The Document to serialize.
190 */ 190 */
191 processDocument(doc) { 191 processDocument(doc) {
192 this.windowHeight = doc.defaultView.innerHeight; 192 this.windowHeight = doc.defaultView.innerHeight;
193 this.windowWidth = doc.defaultView.innerWidth; 193 this.windowWidth = doc.defaultView.innerWidth;
194 194
195 if (doc.doctype) { 195 if (doc.doctype) {
196 this.html.push('<!DOCTYPE html>\n'); 196 this.html.push('<!DOCTYPE html>\n');
197 } 197 }
198 198
199 if (this.iframeFullyQualifiedName(doc.defaultView) == '0') { 199 if (this.iframeFullyQualifiedName(doc.defaultView) == '0') {
200 this.html.push( 200 this.html.push(
(...skipping 23 matching lines...) Expand all
224 style = style.replace(/"/g, escapedQuote); 224 style = style.replace(/"/g, escapedQuote);
225 this.html[this.pseudoElementTestingStyleIndex] = style; 225 this.html[this.pseudoElementTestingStyleIndex] = style;
226 } 226 }
227 227
228 /** 228 /**
229 * Takes an html node, and populates this object's fields such that it can 229 * Takes an html node, and populates this object's fields such that it can
230 * eventually be converted into an html text file. 230 * eventually be converted into an html text file.
231 * 231 *
232 * @param {Node} node The Node to serialize. 232 * @param {Node} node The Node to serialize.
233 * @private 233 * @private
234 */ 234 */
235 processTree(node) { 235 processTree(node) {
236 var tagName = node.tagName; 236 var tagName = node.tagName;
237 if (!tagName && node.nodeType != Node.TEXT_NODE) { 237 if (!tagName && node.nodeType != Node.TEXT_NODE) {
238 // Ignore nodes that don't have tags and are not text. 238 // Ignore nodes that don't have tags and are not text.
239 } else if (tagName && this.FILTERED_TAGS.has(tagName)) { 239 } else if (tagName && this.FILTERED_TAGS.has(tagName)) {
240 // Filter out nodes that are in filteredTags. 240 // Filter out nodes that are in filteredTags.
241 } else if (node.nodeType == Node.TEXT_NODE) { 241 } else if (node.nodeType == Node.TEXT_NODE) {
242 this.processText(node); 242 this.processText(node);
243 } else { 243 } else {
244 this.html.push(`<${tagName.toLowerCase()} `); 244 this.html.push(`<${tagName.toLowerCase()} `);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 this.html.push(text); 329 this.html.push(text);
330 } 330 }
331 331
332 /** 332 /**
333 * Takes an html element, and populates this object's fields with the 333 * Takes an html element, and populates this object's fields with the
334 * appropriate attribute names and values. 334 * appropriate attribute names and values.
335 * 335 *
336 * @param {Element} element The Element to serialize. 336 * @param {Element} element The Element to serialize.
337 * @param {string} id The id of the Element being serialized. 337 * @param {string} id The id of the Element being serialized.
338 * @private 338 * @private
339 */ 339 */
340 processAttributes(element, id) { 340 processAttributes(element, id) {
341 var win = element.ownerDocument.defaultView; 341 var win = element.ownerDocument.defaultView;
342 var style = win.getComputedStyle(element, null); 342 var style = win.getComputedStyle(element, null);
343 var styleMap = {}; 343 var styleMap = {};
344 for (var i = 0; i < style.length; i++) { 344 for (var i = 0; i < style.length; i++) {
345 var propertyName = style.item(i); 345 var propertyName = style.item(i);
346 styleMap[propertyName] = style.getPropertyValue(propertyName); 346 styleMap[propertyName] = style.getPropertyValue(propertyName);
347 } 347 }
348 this.idToStyleMap[id] = styleMap; 348 this.idToStyleMap[id] = styleMap;
349 this.idToStyleIndex[id] = this.html.length; 349 this.idToStyleIndex[id] = this.html.length;
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 * 576 *
577 * @param {Window} win The window to use in the calculation. 577 * @param {Window} win The window to use in the calculation.
578 * @return {string} The full path. 578 * @return {string} The full path.
579 */ 579 */
580 iframeFullyQualifiedName(win) { 580 iframeFullyQualifiedName(win) {
581 if (this.iframeIndex(win) < 0) { 581 if (this.iframeIndex(win) < 0) {
582 return '0'; 582 return '0';
583 } else { 583 } else {
584 var fullyQualifiedName = this.iframeFullyQualifiedName(win.parent); 584 var fullyQualifiedName = this.iframeFullyQualifiedName(win.parent);
585 var index = this.iframeIndex(win); 585 var index = this.iframeIndex(win);
586 return fullyQualifiedName + '.' + index; 586 return fullyQualifiedName + '.' + index;
587 } 587 }
588 } 588 }
589 589
590 /** 590 /**
591 * Calculate the correct encoding of a character that should be used given the 591 * Calculate the correct encoding of a character that should be used given the
592 * nesting depth of the window in the frame tree. 592 * nesting depth of the window in the frame tree.
593 * 593 *
594 * @param {string} char The character that should be escaped. 594 * @param {string} char The character that should be escaped.
595 * @param {number} depth The nesting depth of the appropriate window in the 595 * @param {number} depth The nesting depth of the appropriate window in the
596 * frame tree. 596 * frame tree.
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
717 serializer.processCSSFonts(doc.defaultView, styleSheetSrc, css); 717 serializer.processCSSFonts(doc.defaultView, styleSheetSrc, css);
718 serializer.fillFontHoles(doc, callback); 718 serializer.fillFontHoles(doc, callback);
719 }).catch(function(error) { 719 }).catch(function(error) {
720 console.log(error); 720 console.log(error);
721 serializer.fillFontHoles(doc, callback); 721 serializer.fillFontHoles(doc, callback);
722 }); 722 });
723 } 723 }
724 } 724 }
725 725
726 /** 726 /**
727 * Return a JSONizable dictionary that contain all the data of this object.
728 */
729 asDict() {
wkorman 2017/09/20 20:11:04 Add a unit test for this? May as well while we're
nednguyen 2017/09/26 13:01:35 Acknowledged. I filed a tracking bug here https://
730 return {
731 'html': htmlSerializer.html,
732 'frameHoles': htmlSerializer.frameHoles,
733 'idToStyleIndex': htmlSerializer.idToStyleIndex,
734 'idToStyleMap': htmlSerializer.idToStyleMap,
735 'windowHeight': htmlSerializer.windowHeight,
736 'windowWidth': htmlSerializer.windowWidth,
737 'rootId': htmlSerializer.rootId,
738 'rootStyleIndex': htmlSerializer.rootStyleIndex,
739 'pseudoElementSelectorToCSSMap':
740 htmlSerializer.pseudoElementSelectorToCSSMap,
741 'pseudoElementPlaceHolderIndex':
742 htmlSerializer.pseudoElementPlaceHolderIndex,
743 'pseudoElementTestingStyleIndex':
744 htmlSerializer.pseudoElementStyleTestingIndex,
745 'pseudoElementTestingStyleId': htmlSerializer.pseudoElementTestingStyleId,
746 'unusedId': htmlSerializer.generateId(document),
747 'frameIndex': htmlSerializer.iframeFullyQualifiedName(window)
748 };
749 }
750
751 /**
727 * Take all of the srcHoles and create data urls for the resources, placing 752 * Take all of the srcHoles and create data urls for the resources, placing
728 * them in |this.html|. Calls the callback when complete. 753 * them in |this.html|. Calls the callback when complete.
729 * 754 *
730 * @param {Function} callback The callback function. 755 * @param {Function} callback The callback function.
731 */ 756 */
732 fillSrcHoles(callback) { 757 fillSrcHoles(callback) {
733 if (Object.keys(this.srcHoles).length == 0) { 758 if (Object.keys(this.srcHoles).length == 0) {
734 callback(this); 759 callback(this);
735 } else { 760 } else {
736 var index = Object.keys(this.srcHoles)[0]; 761 var index = Object.keys(this.srcHoles)[0];
737 var src = this.srcHoles[index]; 762 var src = this.srcHoles[index];
738 delete this.srcHoles[index]; 763 delete this.srcHoles[index];
739 var serializer = this; 764 var serializer = this;
740 fetch(src).then(function(response) { 765 fetch(src).then(function(response) {
741 return response.blob(); 766 return response.blob();
742 }).then(function(blob) { 767 }).then(function(blob) {
743 var reader = new FileReader(); 768 var reader = new FileReader();
744 reader.onload = function(e) { 769 reader.onload = function(e) {
745 serializer.html[index] = e.target.result; 770 serializer.html[index] = e.target.result;
746 serializer.fillSrcHoles(callback); 771 serializer.fillSrcHoles(callback);
747 } 772 }
748 reader.readAsDataURL(blob); 773 reader.readAsDataURL(blob);
749 }).catch(function(error) { 774 }).catch(function(error) {
750 console.log(error); 775 console.log(error);
751 serializer.fillSrcHoles(callback); 776 serializer.fillSrcHoles(callback);
752 }); 777 });
753 } 778 }
754 } 779 }
755 } 780 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698