Commit 3e9f2419 authored by Carsten Schoenert's avatar Carsten Schoenert
Browse files

Update upstream source from tag 'upstream/78.6.1'

Update to upstream version '78.6.1'
with Debian dir 4caed757e8e5a081e9163e0f7c65ff356baeaaf4
parents 5309e914 07b47332
......@@ -223,6 +223,11 @@ check_and_add_gcc_warning('-Wno-noexcept-type', cxx_compiler,
when=depends(build_project)
(lambda build_project: build_project == 'js'))
# Disable broken missing-braces warning on old clang versions
check_and_add_gcc_warning(
'-Wno-missing-braces',
when=depends(c_compiler)(lambda c: c.type == 'clang' and c.version < '6.0'))
# Please keep these last in this file
add_old_configure_assignment('_WARNINGS_CFLAGS', warnings_flags.cflags)
......
---
GECKO_BASE_REPOSITORY: https://hg.mozilla.org/mozilla-unified
GECKO_HEAD_REPOSITORY: https://hg.mozilla.org/releases/mozilla-esr78
GECKO_HEAD_REF: FIREFOX_78_6_0esr_BUILD1
GECKO_HEAD_REV: 8e6813a535daf9ef261c2bbb80cb10e9a832d68e
GECKO_HEAD_REF: FIREFOX_78_6_1esr_RELEASE
GECKO_HEAD_REV: df0581e37d875577ff1f2be1d5943e0d03c9e796
### For comm-central
# GECKO_BASE_REPOSITORY: https://hg.mozilla.org/mozilla-unified
......
......@@ -264,7 +264,9 @@ CalTimezoneService.prototype = {
if (!this.mDefaultTimezone) {
let prefTzid = Services.prefs.getStringPref("calendar.timezone.local", null);
let tzid = prefTzid;
if (!tzid) {
// If a user already has a profile created by an earlier version
// with floating timezone, set the correctly guessed timezone.
if (!tzid || tzid == "floating") {
try {
tzid = guessSystemTimezone();
} catch (e) {
......@@ -317,8 +319,9 @@ CalTimezoneService.prototype = {
*/
function guessSystemTimezone() {
// Probe JSDates for basic OS timezone offsets and names.
const dateJun = new Date(2005, 5, 20).toString();
const dateDec = new Date(2005, 11, 20).toString();
// Check timezone rules for current year
const dateJun = new Date(new Date().getFullYear(), 5, 20).toString();
const dateDec = new Date(new Date().getFullYear(), 11, 20).toString();
const tzNameRegex = /[^(]* ([^ ]*) \(([^)]+)\)/;
const nameDataJun = dateJun.match(tzNameRegex);
const nameDataDec = dateDec.match(tzNameRegex);
......@@ -563,7 +566,7 @@ function guessSystemTimezone() {
try {
let line = {},
hasMore = true,
MAXLINES = 10;
MAXLINES = 50;
for (let i = 0; hasMore && i < MAXLINES; i++) {
hasMore = fileInstream.readLine(line);
if (line.value && line.value.match(tzRegex)) {
......
......@@ -65,11 +65,13 @@ var ltnImipBar = {
// We need to extend the HideMessageHeaderPane function to also hide the
// message header pane. Otherwise, the imip bar will still be shown when
// changing folders.
ltnImipBar.tbHideMessageHeaderPane = HideMessageHeaderPane;
HideMessageHeaderPane = function(...args) {
ltnImipBar.resetBar();
ltnImipBar.tbHideMessageHeaderPane(...args);
};
if (!ltnImipBar.tbHideMessageHeaderPane) {
ltnImipBar.tbHideMessageHeaderPane = HideMessageHeaderPane;
HideMessageHeaderPane = function(...args) {
ltnImipBar.resetBar();
ltnImipBar.tbHideMessageHeaderPane(...args);
};
}
// Set up our observers
Services.obs.addObserver(ltnImipBar, "onItipItemCreation");
......
......@@ -253,7 +253,7 @@ class CalDavResponseBase {
});
this.completed = new Promise((resolve, reject) => {
this._oncompleted = resolve;
this._oncompleteerror = reject;
this._oncompletederror = reject;
});
}
......
......@@ -1769,7 +1769,7 @@ CalStorageCalendar.prototype = {
}
let rec = item.recurrenceInfo;
let exc = await this.getEventFromRow(row, false);
let exc = await this.getEventFromRow(row);
rec.modifyException(exc, true);
});
......@@ -1781,7 +1781,7 @@ CalStorageCalendar.prototype = {
}
let rec = item.recurrenceInfo;
let exc = await this.getTodoFromRow(row, false);
let exc = await this.getTodoFromRow(row);
rec.modifyException(exc, true);
});
......
/* 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/. */
/**
* Tests for the CalStorageCalendar.getItems method.
*/
do_get_profile();
/**
* The bug we are interested in testing requires the calendar to clear its
* caches in order to take effect. Since we can't directly access the internals
* of the calendar here, we instead provide a custom function that lets us
* create more than one calendar with the same id.
*/
function createStorageCalendar(id) {
let db = Services.dirsvc.get("TmpD", Ci.nsIFile);
db.append("test_storage.sqlite");
let uri = Services.io.newFileURI(db);
// Make sure timezone service is initialized
Cc["@mozilla.org/calendar/timezone-service;1"].getService(Ci.calIStartupService).startup(null);
let calendar = Cc["@mozilla.org/calendar/calendar;1?type=storage"].createInstance(
Ci.calISyncWriteCalendar
);
calendar.uri = uri;
calendar.id = id;
return cal.async.promisifyCalendar(calendar);
}
/**
* Tests that recurring event/todo exceptions have their properties properly
* loaded. See bug 1664731.
*
* @param {number} filterType - Number indicating the filter type.
* @param {calIITemBase} originalItem - The original item to add to the calendar.
* @param {object} originalProps - The initial properites of originalItem we
* change.
* @param {object} changedProps - The changed properties of originalItem..
*/
async function doPropertiesTest(filterType, originalItem, originalProps, changedProps) {
for (let [key, value] of Object.entries(originalProps)) {
if (key == "CATEGORIES") {
originalItem.setCategories(value);
} else {
originalItem.setProperty(key, value);
}
}
let calId = cal.getUUID();
let calendar = createStorageCalendar(calId);
await calendar.addItem(originalItem);
let filter =
filterType |
Ci.calICalendar.ITEM_FILTER_COMPLETED_ALL |
Ci.calICalendar.ITEM_FILTER_CLASS_OCCURRENCES;
let savedItems = await calendar.getItems(
filter,
0,
cal.createDateTime("20201201T000000Z"),
cal.createDateTime("20201231T000000Z")
);
Assert.equal(savedItems.length, 5, `saved ${savedItems.length} items successfully`);
// Ensure all occurrences have the correct properties initially.
for (let item of savedItems) {
for (let [key, value] of Object.entries(originalProps)) {
if (key == "CATEGORIES") {
Assert.equal(
item.getCategories().join(),
value.join(),
`item categories are set to ${value}`
);
} else {
Assert.equal(item.getProperty(key), value, `item property "${key}" is set to "${value}"`);
}
}
}
// Grab the occurrence whose properties we want to modify.
let targetOccurrence = savedItems[2];
let targetException = targetOccurrence.clone();
let targetDate =
filterType & Ci.calICalendar.ITEM_FILTER_TYPE_TODO
? targetOccurrence.entryDate
: targetOccurrence.startDate;
targetDate = targetDate.clone();
// Make the changes to the properties.
for (let [key, value] of Object.entries(changedProps)) {
if (key == "CATEGORIES") {
targetException.setCategories(value);
} else {
targetException.setProperty(key, value);
}
}
await calendar.modifyItem(
cal.itip.prepareSequence(targetException, targetOccurrence),
targetOccurrence
);
// Get a fresh copy of the items by using a new calendar with the same id.
let itemsAfterUpdate = await createStorageCalendar(calId).getItems(
filter,
0,
cal.createDateTime("20201201T000000Z"),
cal.createDateTime("20201231T000000Z")
);
Assert.equal(itemsAfterUpdate.length, 5, "expected occurrence count retrieved from query");
// Compare each property we changed to ensure the target occurrence has
// the properties we expect.
for (let item of itemsAfterUpdate) {
let isException = targetDate.compare(item.recurrenceId) == 0;
let label = isException ? "occurrence exception" : "unmodified occurrence";
let checkedProps = isException ? changedProps : originalProps;
for (let [key, value] of Object.entries(checkedProps)) {
if (key == "CATEGORIES") {
Assert.equal(
item.getCategories().join(),
value.join(),
`item categories are set to ${value}`
);
} else {
Assert.equal(
item.getProperty(key),
value,
`property "${key}" is set to "${value}" for ${label}`
);
}
}
}
}
/**
* Test event exceptions load their properties.
*/
add_task(async function testEventPropertiesForRecurringExceptionsLoad() {
let event = cal.createEvent(dedent`
BEGIN:VEVENT
CREATED:20201211T000000Z
LAST-MODIFIED:20201211T000000Z
DTSTAMP:20201210T080410Z
UID:c1a6cfe7-7fbb-4bfb-a00d-861e07c649a5
SUMMARY:Original Test Event
DTSTART:20201211T000000Z
DTEND:20201211T110000Z
RRULE:FREQ=DAILY;UNTIL=20201215T140000Z
END:VEVENT
`);
let originalProps = {
DESCRIPTION: "This is a test event.",
CATEGORIES: ["Birthday"],
LOCATION: "Castara",
};
let changedProps = {
DESCRIPTION: "This is an edited occurrence.",
CATEGORIES: ["Holiday"],
LOCATION: "Georgetown",
};
return doPropertiesTest(
Ci.calICalendar.ITEM_FILTER_TYPE_EVENT,
event,
originalProps,
changedProps
);
});
/**
* Test todo exceptions load their properties.
*/
add_task(async function testTodoPropertiesForRecurringExceptionsLoad() {
let todo = cal.createTodo(dedent`
BEGIN:VTODO
CREATED:20201211T000000Z
LAST-MODIFIED:20201211T000000Z
DTSTAMP:20201210T080410Z
UID:c1a6cfe7-7fbb-4bfb-a00d-861e07c649a5
SUMMARY:Original Test Event
DTSTART:20201211T000000Z
DTEND:20201211T110000Z
RRULE:FREQ=DAILY;UNTIL=20201215T140000Z
END:VTODO
`);
let originalProps = {
DESCRIPTION: "This is a test todo.",
CATEGORIES: ["Birthday"],
LOCATION: "Castara",
STATUS: "NEEDS-ACTION",
};
let changedProps = {
DESCRIPTION: "This is an edited occurrence.",
CATEGORIES: ["Holiday"],
LOCATION: "Georgetown",
STATUS: "COMPLETE",
};
return doPropertiesTest(Ci.calICalendar.ITEM_FILTER_TYPE_TODO, todo, originalProps, changedProps);
});
......@@ -47,6 +47,7 @@
[test_search_service.js]
[test_startup_service.js]
[test_storage.js]
[test_storage_get_items.js]
[test_timezone.js]
[test_timezone_changes.js]
[test_timezone_definition.js]
......
......@@ -144,13 +144,17 @@ interface prplIAccount: nsISupports {
/* When a connection error occurred, this value indicates the type of error */
readonly attribute short connectionErrorReason;
/* When a certificate error occurs, the host/port that caused a
/**
* When a certificate error occurs, the host/port that caused a
* SSL/certificate error when connecting to it. This is only valid when
* connectionErrorReason is one of ERROR_CERT_*. */
* connectionErrorReason is one of ERROR_CERT_*
*/
readonly attribute AUTF8String connectionTarget;
/* When a certificate error occurs, the nsITransportSecurityInfo error of
* the socket. This should only be set when connectionTarget is set. */
readonly attribute nsITransportSecurityInfo secInfo;
/**
* When a certificate error occurs, the nsITransportSecurityInfo error of
* the socket. This should only be set when connectionTarget is set.
*/
readonly attribute nsITransportSecurityInfo securityInfo;
/* Possible connection error reasons:
ERROR_NETWORK_ERROR and ERROR_ENCRYPTION_ERROR are not fatal and
......
......@@ -17,7 +17,6 @@ richlistitem[error="true"] .disconnected,
richlistitem[selected="true"]:not([state="disconnected"]) .connectButton,
richlistitem[selected="true"][state="disconnected"] .disconnectButton,
richlistitem[selected="true"][state="disconnecting"] .disconnectButton,
richlistitem[selected="true"]:not([certError="true"]) .addException,
richlistitem:not([selected="true"]) .addException,
richlistitem:not([selected="true"]) .autoSignOn,
richlistitem:not([reconnectPending="true"]) description[anonid="reconnect"]
......
......@@ -72,8 +72,6 @@
<label class="disconnected" crop="end" value="&account.disconnected;"></label>
<description class="error error-description"></description>
<description class="error error-reconnect"></description>
<label class="addException text-link" onclick="gAccountManager.addException()"
data-l10n-id="certmgr-add-exception"></label>
<spacer flex="1"></spacer>
</vbox>
<checkbox label="&account.autoSignOn.label;"
......
......@@ -89,41 +89,41 @@ var GenericAccountPrototype = {
return this._connectionErrorReason;
},
/*
/**
* Convert a socket's nsITransportSecurityInfo into a prplIAccount connection error. Store
* the nsITransportSecurityInfo and the connection location on the account so the
* certificate exception dialog can access the information.
*
* @param {Socket} aSocket - Socket where the connection error occurred.
* @returns {Number} The prplIAccount error constant describing the problem.
*/
handleBadCertificate(aSocket, aIsSslError) {
handleConnectionSecurityError(aSocket) {
// Stash away the connectionTarget and securityInfo.
this._connectionTarget = aSocket.host + ":" + aSocket.port;
let securityInfo = (this._securityInfo = aSocket.securityInfo);
if (aIsSslError) {
return Ci.prplIAccount.ERROR_ENCRYPTION_ERROR;
}
let secInfo = (this._secInfo = aSocket.secInfo);
if (!secInfo) {
if (!securityInfo) {
return Ci.prplIAccount.ERROR_CERT_NOT_PROVIDED;
}
if (secInfo.isUntrusted) {
if (secInfo.serverCert && secInfo.serverCert.isSelfSigned) {
if (securityInfo.isUntrusted) {
if (securityInfo.serverCert && securityInfo.serverCert.isSelfSigned) {
return Ci.prplIAccount.ERROR_CERT_SELF_SIGNED;
}
return Ci.prplIAccount.ERROR_CERT_UNTRUSTED;
}
if (secInfo.isNotValidAtThisTime) {
if (securityInfo.isNotValidAtThisTime) {
if (
secInfo.serverCert &&
secInfo.serverCert.validity.notBefore < Date.now() * 1000
securityInfo.serverCert &&
securityInfo.serverCert.validity.notBefore < Date.now() * 1000
) {
return Ci.prplIAccount.ERROR_CERT_NOT_ACTIVATED;
}
return Ci.prplIAccount.ERROR_CERT_EXPIRED;
}
if (secInfo.isDomainMismatch) {
if (securityInfo.isDomainMismatch) {
return Ci.prplIAccount.ERROR_CERT_HOSTNAME_MISMATCH;
}
......@@ -135,9 +135,9 @@ var GenericAccountPrototype = {
get connectionTarget() {
return this._connectionTarget;
},
_secInfo: null,
get secInfo() {
return this._secInfo;
_securityInfo: null,
get securityInfo() {
return this._securityInfo;
},
reportConnected() {
......@@ -146,7 +146,7 @@ var GenericAccountPrototype = {
reportConnecting(aConnectionStateMsg) {
// Delete any leftover errors from the previous connection.
delete this._connectionTarget;
delete this._secInfo;
delete this._securityInfo;
if (!this.connecting) {
this.imAccount.observe(this, "account-connecting", null);
......
......@@ -33,7 +33,7 @@
* connectTimeout (default is no timeout)
* readWriteTimeout (default is no timeout)
* disconnected
* secInfo
* securityInfo
*
* Users should "subclass" this object, i.e. set their .__proto__ to be it. And
* then implement:
......@@ -41,7 +41,7 @@
* onConnectionHeard()
* onConnectionTimedOut()
* onConnectionReset()
* onBadCertificate(boolean aIsSslError, AString aNSSErrorMessage)
* onConnectionSecurityError(unsigned long aTLSError, optional AString aNSSErrorMessage)
* onConnectionClosed()
* onDataReceived(String <data>)
* <length handled> = onBinaryDataReceived(ArrayBuffer <data>)
......@@ -116,6 +116,12 @@ var ScriptableUnicodeConverter = Components.Constructor(
"nsIScriptableUnicodeConverter"
);
/**
* @implements {nsIStreamListener}
* @implements {nsIRequestObserver}
* @implements {nsITransportEventSink}
* @implements {nsIProtocolProxyCallback}
*/
var Socket = {
// Use this to use binary mode for the
binaryMode: false,
......@@ -136,7 +142,7 @@ var Socket = {
readWriteTimeout: 0,
// A nsITransportSecurityInfo instance giving details about the certificate error.
secInfo: null,
securityInfo: null,
/*
*****************************************************************************
......@@ -156,7 +162,7 @@ var Socket = {
aPort = aOriginPort
) {
if (Services.io.offline) {
throw Components.Exception("", Cr.NS_ERROR_FAILURE);
throw Components.Exception("Offline, can't connect", Cr.NS_ERROR_FAILURE);
}
// This won't work for Linux due to bug 758848.
......@@ -519,31 +525,13 @@ var Socket = {
let nssErrorsService = Cc["@mozilla.org/nss_errors_service;1"].getService(
Ci.nsINSSErrorsService
);
if (
(aStatus <=
nssErrorsService.getXPCOMFromNSSError(
nssErrorsService.NSS_SEC_ERROR_BASE
) &&
aStatus >=
nssErrorsService.getXPCOMFromNSSError(
nssErrorsService.NSS_SEC_ERROR_LIMIT - 1
)) ||
(aStatus <=
nssErrorsService.getXPCOMFromNSSError(
nssErrorsService.NSS_SSL_ERROR_BASE
) &&
aStatus >=
nssErrorsService.getXPCOMFromNSSError(
nssErrorsService.NSS_SSL_ERROR_LIMIT - 1
))
) {
this.onBadCertificate(
nssErrorsService.getErrorClass(aStatus) ==
nssErrorsService.ERROR_CLASS_SSL_PROTOCOL,
nssErrorsService.getErrorMessage(aStatus)
);
return;
}
this.securityInfo = this.transport.securityInfo.QueryInterface(
Ci.nsITransportSecurityInfo
);
this.onConnectionSecurityError(
aStatus,
nssErrorsService.getErrorMessage(aStatus)
);
}
this.onConnectionClosed();
},
......@@ -701,7 +689,7 @@ var Socket = {
// Called when a socket request's network is reset.
onConnectionReset() {},
// Called when the certificate provided by the server didn't satisfy NSS.
onBadCertificate(aNSSErrorMessage) {},
onConnectionSecurityError(aTLSError, aNSSErrorMessage) {},
// Called when the other end has closed the connection.
onConnectionClosed() {},
......
......@@ -917,14 +917,14 @@ ircSocket.prototype = {
_("connection.error.timeOut")
);
},
onBadCertificate(aIsSslError, aNSSErrorMessage) {
onConnectionSecurityError(aTLSError, aNSSErrorMessage) {
this.WARN(
"Bad certificate or SSL connection for " +
this._account.name +
":\n" +
aNSSErrorMessage
);
let error = this._account.handleBadCertificate(this, aIsSslError);
let error = this._account.handleConnectionSecurityError(this);
this._account.gotDisconnected(error, aNSSErrorMessage);
},
......
......@@ -2680,7 +2680,7 @@ var XMPPAccountPrototype = {
conv.supportChatStateNotifications = !!state;
},
/* Called when there is an error in the xmpp session */
/** Called when there is an error in the XMPP session */
onError(aError, aException) {
if (aError === null || aError === undefined) {
aError = Ci.prplIAccount.ERROR_OTHER_ERROR;
......
......@@ -369,8 +369,8 @@ XMPPSession.prototype = {
onConnectionClosed() {
this._networkError(_("connection.error.serverClosedConnection"));
},
onBadCertificate(aIsSslError, aNSSErrorMessage) {
let error = this._account.handleBadCertificate(this, aIsSslError);
onConnectionSecurityError(aTLSError, aNSSErrorMessage) {
let error = this._account.handleConnectionSecurityError(this);
this.onError(error, aNSSErrorMessage);
},
onConnectionReset() {
......
......@@ -220,17 +220,24 @@ nsLDAPConnection::Observe(nsISupports* aSubject, const char* aTopic,
* and this leads to starvation.
* We have to do a copy of pending operations.
*/
nsTArray<nsILDAPOperation*> pending_operations;
nsTArray<nsLDAPOperation*> pending_operations;
{
MutexAutoLock lock(mPendingOperationsMutex);
for (auto iter = mPendingOperations.Iter(); !iter.Done(); iter.Next()) {
pending_operations.AppendElement(iter.UserData());
nsLDAPOperation* op = static_cast<nsLDAPOperation*>(iter.UserData());
pending_operations.AppendElement(op);
}
}
for (uint32_t i = 0; i < pending_operations.Length(); i++) {
pending_operations[i]->AbandonExt();
for (auto op : pending_operations) {
// Tell the operation to free any refcounts it can.
op->Clear();
// Would be nice to tell the server that it can abort any operations