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:
2019-12-24 15:08:05 +08:00
parent b4f606616b
commit 9b34b27e21
26 changed files with 5047 additions and 2707 deletions
+1
View File
@@ -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
-4
View File
@@ -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"
+16 -11
View File
@@ -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"]
+55 -28
View File
@@ -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();
}
}
+38 -2
View File
@@ -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 });
+2 -1
View File
@@ -64,7 +64,8 @@ StreamControl::CloseAllReadStreams()
{
AssertOwningThread();
ReadStreamList::ForwardIterator iter(mReadStreamList);
auto readStreamList = mReadStreamList;
ReadStreamList::ForwardIterator iter(readStreamList);
while (iter.HasMore()) {
iter.GetNext()->CloseStream();
}
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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);
+2 -1
View File
@@ -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;
}
+12
View File
@@ -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")) {
+1 -1
View File
@@ -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);
};
+41 -5
View File
@@ -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");
+6 -3
View File
@@ -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);
+85 -37
View File
@@ -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 dEstalvis 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,
+1 -1
View File
@@ -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);
+3 -1
View File
@@ -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);
File diff suppressed because it is too large Load Diff
+103 -106
View File
@@ -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
+20 -133
View File
@@ -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;
}),
+90
View File
@@ -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);
+11
View File
@@ -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
+6 -2
View File
@@ -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('**'):