mirror of
https://github.com/roytam1/mozilla45esr.git
synced 2026-05-26 06:25:03 +00:00
import changes from tenfourfox:
- remove Get More Tools, since it doesn't work (638361bd8) - #583: always-on (mostly) reader mode (cb5d8f86a) - #583: update Readability to latest tip; update glue to new API (8bd4c09a7) - #581: M1047098 M1355576 (ec8e68102) - closes #582: M1358018 modified for 45ESR (74fd7b6d0) - a better idea for #583 (f0a4e7686) - #584: M1507180 M1598605 (7b58ac561) - #584: update certs, pins, TLDs (f9572b6f0) - #334: remove moar tele (0761d9501)
This commit is contained in:
@@ -166,6 +166,7 @@ toolkit/components/places/**
|
||||
# Uses preprocessing
|
||||
toolkit/content/contentAreaUtils.js
|
||||
toolkit/components/jsdownloads/src/DownloadIntegration.jsm
|
||||
toolkit/components/reader/Readerable.jsm
|
||||
toolkit/components/search/nsSearchService.js
|
||||
toolkit/components/url-classifier/**
|
||||
toolkit/components/urlformatter/nsURLFormatter.js
|
||||
|
||||
@@ -557,10 +557,6 @@
|
||||
accesskey="&errorConsoleCmd.accesskey;"/>
|
||||
<menuitem id="menu_devtools_connect"
|
||||
observes="devtoolsMenuBroadcaster_connect"/>
|
||||
<menuseparator id="devToolsEndSeparator"/>
|
||||
<menuitem id="getMoreDevtools"
|
||||
observes="devtoolsMenuBroadcaster_GetMoreTools"
|
||||
accesskey="&getMoreDevtoolsCmd.accesskey;"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menuitem id="menu_pageInfo"
|
||||
|
||||
@@ -15,8 +15,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
|
||||
"resource://gre/modules/Preferences.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Deprecated",
|
||||
"resource://gre/modules/Deprecated.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
|
||||
"resource:///modules/BrowserUITelemetry.jsm");
|
||||
//XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
|
||||
// "resource:///modules/BrowserUITelemetry.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "E10SUtils",
|
||||
"resource:///modules/E10SUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils",
|
||||
@@ -156,8 +156,8 @@ this.__defineSetter__("AddonManager", function (val) {
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
||||
"resource://gre/modules/PluralForm.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch",
|
||||
"resource://gre/modules/TelemetryStopwatch.jsm");
|
||||
//XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch",
|
||||
// "resource://gre/modules/TelemetryStopwatch.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gCustomizeMode", function() {
|
||||
let scope = {};
|
||||
@@ -1082,9 +1082,9 @@ var gBrowserInit = {
|
||||
|
||||
_delayedStartup: function() {
|
||||
let tmp = {};
|
||||
Cu.import("resource://gre/modules/TelemetryTimestamps.jsm", tmp);
|
||||
let TelemetryTimestamps = tmp.TelemetryTimestamps;
|
||||
TelemetryTimestamps.add("delayedStartupStarted");
|
||||
//Cu.import("resource://gre/modules/TelemetryTimestamps.jsm", tmp);
|
||||
//let TelemetryTimestamps = tmp.TelemetryTimestamps;
|
||||
//TelemetryTimestamps.add("delayedStartupStarted");
|
||||
|
||||
this._cancelDelayedStartup();
|
||||
|
||||
@@ -1317,8 +1317,11 @@ var gBrowserInit = {
|
||||
|
||||
LightWeightThemeWebInstaller.init();
|
||||
|
||||
// See bug 1356587. This is never called on TenFourFox.
|
||||
/*
|
||||
if (Win7Features)
|
||||
Win7Features.onOpenWindow();
|
||||
*/
|
||||
|
||||
FullScreen.init();
|
||||
|
||||
@@ -1507,8 +1510,10 @@ var gBrowserInit = {
|
||||
if (this._boundDelayedStartup) {
|
||||
this._cancelDelayedStartup();
|
||||
} else {
|
||||
/*
|
||||
if (Win7Features)
|
||||
Win7Features.onCloseWindow();
|
||||
*/
|
||||
|
||||
gPrefService.removeObserver(ctrlTab.prefName, ctrlTab);
|
||||
ctrlTab.uninit();
|
||||
@@ -2730,7 +2735,7 @@ var BrowserOnClick = {
|
||||
mm.addMessageListener("Browser:EnableOnlineMode", this);
|
||||
mm.addMessageListener("Browser:SendSSLErrorReport", this);
|
||||
mm.addMessageListener("Browser:SetSSLErrorReportAuto", this);
|
||||
mm.addMessageListener("Browser:SSLErrorReportTelemetry", this);
|
||||
//mm.addMessageListener("Browser:SSLErrorReportTelemetry", this);
|
||||
mm.addMessageListener("Browser:OverrideWeakCrypto", this);
|
||||
mm.addMessageListener("Browser:SSLErrorGoBack", this);
|
||||
},
|
||||
@@ -2742,7 +2747,7 @@ var BrowserOnClick = {
|
||||
mm.removeMessageListener("Browser:EnableOnlineMode", this);
|
||||
mm.removeMessageListener("Browser:SendSSLErrorReport", this);
|
||||
mm.removeMessageListener("Browser:SetSSLErrorReportAuto", this);
|
||||
mm.removeMessageListener("Browser:SSLErrorReportTelemetry", this);
|
||||
//mm.removeMessageListener("Browser:SSLErrorReportTelemetry", this);
|
||||
mm.removeMessageListener("Browser:OverrideWeakCrypto", this);
|
||||
mm.removeMessageListener("Browser:SSLErrorGoBack", this);
|
||||
},
|
||||
@@ -3801,8 +3806,8 @@ const BrowserSearch = {
|
||||
* item was in the suggestion list and how the user selected it.
|
||||
*/
|
||||
recordSearchInHealthReport: function (engine, source, selection) {
|
||||
BrowserUITelemetry.countSearchEvent(source, null, selection);
|
||||
this.recordSearchInTelemetry(engine, source);
|
||||
//BrowserUITelemetry.countSearchEvent(source, null, selection);
|
||||
//this.recordSearchInTelemetry(engine, source);
|
||||
|
||||
let reporter = AppConstants.MOZ_SERVICES_HEALTHREPORT
|
||||
? Cc["@mozilla.org/datareporting/service;1"]
|
||||
|
||||
@@ -17,8 +17,15 @@ XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
|
||||
"resource:///modules/DownloadsCommon.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch",
|
||||
"resource://gre/modules/TelemetryStopwatch.jsm");
|
||||
//XPCOMUtils.defineLazyModuleGetter(this, "//TelemetryStopwatch",
|
||||
// "resource://gre/modules///TelemetryStopwatch.jsm");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "serviceWorkerManager",
|
||||
"@mozilla.org/serviceworkers/manager;1",
|
||||
"nsIServiceWorkerManager");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "quotaManagerService",
|
||||
"@mozilla.org/dom/quota-manager-service;1",
|
||||
"nsIQuotaManagerService");
|
||||
|
||||
|
||||
function Sanitizer() {}
|
||||
Sanitizer.prototype = {
|
||||
@@ -128,7 +135,7 @@ Sanitizer.prototype = {
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
TelemetryStopwatch.start("FX_SANITIZE_TOTAL");
|
||||
//TelemetryStopwatch.start("FX_SANITIZE_TOTAL");
|
||||
|
||||
// Cache the range of times to clear
|
||||
if (this.ignoreTimespan)
|
||||
@@ -139,7 +146,7 @@ Sanitizer.prototype = {
|
||||
let itemCount = Object.keys(itemsToClear).length;
|
||||
let onItemComplete = function() {
|
||||
if (!--itemCount) {
|
||||
TelemetryStopwatch.finish("FX_SANITIZE_TOTAL");
|
||||
//TelemetryStopwatch.finish("FX_SANITIZE_TOTAL");
|
||||
seenError ? deferred.reject() : deferred.resolve();
|
||||
}
|
||||
};
|
||||
@@ -185,7 +192,7 @@ Sanitizer.prototype = {
|
||||
cache: {
|
||||
clear: function ()
|
||||
{
|
||||
TelemetryStopwatch.start("FX_SANITIZE_CACHE");
|
||||
//TelemetryStopwatch.start("FX_SANITIZE_CACHE");
|
||||
|
||||
var cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"].
|
||||
getService(Ci.nsICacheStorageService);
|
||||
@@ -201,7 +208,7 @@ Sanitizer.prototype = {
|
||||
imageCache.clearCache(false); // true=chrome, false=content
|
||||
} catch(er) {}
|
||||
|
||||
TelemetryStopwatch.finish("FX_SANITIZE_CACHE");
|
||||
//TelemetryStopwatch.finish("FX_SANITIZE_CACHE");
|
||||
},
|
||||
|
||||
get canClear()
|
||||
@@ -213,8 +220,8 @@ Sanitizer.prototype = {
|
||||
cookies: {
|
||||
clear: function (aCallback)
|
||||
{
|
||||
TelemetryStopwatch.start("FX_SANITIZE_COOKIES");
|
||||
TelemetryStopwatch.start("FX_SANITIZE_COOKIES_2");
|
||||
//TelemetryStopwatch.start("FX_SANITIZE_COOKIES");
|
||||
//TelemetryStopwatch.start("FX_SANITIZE_COOKIES_2");
|
||||
|
||||
var cookieMgr = Components.classes["@mozilla.org/cookiemanager;1"]
|
||||
.getService(Ci.nsICookieManager);
|
||||
@@ -234,7 +241,7 @@ Sanitizer.prototype = {
|
||||
cookieMgr.removeAll();
|
||||
}
|
||||
|
||||
TelemetryStopwatch.finish("FX_SANITIZE_COOKIES_2");
|
||||
//TelemetryStopwatch.finish("FX_SANITIZE_COOKIES_2");
|
||||
|
||||
// Clear deviceIds. Done asynchronously (returns before complete).
|
||||
let mediaMgr = Components.classes["@mozilla.org/mediaManagerService;1"]
|
||||
@@ -242,11 +249,11 @@ Sanitizer.prototype = {
|
||||
mediaMgr.sanitizeDeviceIds(this.range && this.range[0]);
|
||||
|
||||
// Clear plugin data.
|
||||
TelemetryStopwatch.start("FX_SANITIZE_PLUGINS");
|
||||
//TelemetryStopwatch.start("FX_SANITIZE_PLUGINS");
|
||||
this.clearPluginCookies().then(
|
||||
function() {
|
||||
TelemetryStopwatch.finish("FX_SANITIZE_PLUGINS");
|
||||
TelemetryStopwatch.finish("FX_SANITIZE_COOKIES");
|
||||
//TelemetryStopwatch.finish("FX_SANITIZE_PLUGINS");
|
||||
//TelemetryStopwatch.finish("FX_SANITIZE_COOKIES");
|
||||
aCallback();
|
||||
});
|
||||
return true;
|
||||
@@ -301,10 +308,30 @@ Sanitizer.prototype = {
|
||||
offlineApps: {
|
||||
clear: function ()
|
||||
{
|
||||
TelemetryStopwatch.start("FX_SANITIZE_OFFLINEAPPS");
|
||||
// AppCache
|
||||
//TelemetryStopwatch.start("FX_SANITIZE_OFFLINEAPPS");
|
||||
Components.utils.import("resource:///modules/offlineAppCache.jsm");
|
||||
OfflineAppCacheHelper.clear();
|
||||
TelemetryStopwatch.finish("FX_SANITIZE_OFFLINEAPPS");
|
||||
//TelemetryStopwatch.finish("FX_SANITIZE_OFFLINEAPPS");
|
||||
|
||||
// LocalStorage
|
||||
Services.obs.notifyObservers(null, "extension:purge-localStorage", null);
|
||||
|
||||
// ServiceWorkers
|
||||
// NYI because service workers are disabled
|
||||
// See bug 1047098
|
||||
/*
|
||||
let serviceWorkers = serviceWorkerManager.getAllRegistrations();
|
||||
for (let i = 0; i < serviceWorkers.length; i++) {
|
||||
let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo);
|
||||
let host = sw.principal.URI.host;
|
||||
serviceWorkerManager.removeAndPropagate(host);
|
||||
}
|
||||
*/
|
||||
|
||||
// QuotaManager
|
||||
// NYI due to missing getUsage() in quotaManagerService
|
||||
// See bug 1047098 and bug 1348660 (esp. part 5, but unsure if useable)
|
||||
},
|
||||
|
||||
get canClear()
|
||||
@@ -316,7 +343,7 @@ Sanitizer.prototype = {
|
||||
history: {
|
||||
clear: function ()
|
||||
{
|
||||
TelemetryStopwatch.start("FX_SANITIZE_HISTORY");
|
||||
//TelemetryStopwatch.start("FX_SANITIZE_HISTORY");
|
||||
|
||||
if (this.range)
|
||||
PlacesUtils.history.removeVisitsByTimeframe(this.range[0], this.range[1]);
|
||||
@@ -337,7 +364,7 @@ Sanitizer.prototype = {
|
||||
predictor.reset();
|
||||
} catch (e) { }
|
||||
|
||||
TelemetryStopwatch.finish("FX_SANITIZE_HISTORY");
|
||||
//TelemetryStopwatch.finish("FX_SANITIZE_HISTORY");
|
||||
},
|
||||
|
||||
get canClear()
|
||||
@@ -351,7 +378,7 @@ Sanitizer.prototype = {
|
||||
formdata: {
|
||||
clear: function ()
|
||||
{
|
||||
TelemetryStopwatch.start("FX_SANITIZE_FORMDATA");
|
||||
//TelemetryStopwatch.start("FX_SANITIZE_FORMDATA");
|
||||
|
||||
// Clear undo history of all searchBars
|
||||
var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1']
|
||||
@@ -378,7 +405,7 @@ Sanitizer.prototype = {
|
||||
}
|
||||
FormHistory.update(change);
|
||||
|
||||
TelemetryStopwatch.finish("FX_SANITIZE_FORMDATA");
|
||||
//TelemetryStopwatch.finish("FX_SANITIZE_FORMDATA");
|
||||
},
|
||||
|
||||
canClear : function(aCallback, aArg)
|
||||
@@ -425,7 +452,7 @@ Sanitizer.prototype = {
|
||||
downloads: {
|
||||
clear: function ()
|
||||
{
|
||||
TelemetryStopwatch.start("FX_SANITIZE_DOWNLOADS");
|
||||
//TelemetryStopwatch.start("FX_SANITIZE_DOWNLOADS");
|
||||
Task.spawn(function*() {
|
||||
let filterByTime = null;
|
||||
if (this.range) {
|
||||
@@ -439,9 +466,9 @@ Sanitizer.prototype = {
|
||||
// Clear all completed/cancelled downloads
|
||||
let list = yield Downloads.getList(Downloads.ALL);
|
||||
list.removeFinished(filterByTime);
|
||||
TelemetryStopwatch.finish("FX_SANITIZE_DOWNLOADS");
|
||||
//TelemetryStopwatch.finish("FX_SANITIZE_DOWNLOADS");
|
||||
}.bind(this)).then(null, error => {
|
||||
TelemetryStopwatch.finish("FX_SANITIZE_DOWNLOADS");
|
||||
//TelemetryStopwatch.finish("FX_SANITIZE_DOWNLOADS");
|
||||
Components.utils.reportError(error);
|
||||
});
|
||||
},
|
||||
@@ -456,7 +483,7 @@ Sanitizer.prototype = {
|
||||
sessions: {
|
||||
clear: function ()
|
||||
{
|
||||
TelemetryStopwatch.start("FX_SANITIZE_SESSIONS");
|
||||
//TelemetryStopwatch.start("FX_SANITIZE_SESSIONS");
|
||||
|
||||
// clear all auth tokens
|
||||
var sdr = Components.classes["@mozilla.org/security/sdr;1"]
|
||||
@@ -468,7 +495,7 @@ Sanitizer.prototype = {
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
os.notifyObservers(null, "net:clear-active-logins", null);
|
||||
|
||||
TelemetryStopwatch.finish("FX_SANITIZE_SESSIONS");
|
||||
//TelemetryStopwatch.finish("FX_SANITIZE_SESSIONS");
|
||||
},
|
||||
|
||||
get canClear()
|
||||
@@ -480,7 +507,7 @@ Sanitizer.prototype = {
|
||||
siteSettings: {
|
||||
clear: function ()
|
||||
{
|
||||
TelemetryStopwatch.start("FX_SANITIZE_SITESETTINGS");
|
||||
//TelemetryStopwatch.start("FX_SANITIZE_SITESETTINGS");
|
||||
|
||||
// Clear site-specific permissions like "Allow this site to open popups"
|
||||
// we ignore the "end" range and hope it is now() - none of the
|
||||
@@ -530,7 +557,7 @@ Sanitizer.prototype = {
|
||||
dump("Web Push may not be available.\n");
|
||||
}
|
||||
|
||||
TelemetryStopwatch.finish("FX_SANITIZE_SITESETTINGS");
|
||||
//TelemetryStopwatch.finish("FX_SANITIZE_SITESETTINGS");
|
||||
},
|
||||
|
||||
get canClear()
|
||||
@@ -592,7 +619,7 @@ Sanitizer.prototype = {
|
||||
|
||||
// If/once we get here, we should actually be able to close all windows.
|
||||
|
||||
TelemetryStopwatch.start("FX_SANITIZE_OPENWINDOWS");
|
||||
//TelemetryStopwatch.start("FX_SANITIZE_OPENWINDOWS");
|
||||
|
||||
// First create a new window. We do this first so that on non-mac, we don't
|
||||
// accidentally close the app by closing all the windows.
|
||||
@@ -617,7 +644,7 @@ Sanitizer.prototype = {
|
||||
newWindowOpened = true;
|
||||
// If we're the last thing to happen, invoke callback.
|
||||
if (numWindowsClosing == 0) {
|
||||
TelemetryStopwatch.finish("FX_SANITIZE_OPENWINDOWS");
|
||||
//TelemetryStopwatch.finish("FX_SANITIZE_OPENWINDOWS");
|
||||
aCallback();
|
||||
}
|
||||
}
|
||||
@@ -629,7 +656,7 @@ Sanitizer.prototype = {
|
||||
Services.obs.removeObserver(onWindowClosed, "xul-window-destroyed");
|
||||
// If we're the last thing to happen, invoke callback.
|
||||
if (newWindowOpened) {
|
||||
TelemetryStopwatch.finish("FX_SANITIZE_OPENWINDOWS");
|
||||
//TelemetryStopwatch.finish("FX_SANITIZE_OPENWINDOWS");
|
||||
aCallback();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/ExtensionContent.jsm");
|
||||
|
||||
const g104FxForcePref = "tenfourfox.reader.force-enable"; // TenFourFox issue 583
|
||||
Cu.import("resource://gre/modules/Preferences.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "E10SUtils",
|
||||
"resource:///modules/E10SUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils",
|
||||
@@ -21,6 +24,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "AboutReader",
|
||||
"resource://gre/modules/AboutReader.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode",
|
||||
"resource://gre/modules/ReaderMode.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Readerable",
|
||||
"resource://gre/modules/Readerable.jsm");
|
||||
XPCOMUtils.defineLazyGetter(this, "SimpleServiceDiscovery", function() {
|
||||
let ssdp = Cu.import("resource://gre/modules/SimpleServiceDiscovery.jsm", {}).SimpleServiceDiscovery;
|
||||
// Register targets
|
||||
@@ -254,6 +259,7 @@ AboutPrivateBrowsingListener.init(this);
|
||||
var AboutReaderListener = {
|
||||
|
||||
_articlePromise: null,
|
||||
_alwaysAllowReaderMode: true, // TenFourFox issue 583
|
||||
|
||||
init: function() {
|
||||
addEventListener("AboutReaderContentLoaded", this, false, true);
|
||||
@@ -262,6 +268,17 @@ var AboutReaderListener = {
|
||||
addEventListener("pagehide", this, false);
|
||||
addMessageListener("Reader:ParseDocument", this);
|
||||
addMessageListener("Reader:PushState", this);
|
||||
Services.prefs.addObserver(g104FxForcePref, this, false);
|
||||
},
|
||||
|
||||
// TenFourFox issue 583
|
||||
uninit: function() {
|
||||
Services.prefs.removeObserver(g104FxForcePref, this, false);
|
||||
},
|
||||
observe: function(subject, topic, data) { // jshint ignore:line
|
||||
if (topic === "nsPref:changed") {
|
||||
this._alwaysAllowReaderMode = Preferences.get(g104FxForcePref, true);
|
||||
}
|
||||
},
|
||||
|
||||
receiveMessage: function(message) {
|
||||
@@ -329,7 +346,7 @@ var AboutReaderListener = {
|
||||
* painted is not going to work.
|
||||
*/
|
||||
updateReaderButton: function(forceNonArticle) {
|
||||
if (!ReaderMode.isEnabledForParseOnLoad || this.isAboutReader ||
|
||||
if (!Readerable.isEnabledForParseOnLoad || this.isAboutReader ||
|
||||
!(content.document instanceof content.HTMLDocument) ||
|
||||
content.document.mozSyntheticDocument) {
|
||||
return;
|
||||
@@ -357,9 +374,28 @@ var AboutReaderListener = {
|
||||
|
||||
onPaintWhenWaitedFor: function(forceNonArticle) {
|
||||
this.cancelPotentialPendingReadabilityCheck();
|
||||
|
||||
let doc = content.document;
|
||||
if (!doc) return;
|
||||
|
||||
// TenFourFox issue 583
|
||||
// If we are always allowing reader mode, don't bother spending any time
|
||||
// processing the page. But don't let just everything through.
|
||||
if (!this.isAboutReader && this._alwaysAllowReaderMode) {
|
||||
// This borrows a bit from isProbablyReaderable()
|
||||
if (!doc.mozSyntheticDocument &&
|
||||
doc instanceof doc.defaultView.HTMLDocument) {
|
||||
let uri = Services.io.newURI(doc.location.href, null, null);
|
||||
if (uri && Readerable.shouldCheckUri(uri)) {
|
||||
sendAsyncMessage("Reader:UpdateReaderButton", { isArticle: true });
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only send updates when there are articles; there's no point updating with
|
||||
// |false| all the time.
|
||||
if (ReaderMode.isProbablyReaderable(content.document)) {
|
||||
if (Readerable.isProbablyReaderable(content.document)) {
|
||||
sendAsyncMessage("Reader:UpdateReaderButton", { isArticle: true });
|
||||
} else if (forceNonArticle) {
|
||||
sendAsyncMessage("Reader:UpdateReaderButton", { isArticle: false });
|
||||
|
||||
Vendored
+2
-1
@@ -64,7 +64,8 @@ StreamControl::CloseAllReadStreams()
|
||||
{
|
||||
AssertOwningThread();
|
||||
|
||||
ReadStreamList::ForwardIterator iter(mReadStreamList);
|
||||
auto readStreamList = mReadStreamList;
|
||||
ReadStreamList::ForwardIterator iter(readStreamList);
|
||||
while (iter.HasMore()) {
|
||||
iter.GetNext()->CloseStream();
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ interface nsIDOMCSSGroupingRule : nsIDOMCSSRule
|
||||
readonly attribute nsIDOMCSSRuleList cssRules;
|
||||
|
||||
unsigned long insertRule(in DOMString rule,
|
||||
in unsigned long index)
|
||||
[optional] in unsigned long index)
|
||||
raises(DOMException);
|
||||
void deleteRule(in unsigned long index)
|
||||
raises(DOMException);
|
||||
|
||||
@@ -20,7 +20,7 @@ interface nsIDOMCSSStyleSheet : nsIDOMStyleSheet
|
||||
readonly attribute nsIDOMCSSRuleList cssRules;
|
||||
|
||||
unsigned long insertRule(in DOMString rule,
|
||||
in unsigned long index)
|
||||
[optional] in unsigned long index)
|
||||
raises(DOMException);
|
||||
void deleteRule(in unsigned long index)
|
||||
raises(DOMException);
|
||||
|
||||
@@ -490,7 +490,8 @@ nsresult
|
||||
DOMStorageManager::Observe(const char* aTopic, const nsACString& aScopePrefix)
|
||||
{
|
||||
// Clear everything, caches + database
|
||||
if (!strcmp(aTopic, "cookie-cleared")) {
|
||||
if (!strcmp(aTopic, "cookie-cleared") ||
|
||||
!strcmp(aTopic, "extension:purge-localStorage-caches")) {
|
||||
ClearCaches(DOMStorageCache::kUnloadComplete, EmptyCString());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ DOMStorageObserver::Init()
|
||||
obs->AddObserver(sSelf, "browser:purge-domain-data", true);
|
||||
obs->AddObserver(sSelf, "last-pb-context-exited", true);
|
||||
obs->AddObserver(sSelf, "webapps-clear-data", true);
|
||||
obs->AddObserver(sSelf, "extension:purge-localStorage", true);
|
||||
|
||||
// Shutdown
|
||||
obs->AddObserver(sSelf, "profile-after-change", true);
|
||||
@@ -223,6 +224,17 @@ DOMStorageObserver::Observe(nsISupports* aSubject,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, "extension:purge-localStorage")) {
|
||||
DOMStorageDBBridge* db = DOMStorageCache::StartDatabase();
|
||||
NS_ENSURE_TRUE(db, NS_ERROR_FAILURE);
|
||||
|
||||
db->AsyncClearAll();
|
||||
|
||||
Notify("extension:purge-localStorage-caches");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Clear everything (including so and pb data) from caches and database
|
||||
// for the gived domain and subdomains.
|
||||
if (!strcmp(aTopic, "browser:purge-domain-data")) {
|
||||
|
||||
@@ -15,7 +15,7 @@ interface CSSStyleSheet : StyleSheet {
|
||||
[Throws]
|
||||
readonly attribute CSSRuleList cssRules;
|
||||
[Throws]
|
||||
unsigned long insertRule(DOMString rule, unsigned long index);
|
||||
unsigned long insertRule(DOMString rule, optional unsigned long index = 0);
|
||||
[Throws]
|
||||
void deleteRule(unsigned long index);
|
||||
};
|
||||
|
||||
@@ -634,14 +634,44 @@ ServiceWorkerRegistrar::ProfileStopped()
|
||||
}
|
||||
}
|
||||
|
||||
PBackgroundChild* child = BackgroundChild::GetForCurrentThread();
|
||||
if (!child) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We must set the pointer before potentially entering the fast-path shutdown
|
||||
// below.
|
||||
bool completed = false;
|
||||
mShutdownCompleteFlag = &completed;
|
||||
|
||||
PBackgroundChild* child = BackgroundChild::GetForCurrentThread();
|
||||
if (!child) {
|
||||
// Mutations to the ServiceWorkerRegistrar happen on the PBackground thread,
|
||||
// issued by the ServiceWorkerManagerService, so the appropriate place to
|
||||
// trigger shutdown is on that thread.
|
||||
//
|
||||
// However, it's quite possible that the PBackground thread was not brought
|
||||
// into existence for xpcshell tests. We don't cause it to be created
|
||||
// ourselves for any reason, for example.
|
||||
//
|
||||
// In this scenario, we know that:
|
||||
// - We will receive exactly one call to ourself from BlockShutdown() and
|
||||
// BlockShutdown() will be called (at most) once.
|
||||
// - The only way our Shutdown() method gets called is via
|
||||
// BackgroundParentImpl::RecvShutdownServiceWorkerRegistrar() being
|
||||
// invoked, which only happens if we get to that send below here that we
|
||||
// can't get to.
|
||||
// - All Shutdown() does is set mShuttingDown=true (essential for
|
||||
// invariants) and invoke MaybeScheduleShutdownCompleted().
|
||||
// - Since there is no PBackground thread, mRunnableCounter must be 0
|
||||
// because only ScheduleSaveData() increments it and it only runs on the
|
||||
// background thread, so it cannot have run. And so we would expect
|
||||
// MaybeScheduleShutdownCompleted() to schedule an invocation of
|
||||
// ShutdownCompleted on the main thread.
|
||||
//
|
||||
// So it's appropriate for us to set mShuttingDown=true (as Shutdown would
|
||||
// do) and directly invoke ShutdownCompleted() (as Shutdown would indirectly
|
||||
// do via MaybeScheduleShutdownCompleted).
|
||||
mShuttingDown = true;
|
||||
ShutdownCompleted();
|
||||
return;
|
||||
}
|
||||
|
||||
child->SendShutdownServiceWorkerRegistrar();
|
||||
|
||||
nsCOMPtr<nsIThread> thread(do_GetCurrentThread());
|
||||
@@ -682,6 +712,12 @@ ServiceWorkerRegistrar::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, "profile-before-change")) {
|
||||
// Hygiene; gServiceWorkerRegistrar should still be keeping a reference
|
||||
// alive well past this phase of shutdown, but it's bad form to drop your
|
||||
// last potentially owning reference and then make a call that requires you
|
||||
// to still be alive, especially when you spin a nested event loop.
|
||||
RefPtr<ServiceWorkerRegistrar> kungFuDeathGrip(this);
|
||||
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
services::GetObserverService();
|
||||
observerService->RemoveObserver(this, "profile-before-change");
|
||||
|
||||
@@ -1049,9 +1049,6 @@ pref("dom.disable_window_open_feature.status", true);
|
||||
|
||||
pref("dom.allow_scripts_to_close_windows", false);
|
||||
|
||||
// TenFourFox issue 463
|
||||
pref("tenfourfox.dom.requestIdleCallback.enabled", false);
|
||||
|
||||
pref("dom.require_user_interaction_for_beforeunload", true);
|
||||
|
||||
pref("dom.disable_open_during_load", false);
|
||||
@@ -5167,5 +5164,11 @@ pref("toolkit.pageThumbs.minHeight", 0);
|
||||
// when the page is reloaded. To turn this feature off, just set the limit to 0.
|
||||
pref("prompts.authentication_dialog_abuse_limit", 3);
|
||||
|
||||
// TenFourFox issue 463
|
||||
pref("tenfourfox.dom.requestIdleCallback.enabled", false);
|
||||
|
||||
pref("tenfourfox.adblock.enabled", false);
|
||||
pref("tenfourfox.adblock.logging.enabled", false);
|
||||
|
||||
// TenFourFox issue 583
|
||||
pref("tenfourfox.reader.force-enable", true);
|
||||
|
||||
@@ -5886,14 +5886,9 @@ gov.rs
|
||||
in.rs
|
||||
org.rs
|
||||
|
||||
// ru : https://cctld.ru/en/domains/domens_ru/reserved/
|
||||
// ru : https://cctld.ru/files/pdf/docs/en/rules_ru-rf.pdf
|
||||
// Submitted by George Georgievsky <gug@cctld.ru>
|
||||
ru
|
||||
ac.ru
|
||||
edu.ru
|
||||
gov.ru
|
||||
int.ru
|
||||
mil.ru
|
||||
test.ru
|
||||
|
||||
// rw : https://www.ricta.org.rw/sites/default/files/resources/registry_registrar_contract_0.pdf
|
||||
rw
|
||||
@@ -6958,7 +6953,8 @@ yt
|
||||
ак.срб
|
||||
|
||||
// xn--p1ai ("rf", Russian-Cyrillic) : RU
|
||||
// http://www.cctld.ru/en/docs/rulesrf.php
|
||||
// https://cctld.ru/files/pdf/docs/en/rules_ru-rf.pdf
|
||||
// Submitted by George Georgievsky <gug@cctld.ru>
|
||||
рф
|
||||
|
||||
// xn--wgbl6a ("Qatar", Arabic) : QA
|
||||
@@ -7078,7 +7074,7 @@ org.zw
|
||||
|
||||
// newGTLDs
|
||||
|
||||
// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2019-11-15T17:07:54Z
|
||||
// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2019-12-11T17:19:54Z
|
||||
// This list is auto-generated, don't edit it manually.
|
||||
// aaa : 2015-02-26 American Automobile Association, Inc.
|
||||
aaa
|
||||
@@ -7299,7 +7295,7 @@ auto
|
||||
// autos : 2014-01-09 DERAutos, LLC
|
||||
autos
|
||||
|
||||
// avianca : 2015-01-08 Aerovias del Continente Americano S.A. Avianca
|
||||
// avianca : 2015-01-08 Avianca Holdings S.A.
|
||||
avianca
|
||||
|
||||
// aws : 2015-06-25 Amazon Registry Services, Inc.
|
||||
@@ -7668,9 +7664,6 @@ christmas
|
||||
// chrome : 2014-07-24 Charleston Road Registry Inc.
|
||||
chrome
|
||||
|
||||
// chrysler : 2015-07-30 FCA US LLC.
|
||||
chrysler
|
||||
|
||||
// church : 2014-02-06 Binky Moon, LLC
|
||||
church
|
||||
|
||||
@@ -7950,9 +7943,6 @@ docs
|
||||
// doctor : 2016-06-02 Binky Moon, LLC
|
||||
doctor
|
||||
|
||||
// dodge : 2015-07-30 FCA US LLC.
|
||||
dodge
|
||||
|
||||
// dog : 2014-12-04 Binky Moon, LLC
|
||||
dog
|
||||
|
||||
@@ -8742,9 +8732,6 @@ kyoto
|
||||
// lacaixa : 2014-01-09 Fundación Bancaria Caixa d’Estalvis i Pensions de Barcelona, “la Caixa”
|
||||
lacaixa
|
||||
|
||||
// ladbrokes : 2015-08-06 LADBROKES INTERNATIONAL PLC
|
||||
ladbrokes
|
||||
|
||||
// lamborghini : 2015-06-04 Automobili Lamborghini S.p.A.
|
||||
lamborghini
|
||||
|
||||
@@ -8757,9 +8744,6 @@ lancaster
|
||||
// lancia : 2015-07-31 Fiat Chrysler Automobiles N.V.
|
||||
lancia
|
||||
|
||||
// lancome : 2015-07-23 L'Oréal
|
||||
lancome
|
||||
|
||||
// land : 2013-09-10 Binky Moon, LLC
|
||||
land
|
||||
|
||||
@@ -9057,9 +9041,6 @@ money
|
||||
// monster : 2015-09-11 XYZ.COM LLC
|
||||
monster
|
||||
|
||||
// mopar : 2015-07-30 FCA US LLC.
|
||||
mopar
|
||||
|
||||
// mormon : 2013-12-05 IRI Domain Management, LLC ("Applicant")
|
||||
mormon
|
||||
|
||||
@@ -9852,9 +9833,6 @@ spreadbetting
|
||||
// srl : 2015-05-07 InterNetX, Corp
|
||||
srl
|
||||
|
||||
// srt : 2015-07-30 FCA US LLC.
|
||||
srt
|
||||
|
||||
// stada : 2014-11-13 STADA Arzneimittel AG
|
||||
stada
|
||||
|
||||
@@ -10116,9 +10094,6 @@ ubank
|
||||
// ubs : 2014-12-11 UBS AG
|
||||
ubs
|
||||
|
||||
// uconnect : 2015-07-30 FCA US LLC.
|
||||
uconnect
|
||||
|
||||
// unicom : 2015-10-15 China United Network Communications Corporation Limited
|
||||
unicom
|
||||
|
||||
@@ -10239,9 +10214,6 @@ wang
|
||||
// wanggou : 2014-12-18 Amazon Registry Services, Inc.
|
||||
wanggou
|
||||
|
||||
// warman : 2015-06-18 Weir Group IP Limited
|
||||
warman
|
||||
|
||||
// watch : 2013-11-14 Binky Moon, LLC
|
||||
watch
|
||||
|
||||
@@ -10635,7 +10607,7 @@ yahoo
|
||||
// yamaxun : 2014-12-18 Amazon Registry Services, Inc.
|
||||
yamaxun
|
||||
|
||||
// yandex : 2014-04-10 YANDEX, LLC
|
||||
// yandex : 2014-04-10 Yandex Europe B.V.
|
||||
yandex
|
||||
|
||||
// yodobashi : 2014-11-20 YODOBASHI CAMERA CO.,LTD.
|
||||
@@ -10685,6 +10657,12 @@ cc.ua
|
||||
inf.ua
|
||||
ltd.ua
|
||||
|
||||
// Adobe : https://www.adobe.com/
|
||||
// Submitted by Ian Boston <boston@adobe.com>
|
||||
adobeaemcloud.com
|
||||
adobeaemcloud.net
|
||||
*.dev.adobeaemcloud.com
|
||||
|
||||
// Agnat sp. z o.o. : https://domena.pl
|
||||
// Submitted by Przemyslaw Plewa <it-admin@domena.pl>
|
||||
beep.pl
|
||||
@@ -10802,6 +10780,10 @@ s3-website.eu-west-2.amazonaws.com
|
||||
s3-website.eu-west-3.amazonaws.com
|
||||
s3-website.us-east-2.amazonaws.com
|
||||
|
||||
// Amsterdam Wireless: https://www.amsterdamwireless.nl/
|
||||
// Submitted by Imre Jonk <hostmaster@amsterdamwireless.nl>
|
||||
amsw.nl
|
||||
|
||||
// Amune : https://amune.org/
|
||||
// Submitted by Team Amune <cert@amune.org>
|
||||
t3l3p0rt.net
|
||||
@@ -11070,6 +11052,15 @@ co.no
|
||||
webhosting.be
|
||||
hosting-cluster.nl
|
||||
|
||||
// Coordination Center for TLD RU and XN--P1AI : https://cctld.ru/en/domains/domens_ru/reserved/
|
||||
// Submitted by George Georgievsky <gug@cctld.ru>
|
||||
ac.ru
|
||||
edu.ru
|
||||
gov.ru
|
||||
int.ru
|
||||
mil.ru
|
||||
test.ru
|
||||
|
||||
// COSIMO GmbH : http://www.cosimo.de
|
||||
// Submitted by Rene Marticke <rmarticke@cosimo.de>
|
||||
dyn.cosidns.de
|
||||
@@ -11094,6 +11085,14 @@ realm.cz
|
||||
// Submitted by Jonathan Rudenberg <jonathan@cupcake.io>
|
||||
cupcake.is
|
||||
|
||||
// Customer OCI - Oracle Dyn https://cloud.oracle.com/home https://dyn.com/dns/
|
||||
// Submitted by Gregory Drake <support@dyn.com>
|
||||
// Note: This is intended to also include customer-oci.com due to wildcards implicitly including the current label
|
||||
*.customer-oci.com
|
||||
*.oci.customer-oci.com
|
||||
*.ocp.customer-oci.com
|
||||
*.ocs.customer-oci.com
|
||||
|
||||
// cyon GmbH : https://www.cyon.ch/
|
||||
// Submitted by Dominic Luechinger <dol@cyon.ch>
|
||||
cyon.link
|
||||
@@ -11126,6 +11125,14 @@ store.dk
|
||||
*.dapps.earth
|
||||
*.bzz.dapps.earth
|
||||
|
||||
// Dark, Inc. : https://darklang.com
|
||||
// Submitted by Paul Biggar <ops@darklang.com>
|
||||
builtwithdark.com
|
||||
|
||||
// Datawire, Inc : https://www.datawire.io
|
||||
// Submitted by Richard Li <secalert@datawire.io>
|
||||
edgestack.me
|
||||
|
||||
// Debian : https://www.debian.org/
|
||||
// Submitted by Peter Palfrader / Debian Sysadmin Team <dsa-publicsuffixlist@debian.org>
|
||||
debian.net
|
||||
@@ -11499,6 +11506,10 @@ dynv6.net
|
||||
// Submitted by Vladimir Dudr <info@e4you.cz>
|
||||
e4.cz
|
||||
|
||||
// En root‽ : https://en-root.org
|
||||
// Submitted by Emmanuel Raviart <emmanuel@raviart.com>
|
||||
en-root.fr
|
||||
|
||||
// Enalean SAS: https://www.enalean.com
|
||||
// Submitted by Thomas Cottier <thomas.cottier@enalean.com>
|
||||
mytuleap.com
|
||||
@@ -11728,6 +11739,10 @@ firebaseapp.com
|
||||
flynnhub.com
|
||||
flynnhosting.net
|
||||
|
||||
// Frederik Braun https://frederik-braun.com
|
||||
// Submitted by Frederik Braun <fb@frederik-braun.com>
|
||||
0e.vc
|
||||
|
||||
// Freebox : http://www.freebox.fr
|
||||
// Submitted by Romain Fliedel <rfliedel@freebox.fr>
|
||||
freebox-os.com
|
||||
@@ -11761,8 +11776,9 @@ service.gov.uk
|
||||
gehirn.ne.jp
|
||||
usercontent.jp
|
||||
|
||||
// Gentlent, Limited : https://www.gentlent.com
|
||||
// Submitted by Tom Klein <tklein@gentlent.com>
|
||||
// Gentlent, Inc. : https://www.gentlent.com
|
||||
// Submitted by Tom Klein <tom@gentlent.com>
|
||||
gentapps.com
|
||||
lab.ms
|
||||
|
||||
// GitHub, Inc.
|
||||
@@ -11807,6 +11823,7 @@ a.run.app
|
||||
web.app
|
||||
*.0emm.com
|
||||
appspot.com
|
||||
*.r.appspot.com
|
||||
blogspot.ae
|
||||
blogspot.al
|
||||
blogspot.am
|
||||
@@ -11891,6 +11908,10 @@ publishproxy.com
|
||||
withgoogle.com
|
||||
withyoutube.com
|
||||
|
||||
// Group 53, LLC : https://www.group53.com
|
||||
// Submitted by Tyler Todd <noc@nova53.net>
|
||||
awsmppl.com
|
||||
|
||||
// Hakaran group: http://hakaran.cz
|
||||
// Submited by Arseniy Sokolov <security@hakaran.cz>
|
||||
fin.ci
|
||||
@@ -11940,6 +11961,7 @@ col.ng
|
||||
firm.ng
|
||||
gen.ng
|
||||
ltd.ng
|
||||
ngo.ng
|
||||
ng.school
|
||||
sch.so
|
||||
|
||||
@@ -12060,6 +12082,10 @@ uni5.net
|
||||
// Submitted by Roy Keene <rkeene@knightpoint.com>
|
||||
knightpoint.systems
|
||||
|
||||
// KUROKU LTD : https://kuroku.ltd/
|
||||
// Submitted by DisposaBoy <security@oya.to>
|
||||
oya.to
|
||||
|
||||
// .KRD : http://nic.krd/data/krd/Registration%20Policy.pdf
|
||||
co.krd
|
||||
edu.krd
|
||||
@@ -12454,6 +12480,10 @@ nom.uy
|
||||
nom.vc
|
||||
nom.vg
|
||||
|
||||
// Observable, Inc. : https://observablehq.com
|
||||
// Submitted by Mike Bostock <dns@observablehq.com>
|
||||
static.observableusercontent.com
|
||||
|
||||
// Octopodal Solutions, LLC. : https://ulterius.io/
|
||||
// Submitted by Andrew Sampson <andrew@ulterius.io>
|
||||
cya.gg
|
||||
@@ -12474,6 +12504,10 @@ opencraft.hosting
|
||||
// Submitted by Yngve Pettersen <yngve@opera.com>
|
||||
operaunite.com
|
||||
|
||||
// Oursky Limited : https://skygear.io/
|
||||
// Submited by Skygear Developer <hello@skygear.io>
|
||||
skygearapp.com
|
||||
|
||||
// OutSystems
|
||||
// Submitted by Duarte Santos <domain-admin@outsystemscloud.com>
|
||||
outsystemscloud.com
|
||||
@@ -12516,6 +12550,10 @@ gotpantheon.com
|
||||
// Submitted by Steve Leung <steveleung@peplink.com>
|
||||
mypep.link
|
||||
|
||||
// Perspecta : https://perspecta.com/
|
||||
// Submitted by Kenneth Van Alstyne <kvanalstyne@perspecta.com>
|
||||
perspecta.cloud
|
||||
|
||||
// Planet-Work : https://www.planet-work.com/
|
||||
// Submitted by Frédéric VANNIÈRE <f.vanniere@planet-work.com>
|
||||
on-web.fr
|
||||
@@ -12578,6 +12616,11 @@ ras.ru
|
||||
// Submitted by Daniel Dent (https://www.danieldent.com/)
|
||||
qa2.com
|
||||
|
||||
// QCX
|
||||
// Submitted by Cassandra Beelen <cassandra@beelen.one>
|
||||
qcx.io
|
||||
*.sys.qcx.io
|
||||
|
||||
// QNAP System Inc : https://www.qnap.com
|
||||
// Submitted by Nick Chang <nickchang@qnap.com>
|
||||
dev-myqnapcloud.com
|
||||
@@ -12600,6 +12643,7 @@ rackmaze.net
|
||||
|
||||
// Rancher Labs, Inc : https://rancher.com
|
||||
// Submitted by Vincent Fiduccia <domains@rancher.com>
|
||||
*.on-k3s.io
|
||||
*.on-rancher.cloud
|
||||
*.on-rio.io
|
||||
|
||||
@@ -12918,6 +12962,10 @@ v-info.info
|
||||
// Submitted by Nathan van Bakel <info@voorloper.com>
|
||||
voorloper.cloud
|
||||
|
||||
// V.UA Domain Administrator : https://domain.v.ua/
|
||||
// Submitted by Serhii Rostilo <sergey@rostilo.kiev.ua>
|
||||
v.ua
|
||||
|
||||
// Waffle Computer Inc., Ltd. : https://docs.waffleinfo.com
|
||||
// Submitted by Masayuki Note <masa@blade.wafflecell.com>
|
||||
wafflecell.com
|
||||
|
||||
@@ -974,6 +974,7 @@ GatherBaselineRequirementsTelemetry(const ScopedCERTCertList& certList)
|
||||
// According to DNS.h, this includes space for the null-terminator
|
||||
char buf[net::kNetAddrMaxCStrBufSize] = { 0 };
|
||||
PRNetAddr addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
if (currentName->name.other.len == 4) {
|
||||
addr.inet.family = PR_AF_INET;
|
||||
memcpy(&addr.inet.ip, currentName->name.other.data,
|
||||
|
||||
@@ -1137,4 +1137,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
|
||||
|
||||
static const int32_t kUnknownId = -1;
|
||||
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1582550105358000);
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1585251655362000);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "PSMRunnable.h"
|
||||
#include "mozilla/net/DNS.h"
|
||||
|
||||
#include "secerr.h"
|
||||
|
||||
@@ -677,8 +678,10 @@ GetSubjectAltNames(CERTCertificate *nssCert,
|
||||
|
||||
case certIPAddress:
|
||||
{
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
// According to DNS.h, this includes space for the null-terminator
|
||||
char buf[net::kNetAddrMaxCStrBufSize] = {0};
|
||||
PRNetAddr addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
if (current->name.other.len == 4) {
|
||||
addr.inet.family = PR_AF_INET;
|
||||
memcpy(&addr.inet.ip, current->name.other.data, current->name.other.len);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "nsIDateTimeFormat.h"
|
||||
#include "nsDateTimeFormatCID.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "mozilla/net/DNS.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace mozilla;
|
||||
@@ -1033,8 +1034,9 @@ ProcessGeneralName(PLArenaPool *arena,
|
||||
break;
|
||||
case certIPAddress:
|
||||
{
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
PRStatus status = PR_FAILURE;
|
||||
// According to DNS.h, this includes space for the null-terminator
|
||||
char buf[net::kNetAddrMaxCStrBufSize] = {0};
|
||||
PRNetAddr addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
nssComponent->GetPIPNSSBundleString("CertDumpIPAddress", key);
|
||||
|
||||
+3639
-1590
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,4 @@
|
||||
/*
|
||||
* DO NOT MODIFY THIS FILE DIRECTLY!
|
||||
*
|
||||
* This is a shared library that is maintained in an external repo:
|
||||
* https://github.com/mozilla/readability
|
||||
*/
|
||||
|
||||
/*eslint-env es6:false*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
@@ -33,10 +27,6 @@
|
||||
*/
|
||||
(function (global) {
|
||||
|
||||
function error(m) {
|
||||
dump("JSDOMParser error: " + m + "\n");
|
||||
}
|
||||
|
||||
// XML only defines these and the numeric ones:
|
||||
|
||||
var entityTable = {
|
||||
@@ -463,16 +453,15 @@
|
||||
else
|
||||
this.children.push(newNode);
|
||||
}
|
||||
} else {
|
||||
} else if (oldNode.nodeType === Node.ELEMENT_NODE) {
|
||||
// new node is not an element node.
|
||||
// if the old one was, update its element siblings:
|
||||
if (oldNode.nodeType === Node.ELEMENT_NODE) {
|
||||
if (oldNode.previousElementSibling)
|
||||
oldNode.previousElementSibling.nextElementSibling = oldNode.nextElementSibling;
|
||||
if (oldNode.nextElementSibling)
|
||||
oldNode.nextElementSibling.previousElementSibling = oldNode.previousElementSibling;
|
||||
this.children.splice(this.children.indexOf(oldNode), 1);
|
||||
}
|
||||
if (oldNode.previousElementSibling)
|
||||
oldNode.previousElementSibling.nextElementSibling = oldNode.nextElementSibling;
|
||||
if (oldNode.nextElementSibling)
|
||||
oldNode.nextElementSibling.previousElementSibling = oldNode.previousElementSibling;
|
||||
this.children.splice(this.children.indexOf(oldNode), 1);
|
||||
|
||||
// If the old node wasn't an element, neither the new nor the old node was an element,
|
||||
// and the children array and its members shouldn't need any updating.
|
||||
}
|
||||
@@ -492,8 +481,8 @@
|
||||
__JSDOMParser__: true,
|
||||
};
|
||||
|
||||
for (var i in nodeTypes) {
|
||||
Node[i] = Node.prototype[i] = nodeTypes[i];
|
||||
for (var nodeType in nodeTypes) {
|
||||
Node[nodeType] = Node.prototype[nodeType] = nodeTypes[nodeType];
|
||||
}
|
||||
|
||||
var Attribute = function (name, value) {
|
||||
@@ -507,17 +496,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);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -562,9 +543,10 @@
|
||||
this._textContent = newText;
|
||||
delete this._innerHTML;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
var Document = function () {
|
||||
var Document = function (url) {
|
||||
this.documentURI = url;
|
||||
this.styleSheets = [];
|
||||
this.childNodes = [];
|
||||
this.children = [];
|
||||
@@ -604,9 +586,30 @@
|
||||
node.textContent = text;
|
||||
return node;
|
||||
},
|
||||
|
||||
get baseURI() {
|
||||
if (!this.hasOwnProperty("_baseURI")) {
|
||||
this._baseURI = this.documentURI;
|
||||
var baseElements = this.getElementsByTagName("base");
|
||||
var href = baseElements[0] && baseElements[0].getAttribute("href");
|
||||
if (href) {
|
||||
try {
|
||||
this._baseURI = (new URL(href, this._baseURI)).href;
|
||||
} catch (ex) {/* Just fall back to documentURI */}
|
||||
}
|
||||
}
|
||||
return this._baseURI;
|
||||
},
|
||||
};
|
||||
|
||||
var Element = function (tag) {
|
||||
// We use this to find the closing tag.
|
||||
this._matchingTag = tag;
|
||||
// We're explicitly a non-namespace aware parser, we just pretend it's all HTML.
|
||||
var lastColonIndex = tag.lastIndexOf(":");
|
||||
if (lastColonIndex != -1) {
|
||||
tag = tag.substring(lastColonIndex + 1);
|
||||
}
|
||||
this.attributes = [];
|
||||
this.childNodes = [];
|
||||
this.children = [];
|
||||
@@ -655,6 +658,14 @@
|
||||
this.setAttribute("src", str);
|
||||
},
|
||||
|
||||
get srcset() {
|
||||
return this.getAttribute("srcset") || "";
|
||||
},
|
||||
|
||||
set srcset(str) {
|
||||
this.setAttribute("srcset", str);
|
||||
},
|
||||
|
||||
get nodeName() {
|
||||
return this.tagName;
|
||||
},
|
||||
@@ -671,14 +682,14 @@
|
||||
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);
|
||||
arr.push(" " + attr.name + "=" + quote + val + quote);
|
||||
}
|
||||
|
||||
if (child.localName in voidElems) {
|
||||
if (child.localName in voidElems && !child.childNodes.length) {
|
||||
// if this is a self-closing element, end it here
|
||||
arr.push(">");
|
||||
arr.push("/>");
|
||||
} else {
|
||||
// otherwise, add its children
|
||||
arr.push(">");
|
||||
@@ -702,12 +713,13 @@
|
||||
set innerHTML(html) {
|
||||
var parser = new JSDOMParser();
|
||||
var node = parser.parse(html);
|
||||
for (var i = this.childNodes.length; --i >= 0;) {
|
||||
var i;
|
||||
for (i = this.childNodes.length; --i >= 0;) {
|
||||
this.childNodes[i].parentNode = null;
|
||||
}
|
||||
this.childNodes = node.childNodes;
|
||||
this.children = node.children;
|
||||
for (var i = this.childNodes.length; --i >= 0;) {
|
||||
for (i = this.childNodes.length; --i >= 0;) {
|
||||
this.childNodes[i].parentNode = this;
|
||||
}
|
||||
},
|
||||
@@ -748,8 +760,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;
|
||||
},
|
||||
@@ -758,11 +771,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) {
|
||||
@@ -773,7 +786,13 @@
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
hasAttribute: function (name) {
|
||||
return this.attributes.some(function (attr) {
|
||||
return attr.name == name;
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
var Style = function (node) {
|
||||
@@ -831,7 +850,7 @@
|
||||
Style.prototype.__defineSetter__(jsName, function (value) {
|
||||
this.setStyle(cssName, value);
|
||||
});
|
||||
}) (styleMap[jsName]);
|
||||
})(styleMap[jsName]);
|
||||
}
|
||||
|
||||
var JSDOMParser = function () {
|
||||
@@ -849,9 +868,16 @@
|
||||
// makeElementNode(), which saves us from having to allocate a new array
|
||||
// every time.
|
||||
this.retPair = [];
|
||||
|
||||
this.errorState = "";
|
||||
};
|
||||
|
||||
JSDOMParser.prototype = {
|
||||
error: function(m) {
|
||||
dump("JSDOMParser error: " + m + "\n");
|
||||
this.errorState += m + "\n";
|
||||
},
|
||||
|
||||
/**
|
||||
* Look at the next character without advancing the index.
|
||||
*/
|
||||
@@ -906,14 +932,14 @@
|
||||
// After a '=', we should see a '"' for the attribute value
|
||||
var c = this.nextChar();
|
||||
if (c !== '"' && c !== "'") {
|
||||
error("Error reading attribute " + name + ", expecting '\"'");
|
||||
this.error("Error reading attribute " + name + ", expecting '\"'");
|
||||
return;
|
||||
}
|
||||
|
||||
// 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;
|
||||
},
|
||||
@@ -938,7 +964,7 @@
|
||||
strBuf.push(c);
|
||||
c = this.nextChar();
|
||||
}
|
||||
var tag = strBuf.join('');
|
||||
var tag = strBuf.join("");
|
||||
|
||||
if (!tag)
|
||||
return false;
|
||||
@@ -949,7 +975,9 @@
|
||||
while (c !== "/" && c !== ">") {
|
||||
if (c === undefined)
|
||||
return false;
|
||||
while (whitespace.indexOf(this.html[this.currentChar++]) != -1);
|
||||
while (whitespace.indexOf(this.html[this.currentChar++]) != -1) {
|
||||
// Advance cursor to first non-whitespace char.
|
||||
}
|
||||
this.currentChar--;
|
||||
c = this.nextChar();
|
||||
if (c !== "/" && c !== ">") {
|
||||
@@ -959,19 +987,19 @@
|
||||
}
|
||||
|
||||
// If this is a self-closing tag, read '/>'
|
||||
var closed = tag in voidElems;
|
||||
var closed = false;
|
||||
if (c === "/") {
|
||||
closed = true;
|
||||
c = this.nextChar();
|
||||
if (c !== ">") {
|
||||
error("expected '>' to close " + tag);
|
||||
this.error("expected '>' to close " + tag);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
retPair[0] = node;
|
||||
retPair[1] = closed;
|
||||
return true
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -1013,46 +1041,6 @@
|
||||
}
|
||||
},
|
||||
|
||||
readScript: function (node) {
|
||||
while (this.currentChar < this.html.length) {
|
||||
var c = this.nextChar();
|
||||
var nextC = this.peekNext();
|
||||
if (c === "<") {
|
||||
if (nextC === "!" || nextC === "?") {
|
||||
// We're still before the ! or ? that is starting this comment:
|
||||
this.currentChar++;
|
||||
node.appendChild(this.discardNextComment());
|
||||
continue;
|
||||
}
|
||||
if (nextC === "/" && this.html.substr(this.currentChar, 8 /*"/script>".length */).toLowerCase() == "/script>") {
|
||||
// Go back before the '<' so we find the end tag.
|
||||
this.currentChar--;
|
||||
// Done with this script tag, the caller will close:
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Either c wasn't a '<' or it was but we couldn't find either a comment
|
||||
// or a closing script tag, so we should just parse as text until the next one
|
||||
// comes along:
|
||||
|
||||
var haveTextNode = node.lastChild && node.lastChild.nodeType === Node.TEXT_NODE;
|
||||
var textNode = haveTextNode ? node.lastChild : new Text();
|
||||
var n = this.html.indexOf("<", this.currentChar);
|
||||
// Decrement this to include the current character *afterwards* so we don't get stuck
|
||||
// looking for the same < all the time.
|
||||
this.currentChar--;
|
||||
if (n === -1) {
|
||||
textNode.innerHTML += this.html.substring(this.currentChar, this.html.length);
|
||||
this.currentChar = this.html.length;
|
||||
} else {
|
||||
textNode.innerHTML += this.html.substring(this.currentChar, n);
|
||||
this.currentChar = n;
|
||||
}
|
||||
if (!haveTextNode)
|
||||
node.appendChild(textNode);
|
||||
}
|
||||
},
|
||||
|
||||
discardNextComment: function() {
|
||||
if (this.match("--")) {
|
||||
this.discardTo("-->");
|
||||
@@ -1083,18 +1071,31 @@
|
||||
return null;
|
||||
|
||||
// Read any text as Text node
|
||||
var textNode;
|
||||
if (c !== "<") {
|
||||
--this.currentChar;
|
||||
var node = new Text();
|
||||
textNode = new Text();
|
||||
var n = this.html.indexOf("<", this.currentChar);
|
||||
if (n === -1) {
|
||||
node.innerHTML = this.html.substring(this.currentChar, this.html.length);
|
||||
textNode.innerHTML = this.html.substring(this.currentChar, this.html.length);
|
||||
this.currentChar = this.html.length;
|
||||
} else {
|
||||
node.innerHTML = this.html.substring(this.currentChar, n);
|
||||
textNode.innerHTML = this.html.substring(this.currentChar, n);
|
||||
this.currentChar = n;
|
||||
}
|
||||
return node;
|
||||
return textNode;
|
||||
}
|
||||
|
||||
if (this.match("![CDATA[")) {
|
||||
var endChar = this.html.indexOf("]]>", this.currentChar);
|
||||
if (endChar === -1) {
|
||||
this.error("unclosed CDATA section");
|
||||
return null;
|
||||
}
|
||||
textNode = new Text();
|
||||
textNode.textContent = this.html.substring(this.currentChar, endChar);
|
||||
this.currentChar = endChar + ("]]>").length;
|
||||
return textNode;
|
||||
}
|
||||
|
||||
c = this.peekNext();
|
||||
@@ -1127,14 +1128,10 @@
|
||||
|
||||
// If this isn't a void Element, read its child nodes
|
||||
if (!closed) {
|
||||
if (localName == "script") {
|
||||
this.readScript(node);
|
||||
} else {
|
||||
this.readChildren(node);
|
||||
}
|
||||
var closingTag = "</" + localName + ">";
|
||||
this.readChildren(node);
|
||||
var closingTag = "</" + node._matchingTag + ">";
|
||||
if (!this.match(closingTag)) {
|
||||
error("expected '" + closingTag + "'");
|
||||
this.error("expected '" + closingTag + "' and got " + this.html.substr(this.currentChar, closingTag.length));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1158,9 +1155,9 @@
|
||||
/**
|
||||
* Parses an HTML string and returns a JS implementation of the Document.
|
||||
*/
|
||||
parse: function (html) {
|
||||
parse: function (html, url) {
|
||||
this.html = html;
|
||||
var doc = this.doc = new Document();
|
||||
var doc = this.doc = new Document(url);
|
||||
this.readChildren(doc);
|
||||
|
||||
// If this is an HTML document, remove root-level children except for the
|
||||
@@ -1188,4 +1185,4 @@
|
||||
// Attach JSDOMParser to the global scope
|
||||
global.JSDOMParser = JSDOMParser;
|
||||
|
||||
}) (this);
|
||||
})(this);
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/* eslint-env es6:false */
|
||||
/* globals exports */
|
||||
/*
|
||||
* Copyright (c) 2010 Arc90 Inc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is heavily based on Arc90's readability.js (1.7.1) script
|
||||
* available at: http://code.google.com/p/arc90labs-readability
|
||||
*/
|
||||
|
||||
var REGEXPS = {
|
||||
// NOTE: These two regular expressions are duplicated in
|
||||
// Readability.js. Please keep both copies in sync.
|
||||
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")
|
||||
&& (!node.hasAttribute("aria-hidden") || node.getAttribute("aria-hidden") != "true");
|
||||
}
|
||||
|
||||
/**
|
||||
* Decides whether or not the document is reader-able without parsing the whole thing.
|
||||
*
|
||||
* @return boolean Whether or not we suspect Readability.parse() will suceeed at returning an article object.
|
||||
*/
|
||||
function isProbablyReaderable(doc, isVisible) {
|
||||
if (!isVisible) {
|
||||
isVisible = isNodeVisible;
|
||||
}
|
||||
|
||||
var nodes = doc.querySelectorAll("p, pre");
|
||||
|
||||
// Get <div> nodes which have <br> node(s) and append them into the `nodes` variable.
|
||||
// Some articles' DOM structures might look like
|
||||
// <div>
|
||||
// Sentences<br>
|
||||
// <br>
|
||||
// Sentences<br>
|
||||
// </div>
|
||||
var brNodes = doc.querySelectorAll("div > br");
|
||||
if (brNodes.length) {
|
||||
var set = new Set(nodes);
|
||||
[].forEach.call(brNodes, function(node) {
|
||||
set.add(node.parentNode);
|
||||
});
|
||||
nodes = Array.from(set);
|
||||
}
|
||||
|
||||
var score = 0;
|
||||
// This is a little cheeky, we use the accumulator 'score' to decide what to return from
|
||||
// this callback:
|
||||
return [].some.call(nodes, function(node) {
|
||||
if (!isVisible(node))
|
||||
return false;
|
||||
|
||||
var matchString = node.className + " " + node.id;
|
||||
if (REGEXPS.unlikelyCandidates.test(matchString) &&
|
||||
!REGEXPS.okMaybeItsACandidate.test(matchString)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (node.matches("li p")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var textContentLength = node.textContent.trim().length;
|
||||
if (textContentLength < 140) {
|
||||
return false;
|
||||
}
|
||||
|
||||
score += Math.sqrt(textContentLength - 140);
|
||||
|
||||
if (score > 20) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof exports === "object") {
|
||||
exports.isProbablyReaderable = isProbablyReaderable;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,14 +27,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils", "resource://services-comm
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ReaderWorker", "resource://gre/modules/reader/ReaderWorker.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch", "resource://gre/modules/TelemetryStopwatch.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "Readability", function() {
|
||||
let scope = {};
|
||||
scope.dump = this.dump;
|
||||
Services.scriptloader.loadSubScript("resource://gre/modules/reader/Readability.js", scope);
|
||||
return scope["Readability"];
|
||||
});
|
||||
//XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch", "resource://gre/modules/TelemetryStopwatch.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Readerable", "resource://gre/modules/Readerable.jsm");
|
||||
|
||||
this.ReaderMode = {
|
||||
// Version of the cache schema.
|
||||
@@ -42,50 +36,6 @@ this.ReaderMode = {
|
||||
|
||||
DEBUG: 0,
|
||||
|
||||
// Don't try to parse the page if it has too many elements (for memory and
|
||||
// performance reasons)
|
||||
get maxElemsToParse() {
|
||||
delete this.parseNodeLimit;
|
||||
|
||||
Services.prefs.addObserver("reader.parse-node-limit", this, false);
|
||||
return this.parseNodeLimit = Services.prefs.getIntPref("reader.parse-node-limit");
|
||||
},
|
||||
|
||||
get isEnabledForParseOnLoad() {
|
||||
delete this.isEnabledForParseOnLoad;
|
||||
|
||||
// Listen for future pref changes.
|
||||
Services.prefs.addObserver("reader.parse-on-load.", this, false);
|
||||
|
||||
return this.isEnabledForParseOnLoad = this._getStateForParseOnLoad();
|
||||
},
|
||||
|
||||
get isOnLowMemoryPlatform() {
|
||||
let memory = Cc["@mozilla.org/xpcom/memory-service;1"].getService(Ci.nsIMemory);
|
||||
delete this.isOnLowMemoryPlatform;
|
||||
return this.isOnLowMemoryPlatform = memory.isLowMemoryPlatform();
|
||||
},
|
||||
|
||||
_getStateForParseOnLoad: function () {
|
||||
let isEnabled = Services.prefs.getBoolPref("reader.parse-on-load.enabled");
|
||||
let isForceEnabled = Services.prefs.getBoolPref("reader.parse-on-load.force-enabled");
|
||||
// For low-memory devices, don't allow reader mode since it takes up a lot of memory.
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=792603 for details.
|
||||
return isForceEnabled || (isEnabled && !this.isOnLowMemoryPlatform);
|
||||
},
|
||||
|
||||
observe: function(aMessage, aTopic, aData) {
|
||||
switch(aTopic) {
|
||||
case "nsPref:changed":
|
||||
if (aData.startsWith("reader.parse-on-load.")) {
|
||||
this.isEnabledForParseOnLoad = this._getStateForParseOnLoad();
|
||||
} else if (aData === "reader.parse-node-limit") {
|
||||
this.parseNodeLimit = Services.prefs.getIntPref(aData);
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns original URL from an about:reader URL.
|
||||
*
|
||||
@@ -111,39 +61,6 @@ this.ReaderMode = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Decides whether or not a document is reader-able without parsing the whole thing.
|
||||
*
|
||||
* @param doc A document to parse.
|
||||
* @return boolean Whether or not we should show the reader mode button.
|
||||
*/
|
||||
isProbablyReaderable: function(doc) {
|
||||
// Only care about 'real' HTML documents:
|
||||
if (doc.mozSyntheticDocument || !(doc instanceof doc.defaultView.HTMLDocument)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let uri = Services.io.newURI(doc.location.href, null, null);
|
||||
if (!this._shouldCheckUri(uri)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let utils = this.getUtilsForWin(doc.defaultView);
|
||||
// We pass in a helper function to determine if a node is visible, because
|
||||
// it uses gecko APIs that the engine-agnostic readability code can't rely
|
||||
// upon.
|
||||
return new Readability(uri, doc).isProbablyReaderable(this.isNodeVisible.bind(this, utils));
|
||||
},
|
||||
|
||||
isNodeVisible: function(utils, node) {
|
||||
let bounds = utils.getBoundsWithoutFlushing(node);
|
||||
return bounds.height > 0 && bounds.width > 0;
|
||||
},
|
||||
|
||||
getUtilsForWin: function(win) {
|
||||
return win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets an article from a loaded browser's document. This method will not attempt
|
||||
* to parse certain URIs (e.g. about: URIs).
|
||||
@@ -154,7 +71,7 @@ this.ReaderMode = {
|
||||
*/
|
||||
parseDocument: Task.async(function* (doc) {
|
||||
let uri = Services.io.newURI(doc.documentURI, null, null);
|
||||
if (!this._shouldCheckUri(uri)) {
|
||||
if (!Readerable.shouldCheckUri(uri)) {
|
||||
this.log("Reader mode disabled for URI");
|
||||
return null;
|
||||
}
|
||||
@@ -171,12 +88,12 @@ this.ReaderMode = {
|
||||
*/
|
||||
downloadAndParseDocument: Task.async(function* (url) {
|
||||
let uri = Services.io.newURI(url, null, null);
|
||||
TelemetryStopwatch.start("READER_MODE_DOWNLOAD_MS");
|
||||
//TelemetryStopwatch.start("READER_MODE_DOWNLOAD_MS");
|
||||
let doc = yield this._downloadDocument(url).catch(e => {
|
||||
TelemetryStopwatch.finish("READER_MODE_DOWNLOAD_MS");
|
||||
//TelemetryStopwatch.finish("READER_MODE_DOWNLOAD_MS");
|
||||
throw e;
|
||||
});
|
||||
TelemetryStopwatch.finish("READER_MODE_DOWNLOAD_MS");
|
||||
//TelemetryStopwatch.finish("READER_MODE_DOWNLOAD_MS");
|
||||
return yield this._readerParse(uri, doc);
|
||||
}),
|
||||
|
||||
@@ -306,39 +223,6 @@ this.ReaderMode = {
|
||||
dump("Reader: " + msg);
|
||||
},
|
||||
|
||||
_blockedHosts: [
|
||||
"twitter.com",
|
||||
"mail.google.com",
|
||||
"github.com",
|
||||
"reddit.com",
|
||||
],
|
||||
|
||||
_shouldCheckUri: function (uri) {
|
||||
if (!(uri.schemeIs("http") || uri.schemeIs("https"))) {
|
||||
this.log("Not parsing URI scheme: " + uri.scheme);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
uri.QueryInterface(Ci.nsIURL);
|
||||
} catch (ex) {
|
||||
// If this doesn't work, presumably the URL is not well-formed or something
|
||||
return false;
|
||||
}
|
||||
// Sadly, some high-profile pages have false positives, so bail early for those:
|
||||
let asciiHost = uri.asciiHost;
|
||||
if (this._blockedHosts.some(blockedHost => asciiHost.endsWith(blockedHost))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!uri.filePath || uri.filePath == "/") {
|
||||
this.log("Not parsing home page: " + uri.spec);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Attempts to parse a document into an article. Heavy lifting happens
|
||||
* in readerWorker.js.
|
||||
@@ -349,16 +233,17 @@ this.ReaderMode = {
|
||||
* @resolves JS object representing the article, or null if no article is found.
|
||||
*/
|
||||
_readerParse: Task.async(function* (uri, doc) {
|
||||
let histogram = Services.telemetry.getHistogramById("READER_MODE_PARSE_RESULT");
|
||||
//let histogram = Services.telemetry.getHistogramById("READER_MODE_PARSE_RESULT");
|
||||
if (this.parseNodeLimit) {
|
||||
let numTags = doc.getElementsByTagName("*").length;
|
||||
if (numTags > this.parseNodeLimit) {
|
||||
this.log("Aborting parse for " + uri.spec + "; " + numTags + " elements found");
|
||||
histogram.add(PARSE_ERROR_TOO_MANY_ELEMENTS);
|
||||
//histogram.add(PARSE_ERROR_TOO_MANY_ELEMENTS);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
let { documentURI } = doc;
|
||||
let uriParam = {
|
||||
spec: uri.spec,
|
||||
host: uri.host,
|
||||
@@ -367,37 +252,39 @@ this.ReaderMode = {
|
||||
pathBase: Services.io.newURI(".", null, uri).spec
|
||||
};
|
||||
|
||||
TelemetryStopwatch.start("READER_MODE_SERIALIZE_DOM_MS");
|
||||
//TelemetryStopwatch.start("READER_MODE_SERIALIZE_DOM_MS");
|
||||
let serializer = Cc["@mozilla.org/xmlextras/xmlserializer;1"].
|
||||
createInstance(Ci.nsIDOMSerializer);
|
||||
let serializedDoc = serializer.serializeToString(doc);
|
||||
TelemetryStopwatch.finish("READER_MODE_SERIALIZE_DOM_MS");
|
||||
//TelemetryStopwatch.finish("READER_MODE_SERIALIZE_DOM_MS");
|
||||
|
||||
TelemetryStopwatch.start("READER_MODE_WORKER_PARSE_MS");
|
||||
//TelemetryStopwatch.start("READER_MODE_WORKER_PARSE_MS");
|
||||
let article = null;
|
||||
try {
|
||||
article = yield ReaderWorker.post("parseDocument", [uriParam, serializedDoc]);
|
||||
} catch (e) {
|
||||
Cu.reportError("Error in ReaderWorker: " + e);
|
||||
histogram.add(PARSE_ERROR_WORKER);
|
||||
//histogram.add(PARSE_ERROR_WORKER);
|
||||
}
|
||||
TelemetryStopwatch.finish("READER_MODE_WORKER_PARSE_MS");
|
||||
//TelemetryStopwatch.finish("READER_MODE_WORKER_PARSE_MS");
|
||||
|
||||
if (!article) {
|
||||
this.log("Worker did not return an article");
|
||||
histogram.add(PARSE_ERROR_NO_ARTICLE);
|
||||
//histogram.add(PARSE_ERROR_NO_ARTICLE);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Readability returns a URI object, but we only care about the URL.
|
||||
article.url = article.uri.spec;
|
||||
// Readability returns a URI object based on the baseURI, but we only care
|
||||
// about the original document's URL from now on. This also avoids spoofing
|
||||
// attempts where the baseURI doesn't match the domain of the documentURI
|
||||
article.url = documentURI;
|
||||
delete article.uri;
|
||||
|
||||
let flags = Ci.nsIDocumentEncoder.OutputSelectionOnly | Ci.nsIDocumentEncoder.OutputAbsoluteLinks;
|
||||
article.title = Cc["@mozilla.org/parserutils;1"].getService(Ci.nsIParserUtils)
|
||||
.convertToPlainText(article.title, flags, 0);
|
||||
|
||||
histogram.add(PARSE_SUCCESS);
|
||||
//histogram.add(PARSE_SUCCESS);
|
||||
return article;
|
||||
}),
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
// This file and Readability-readerable.js are merged together into
|
||||
// Readerable.jsm.
|
||||
|
||||
/* exported Readerable */
|
||||
/* import-globals-from Readability-readerable.js */
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
function isNodeVisible(node) {
|
||||
return node.clientHeight > 0 && node.clientWidth > 0;
|
||||
}
|
||||
|
||||
var Readerable = {
|
||||
isEnabled: true,
|
||||
isForceEnabled: false,
|
||||
|
||||
get isEnabledForParseOnLoad() {
|
||||
return this.isEnabled || this.isForceEnabled;
|
||||
},
|
||||
|
||||
/**
|
||||
* Decides whether or not a document is reader-able without parsing the whole thing.
|
||||
*
|
||||
* @param doc A document to parse.
|
||||
* @return boolean Whether or not we should show the reader mode button.
|
||||
*/
|
||||
isProbablyReaderable(doc) {
|
||||
// Only care about 'real' HTML documents:
|
||||
if (doc.mozSyntheticDocument || !(doc instanceof doc.defaultView.HTMLDocument)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let uri = Services.io.newURI(doc.location.href, null, null);
|
||||
if (!this.shouldCheckUri(uri)) {
|
||||
return false;
|
||||
}
|
||||
return isProbablyReaderable(doc, isNodeVisible);
|
||||
},
|
||||
|
||||
_blockedHosts: [
|
||||
"amazon.com",
|
||||
"github.com",
|
||||
"mail.google.com",
|
||||
"pinterest.com",
|
||||
"reddit.com",
|
||||
"twitter.com",
|
||||
"youtube.com",
|
||||
],
|
||||
|
||||
shouldCheckUri(uri, isBaseUri = false) {
|
||||
if (!(uri.schemeIs("http") || uri.schemeIs("https"))) {
|
||||
return false;
|
||||
}
|
||||
if (!isBaseUri) {
|
||||
// Sadly, some high-profile pages have false positives, so bail early for those:
|
||||
let asciiHost = uri.asciiHost;
|
||||
if (this._blockedHosts.some(blockedHost => asciiHost.endsWith(blockedHost))) {
|
||||
return false;
|
||||
}
|
||||
if (uri.filePath == "/") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
observe: function(aMessage, aTopic, aData) {
|
||||
switch(aTopic) {
|
||||
case "nsPref:changed":
|
||||
if (aData === "reader.parse-on-load.enabled") {
|
||||
this.isEnabled = Services.prefs.getBoolPref(aData);
|
||||
} else if (aData === "reader.parse-on-load.force-enabled") {
|
||||
this.isForceEnabled = Services.prefs.getBoolPref(aData);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
Services.prefs.addObserver("reader.parse-on-load.", Readerable, false);
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["Readerable"];
|
||||
|
||||
#include Readability-readerable.js
|
||||
#include Readerable.js
|
||||
|
||||
@@ -8,14 +8,18 @@ JAR_MANIFESTS += ['jar.mn']
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'AboutReader.jsm',
|
||||
'ReaderMode.jsm'
|
||||
'ReaderMode.jsm',
|
||||
]
|
||||
|
||||
EXTRA_PP_JS_MODULES += [
|
||||
'Readerable.jsm',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES.reader = [
|
||||
'JSDOMParser.js',
|
||||
'Readability.js',
|
||||
'ReaderWorker.js',
|
||||
'ReaderWorker.jsm'
|
||||
'ReaderWorker.jsm',
|
||||
]
|
||||
|
||||
with Files('**'):
|
||||
|
||||
Reference in New Issue
Block a user