Merge pull request #606 from BeaudanBrown/contact-sync

[multi-device]Contact syncing
pull/620/head
Beaudan Campbell-Brown 5 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
window.lokiPublicChatAPI = new window.LokiPublicChatAPI(ourKey);
// singleton to interface the File server
window.lokiFileServerAPI = new window.LokiFileServerAPI(ourKey);
await window.lokiFileServerAPI.establishConnection(
window.getDefaultFileServer()
);
// If already exists we registered as a secondary device
if (!window.lokiFileServerAPI) {
window.lokiFileServerAPI = new window.LokiFileServerAPI(ourKey);
await window.lokiFileServerAPI.establishConnection(
window.getDefaultFileServer()
);
}
// are there limits on tracking, is this unneeded?
// window.mixpanel.track("Desktop boot");
window.lokiP2pAPI = new window.LokiP2pAPI(ourKey);
@ -262,7 +265,6 @@
if (storage.get('isSecondaryDevice')) {
window.lokiFileServerAPI.updateOurDeviceMapping();
}
Whisper.events.trigger('apisReady');
};
function mapOldThemeToNew(theme) {
@ -957,6 +959,10 @@
if (Whisper.Registration.ongoingSecondaryDeviceRegistration()) {
const ourKey = textsecure.storage.user.getNumber();
window.lokiMessageAPI = new window.LokiMessageAPI(ourKey);
window.lokiFileServerAPI = new window.LokiFileServerAPI(ourKey);
await window.lokiFileServerAPI.establishConnection(
window.getDefaultFileServer()
);
window.localLokiServer = null;
window.lokiPublicChatAPI = null;
window.feeds = [];
@ -967,6 +973,7 @@
options
);
messageReceiver.addEventListener('message', onMessageReceived);
messageReceiver.addEventListener('contact', onContactReceived);
window.textsecure.messaging = new textsecure.MessageSender(
USERNAME,
PASSWORD
@ -1239,6 +1246,14 @@
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) {
const profileKey = window.Signal.Crypto.arrayBufferToBase64(
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
if (!(newStatus in Object.values(FriendRequestStatusEnum))) {
return;
@ -791,6 +792,10 @@
Conversation: Whisper.Conversation,
});
await this.updateTextInputState();
if (!blockSync && newStatus === FriendRequestStatusEnum.friends) {
// Sync contact
this.wrapSend(textsecure.messaging.sendContactSyncMessage(this));
}
}
},
async respondToAllFriendRequests(options) {
@ -837,12 +842,12 @@
await window.libloki.storage.removeContactPreKeyBundle(this.id);
},
// We have accepted an incoming friend request
async onAcceptFriendRequest() {
async onAcceptFriendRequest(options = {}) {
if (this.unlockTimer) {
clearTimeout(this.unlockTimer);
}
if (this.hasReceivedFriendRequest()) {
this.setFriendRequestStatus(FriendRequestStatusEnum.friends);
this.setFriendRequestStatus(FriendRequestStatusEnum.friends, options);
await this.respondToAllFriendRequests({
response: 'accepted',
direction: 'incoming',

@ -38,15 +38,22 @@
let p2pPort = null;
let type;
if (!window.localLokiServer || !window.localLokiServer.isListening()) {
type = textsecure.protobuf.LokiAddressMessage.Type.HOST_UNREACHABLE;
} else {
// clearnet change: getMyLokiAddress -> getMyClearIP
// const myLokiAddress = await window.lokiSnodeAPI.getMyLokiAddress();
const myIp = await window.lokiSnodeAPI.getMyClearIp();
let myIp;
if (window.localLokiServer && window.localLokiServer.isListening()) {
try {
// clearnet change: getMyLokiAddress -> getMyClearIP
// const myLokiAddress = await window.lokiSnodeAPI.getMyLokiAddress();
myIp = await window.lokiSnodeAPI.getMyClearIp();
} catch (e) {
log.warn(`Failed to get clear IP for local server ${e}`);
}
}
if (myIp) {
p2pAddress = `https://${myIp}`;
p2pPort = window.localLokiServer.getPublicPort();
type = textsecure.protobuf.LokiAddressMessage.Type.HOST_REACHABLE;
} else {
type = textsecure.protobuf.LokiAddressMessage.Type.HOST_UNREACHABLE;
}
const lokiAddressMessage = new textsecure.protobuf.LokiAddressMessage({
@ -114,11 +121,7 @@
result.reset();
return result;
}
async function createContactSyncProtoMessage() {
const conversations = await window.Signal.Data.getConversationsWithFriendStatus(
window.friends.friendRequestStatusEnum.friends,
{ ConversationCollection: Whisper.ConversationCollection }
);
async function createContactSyncProtoMessage(conversations) {
// Extract required contacts information out of conversations
const rawContacts = await Promise.all(
conversations.map(async conversation => {
@ -171,29 +174,28 @@
ourNumber,
'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({
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
const options = { messageType: 'pairing-request' };
const p = new Promise((resolve, reject) => {

@ -1130,14 +1130,6 @@ MessageReceiver.prototype.extend({
// This call already removes the envelope from the cache
await this.handleContacts(envelope, syncMessage.contacts);
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 {
window.log.warn('Unimplemented pairing authorisation message type');
@ -1232,8 +1224,6 @@ MessageReceiver.prototype.extend({
return false;
}
await libloki.storage.savePairingAuthorisation(authorisation);
// sending a message back = accepting friend request
window.libloki.api.sendBackgroundMessage(pubKey);
return true;
},
@ -1293,7 +1283,12 @@ MessageReceiver.prototype.extend({
deviceMapping
);
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);
}
}

@ -452,7 +452,7 @@ MessageSender.prototype = {
// Don't send to ourselves
.filter(pubKey => pubKey !== textsecure.storage.user.getNumber());
if (allOurDevices.length === 0) {
return Promise.resolve();
return null;
}
const dataMessage = textsecure.protobuf.DataMessage.decode(
@ -563,6 +563,38 @@ MessageSender.prototype = {
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) {
const myNumber = textsecure.storage.user.getNumber();
const myDevice = textsecure.storage.user.getDeviceId();
@ -1160,6 +1192,7 @@ textsecure.MessageSender = function MessageSenderWrapper(username, password) {
this.sendRequestContactSyncMessage = sender.sendRequestContactSyncMessage.bind(
sender
);
this.sendContactSyncMessage = sender.sendContactSyncMessage.bind(sender);
this.sendRequestConfigurationSyncMessage = sender.sendRequestConfigurationSyncMessage.bind(
sender
);

Loading…
Cancel
Save