summaryrefslogtreecommitdiffstats
path: root/toolkit
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2020-06-01 21:58:35 +0000
committerMoonchild <moonchild@palemoon.org>2020-06-01 21:58:35 +0000
commitc6ca4380e9e5e95df9de02daf8bfb9a6ebc22810 (patch)
treec7672903a2030d37f861b12900165a015f49d10a /toolkit
parent451509e2c0188a4164d4b3d1d9f5839ed1e95246 (diff)
parent744b044935f7d1d67fbe0df42d898efcbdd00536 (diff)
downloadUXP-c6ca4380e9e5e95df9de02daf8bfb9a6ebc22810.tar
UXP-c6ca4380e9e5e95df9de02daf8bfb9a6ebc22810.tar.gz
UXP-c6ca4380e9e5e95df9de02daf8bfb9a6ebc22810.tar.lz
UXP-c6ca4380e9e5e95df9de02daf8bfb9a6ebc22810.tar.xz
UXP-c6ca4380e9e5e95df9de02daf8bfb9a6ebc22810.zip
Merge remote-tracking branch 'origin/redwood' into release
Diffstat (limited to 'toolkit')
-rw-r--r--toolkit/components/reader/AboutReader.jsm89
-rw-r--r--toolkit/components/reader/JSDOMParser.js34
-rw-r--r--toolkit/components/reader/Readability-readerable.js11
-rw-r--r--toolkit/components/reader/Readability.js390
-rw-r--r--toolkit/components/reader/ReaderMode.jsm44
-rw-r--r--toolkit/components/reader/content/aboutReader.html1
-rw-r--r--toolkit/components/telemetry/Histograms.json259
-rw-r--r--toolkit/components/telemetry/histogram-whitelists.json78
-rw-r--r--toolkit/content/license.html47
-rw-r--r--toolkit/moz.configure34
-rw-r--r--toolkit/themes/shared/aboutReader.css5
11 files changed, 413 insertions, 579 deletions
diff --git a/toolkit/components/reader/AboutReader.jsm b/toolkit/components/reader/AboutReader.jsm
index 9d9362a0c..3958af081 100644
--- a/toolkit/components/reader/AboutReader.jsm
+++ b/toolkit/components/reader/AboutReader.jsm
@@ -70,8 +70,6 @@ var AboutReader = function(win, articlePromise) {
Services.obs.addObserver(this, "inner-window-destroyed", false);
- doc.addEventListener("visibilitychange", this);
-
this._setupStyleDropdown();
this._setupButton("close-button", this._onReaderClose.bind(this), "aboutReader.toolbar.close");
@@ -238,14 +236,6 @@ AboutReader.prototype = {
}
break;
- case "devicelight":
- this._handleDeviceLight(aEvent.value);
- break;
-
- case "visibilitychange":
- this._handleVisibilityChange();
- break;
-
case "pagehide":
// Close the Banners Font-dropdown, cleanup Android BackPressListener.
this._closeDropdowns();
@@ -310,10 +300,6 @@ AboutReader.prototype = {
const FONT_SIZE_MIN = 1;
const FONT_SIZE_MAX = 9;
- // Sample text shown in Android UI.
- let sampleText = this._doc.querySelector(".font-size-sample");
- sampleText.textContent = gStrings.GetStringFromName("aboutReader.fontTypeSample");
-
let currentSize = Services.prefs.getIntPref("reader.font_size");
currentSize = Math.max(FONT_SIZE_MIN, Math.min(FONT_SIZE_MAX, currentSize));
@@ -503,77 +489,8 @@ AboutReader.prototype = {
}, true);
},
- _handleDeviceLight(newLux) {
- // Desired size of the this._luxValues array.
- let luxValuesSize = 10;
- // Add new lux value at the front of the array.
- this._luxValues.unshift(newLux);
- // Add new lux value to this._totalLux for averaging later.
- this._totalLux += newLux;
-
- // Don't update when length of array is less than luxValuesSize except when it is 1.
- if (this._luxValues.length < luxValuesSize) {
- // Use the first lux value to set the color scheme until our array equals luxValuesSize.
- if (this._luxValues.length == 1) {
- this._updateColorScheme(newLux);
- }
- return;
- }
- // Holds the average of the lux values collected in this._luxValues.
- let averageLuxValue = this._totalLux / luxValuesSize;
-
- this._updateColorScheme(averageLuxValue);
- // Pop the oldest value off the array.
- let oldLux = this._luxValues.pop();
- // Subtract oldLux since it has been discarded from the array.
- this._totalLux -= oldLux;
- },
-
- _handleVisibilityChange() {
- let colorScheme = Services.prefs.getCharPref("reader.color_scheme");
- if (colorScheme != "auto") {
- return;
- }
-
- // Turn off the ambient light sensor if the page is hidden
- this._enableAmbientLighting(!this._doc.hidden);
- },
-
- // Setup or teardown the ambient light tracking system.
- _enableAmbientLighting(enable) {
- if (enable) {
- this._win.addEventListener("devicelight", this);
- this._luxValues = [];
- this._totalLux = 0;
- } else {
- this._win.removeEventListener("devicelight", this);
- delete this._luxValues;
- delete this._totalLux;
- }
- },
-
- _updateColorScheme(luxValue) {
- // Upper bound value for "dark" color scheme beyond which it changes to "light".
- let upperBoundDark = 50;
- // Lower bound value for "light" color scheme beyond which it changes to "dark".
- let lowerBoundLight = 10;
- // Threshold for color scheme change.
- let colorChangeThreshold = 20;
-
- // Ignore changes that are within a certain threshold of previous lux values.
- if ((this._colorScheme === "dark" && luxValue < upperBoundDark) ||
- (this._colorScheme === "light" && luxValue > lowerBoundLight))
- return;
-
- if (luxValue < colorChangeThreshold)
- this._setColorScheme("dark");
- else
- this._setColorScheme("light");
- },
-
_setColorScheme(newColorScheme) {
- // "auto" is not a real color scheme
- if (this._colorScheme === newColorScheme || newColorScheme === "auto")
+ if (this._colorScheme === newColorScheme)
return;
let bodyClasses = this._doc.body.classList;
@@ -585,10 +502,8 @@ AboutReader.prototype = {
bodyClasses.add(this._colorScheme);
},
- // Pref values include "dark", "light", and "auto", which automatically switches
- // between light and dark color schemes based on the ambient light level.
+ // Pref values include "dark", "light", and "sepia".
_setColorSchemePref(colorSchemePref) {
- this._enableAmbientLighting(colorSchemePref === "auto");
this._setColorScheme(colorSchemePref);
AsyncPrefs.set("reader.color_scheme", colorSchemePref);
diff --git a/toolkit/components/reader/JSDOMParser.js b/toolkit/components/reader/JSDOMParser.js
index ab2f503e1..2d3d6f156 100644
--- a/toolkit/components/reader/JSDOMParser.js
+++ b/toolkit/components/reader/JSDOMParser.js
@@ -315,6 +315,7 @@
}
}
getElems(this);
+ elems._isLiveNodeList = true;
return elems;
}
@@ -503,17 +504,9 @@
},
setValue: function(newValue) {
this._value = newValue;
- delete this._decodedValue;
},
- setDecodedValue: function(newValue) {
- this._value = encodeHTML(newValue);
- this._decodedValue = newValue;
- },
- getDecodedValue: function() {
- if (typeof this._decodedValue === "undefined") {
- this._decodedValue = (this._value && decodeHTML(this._value)) || "";
- }
- return this._decodedValue;
+ getEncodedValue: function() {
+ return encodeHTML(this._value);
},
};
@@ -673,6 +666,14 @@
this.setAttribute("src", str);
},
+ get srcset() {
+ return this.getAttribute("srcset") || "";
+ },
+
+ set srcset(str) {
+ this.setAttribute("srcset", str);
+ },
+
get nodeName() {
return this.tagName;
},
@@ -689,7 +690,7 @@
for (var j = 0; j < child.attributes.length; j++) {
var attr = child.attributes[j];
// the attribute value will be HTML escaped.
- var val = attr.value;
+ var val = attr.getEncodedValue();
var quote = (val.indexOf('"') === -1 ? '"' : "'");
arr.push(" " + attr.name + "=" + quote + val + quote);
}
@@ -767,8 +768,9 @@
getAttribute: function (name) {
for (var i = this.attributes.length; --i >= 0;) {
var attr = this.attributes[i];
- if (attr.name === name)
- return attr.getDecodedValue();
+ if (attr.name === name) {
+ return attr.value;
+ }
}
return undefined;
},
@@ -777,11 +779,11 @@
for (var i = this.attributes.length; --i >= 0;) {
var attr = this.attributes[i];
if (attr.name === name) {
- attr.setDecodedValue(value);
+ attr.setValue(value);
return;
}
}
- this.attributes.push(new Attribute(name, encodeHTML(value)));
+ this.attributes.push(new Attribute(name, value));
},
removeAttribute: function (name) {
@@ -945,7 +947,7 @@
// Read the attribute value (and consume the matching quote)
var value = this.readString(c);
- node.attributes.push(new Attribute(name, value));
+ node.attributes.push(new Attribute(name, decodeHTML(value)));
return;
},
diff --git a/toolkit/components/reader/Readability-readerable.js b/toolkit/components/reader/Readability-readerable.js
index d0e1b8164..839d9fbf7 100644
--- a/toolkit/components/reader/Readability-readerable.js
+++ b/toolkit/components/reader/Readability-readerable.js
@@ -31,13 +31,16 @@
var REGEXPS = {
// NOTE: These two regular expressions are duplicated in
// Readability.js. Please keep both copies in sync.
- unlikelyCandidates: /-ad-|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|foot|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i,
- okMaybeItsACandidate: /and|article|body|column|main|shadow/i,
+ unlikelyCandidates: /-ad-|ai2html|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|footer|gdpr|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i,
+ okMaybeItsACandidate: /and|article|body|column|content|main|shadow/i,
};
function isNodeVisible(node) {
- // Have to null-check node.style to deal with SVG and MathML nodes.
- return (!node.style || node.style.display != "none") && !node.hasAttribute("hidden");
+ // Have to null-check node.style and node.className.indexOf to deal with SVG and MathML nodes.
+ return (!node.style || node.style.display != "none")
+ && !node.hasAttribute("hidden")
+ //check for "fallback-image" so that wikimedia math images are displayed
+ && (!node.hasAttribute("aria-hidden") || node.getAttribute("aria-hidden") != "true" || (node.className && node.className.indexOf && node.className.indexOf("fallback-image") !== -1));
}
/**
diff --git a/toolkit/components/reader/Readability.js b/toolkit/components/reader/Readability.js
index 69fb53f86..4a3689885 100644
--- a/toolkit/components/reader/Readability.js
+++ b/toolkit/components/reader/Readability.js
@@ -43,6 +43,7 @@ function Readability(doc, options) {
options = options || {};
this._doc = doc;
+ this._docJSDOMParser = this._doc.firstChild.__JSDOMParser__;
this._articleTitle = null;
this._articleByline = null;
this._articleDir = null;
@@ -55,6 +56,7 @@ function Readability(doc, options) {
this._nbTopCandidates = options.nbTopCandidates || this.DEFAULT_N_TOP_CANDIDATES;
this._charThreshold = options.charThreshold || this.DEFAULT_CHAR_THRESHOLD;
this._classesToPreserve = this.CLASSES_TO_PRESERVE.concat(options.classesToPreserve || []);
+ this._keepClasses = !!options.keepClasses;
// Start with all flags set
this._flags = this.FLAG_STRIP_UNLIKELYS |
@@ -121,20 +123,23 @@ Readability.prototype = {
REGEXPS: {
// NOTE: These two regular expressions are duplicated in
// Readability-readerable.js. Please keep both copies in sync.
- unlikelyCandidates: /-ad-|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|foot|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i,
- okMaybeItsACandidate: /and|article|body|column|main|shadow/i,
+ unlikelyCandidates: /-ad-|ai2html|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|footer|gdpr|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i,
+ okMaybeItsACandidate: /and|article|body|column|content|main|shadow/i,
positive: /article|body|content|entry|hentry|h-entry|main|page|pagination|post|text|blog|story/i,
- negative: /hidden|^hid$| hid$| hid |^hid |banner|combx|comment|com-|contact|foot|footer|footnote|masthead|media|meta|outbrain|promo|related|scroll|share|shoutbox|sidebar|skyscraper|sponsor|shopping|tags|tool|widget/i,
+ negative: /hidden|^hid$| hid$| hid |^hid |banner|combx|comment|com-|contact|foot|footer|footnote|gdpr|masthead|media|meta|outbrain|promo|related|scroll|share|shoutbox|sidebar|skyscraper|sponsor|shopping|tags|tool|widget/i,
extraneous: /print|archive|comment|discuss|e[\-]?mail|share|reply|all|login|sign|single|utility/i,
byline: /byline|author|dateline|writtenby|p-author/i,
replaceFonts: /<(\/?)font[^>]*>/gi,
normalize: /\s{2,}/g,
videos: /\/\/(www\.)?((dailymotion|youtube|youtube-nocookie|player\.vimeo|v\.qq)\.com|(archive|upload\.wikimedia)\.org|player\.twitch\.tv)/i,
+ shareElements: /(\b|_)(share|sharedaddy)(\b|_)/i,
nextLink: /(next|weiter|continue|>([^\|]|$)|»([^\|]|$))/i,
prevLink: /(prev|earl|old|new|<|«)/i,
whitespace: /^\s*$/,
hasContent: /\S$/,
+ srcsetUrl: /(\S+)(\s+[\d.]+[xw])?(\s*(?:,|$))/g,
+ b64DataUrl: /^data:\s*([^\s;,]+)\s*;\s*base64\s*,/i
},
DIV_TO_P_ELEMS: [ "A", "BLOCKQUOTE", "DL", "DIV", "IMG", "OL", "P", "PRE", "TABLE", "UL", "SELECT" ],
@@ -159,6 +164,15 @@ Readability.prototype = {
// These are the classes that readability sets itself.
CLASSES_TO_PRESERVE: [ "page" ],
+ // These are the list of HTML entities that need to be escaped.
+ HTML_ESCAPE_MAP: {
+ "lt": "<",
+ "gt": ">",
+ "amp": "&",
+ "quot": '"',
+ "apos": "'",
+ },
+
/**
* Run any post-process modifications to article content as necessary.
*
@@ -169,8 +183,10 @@ Readability.prototype = {
// Readability cannot open relative uris so we convert them to absolute uris.
this._fixRelativeUris(articleContent);
- // Remove classes.
- this._cleanClasses(articleContent);
+ if (!this._keepClasses) {
+ // Remove classes.
+ this._cleanClasses(articleContent);
+ }
},
/**
@@ -184,6 +200,10 @@ Readability.prototype = {
* @return void
*/
_removeNodes: function(nodeList, filterFn) {
+ // Avoid ever operating on live node lists.
+ if (this._docJSDOMParser && nodeList._isLiveNodeList) {
+ throw new Error("Do not pass live node lists to _removeNodes");
+ }
for (var i = nodeList.length - 1; i >= 0; i--) {
var node = nodeList[i];
var parentNode = node.parentNode;
@@ -203,6 +223,10 @@ Readability.prototype = {
* @return void
*/
_replaceNodeTags: function(nodeList, newTagName) {
+ // Avoid ever operating on live node lists.
+ if (this._docJSDOMParser && nodeList._isLiveNodeList) {
+ throw new Error("Do not pass live node lists to _replaceNodeTags");
+ }
for (var i = nodeList.length - 1; i >= 0; i--) {
var node = nodeList[i];
this._setNodeTag(node, newTagName);
@@ -322,6 +346,7 @@ Readability.prototype = {
if (baseURI == documentURI && uri.charAt(0) == "#") {
return uri;
}
+
// Otherwise, resolve against base URI:
try {
return new URL(uri, baseURI).href;
@@ -335,22 +360,50 @@ Readability.prototype = {
this._forEachNode(links, function(link) {
var href = link.getAttribute("href");
if (href) {
- // Replace links with javascript: URIs with text content, since
+ // Remove links with javascript: URIs, since
// they won't work after scripts have been removed from the page.
if (href.indexOf("javascript:") === 0) {
- var text = this._doc.createTextNode(link.textContent);
- link.parentNode.replaceChild(text, link);
+ // if the link only contains simple text content, it can be converted to a text node
+ if (link.childNodes.length === 1 && link.childNodes[0].nodeType === this.TEXT_NODE) {
+ var text = this._doc.createTextNode(link.textContent);
+ link.parentNode.replaceChild(text, link);
+ } else {
+ // if the link has multiple children, they should all be preserved
+ var container = this._doc.createElement("span");
+ while (link.childNodes.length > 0) {
+ container.appendChild(link.childNodes[0]);
+ }
+ link.parentNode.replaceChild(container, link);
+ }
} else {
link.setAttribute("href", toAbsoluteURI(href));
}
}
});
- var imgs = this._getAllNodesWithTag(articleContent, ["img"]);
- this._forEachNode(imgs, function(img) {
- var src = img.getAttribute("src");
+ var medias = this._getAllNodesWithTag(articleContent, [
+ "img", "picture", "figure", "video", "audio", "source"
+ ]);
+
+ this._forEachNode(medias, function(media) {
+ var src = media.getAttribute("src");
+ var poster = media.getAttribute("poster");
+ var srcset = media.getAttribute("srcset");
+
if (src) {
- img.setAttribute("src", toAbsoluteURI(src));
+ media.setAttribute("src", toAbsoluteURI(src));
+ }
+
+ if (poster) {
+ media.setAttribute("poster", toAbsoluteURI(poster));
+ }
+
+ if (srcset) {
+ var newSrcset = srcset.replace(this.REGEXPS.srcsetUrl, function(_, p1, p2, p3) {
+ return toAbsoluteURI(p1) + (p2 || "") + p3;
+ });
+
+ media.setAttribute("srcset", newSrcset);
}
});
},
@@ -444,13 +497,13 @@ Readability.prototype = {
var doc = this._doc;
// Remove all style tags in head
- this._removeNodes(doc.getElementsByTagName("style"));
+ this._removeNodes(this._getAllNodesWithTag(doc, ["style"]));
if (doc.body) {
this._replaceBrs(doc.body);
}
- this._replaceNodeTags(doc.getElementsByTagName("font"), "SPAN");
+ this._replaceNodeTags(this._getAllNodesWithTag(doc, ["font"]), "SPAN");
},
/**
@@ -530,7 +583,7 @@ Readability.prototype = {
_setNodeTag: function (node, tag) {
this.log("_setNodeTag", node, tag);
- if (node.__JSDOMParser__) {
+ if (this._docJSDOMParser) {
node.localName = tag.toLowerCase();
node.tagName = tag.toUpperCase();
return node;
@@ -545,7 +598,16 @@ Readability.prototype = {
replacement.readability = node.readability;
for (var i = 0; i < node.attributes.length; i++) {
- replacement.setAttribute(node.attributes[i].name, node.attributes[i].value);
+ try {
+ replacement.setAttribute(node.attributes[i].name, node.attributes[i].value);
+ } catch (ex) {
+ /* it's possible for setAttribute() to throw if the attribute name
+ * isn't a valid XML Name. Such attributes can however be parsed from
+ * source in HTML docs, see https://github.com/whatwg/html/issues/4275,
+ * so we can hit them here and then throw. We don't care about such
+ * attributes so we ignore them.
+ */
+ }
}
return replacement;
},
@@ -565,6 +627,8 @@ Readability.prototype = {
// visually linked to other content-ful elements (text, images, etc.).
this._markDataTables(articleContent);
+ this._fixLazyImages(articleContent);
+
// Clean out junk from the article content
this._cleanConditionally(articleContent, "form");
this._cleanConditionally(articleContent, "fieldset");
@@ -575,10 +639,15 @@ Readability.prototype = {
this._clean(articleContent, "link");
this._clean(articleContent, "aside");
- // Clean out elements have "share" in their id/class combinations from final top candidates,
+ // Clean out elements with little content that have "share" in their id/class combinations from final top candidates,
// which means we don't remove the top candidates even they have "share".
- this._forEachNode(articleContent.children, function(topCandidate) {
- this._cleanMatchedNodes(topCandidate, /share/);
+
+ var shareElementThreshold = this.DEFAULT_CHAR_THRESHOLD;
+
+ this._forEachNode(articleContent.children, function (topCandidate) {
+ this._cleanMatchedNodes(topCandidate, function (node, matchString) {
+ return this.REGEXPS.shareElements.test(matchString) && node.textContent.length < shareElementThreshold;
+ });
});
// If there is only one h2 and its text content substantially equals article title,
@@ -614,7 +683,7 @@ Readability.prototype = {
this._cleanConditionally(articleContent, "div");
// Remove extra paragraphs
- this._removeNodes(articleContent.getElementsByTagName("p"), function (paragraph) {
+ this._removeNodes(this._getAllNodesWithTag(articleContent, ["p"]), function (paragraph) {
var imgCount = paragraph.getElementsByTagName("img").length;
var embedCount = paragraph.getElementsByTagName("embed").length;
var objectCount = paragraph.getElementsByTagName("object").length;
@@ -729,9 +798,10 @@ Readability.prototype = {
if (node.getAttribute !== undefined) {
var rel = node.getAttribute("rel");
+ var itemprop = node.getAttribute("itemprop");
}
- if ((rel === "author" || this.REGEXPS.byline.test(matchString)) && this._isValidByline(node.textContent)) {
+ if ((rel === "author" || (itemprop && itemprop.indexOf("author") !== -1) || this.REGEXPS.byline.test(matchString)) && this._isValidByline(node.textContent)) {
this._articleByline = node.textContent.trim();
return true;
}
@@ -800,12 +870,19 @@ Readability.prototype = {
if (stripUnlikelyCandidates) {
if (this.REGEXPS.unlikelyCandidates.test(matchString) &&
!this.REGEXPS.okMaybeItsACandidate.test(matchString) &&
+ !this._hasAncestorTag(node, "table") &&
node.tagName !== "BODY" &&
node.tagName !== "A") {
this.log("Removing unlikely candidate - " + matchString);
node = this._removeAndGetNext(node);
continue;
}
+
+ if (node.getAttribute("role") == "complementary") {
+ this.log("Removing complementary content - " + matchString);
+ node = this._removeAndGetNext(node);
+ continue;
+ }
}
// Remove DIV, SECTION, and HEADER nodes without any content(e.g. text, image, video, or iframe).
@@ -1200,6 +1277,26 @@ Readability.prototype = {
},
/**
+ * Converts some of the common HTML entities in string to their corresponding characters.
+ *
+ * @param str {string} - a string to unescape.
+ * @return string without HTML entity.
+ */
+ _unescapeHtmlEntities: function(str) {
+ if (!str) {
+ return str;
+ }
+
+ var htmlEscapeMap = this.HTML_ESCAPE_MAP;
+ return str.replace(/&(quot|amp|apos|lt|gt);/g, function(_, tag) {
+ return htmlEscapeMap[tag];
+ }).replace(/&#(?:x([0-9a-z]{1,4})|([0-9]{1,4}));/gi, function(_, hex, numStr) {
+ var num = parseInt(hex || numStr, hex ? 16 : 10);
+ return String.fromCharCode(num);
+ });
+ },
+
+ /**
* Attempts to get excerpt and byline metadata for the article.
*
* @return Object with optional "excerpt" and "byline" properties
@@ -1220,6 +1317,9 @@ Readability.prototype = {
var elementName = element.getAttribute("name");
var elementProperty = element.getAttribute("property");
var content = element.getAttribute("content");
+ if (!content) {
+ return;
+ }
var matches = null;
var name = null;
@@ -1276,21 +1376,123 @@ Readability.prototype = {
// get site name
metadata.siteName = values["og:site_name"];
+ // in many sites the meta value is escaped with HTML entities,
+ // so here we need to unescape it
+ metadata.title = this._unescapeHtmlEntities(metadata.title);
+ metadata.byline = this._unescapeHtmlEntities(metadata.byline);
+ metadata.excerpt = this._unescapeHtmlEntities(metadata.excerpt);
+ metadata.siteName = this._unescapeHtmlEntities(metadata.siteName);
+
return metadata;
},
/**
+ * Check if node is image, or if node contains exactly only one image
+ * whether as a direct child or as its descendants.
+ *
+ * @param Element
+ **/
+ _isSingleImage: function(node) {
+ if (node.tagName === "IMG") {
+ return true;
+ }
+
+ if (node.children.length !== 1 || node.textContent.trim() !== "") {
+ return false;
+ }
+
+ return this._isSingleImage(node.children[0]);
+ },
+
+ /**
+ * Find all <noscript> that are located after <img> nodes, and which contain only one
+ * <img> element. Replace the first image with the image from inside the <noscript> tag,
+ * and remove the <noscript> tag. This improves the quality of the images we use on
+ * some sites (e.g. Medium).
+ *
+ * @param Element
+ **/
+ _unwrapNoscriptImages: function(doc) {
+ // Find img without source or attributes that might contains image, and remove it.
+ // This is done to prevent a placeholder img is replaced by img from noscript in next step.
+ var imgs = Array.from(doc.getElementsByTagName("img"));
+ this._forEachNode(imgs, function(img) {
+ for (var i = 0; i < img.attributes.length; i++) {
+ var attr = img.attributes[i];
+ switch (attr.name) {
+ case "src":
+ case "srcset":
+ case "data-src":
+ case "data-srcset":
+ return;
+ }
+
+ if (/\.(jpg|jpeg|png|webp)/i.test(attr.value)) {
+ return;
+ }
+ }
+
+ img.parentNode.removeChild(img);
+ });
+
+ // Next find noscript and try to extract its image
+ var noscripts = Array.from(doc.getElementsByTagName("noscript"));
+ this._forEachNode(noscripts, function(noscript) {
+ // Parse content of noscript and make sure it only contains image
+ var tmp = doc.createElement("div");
+ tmp.innerHTML = noscript.innerHTML;
+ if (!this._isSingleImage(tmp)) {
+ return;
+ }
+
+ // If noscript has previous sibling and it only contains image,
+ // replace it with noscript content. However we also keep old
+ // attributes that might contains image.
+ var prevElement = noscript.previousElementSibling;
+ if (prevElement && this._isSingleImage(prevElement)) {
+ var prevImg = prevElement;
+ if (prevImg.tagName !== "IMG") {
+ prevImg = prevElement.getElementsByTagName("img")[0];
+ }
+
+ var newImg = tmp.getElementsByTagName("img")[0];
+ for (var i = 0; i < prevImg.attributes.length; i++) {
+ var attr = prevImg.attributes[i];
+ if (attr.value === "") {
+ continue;
+ }
+
+ if (attr.name === "src" || attr.name === "srcset" || /\.(jpg|jpeg|png|webp)/i.test(attr.value)) {
+ if (newImg.getAttribute(attr.name) === attr.value) {
+ continue;
+ }
+
+ var attrName = attr.name;
+ if (newImg.hasAttribute(attrName)) {
+ attrName = "data-old-" + attrName;
+ }
+
+ newImg.setAttribute(attrName, attr.value);
+ }
+ }
+
+ noscript.parentNode.replaceChild(tmp.firstElementChild, prevElement);
+ }
+ });
+ },
+
+ /**
* Removes script tags from the document.
*
* @param Element
**/
_removeScripts: function(doc) {
- this._removeNodes(doc.getElementsByTagName("script"), function(scriptNode) {
+ this._removeNodes(this._getAllNodesWithTag(doc, ["script"]), function(scriptNode) {
scriptNode.nodeValue = "";
scriptNode.removeAttribute("src");
return true;
});
- this._removeNodes(doc.getElementsByTagName("noscript"));
+ this._removeNodes(this._getAllNodesWithTag(doc, ["noscript"]));
},
/**
@@ -1473,20 +1675,20 @@ Readability.prototype = {
_clean: function(e, tag) {
var isEmbed = ["object", "embed", "iframe"].indexOf(tag) !== -1;
- this._removeNodes(e.getElementsByTagName(tag), function(element) {
+ this._removeNodes(this._getAllNodesWithTag(e, [tag]), function(element) {
// Allow youtube and vimeo videos through as people usually want to see those.
if (isEmbed) {
- var attributeValues = [].map.call(element.attributes, function(attr) {
- return attr.value;
- }).join("|");
-
// First, check the elements attributes to see if any of them contain youtube or vimeo
- if (this.REGEXPS.videos.test(attributeValues))
- return false;
+ for (var i = 0; i < element.attributes.length; i++) {
+ if (this.REGEXPS.videos.test(element.attributes[i].value)) {
+ return false;
+ }
+ }
- // Then check the elements inside this element for the same.
- if (this.REGEXPS.videos.test(element.innerHTML))
+ // For embed with <object> tag, check inner HTML as well.
+ if (element.tagName === "object" && this.REGEXPS.videos.test(element.innerHTML)) {
return false;
+ }
}
return true;
@@ -1604,6 +1806,76 @@ Readability.prototype = {
}
},
+ /* convert images and figures that have properties like data-src into images that can be loaded without JS */
+ _fixLazyImages: function (root) {
+ this._forEachNode(this._getAllNodesWithTag(root, ["img", "picture", "figure"]), function (elem) {
+ // In some sites (e.g. Kotaku), they put 1px square image as base64 data uri in the src attribute.
+ // So, here we check if the data uri is too short, just might as well remove it.
+ if (elem.src && this.REGEXPS.b64DataUrl.test(elem.src)) {
+ // Make sure it's not SVG, because SVG can have a meaningful image in under 133 bytes.
+ var parts = this.REGEXPS.b64DataUrl.exec(elem.src);
+ if (parts[1] === "image/svg+xml") {
+ return;
+ }
+
+ // Make sure this element has other attributes which contains image.
+ // If it doesn't, then this src is important and shouldn't be removed.
+ var srcCouldBeRemoved = false;
+ for (var i = 0; i < elem.attributes.length; i++) {
+ var attr = elem.attributes[i];
+ if (attr.name === "src") {
+ continue;
+ }
+
+ if (/\.(jpg|jpeg|png|webp)/i.test(attr.value)) {
+ srcCouldBeRemoved = true;
+ break;
+ }
+ }
+
+ // Here we assume if image is less than 100 bytes (or 133B after encoded to base64)
+ // it will be too small, therefore it might be placeholder image.
+ if (srcCouldBeRemoved) {
+ var b64starts = elem.src.search(/base64\s*/i) + 7;
+ var b64length = elem.src.length - b64starts;
+ if (b64length < 133) {
+ elem.removeAttribute("src");
+ }
+ }
+ }
+
+ // also check for "null" to work around https://github.com/jsdom/jsdom/issues/2580
+ if ((elem.src || (elem.srcset && elem.srcset != "null")) && elem.className.toLowerCase().indexOf("lazy") === -1) {
+ return;
+ }
+
+ for (var j = 0; j < elem.attributes.length; j++) {
+ attr = elem.attributes[j];
+ if (attr.name === "src" || attr.name === "srcset") {
+ continue;
+ }
+ var copyTo = null;
+ if (/\.(jpg|jpeg|png|webp)\s+\d/.test(attr.value)) {
+ copyTo = "srcset";
+ } else if (/^\s*\S+\.(jpg|jpeg|png|webp)\S*\s*$/.test(attr.value)) {
+ copyTo = "src";
+ }
+ if (copyTo) {
+ //if this is an img or picture, set the attribute directly
+ if (elem.tagName === "IMG" || elem.tagName === "PICTURE") {
+ elem.setAttribute(copyTo, attr.value);
+ } else if (elem.tagName === "FIGURE" && !this._getAllNodesWithTag(elem, ["img", "picture"]).length) {
+ //if the item is a <figure> that does not contain an image or picture, create one and place it inside the figure
+ //see the nytimes-3 testcase for an example
+ var img = this._doc.createElement("img");
+ img.setAttribute(copyTo, attr.value);
+ elem.appendChild(img);
+ }
+ }
+ }
+ });
+ },
+
/**
* Clean an element of all tags of type "tag" if they look fishy.
* "Fishy" is an algorithm based on content length, classnames, link density, number of images & embeds, etc.
@@ -1621,12 +1893,17 @@ Readability.prototype = {
// without effecting the traversal.
//
// TODO: Consider taking into account original contentScore here.
- this._removeNodes(e.getElementsByTagName(tag), function(node) {
- // First check if we're in a data table, in which case don't remove us.
+ this._removeNodes(this._getAllNodesWithTag(e, [tag]), function(node) {
+ // First check if this node IS data table, in which case don't remove it.
var isDataTable = function(t) {
return t._readabilityDataTable;
};
+ if (tag === "table" && isDataTable(node)) {
+ return false;
+ }
+
+ // Next check if we're inside a data table, in which case don't remove it as well.
if (this._hasAncestorTag(node, "table", -1, isDataTable)) {
return false;
}
@@ -1650,10 +1927,22 @@ Readability.prototype = {
var input = node.getElementsByTagName("input").length;
var embedCount = 0;
- var embeds = node.getElementsByTagName("embed");
- for (var ei = 0, il = embeds.length; ei < il; ei += 1) {
- if (!this.REGEXPS.videos.test(embeds[ei].src))
- embedCount += 1;
+ var embeds = this._getAllNodesWithTag(node, ["object", "embed", "iframe"]);
+
+ for (var i = 0; i < embeds.length; i++) {
+ // If this embed has attribute that matches video regex, don't delete it.
+ for (var j = 0; j < embeds[i].attributes.length; j++) {
+ if (this.REGEXPS.videos.test(embeds[i].attributes[j].value)) {
+ return false;
+ }
+ }
+
+ // For embed with <object> tag, check inner HTML as well.
+ if (embeds[i].tagName === "object" && this.REGEXPS.videos.test(embeds[i].innerHTML)) {
+ return false;
+ }
+
+ embedCount++;
}
var linkDensity = this._getLinkDensity(node);
@@ -1674,17 +1963,17 @@ Readability.prototype = {
},
/**
- * Clean out elements whose id/class combinations match specific string.
+ * Clean out elements that match the specified conditions
*
* @param Element
- * @param RegExp match id/class combination.
+ * @param Function determines whether a node should be removed
* @return void
**/
- _cleanMatchedNodes: function(e, regex) {
+ _cleanMatchedNodes: function(e, filter) {
var endOfSearchMarkerNode = this._getNextNode(e, true);
var next = this._getNextNode(e);
while (next && next != endOfSearchMarkerNode) {
- if (regex.test(next.className + " " + next.id)) {
+ if (filter.call(this, next, next.className + " " + next.id)) {
next = this._removeAndGetNext(next);
} else {
next = this._getNextNode(next);
@@ -1699,11 +1988,9 @@ Readability.prototype = {
* @return void
**/
_cleanHeaders: function(e) {
- for (var headerIndex = 1; headerIndex < 3; headerIndex += 1) {
- this._removeNodes(e.getElementsByTagName("h" + headerIndex), function (header) {
- return this._getClassWeight(header) < 0;
- });
- }
+ this._removeNodes(this._getAllNodesWithTag(e, ["h1", "h2"]), function (header) {
+ return this._getClassWeight(header) < 0;
+ });
},
_flagIsActive: function(flag) {
@@ -1715,7 +2002,11 @@ Readability.prototype = {
},
_isProbablyVisible: function(node) {
- return (!node.style || node.style.display != "none") && !node.hasAttribute("hidden");
+ // Have to null-check node.style and node.className.indexOf to deal with SVG and MathML nodes.
+ return (!node.style || node.style.display != "none")
+ && !node.hasAttribute("hidden")
+ //check for "fallback-image" so that wikimedia math images are displayed
+ && (!node.hasAttribute("aria-hidden") || node.getAttribute("aria-hidden") != "true" || (node.className && node.className.indexOf && node.className.indexOf("fallback-image") !== -1));
},
/**
@@ -1739,6 +2030,9 @@ Readability.prototype = {
}
}
+ // Unwrap image from noscript
+ this._unwrapNoscriptImages(this._doc);
+
// Remove script tags from the document.
this._removeScripts(this._doc);
diff --git a/toolkit/components/reader/ReaderMode.jsm b/toolkit/components/reader/ReaderMode.jsm
index 5ba898aec..a1d2c5643 100644
--- a/toolkit/components/reader/ReaderMode.jsm
+++ b/toolkit/components/reader/ReaderMode.jsm
@@ -14,7 +14,7 @@ const CLASSES_TO_PRESERVE = [
"caption",
"emoji",
"hidden",
- "invisble",
+ "invisible",
"sr-only",
"visually-hidden",
"visuallyhidden",
@@ -346,6 +346,11 @@ this.ReaderMode = {
pathBase: Services.io.newURI(".", null, doc.baseURIObject).spec
};
+ // convert text/plain document, if any, to XHTML format
+ if (this._isDocumentPlainText(doc)) {
+ doc = this._convertPlainTextDocument(doc);
+ }
+
let langAttributes = {
charset: doc.characterSet,
lang: doc.documentElement.lang
@@ -540,6 +545,43 @@ this.ReaderMode = {
return readingSpeed.get(lang) || readingSpeed.get("en");
},
+
+ /**
+ *
+ * Check if the document to be parsed is text document.
+ * @param doc the doc object to be parsed.
+ * @return boolean
+ *
+ */
+ _isDocumentPlainText(doc) {
+ return doc.contentType == "text/plain";
+ },
+
+ /**
+ *
+ * The document to be parsed is text document and is converted to HTML format.
+ * @param doc the doc object to be parsed.
+ * @return doc
+ *
+ */
+ _convertPlainTextDocument(doc) {
+ let preTag = doc.querySelector("pre");
+ let docFrag = doc.createDocumentFragment();
+ let content = preTag.textContent;
+ let paragraphs = content.split(/\r?\n\r?\n/);
+ for (let para of paragraphs) {
+ let pElem = doc.createElement("p");
+ let lines = para.split(/\n/);
+ for (let line of lines) {
+ pElem.append(line);
+ let brElem = doc.createElement("br");
+ pElem.append(brElem);
+ }
+ docFrag.append(pElem);
+ }
+ preTag.parentNode.replaceChild(docFrag, preTag);
+ return doc;
+ },
};
// Don't try to parse the page if it has too many elements (for memory and
diff --git a/toolkit/components/reader/content/aboutReader.html b/toolkit/components/reader/content/aboutReader.html
index 1aa644474..58006c0a5 100644
--- a/toolkit/components/reader/content/aboutReader.html
+++ b/toolkit/components/reader/content/aboutReader.html
@@ -42,7 +42,6 @@
<hr>
<div class="font-size-buttons">
<button class="minus-button"/>
- <button class="font-size-sample"/>
<button class="plus-button"/>
</div>
<hr>
diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json
index f61a67efc..2d90166a6 100644
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -3704,265 +3704,6 @@
"n_values": 30,
"description": "Flash object instances count on page"
},
- "MOZ_SQLITE_OPEN_MS": {
- "expires_in_version": "default",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite open() (ms)"
- },
- "MOZ_SQLITE_OPEN_MAIN_THREAD_MS": {
- "expires_in_version": "40",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite open() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_TRUNCATE_MS": {
- "expires_in_version": "40",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite truncate() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_TRUNCATE_MAIN_THREAD_MS": {
- "expires_in_version": "40",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite truncate() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_OTHER_READ_MS": {
- "expires_in_version": "40",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite read() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_OTHER_READ_MAIN_THREAD_MS": {
- "expires_in_version": "40",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite read() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_PLACES_READ_MS": {
- "expires_in_version": "40",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite read() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_PLACES_READ_MAIN_THREAD_MS": {
- "expires_in_version": "40",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite read() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_COOKIES_OPEN_READAHEAD_MS": {
- "expires_in_version": "never",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on cookie DB open with readahead (ms)"
- },
- "MOZ_SQLITE_COOKIES_READ_MS": {
- "expires_in_version": "40",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite read() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_COOKIES_READ_MAIN_THREAD_MS": {
- "expires_in_version": "40",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite read() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_WEBAPPS_READ_MS": {
- "expires_in_version": "40",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite read() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_WEBAPPS_READ_MAIN_THREAD_MS": {
- "expires_in_version": "40",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite read() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_OTHER_WRITE_MS": {
- "expires_in_version": "40",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite write() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_OTHER_WRITE_MAIN_THREAD_MS": {
- "expires_in_version": "40",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite write() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_PLACES_WRITE_MS": {
- "expires_in_version": "default",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite write() (ms)"
- },
- "MOZ_SQLITE_PLACES_WRITE_MAIN_THREAD_MS": {
- "expires_in_version": "40",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite write() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_COOKIES_WRITE_MS": {
- "expires_in_version": "40",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite write() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_COOKIES_WRITE_MAIN_THREAD_MS": {
- "expires_in_version": "40",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite write() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_WEBAPPS_WRITE_MS": {
- "expires_in_version": "40",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite write() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_WEBAPPS_WRITE_MAIN_THREAD_MS": {
- "expires_in_version": "40",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite write() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_OTHER_SYNC_MS": {
- "expires_in_version": "never",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite fsync() (ms)"
- },
- "MOZ_SQLITE_OTHER_SYNC_MAIN_THREAD_MS": {
- "expires_in_version": "never",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite fsync() (ms)"
- },
- "MOZ_SQLITE_PLACES_SYNC_MS": {
- "expires_in_version": "never",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite fsync() (ms)"
- },
- "MOZ_SQLITE_PLACES_SYNC_MAIN_THREAD_MS": {
- "expires_in_version": "never",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite fsync() (ms)"
- },
- "MOZ_SQLITE_COOKIES_SYNC_MS": {
- "expires_in_version": "never",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite fsync() (ms)"
- },
- "MOZ_SQLITE_COOKIES_SYNC_MAIN_THREAD_MS": {
- "expires_in_version": "never",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite fsync() (ms)"
- },
- "MOZ_SQLITE_WEBAPPS_SYNC_MS": {
- "expires_in_version": "never",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite fsync() (ms)"
- },
- "MOZ_SQLITE_WEBAPPS_SYNC_MAIN_THREAD_MS": {
- "expires_in_version": "never",
- "kind": "exponential",
- "high": 3000,
- "n_buckets": 10,
- "description": "Time spent on SQLite fsync() (ms)"
- },
- "MOZ_SQLITE_OTHER_READ_B": {
- "expires_in_version": "default",
- "kind": "linear",
- "high": 32768,
- "n_buckets": 3,
- "description": "SQLite read() (bytes)"
- },
- "MOZ_SQLITE_PLACES_READ_B": {
- "expires_in_version": "40",
- "kind": "linear",
- "high": 32768,
- "n_buckets": 3,
- "description": "SQLite read() (bytes) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_COOKIES_READ_B": {
- "expires_in_version": "40",
- "kind": "linear",
- "high": 32768,
- "n_buckets": 3,
- "description": "SQLite read() (bytes) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_WEBAPPS_READ_B": {
- "expires_in_version": "40",
- "kind": "linear",
- "high": 32768,
- "n_buckets": 3,
- "description": "SQLite read() (bytes) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_PLACES_WRITE_B": {
- "expires_in_version": "40",
- "kind": "linear",
- "high": 32768,
- "n_buckets": 3,
- "description": "SQLite write (bytes) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_COOKIES_WRITE_B": {
- "expires_in_version": "40",
- "kind": "linear",
- "high": 32768,
- "n_buckets": 3,
- "description": "SQLite write (bytes) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_WEBAPPS_WRITE_B": {
- "expires_in_version": "40",
- "kind": "linear",
- "high": 32768,
- "n_buckets": 3,
- "description": "SQLite write (bytes) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
- },
- "MOZ_SQLITE_OTHER_WRITE_B": {
- "expires_in_version": "default",
- "kind": "linear",
- "high": 32768,
- "n_buckets": 3,
- "description": "SQLite write (bytes)"
- },
"MOZ_STORAGE_ASYNC_REQUESTS_MS": {
"alert_emails": ["perf-telemetry-alerts@mozilla.com"],
"expires_in_version": "40",
diff --git a/toolkit/components/telemetry/histogram-whitelists.json b/toolkit/components/telemetry/histogram-whitelists.json
index 529d9f4d5..5cd7c3145 100644
--- a/toolkit/components/telemetry/histogram-whitelists.json
+++ b/toolkit/components/telemetry/histogram-whitelists.json
@@ -392,43 +392,6 @@
"MEDIA_WMF_DECODE_ERROR",
"MIXED_CONTENT_PAGE_LOAD",
"MIXED_CONTENT_UNBLOCK_COUNTER",
- "MOZ_SQLITE_COOKIES_OPEN_READAHEAD_MS",
- "MOZ_SQLITE_COOKIES_READ_B",
- "MOZ_SQLITE_COOKIES_READ_MAIN_THREAD_MS",
- "MOZ_SQLITE_COOKIES_READ_MS",
- "MOZ_SQLITE_COOKIES_SYNC_MAIN_THREAD_MS",
- "MOZ_SQLITE_COOKIES_SYNC_MS",
- "MOZ_SQLITE_COOKIES_WRITE_B",
- "MOZ_SQLITE_COOKIES_WRITE_MAIN_THREAD_MS",
- "MOZ_SQLITE_COOKIES_WRITE_MS",
- "MOZ_SQLITE_OPEN_MAIN_THREAD_MS",
- "MOZ_SQLITE_OPEN_MS",
- "MOZ_SQLITE_OTHER_READ_B",
- "MOZ_SQLITE_OTHER_READ_MAIN_THREAD_MS",
- "MOZ_SQLITE_OTHER_READ_MS",
- "MOZ_SQLITE_OTHER_SYNC_MAIN_THREAD_MS",
- "MOZ_SQLITE_OTHER_SYNC_MS",
- "MOZ_SQLITE_OTHER_WRITE_B",
- "MOZ_SQLITE_OTHER_WRITE_MAIN_THREAD_MS",
- "MOZ_SQLITE_OTHER_WRITE_MS",
- "MOZ_SQLITE_PLACES_READ_B",
- "MOZ_SQLITE_PLACES_READ_MAIN_THREAD_MS",
- "MOZ_SQLITE_PLACES_READ_MS",
- "MOZ_SQLITE_PLACES_SYNC_MAIN_THREAD_MS",
- "MOZ_SQLITE_PLACES_SYNC_MS",
- "MOZ_SQLITE_PLACES_WRITE_B",
- "MOZ_SQLITE_PLACES_WRITE_MAIN_THREAD_MS",
- "MOZ_SQLITE_PLACES_WRITE_MS",
- "MOZ_SQLITE_TRUNCATE_MAIN_THREAD_MS",
- "MOZ_SQLITE_TRUNCATE_MS",
- "MOZ_SQLITE_WEBAPPS_READ_B",
- "MOZ_SQLITE_WEBAPPS_READ_MAIN_THREAD_MS",
- "MOZ_SQLITE_WEBAPPS_READ_MS",
- "MOZ_SQLITE_WEBAPPS_SYNC_MAIN_THREAD_MS",
- "MOZ_SQLITE_WEBAPPS_SYNC_MS",
- "MOZ_SQLITE_WEBAPPS_WRITE_B",
- "MOZ_SQLITE_WEBAPPS_WRITE_MAIN_THREAD_MS",
- "MOZ_SQLITE_WEBAPPS_WRITE_MS",
"NETWORK_CACHE_METADATA_FIRST_READ_SIZE",
"NETWORK_CACHE_METADATA_FIRST_READ_TIME_MS",
"NETWORK_CACHE_METADATA_SECOND_READ_TIME_MS",
@@ -1232,43 +1195,6 @@
"MIXED_CONTENT_HSTS",
"MIXED_CONTENT_PAGE_LOAD",
"MIXED_CONTENT_UNBLOCK_COUNTER",
- "MOZ_SQLITE_COOKIES_OPEN_READAHEAD_MS",
- "MOZ_SQLITE_COOKIES_READ_B",
- "MOZ_SQLITE_COOKIES_READ_MAIN_THREAD_MS",
- "MOZ_SQLITE_COOKIES_READ_MS",
- "MOZ_SQLITE_COOKIES_SYNC_MAIN_THREAD_MS",
- "MOZ_SQLITE_COOKIES_SYNC_MS",
- "MOZ_SQLITE_COOKIES_WRITE_B",
- "MOZ_SQLITE_COOKIES_WRITE_MAIN_THREAD_MS",
- "MOZ_SQLITE_COOKIES_WRITE_MS",
- "MOZ_SQLITE_OPEN_MAIN_THREAD_MS",
- "MOZ_SQLITE_OPEN_MS",
- "MOZ_SQLITE_OTHER_READ_B",
- "MOZ_SQLITE_OTHER_READ_MAIN_THREAD_MS",
- "MOZ_SQLITE_OTHER_READ_MS",
- "MOZ_SQLITE_OTHER_SYNC_MAIN_THREAD_MS",
- "MOZ_SQLITE_OTHER_SYNC_MS",
- "MOZ_SQLITE_OTHER_WRITE_B",
- "MOZ_SQLITE_OTHER_WRITE_MAIN_THREAD_MS",
- "MOZ_SQLITE_OTHER_WRITE_MS",
- "MOZ_SQLITE_PLACES_READ_B",
- "MOZ_SQLITE_PLACES_READ_MAIN_THREAD_MS",
- "MOZ_SQLITE_PLACES_READ_MS",
- "MOZ_SQLITE_PLACES_SYNC_MAIN_THREAD_MS",
- "MOZ_SQLITE_PLACES_SYNC_MS",
- "MOZ_SQLITE_PLACES_WRITE_B",
- "MOZ_SQLITE_PLACES_WRITE_MAIN_THREAD_MS",
- "MOZ_SQLITE_PLACES_WRITE_MS",
- "MOZ_SQLITE_TRUNCATE_MAIN_THREAD_MS",
- "MOZ_SQLITE_TRUNCATE_MS",
- "MOZ_SQLITE_WEBAPPS_READ_B",
- "MOZ_SQLITE_WEBAPPS_READ_MAIN_THREAD_MS",
- "MOZ_SQLITE_WEBAPPS_READ_MS",
- "MOZ_SQLITE_WEBAPPS_SYNC_MAIN_THREAD_MS",
- "MOZ_SQLITE_WEBAPPS_SYNC_MS",
- "MOZ_SQLITE_WEBAPPS_WRITE_B",
- "MOZ_SQLITE_WEBAPPS_WRITE_MAIN_THREAD_MS",
- "MOZ_SQLITE_WEBAPPS_WRITE_MS",
"MOZ_STORAGE_ASYNC_REQUESTS_MS",
"MOZ_STORAGE_ASYNC_REQUESTS_SUCCESS",
"NETWORK_CACHE_METADATA_FIRST_READ_SIZE",
@@ -1885,7 +1811,6 @@
"WEAVE_CONFIGURED",
"NEWTAB_PAGE_ENABLED",
"GRADIENT_DURATION",
- "MOZ_SQLITE_OPEN_MS",
"SHOULD_TRANSLATION_UI_APPEAR",
"NEWTAB_PAGE_LIFE_SPAN",
"FX_TOTAL_TOP_VISITS",
@@ -1902,7 +1827,6 @@
"FX_NEW_WINDOW_MS",
"PDF_VIEWER_TIME_TO_VIEW_MS",
"SSL_OCSP_MAY_FETCH",
- "MOZ_SQLITE_OTHER_READ_B",
"CHECK_JAVA_ENABLED",
"TRANSLATION_OPPORTUNITIES",
"FX_SESSION_RESTORE_CONTENT_COLLECT_DATA_LONGEST_OP_MS",
@@ -1928,11 +1852,9 @@
"FX_SESSION_RESTORE_DOM_STORAGE_SIZE_ESTIMATE_CHARS",
"DATA_STORAGE_ENTRIES",
"TRANSLATED_PAGES_BY_LANGUAGE",
- "MOZ_SQLITE_OTHER_WRITE_B",
"LOCALDOMSTORAGE_SHUTDOWN_DATABASE_MS",
"SSL_CERT_VERIFICATION_ERRORS",
"FX_SESSION_RESTORE_NUMBER_OF_WINDOWS_RESTORED",
- "MOZ_SQLITE_PLACES_WRITE_MS",
"FX_THUMBNAILS_BG_CAPTURE_CANVAS_DRAW_TIME_MS",
"FX_SESSION_RESTORE_STARTUP_INIT_SESSION_MS",
"FX_SESSION_RESTORE_WRITE_FILE_MS",
diff --git a/toolkit/content/license.html b/toolkit/content/license.html
index 7221a8ae2..1041ec42f 100644
--- a/toolkit/content/license.html
+++ b/toolkit/content/license.html
@@ -128,9 +128,6 @@
<li><a href="about:license#openaes">OpenAES License</a></li>
<li><a href="about:license#openvision">OpenVision License</a></li>
<li><a href="about:license#pbkdf2-sha256">pbkdf2_sha256 License</a></li>
-#ifdef MOZ_WEBSPEECH_POCKETSPHINX
- <li><a href="about:license#pocketsphinx">Pocketsphinx License</a></li>
-#endif
<li><a href="about:license#praton">praton License</a></li>
<li><a href="about:license#qcms">qcms License</a></li>
<li><a href="about:license#qrcode-generator">QR Code Generator License</a></li>
@@ -4481,50 +4478,6 @@ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
</pre>
-#ifdef MOZ_WEBSPEECH_POCKETSPHINX
-
- <hr>
-
- <h1><a id="pocketsphinx"></a>Pocketsphinx License</h1>
-
- <p>This license applies to files in the directories
- <span class="path">media/pocketsphinx/</span> and
- <span class="path">media/sphinxbase/</span>.
- </p>
-
-<pre>
-Copyright (c) 1999-2014 Carnegie Mellon University. All rights
-reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
-This work was supported in part by funding from the Defense Advanced
-Research Projects Agency and the National Science Foundation of the
-United States of America, and the CMU Sphinx Speech Consortium.
-
-THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND
-ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
-NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-</pre>
-#endif
<hr>
diff --git a/toolkit/moz.configure b/toolkit/moz.configure
index fe14cb567..863327751 100644
--- a/toolkit/moz.configure
+++ b/toolkit/moz.configure
@@ -495,7 +495,7 @@ set_config('MOZ_SYNTH_SPEECHD',
# Speech API
# ==============================================================
-option('--disable-webspeech', help='Disable support for HTML Speech API')
+option('--disable-webspeech', help='Disable support for HTML Speech synthesis API')
@depends('--disable-webspeech', '--help')
def webspeech(value, _):
@@ -506,38 +506,6 @@ set_config('MOZ_WEBSPEECH', webspeech)
set_define('MOZ_WEBSPEECH', webspeech)
add_old_configure_assignment('MOZ_WEBSPEECH', webspeech)
-# Speech API pocketsphinx backend
-# ==============================================================
-@depends(build_project, milestone, webspeech)
-def webspeech_pocketsphinx(build_project, milestone, webspeech):
- if webspeech and milestone.is_nightly and build_project == 'b2g':
- return True
-
-set_config('MOZ_WEBSPEECH_POCKETSPHINX', webspeech_pocketsphinx)
-set_define('MOZ_WEBSPEECH_POCKETSPHINX', webspeech_pocketsphinx)
-
-# Speech API models
-# ==============================================================
-@depends(build_project, milestone, webspeech)
-def webspeech_models(build_project, milestone, webspeech):
- if webspeech and milestone.is_nightly and build_project == 'b2g':
- return True
-
-set_config('MOZ_WEBSPEECH_MODELS', webspeech_models)
-set_define('MOZ_WEBSPEECH_MODELS', webspeech_models)
-
-# Speech API test backend
-# ==============================================================
-option('--enable-webspeechtestbackend', default=webspeech,
- help='Enable support for HTML Speech API Test Backend')
-
-@depends_if('--enable-webspeechtestbackend')
-def webspeech_test_backend(value):
- return True
-
-set_config('MOZ_WEBSPEECH_TEST_BACKEND', webspeech_test_backend)
-set_define('MOZ_WEBSPEECH_TEST_BACKEND', webspeech_test_backend)
-
# Enable IPDL's "expensive" unit tests
# ==============================================================
option('--enable-ipdl-tests', help='Enable expensive IPDL tests')
diff --git a/toolkit/themes/shared/aboutReader.css b/toolkit/themes/shared/aboutReader.css
index ff8f27565..1bfbd0309 100644
--- a/toolkit/themes/shared/aboutReader.css
+++ b/toolkit/themes/shared/aboutReader.css
@@ -445,11 +445,6 @@ body:not(.loaded) .toolbar:-moz-locale-dir(rtl) {
background-color: #dadada;
}
-/* Only used on Android */
-.font-size-sample {
- display: none;
-}
-
.minus-button,
.plus-button,
.content-width-minus-button,