diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 3c62eec8a..67cb93cea 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1116,22 +1116,6 @@ "message": "Typing Indicators", "description": "Title of the typing indicators setting" }, - "multiDeviceDisabledTemporary": { - "message": "MultiDevice disabled temporarily", - "description": "Description of why multi device is disabled" - }, - "multiDeviceDisabledTemporaryTitle": { - "message": "Changes to Multi-device", - "description": "Description of why multi device is disabled on app start" - }, - "multiDeviceDisabledTemporaryDescriptionPrimary": { - "message": "You’re seeing this because you have a secondary device linked to your Session ID. To improve reliability and stability, we’ve decided to temporarily disable Session’s multi-device functionality. Device linking has been disabled, and existing secondary clients will be erased on August 6th.

To read more about this change, visit the Session FAQ at getsession.org/faq.", - "description": "Description of why multi device is disabled on app start for a primary device" - }, - "multiDeviceDisabledTemporaryDescriptionSecondary": { - "message": "You’re seeing this because this is a secondary device in a multi-device setup. To improve reliability and stability, we’ve decided to temporarily disable Session’s multi-device functionality. Device linking has been disabled, and existing secondary clients will be erased on August 6th.

To read more about this change, visit the Session FAQ at getsession.org/faq.", - "description": "Description of why multi device is disabled on app start for a secondary device" - }, "messageTTL": { "message": "Message TTL", "description": "Title of the Message TTL setting" diff --git a/app/sql.js b/app/sql.js index 086100c5b..301956921 100644 --- a/app/sql.js +++ b/app/sql.js @@ -810,6 +810,7 @@ const LOKI_SCHEMA_VERSIONS = [ updateToLokiSchemaVersion4, updateToLokiSchemaVersion5, updateToLokiSchemaVersion6, + updateToLokiSchemaVersion7, ]; async function updateToLokiSchemaVersion1(currentVersion, instance) { @@ -1027,6 +1028,30 @@ async function updateToLokiSchemaVersion6(currentVersion, instance) { console.log('updateToLokiSchemaVersion6: success!'); } +async function updateToLokiSchemaVersion7(currentVersion, instance) { + if (currentVersion >= 7) { + return; + } + + console.log('updateToLokiSchemaVersion7: starting...'); + + await instance.run('BEGIN TRANSACTION;'); + + // Remove multi device data + await instance.run('DELETE FROM pairingAuthorisations;'); + + await instance.run( + `INSERT INTO loki_schema ( + version + ) values ( + 7 + );` + ); + + await instance.run('COMMIT TRANSACTION;'); + console.log('updateToLokiSchemaVersion7: success!'); +} + async function updateLokiSchema(instance) { const result = await instance.get( "SELECT name FROM sqlite_master WHERE type = 'table' AND name='loki_schema';" diff --git a/js/background.js b/js/background.js index 67c556030..ff7a7357e 100644 --- a/js/background.js +++ b/js/background.js @@ -300,6 +300,12 @@ storage.put('primaryDevicePubKey', textsecure.storage.user.getNumber()); } + // 4th August 2020 - Force wipe of secondary devices as multi device is being disabled. + if (storage.get('isSecondaryDevice')) { + await window.deleteAccount(); + return; + } + // These make key operations available to IPC handlers created in preload.js window.Events = { getThemeSetting: () => 'dark', // storage.get('theme-setting', 'dark') @@ -803,27 +809,6 @@ // Get memberlist. This function is not accurate >> // window.getMemberList = window.lokiPublicChatAPI.getListOfMembers(); - window.deleteAccount = async () => { - try { - window.log.info('Deleting everything!'); - - const { Logs } = window.Signal; - await Logs.deleteAll(); - - await window.Signal.Data.removeAll(); - await window.Signal.Data.close(); - await window.Signal.Data.removeDB(); - - await window.Signal.Data.removeOtherData(); - } catch (error) { - window.log.error( - 'Something went wrong deleting all data:', - error && error.stack ? error.stack : error - ); - } - window.restart(); - }; - window.toggleTheme = () => { const theme = window.Events.getThemeSetting(); const updatedTheme = theme === 'dark' ? 'light' : 'dark'; diff --git a/js/modules/loki_app_dot_net_api.js b/js/modules/loki_app_dot_net_api.js index 526f1b44f..ae606fb35 100644 --- a/js/modules/loki_app_dot_net_api.js +++ b/js/modules/loki_app_dot_net_api.js @@ -1710,8 +1710,9 @@ class LokiPublicChannelAPI { sigString += [...attachmentAnnotations, ...previewAnnotations] .map(data => data.id || data.image.id) .sort() - .join(); + .join(''); sigString += sigVer; + return dcodeIO.ByteBuffer.wrap(sigString, 'utf8').toArrayBuffer(); } diff --git a/js/modules/loki_file_server_api.js b/js/modules/loki_file_server_api.js index 8956c7f21..9287875c9 100644 --- a/js/modules/loki_file_server_api.js +++ b/js/modules/loki_file_server_api.js @@ -218,6 +218,10 @@ class LokiHomeServerInstance extends LokiFileServerInstance { } async updateOurDeviceMapping() { + if (!window.lokiFeatureFlags.useMultiDevice) { + return undefined; + } + const isPrimary = !storage.get('isSecondaryDevice'); const authorisations = await window.libsession.Protocols.MultiDeviceProtocol.getPairingAuthorisations( this.ourKey diff --git a/preload.js b/preload.js index bf4471ec0..49b3ec0a9 100644 --- a/preload.js +++ b/preload.js @@ -456,6 +456,7 @@ window.lokiFeatureFlags = { enableSenderKeys: false, onionRequestHops: 3, debugMessageLogs: process.env.ENABLE_MESSAGE_LOGS, + useMultiDevice: false, }; // eslint-disable-next-line no-extend-native,func-names @@ -492,6 +493,7 @@ if (config.environment.includes('test-integration')) { useFileOnionRequests: false, debugMessageLogs: true, enableSenderKeys: true, + useMultiDevice: false, }; } @@ -502,3 +504,24 @@ const { } = require('./ts/util/blockedNumberController'); window.BlockedNumberController = BlockedNumberController; + +window.deleteAccount = async () => { + try { + window.log.info('Deleting everything!'); + + const { Logs } = window.Signal; + await Logs.deleteAll(); + + await window.Signal.Data.removeAll(); + await window.Signal.Data.close(); + await window.Signal.Data.removeDB(); + + await window.Signal.Data.removeOtherData(); + } catch (error) { + window.log.error( + 'Something went wrong deleting all data:', + error && error.stack ? error.stack : error + ); + } + window.restart(); +}; diff --git a/ts/components/session/ActionsPanel.tsx b/ts/components/session/ActionsPanel.tsx index 484a3b89f..84d653bfa 100644 --- a/ts/components/session/ActionsPanel.tsx +++ b/ts/components/session/ActionsPanel.tsx @@ -59,48 +59,6 @@ export class ActionsPanel extends React.Component { }, 'refreshAvatarCallback' ); - setTimeout(async () => { - const disabledMultiDeviceCountDb = await getItemById( - 'disabledMultiDeviceCount' - ); - const disabledMultiDeviceCount = - Number(disabledMultiDeviceCountDb?.value) || 0; - const data = { - id: 'disabledMultiDeviceCount', - value: String(disabledMultiDeviceCount + 1), - }; - await createOrUpdateItem(data); - if (disabledMultiDeviceCount % 5 !== 0) { - return; - } - const currentDevice = await UserUtil.getCurrentDevicePubKey(); - if (!currentDevice) { - return; - } - const secondaryDevices = await MultiDeviceProtocol.getSecondaryDevices( - currentDevice - ); - const isSecondary = - secondaryDevices.find(s => s.key === currentDevice) || - !!window.textsecure.storage.get('isSecondaryDevice'); - - const hasMultipleDevices = - (await MultiDeviceProtocol.getOurDevices()).length > 1; - const primaryWithSecondary = !isSecondary && hasMultipleDevices; - - if (!primaryWithSecondary && !isSecondary) { - return; - } - - const opts = { - hideCancel: true, - title: window.i18n('multiDeviceDisabledTemporaryTitle'), - message: primaryWithSecondary - ? window.i18n('multiDeviceDisabledTemporaryDescriptionPrimary') - : window.i18n('multiDeviceDisabledTemporaryDescriptionSecondary'), - }; - window.Whisper.events.trigger('showConfirmationDialog', opts); - }, 1000); } ); } diff --git a/ts/components/session/LeftPaneSettingSection.tsx b/ts/components/session/LeftPaneSettingSection.tsx index 7d729e498..cecb27ad8 100644 --- a/ts/components/session/LeftPaneSettingSection.tsx +++ b/ts/components/session/LeftPaneSettingSection.tsx @@ -225,7 +225,7 @@ export class LeftPaneSettingSection extends React.Component { { id: SessionSettingCategory.Devices, title: window.i18n('devicesSettingsTitle'), - hidden: isSecondaryDevice, + hidden: !window.lokiFeatureFlags.useMultiDevice || isSecondaryDevice, }, ]; } diff --git a/ts/components/session/RegistrationTabs.tsx b/ts/components/session/RegistrationTabs.tsx index 4690a3d34..71fa3aac7 100644 --- a/ts/components/session/RegistrationTabs.tsx +++ b/ts/components/session/RegistrationTabs.tsx @@ -557,9 +557,12 @@ export class RegistrationTabs extends React.Component<{}, State> { SessionButtonType.BrandOutline, SessionButtonColor.Green )} - {/*

{or}

*/} - {/* FIXME enable back to allow linking of device - this.renderLinkDeviceToExistingAccountButton() */} + {window.lokiFeatureFlags.useMultiDevice && ( + <> +

{or}

+ {this.renderLinkDeviceToExistingAccountButton()} + + )} ); } @@ -584,9 +587,12 @@ export class RegistrationTabs extends React.Component<{}, State> { return (
{this.renderContinueYourSessionButton()} - {/*

{or}

*/} - {/* FIXME enable back to allow linking of device - this.renderLinkDeviceToExistingAccountButton()*/} + {window.lokiFeatureFlags.useMultiDevice && ( + <> +

{or}

+ {this.renderLinkDeviceToExistingAccountButton()} + + )}
); } diff --git a/ts/components/session/settings/SessionSettings.tsx b/ts/components/session/settings/SessionSettings.tsx index f60459ea8..3b4076da0 100644 --- a/ts/components/session/settings/SessionSettings.tsx +++ b/ts/components/session/settings/SessionSettings.tsx @@ -644,7 +644,7 @@ export class SettingsView extends React.Component { id: 'no-linked-device', title: noPairedDeviceText, type: undefined, - description: window.i18n('multiDeviceDisabledTemporary'), + description: '', category: SessionSettingCategory.Devices, content: {}, comparisonValue: undefined, diff --git a/ts/components/session/settings/SessionSettingsHeader.tsx b/ts/components/session/settings/SessionSettingsHeader.tsx index b1e33393a..21e663e96 100644 --- a/ts/components/session/settings/SessionSettingsHeader.tsx +++ b/ts/components/session/settings/SessionSettingsHeader.tsx @@ -74,12 +74,9 @@ export class SettingsHeader extends React.Component { ? `${categoryTitlePrefix.slice(0, -1)} Settings` : `${categoryTitlePrefix} Settings`; const showSearch = false; - const showAddDevice = false; - /* FIXME enable back to allow linking of device - const showAddDevice = + const showAddDevice = category === SessionSettingCategory.Devices && this.props.showLinkDeviceButton; - */ return (
diff --git a/ts/receiver/multidevice.ts b/ts/receiver/multidevice.ts index 6dd9142b6..c1c69261d 100644 --- a/ts/receiver/multidevice.ts +++ b/ts/receiver/multidevice.ts @@ -87,6 +87,14 @@ export async function handlePairingAuthorisationMessage( pairingAuthorisation: SignalService.IPairingAuthorisationMessage, dataMessage: SignalService.IDataMessage | undefined | null ): Promise { + if (!window.lokiFeatureFlags.useMultiDevice) { + window.log.info( + `Received a pairing authorisation message from ${envelope.source} while multi device is disabled.` + ); + await removeFromCache(envelope); + return; + } + const { secondaryDevicePubKey, grantSignature } = pairingAuthorisation; const isGrant = grantSignature && diff --git a/ts/session/protocols/MultiDeviceProtocol.ts b/ts/session/protocols/MultiDeviceProtocol.ts index 2ae330040..3e3a2320a 100644 --- a/ts/session/protocols/MultiDeviceProtocol.ts +++ b/ts/session/protocols/MultiDeviceProtocol.ts @@ -28,6 +28,11 @@ export class MultiDeviceProtocol { public static async fetchPairingAuthorisationsIfNeeded( device: PubKey ): Promise { + // Disable fetching if we don't want to use multi device + if (!window.lokiFeatureFlags.useMultiDevice) { + return; + } + // This return here stops an infinite loop when we get all our other devices const ourKey = await UserUtil.getCurrentDevicePubKey(); if (!ourKey || device.key === ourKey) { diff --git a/ts/test/session/protocols/MultiDeviceProtocol_test.ts b/ts/test/session/protocols/MultiDeviceProtocol_test.ts index e1d248121..1a5dd8220 100644 --- a/ts/test/session/protocols/MultiDeviceProtocol_test.ts +++ b/ts/test/session/protocols/MultiDeviceProtocol_test.ts @@ -25,6 +25,13 @@ function generateFakeAuthorisations( describe('MultiDeviceProtocol', () => { const sandbox = sinon.createSandbox(); + beforeEach(() => { + // Enable multidevice for tests + TestUtils.stubWindow('lokiFeatureFlags', { + useMultiDevice: true, + }); + }); + afterEach(() => { TestUtils.restoreStubs(); sandbox.restore(); diff --git a/ts/window.d.ts b/ts/window.d.ts index f6d15c2d6..d6b245677 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -51,7 +51,17 @@ declare global { libloki: Libloki; libsignal: LibsignalProtocol; log: any; - lokiFeatureFlags: any; + lokiFeatureFlags: { + multiDeviceUnpairing: boolean; + privateGroupChats: boolean; + useSnodeProxy: boolean; + useOnionRequests: boolean; + useFileOnionRequests: boolean; + enableSenderKeys: boolean; + onionRequestHops: number; + debugMessageLogs: boolean; + useMultiDevice: boolean; + }; lokiFileServerAPI: LokiFileServerInstance; lokiMessageAPI: LokiMessageInterface; lokiPublicChatAPI: LokiPublicChatFactoryInterface;