Merge pull request #606 from BeaudanBrown/contact-sync

[multi-device]Contact syncing
pull/620/head
Beaudan Campbell-Brown 6 years ago committed by GitHub
commit deedcc1d64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -244,10 +244,13 @@
// singleton to relay events to libtextsecure/message_receiver // singleton to relay events to libtextsecure/message_receiver
window.lokiPublicChatAPI = new window.LokiPublicChatAPI(ourKey); window.lokiPublicChatAPI = new window.LokiPublicChatAPI(ourKey);
// singleton to interface the File server // singleton to interface the File server
window.lokiFileServerAPI = new window.LokiFileServerAPI(ourKey); // If already exists we registered as a secondary device
await window.lokiFileServerAPI.establishConnection( if (!window.lokiFileServerAPI) {
window.getDefaultFileServer() window.lokiFileServerAPI = new window.LokiFileServerAPI(ourKey);
); await window.lokiFileServerAPI.establishConnection(
window.getDefaultFileServer()
);
}
// are there limits on tracking, is this unneeded? // are there limits on tracking, is this unneeded?
// window.mixpanel.track("Desktop boot"); // window.mixpanel.track("Desktop boot");
window.lokiP2pAPI = new window.LokiP2pAPI(ourKey); window.lokiP2pAPI = new window.LokiP2pAPI(ourKey);
@ -262,7 +265,6 @@
if (storage.get('isSecondaryDevice')) { if (storage.get('isSecondaryDevice')) {
window.lokiFileServerAPI.updateOurDeviceMapping(); window.lokiFileServerAPI.updateOurDeviceMapping();
} }
Whisper.events.trigger('apisReady');
}; };
function mapOldThemeToNew(theme) { function mapOldThemeToNew(theme) {
@ -957,6 +959,10 @@
if (Whisper.Registration.ongoingSecondaryDeviceRegistration()) { if (Whisper.Registration.ongoingSecondaryDeviceRegistration()) {
const ourKey = textsecure.storage.user.getNumber(); const ourKey = textsecure.storage.user.getNumber();
window.lokiMessageAPI = new window.LokiMessageAPI(ourKey); window.lokiMessageAPI = new window.LokiMessageAPI(ourKey);
window.lokiFileServerAPI = new window.LokiFileServerAPI(ourKey);
await window.lokiFileServerAPI.establishConnection(
window.getDefaultFileServer()
);
window.localLokiServer = null; window.localLokiServer = null;
window.lokiPublicChatAPI = null; window.lokiPublicChatAPI = null;
window.feeds = []; window.feeds = [];
@ -967,6 +973,7 @@
options options
); );
messageReceiver.addEventListener('message', onMessageReceived); messageReceiver.addEventListener('message', onMessageReceived);
messageReceiver.addEventListener('contact', onContactReceived);
window.textsecure.messaging = new textsecure.MessageSender( window.textsecure.messaging = new textsecure.MessageSender(
USERNAME, USERNAME,
PASSWORD PASSWORD
@ -1239,6 +1246,14 @@
await conversation.setSecondaryStatus(true); await conversation.setSecondaryStatus(true);
} }
if (conversation.isFriendRequestStatusNone()) {
// Will be replaced with automatic friend request
libloki.api.sendBackgroundMessage(conversation.id);
} else {
// Accept any pending friend requests if there are any
conversation.onAcceptFriendRequest({ blockSync: true });
}
if (details.profileKey) { if (details.profileKey) {
const profileKey = window.Signal.Crypto.arrayBufferToBase64( const profileKey = window.Signal.Crypto.arrayBufferToBase64(
details.profileKey details.profileKey

@ -774,7 +774,8 @@
}); });
} }
}, },
async setFriendRequestStatus(newStatus) { async setFriendRequestStatus(newStatus, options = {}) {
const { blockSync } = options;
// Ensure that the new status is a valid FriendStatusEnum value // Ensure that the new status is a valid FriendStatusEnum value
if (!(newStatus in Object.values(FriendRequestStatusEnum))) { if (!(newStatus in Object.values(FriendRequestStatusEnum))) {
return; return;
@ -791,6 +792,10 @@
Conversation: Whisper.Conversation, Conversation: Whisper.Conversation,
}); });
await this.updateTextInputState(); await this.updateTextInputState();
if (!blockSync && newStatus === FriendRequestStatusEnum.friends) {
// Sync contact
this.wrapSend(textsecure.messaging.sendContactSyncMessage(this));
}
} }
}, },
async respondToAllFriendRequests(options) { async respondToAllFriendRequests(options) {
@ -837,12 +842,12 @@
await window.libloki.storage.removeContactPreKeyBundle(this.id); await window.libloki.storage.removeContactPreKeyBundle(this.id);
}, },
// We have accepted an incoming friend request // We have accepted an incoming friend request
async onAcceptFriendRequest() { async onAcceptFriendRequest(options = {}) {
if (this.unlockTimer) { if (this.unlockTimer) {
clearTimeout(this.unlockTimer); clearTimeout(this.unlockTimer);
} }
if (this.hasReceivedFriendRequest()) { if (this.hasReceivedFriendRequest()) {
this.setFriendRequestStatus(FriendRequestStatusEnum.friends); this.setFriendRequestStatus(FriendRequestStatusEnum.friends, options);
await this.respondToAllFriendRequests({ await this.respondToAllFriendRequests({
response: 'accepted', response: 'accepted',
direction: 'incoming', direction: 'incoming',

@ -38,15 +38,22 @@
let p2pPort = null; let p2pPort = null;
let type; let type;
if (!window.localLokiServer || !window.localLokiServer.isListening()) { let myIp;
type = textsecure.protobuf.LokiAddressMessage.Type.HOST_UNREACHABLE; if (window.localLokiServer && window.localLokiServer.isListening()) {
} else { try {
// clearnet change: getMyLokiAddress -> getMyClearIP // clearnet change: getMyLokiAddress -> getMyClearIP
// const myLokiAddress = await window.lokiSnodeAPI.getMyLokiAddress(); // const myLokiAddress = await window.lokiSnodeAPI.getMyLokiAddress();
const myIp = await window.lokiSnodeAPI.getMyClearIp(); myIp = await window.lokiSnodeAPI.getMyClearIp();
} catch (e) {
log.warn(`Failed to get clear IP for local server ${e}`);
}
}
if (myIp) {
p2pAddress = `https://${myIp}`; p2pAddress = `https://${myIp}`;
p2pPort = window.localLokiServer.getPublicPort(); p2pPort = window.localLokiServer.getPublicPort();
type = textsecure.protobuf.LokiAddressMessage.Type.HOST_REACHABLE; type = textsecure.protobuf.LokiAddressMessage.Type.HOST_REACHABLE;
} else {
type = textsecure.protobuf.LokiAddressMessage.Type.HOST_UNREACHABLE;
} }
const lokiAddressMessage = new textsecure.protobuf.LokiAddressMessage({ const lokiAddressMessage = new textsecure.protobuf.LokiAddressMessage({
@ -114,11 +121,7 @@
result.reset(); result.reset();
return result; return result;
} }
async function createContactSyncProtoMessage() { async function createContactSyncProtoMessage(conversations) {
const conversations = await window.Signal.Data.getConversationsWithFriendStatus(
window.friends.friendRequestStatusEnum.friends,
{ ConversationCollection: Whisper.ConversationCollection }
);
// Extract required contacts information out of conversations // Extract required contacts information out of conversations
const rawContacts = await Promise.all( const rawContacts = await Promise.all(
conversations.map(async conversation => { conversations.map(async conversation => {
@ -171,29 +174,28 @@
ourNumber, ourNumber,
'private' 'private'
); );
const secondaryConversation = await ConversationController.getOrCreateAndWait(
recipientPubKey,
'private'
);
// Always be friends with secondary devices
secondaryConversation.setFriendRequestStatus(
window.friends.friendRequestStatusEnum.friends
);
// Send profile name to secondary device
const lokiProfile = ourConversation.getLokiProfile();
const profile = new textsecure.protobuf.DataMessage.LokiProfile(
lokiProfile
);
const dataMessage = new textsecure.protobuf.DataMessage({
profile,
});
// Attach contact list
const syncMessage = await createContactSyncProtoMessage();
const content = new textsecure.protobuf.Content({ const content = new textsecure.protobuf.Content({
pairingAuthorisation, pairingAuthorisation,
dataMessage,
syncMessage,
}); });
const isGrant = authorisation.primaryDevicePubKey === ourNumber;
if (isGrant) {
// Send profile name to secondary device
const lokiProfile = ourConversation.getLokiProfile();
const profile = new textsecure.protobuf.DataMessage.LokiProfile(
lokiProfile
);
const dataMessage = new textsecure.protobuf.DataMessage({
profile,
});
// Attach contact list
const conversations = await window.Signal.Data.getConversationsWithFriendStatus(
window.friends.friendRequestStatusEnum.friends,
{ ConversationCollection: Whisper.ConversationCollection }
);
const syncMessage = await createContactSyncProtoMessage(conversations);
content.syncMessage = syncMessage;
content.dataMessage = dataMessage;
}
// Send // Send
const options = { messageType: 'pairing-request' }; const options = { messageType: 'pairing-request' };
const p = new Promise((resolve, reject) => { const p = new Promise((resolve, reject) => {

@ -1130,14 +1130,6 @@ MessageReceiver.prototype.extend({
// This call already removes the envelope from the cache // This call already removes the envelope from the cache
await this.handleContacts(envelope, syncMessage.contacts); await this.handleContacts(envelope, syncMessage.contacts);
removedFromCache = true; removedFromCache = true;
if (window.initialisedAPI) {
await this.sendFriendRequestsToSyncContacts(syncMessage.contacts);
} else {
// We need to wait here because initAPIs hasn't been called yet
Whisper.events.once('apisReady', async () => {
await this.sendFriendRequestsToSyncContacts(syncMessage.contacts);
});
}
} }
} else { } else {
window.log.warn('Unimplemented pairing authorisation message type'); window.log.warn('Unimplemented pairing authorisation message type');
@ -1232,8 +1224,6 @@ MessageReceiver.prototype.extend({
return false; return false;
} }
await libloki.storage.savePairingAuthorisation(authorisation); await libloki.storage.savePairingAuthorisation(authorisation);
// sending a message back = accepting friend request
window.libloki.api.sendBackgroundMessage(pubKey);
return true; return true;
}, },
@ -1293,7 +1283,12 @@ MessageReceiver.prototype.extend({
deviceMapping deviceMapping
); );
if (autoAccepted) { if (autoAccepted) {
await conversation.onFriendRequestAccepted(); // sending a message back = accepting friend request
// Directly setting friend request status to skip the pending state
await conversation.setFriendRequestStatus(
window.friends.friendRequestStatusEnum.friends
);
window.libloki.api.sendBackgroundMessage(envelope.source);
return this.removeFromCache(envelope); return this.removeFromCache(envelope);
} }
} }

@ -452,7 +452,7 @@ MessageSender.prototype = {
// Don't send to ourselves // Don't send to ourselves
.filter(pubKey => pubKey !== textsecure.storage.user.getNumber()); .filter(pubKey => pubKey !== textsecure.storage.user.getNumber());
if (allOurDevices.length === 0) { if (allOurDevices.length === 0) {
return Promise.resolve(); return null;
} }
const dataMessage = textsecure.protobuf.DataMessage.decode( const dataMessage = textsecure.protobuf.DataMessage.decode(
@ -563,6 +563,38 @@ MessageSender.prototype = {
return Promise.resolve(); return Promise.resolve();
}, },
async sendContactSyncMessage(contactConversation) {
const primaryDeviceKey = window.storage.get('primaryDevicePubKey');
const allOurDevices = (await libloki.storage.getAllDevicePubKeysForPrimaryPubKey(
primaryDeviceKey
))
// Don't send to ourselves
.filter(pubKey => pubKey !== textsecure.storage.user.getNumber());
if (
allOurDevices.includes(contactConversation.id) ||
!primaryDeviceKey ||
allOurDevices.length === 0
) {
// If we havn't got a primaryDeviceKey then we are in the middle of pairing
return Promise.resolve();
}
const syncMessage = await libloki.api.createContactSyncProtoMessage([
contactConversation,
]);
const contentMessage = new textsecure.protobuf.Content();
contentMessage.syncMessage = syncMessage;
const silent = true;
return this.sendIndividualProto(
primaryDeviceKey,
contentMessage,
Date.now(),
silent,
{} // options
);
},
sendRequestContactSyncMessage(options) { sendRequestContactSyncMessage(options) {
const myNumber = textsecure.storage.user.getNumber(); const myNumber = textsecure.storage.user.getNumber();
const myDevice = textsecure.storage.user.getDeviceId(); const myDevice = textsecure.storage.user.getDeviceId();
@ -1160,6 +1192,7 @@ textsecure.MessageSender = function MessageSenderWrapper(username, password) {
this.sendRequestContactSyncMessage = sender.sendRequestContactSyncMessage.bind( this.sendRequestContactSyncMessage = sender.sendRequestContactSyncMessage.bind(
sender sender
); );
this.sendContactSyncMessage = sender.sendContactSyncMessage.bind(sender);
this.sendRequestConfigurationSyncMessage = sender.sendRequestConfigurationSyncMessage.bind( this.sendRequestConfigurationSyncMessage = sender.sendRequestConfigurationSyncMessage.bind(
sender sender
); );

Loading…
Cancel
Save