Eliminate remaining Electron 8 deprecations
* Change systemPreferences.isDarkMode() to nativeTheme.shouldUseDarkColors * Remove vibrancy parameter to BrowserWindow * Update curve25519-n; removes context-aware deprecation warning * Set app.allowRendererProcessReuse = true to remove warning * Move from deprecated setters to direct property set * Serialized sender certificates: Store less, store plain object * isMenuBarAutoHide -> autoHideMenuBar * UUID: Fix sealed sender indicator on message details screen * Data._cleanData: Remove function keys, handle null in array Also: - run _cleanData when saving attachment download jobs - remove job from jobs table when the send itself throws error * _cleanData: Don't dig into strings, booleans, or numbers * getPropsForMessageDetail: Make it clear what we're reducing Co-authored-by: Ken Powers <ken@signal.org>
This commit is contained in:
parent
841461934d
commit
8d6cba1b43
11 changed files with 108 additions and 107 deletions
|
@ -180,8 +180,22 @@ module.exports = {
|
|||
};
|
||||
|
||||
// When IPC arguments are prepared for the cross-process send, they are JSON.stringified.
|
||||
// We can't send ArrayBuffers or BigNumbers (what we get from proto library for dates).
|
||||
function _cleanData(data) {
|
||||
// We can't send ArrayBuffers or BigNumbers (what we get from proto library for dates),
|
||||
// We also cannot send objects with function-value keys, like what protobufjs gives us.
|
||||
function _cleanData(data, path = 'root') {
|
||||
if (data === null || data === undefined) {
|
||||
window.log.warn(`_cleanData: null or undefined value at path ${path}`);
|
||||
return data;
|
||||
}
|
||||
|
||||
if (
|
||||
typeof data === 'string' ||
|
||||
typeof data === 'number' ||
|
||||
typeof data === 'boolean'
|
||||
) {
|
||||
return data;
|
||||
}
|
||||
|
||||
const keys = Object.keys(data);
|
||||
for (let index = 0, max = keys.length; index < max; index += 1) {
|
||||
const key = keys[index];
|
||||
|
@ -192,15 +206,21 @@ function _cleanData(data) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (isFunction(value.toNumber)) {
|
||||
if (isFunction(value)) {
|
||||
// To prepare for Electron v9 IPC, we need to take functions off of any object
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
delete data[key];
|
||||
} else if (isFunction(value.toNumber)) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
data[key] = value.toNumber();
|
||||
} else if (Array.isArray(value)) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
data[key] = value.map(item => _cleanData(item));
|
||||
data[key] = value.map((item, mapIndex) =>
|
||||
_cleanData(item, `${path}.${key}.${mapIndex}`)
|
||||
);
|
||||
} else if (isObject(value)) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
data[key] = _cleanData(value);
|
||||
data[key] = _cleanData(value, `${path}.${key}`);
|
||||
} else if (
|
||||
typeof value !== 'string' &&
|
||||
typeof value !== 'number' &&
|
||||
|
@ -209,6 +229,7 @@ function _cleanData(data) {
|
|||
window.log.info(`_cleanData: key ${key} had type ${typeof value}`);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -352,19 +373,25 @@ function makeChannel(fnName) {
|
|||
const jobId = _makeJob(fnName);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
ipcRenderer.send(SQL_CHANNEL_KEY, jobId, fnName, ...args);
|
||||
try {
|
||||
ipcRenderer.send(SQL_CHANNEL_KEY, jobId, fnName, ...args);
|
||||
|
||||
_updateJob(jobId, {
|
||||
resolve,
|
||||
reject,
|
||||
args: _DEBUG ? args : null,
|
||||
});
|
||||
_updateJob(jobId, {
|
||||
resolve,
|
||||
reject,
|
||||
args: _DEBUG ? args : null,
|
||||
});
|
||||
|
||||
setTimeout(
|
||||
() =>
|
||||
reject(new Error(`SQL channel job ${jobId} (${fnName}) timed out`)),
|
||||
DATABASE_UPDATE_TIMEOUT
|
||||
);
|
||||
setTimeout(
|
||||
() =>
|
||||
reject(new Error(`SQL channel job ${jobId} (${fnName}) timed out`)),
|
||||
DATABASE_UPDATE_TIMEOUT
|
||||
);
|
||||
} catch (error) {
|
||||
_removeJob(jobId);
|
||||
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -515,16 +542,8 @@ async function removeAllSignedPreKeys() {
|
|||
|
||||
const ITEM_KEYS = {
|
||||
identityKey: ['value.pubKey', 'value.privKey'],
|
||||
senderCertificate: [
|
||||
'value.certificate',
|
||||
'value.signature',
|
||||
'value.serialized',
|
||||
],
|
||||
senderCertificateWithUuid: [
|
||||
'value.certificate',
|
||||
'value.signature',
|
||||
'value.serialized',
|
||||
],
|
||||
senderCertificate: ['value.serialized'],
|
||||
senderCertificateWithUuid: ['value.serialized'],
|
||||
signaling_key: ['value'],
|
||||
profileKey: ['value'],
|
||||
};
|
||||
|
@ -981,7 +1000,7 @@ async function getNextAttachmentDownloadJobs(limit) {
|
|||
return channels.getNextAttachmentDownloadJobs(limit);
|
||||
}
|
||||
async function saveAttachmentDownloadJob(job) {
|
||||
await channels.saveAttachmentDownloadJob(job);
|
||||
await channels.saveAttachmentDownloadJob(_cleanData(job));
|
||||
}
|
||||
async function setAttachmentDownloadJobPending(id, pending) {
|
||||
await channels.setAttachmentDownloadJobPending(id, pending);
|
||||
|
|
|
@ -43,28 +43,27 @@ function initialize({ events, storage, navigator, logger }) {
|
|||
function scheduleNextRotation() {
|
||||
const now = Date.now();
|
||||
const certificate = storage.get('senderCertificate');
|
||||
if (!certificate) {
|
||||
if (!certificate || !certificate.expires) {
|
||||
setTimeoutForNextRun(scheduledTime || now);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// The useful information in a SenderCertificate is all serialized, so we
|
||||
// need to do another layer of decoding.
|
||||
const decoded = textsecure.protobuf.SenderCertificate.Certificate.decode(
|
||||
certificate.certificate
|
||||
);
|
||||
const expires = decoded.expires.toNumber();
|
||||
|
||||
// If we have a time in place and it's already before the safety zone before expire,
|
||||
// we keep it
|
||||
if (scheduledTime && scheduledTime <= expires - MINIMUM_TIME_LEFT) {
|
||||
if (
|
||||
scheduledTime &&
|
||||
scheduledTime <= certificate.expires - MINIMUM_TIME_LEFT
|
||||
) {
|
||||
setTimeoutForNextRun(scheduledTime);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, we reset every day, or earlier if the safety zone requires it
|
||||
const time = Math.min(now + ONE_DAY, expires - MINIMUM_TIME_LEFT);
|
||||
const time = Math.min(
|
||||
now + ONE_DAY,
|
||||
certificate.expires - MINIMUM_TIME_LEFT
|
||||
);
|
||||
setTimeoutForNextRun(time);
|
||||
}
|
||||
|
||||
|
@ -88,18 +87,21 @@ function initialize({ events, storage, navigator, logger }) {
|
|||
const arrayBuffer = window.Signal.Crypto.base64ToArrayBuffer(
|
||||
certificate
|
||||
);
|
||||
const decoded = textsecure.protobuf.SenderCertificate.decode(
|
||||
const decodedContainer = textsecure.protobuf.SenderCertificate.decode(
|
||||
arrayBuffer
|
||||
);
|
||||
|
||||
decoded.certificate = decoded.certificate.toArrayBuffer();
|
||||
decoded.signature = decoded.signature.toArrayBuffer();
|
||||
decoded.serialized = arrayBuffer;
|
||||
|
||||
storage.put(
|
||||
`senderCertificate${withUuid ? 'WithUuid' : ''}`,
|
||||
decoded
|
||||
const decodedCert = textsecure.protobuf.SenderCertificate.Certificate.decode(
|
||||
decodedContainer.certificate
|
||||
);
|
||||
|
||||
// We don't want to send a protobuf-generated object across IPC, so we make
|
||||
// our own object.
|
||||
const toSave = {
|
||||
expires: decodedCert.expires.toNumber(),
|
||||
serialized: arrayBuffer,
|
||||
};
|
||||
|
||||
storage.put(`senderCertificate${withUuid ? 'WithUuid' : ''}`, toSave);
|
||||
})
|
||||
);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue