background.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*
  2. * vim: ts=4:sw=4:expandtab
  3. */
  4. ;(function() {
  5. 'use strict';
  6. window.onInvalidStateError = function(e) {
  7. console.log(e);
  8. };
  9. console.log('background page reloaded');
  10. extension.notification.init();
  11. // Close and reopen existing windows
  12. var open = false;
  13. extension.windows.getAll().forEach(function(appWindow) {
  14. open = true;
  15. appWindow.close();
  16. });
  17. // start a background worker for ecc
  18. textsecure.startWorker('/js/libsignal-protocol-worker.js');
  19. extension.onLaunched(function() {
  20. console.log('extension launched');
  21. storage.onready(function() {
  22. if (Whisper.Registration.everDone()) {
  23. openInbox();
  24. }
  25. if (!Whisper.Registration.isDone()) {
  26. extension.install();
  27. }
  28. });
  29. });
  30. var SERVER_URL = 'https://textsecure-service-staging.whispersystems.org';
  31. var SERVER_PORTS = [80, 4433, 8443];
  32. var ATTACHMENT_SERVER_URL = 'https://whispersystems-textsecure-attachments-staging.s3.amazonaws.com';
  33. var messageReceiver;
  34. window.getSocketStatus = function() {
  35. if (messageReceiver) {
  36. return messageReceiver.getStatus();
  37. } else {
  38. return -1;
  39. }
  40. };
  41. window.getAccountManager = function() {
  42. var USERNAME = storage.get('number_id');
  43. var PASSWORD = storage.get('password');
  44. var accountManager = new textsecure.AccountManager(
  45. SERVER_URL, SERVER_PORTS, USERNAME, PASSWORD
  46. );
  47. accountManager.addEventListener('registration', function() {
  48. if (!Whisper.Registration.everDone()) {
  49. storage.put('safety-numbers-approval', false);
  50. }
  51. Whisper.Registration.markDone();
  52. extension.trigger('registration_done');
  53. });
  54. return accountManager;
  55. };
  56. storage.fetch();
  57. storage.onready(function() {
  58. window.dispatchEvent(new Event('storage_ready'));
  59. setUnreadCount(storage.get("unreadCount", 0));
  60. if (Whisper.Registration.isDone()) {
  61. extension.keepAwake();
  62. init();
  63. }
  64. extension.on('registration_done', function() {
  65. extension.keepAwake();
  66. init(true);
  67. });
  68. if (open) {
  69. openInbox();
  70. }
  71. });
  72. window.getSyncRequest = function() {
  73. return new textsecure.SyncRequest(textsecure.messaging, messageReceiver);
  74. };
  75. function init(firstRun) {
  76. window.removeEventListener('online', init);
  77. if (!Whisper.Registration.isDone()) { return; }
  78. if (messageReceiver) { messageReceiver.close(); }
  79. var USERNAME = storage.get('number_id');
  80. var PASSWORD = storage.get('password');
  81. var mySignalingKey = storage.get('signaling_key');
  82. // initialize the socket and start listening for messages
  83. messageReceiver = new textsecure.MessageReceiver(
  84. SERVER_URL, SERVER_PORTS, USERNAME, PASSWORD, mySignalingKey, ATTACHMENT_SERVER_URL
  85. );
  86. messageReceiver.addEventListener('message', onMessageReceived);
  87. messageReceiver.addEventListener('receipt', onDeliveryReceipt);
  88. messageReceiver.addEventListener('contact', onContactReceived);
  89. messageReceiver.addEventListener('group', onGroupReceived);
  90. messageReceiver.addEventListener('sent', onSentMessage);
  91. messageReceiver.addEventListener('read', onReadReceipt);
  92. messageReceiver.addEventListener('error', onError);
  93. window.textsecure.messaging = new textsecure.MessageSender(
  94. SERVER_URL, SERVER_PORTS, USERNAME, PASSWORD, ATTACHMENT_SERVER_URL
  95. );
  96. if (firstRun === true && textsecure.storage.user.getDeviceId() != '1') {
  97. if (!storage.get('theme-setting') && textsecure.storage.get('userAgent') === 'OWI') {
  98. storage.put('theme-setting', 'ios');
  99. }
  100. var syncRequest = new textsecure.SyncRequest(textsecure.messaging, messageReceiver);
  101. syncRequest.addEventListener('success', function() {
  102. console.log('sync successful');
  103. storage.put('synced_at', Date.now());
  104. window.dispatchEvent(new Event('textsecure:contactsync'));
  105. });
  106. syncRequest.addEventListener('timeout', function() {
  107. console.log('sync timed out');
  108. window.dispatchEvent(new Event('textsecure:contactsync'));
  109. });
  110. }
  111. }
  112. function onContactReceived(ev) {
  113. var contactDetails = ev.contactDetails;
  114. ConversationController.create({
  115. name: contactDetails.name,
  116. id: contactDetails.number,
  117. avatar: contactDetails.avatar,
  118. color: contactDetails.color,
  119. type: 'private',
  120. active_at: Date.now()
  121. }).save();
  122. }
  123. function onGroupReceived(ev) {
  124. var groupDetails = ev.groupDetails;
  125. var attributes = {
  126. id: groupDetails.id,
  127. name: groupDetails.name,
  128. members: groupDetails.members,
  129. avatar: groupDetails.avatar,
  130. type: 'group',
  131. };
  132. if (groupDetails.active) {
  133. attributes.active_at = Date.now();
  134. } else {
  135. attributes.left = true;
  136. }
  137. var conversation = ConversationController.create(attributes);
  138. conversation.save();
  139. }
  140. function onMessageReceived(ev) {
  141. var data = ev.data;
  142. var message = initIncomingMessage(data.source, data.timestamp);
  143. message.handleDataMessage(data.message);
  144. }
  145. function onSentMessage(ev) {
  146. var now = new Date().getTime();
  147. var data = ev.data;
  148. var message = new Whisper.Message({
  149. source : textsecure.storage.user.getNumber(),
  150. sent_at : data.timestamp,
  151. received_at : now,
  152. conversationId : data.destination,
  153. type : 'outgoing',
  154. sent : true,
  155. expirationStartTimestamp: data.expirationStartTimestamp,
  156. });
  157. message.handleDataMessage(data.message);
  158. }
  159. function initIncomingMessage(source, timestamp) {
  160. var now = new Date().getTime();
  161. var message = new Whisper.Message({
  162. source : source,
  163. sent_at : timestamp,
  164. received_at : now,
  165. conversationId : source,
  166. type : 'incoming',
  167. unread : 1
  168. });
  169. return message;
  170. }
  171. function onError(ev) {
  172. var e = ev.error;
  173. console.log(e);
  174. console.log(e.stack);
  175. if (e.name === 'HTTPError' && (e.code == 401 || e.code == 403)) {
  176. Whisper.Registration.remove();
  177. extension.install();
  178. return;
  179. }
  180. if (e.name === 'HTTPError' && e.code == -1) {
  181. // Failed to connect to server
  182. if (navigator.onLine) {
  183. console.log('retrying in 1 minute');
  184. setTimeout(init, 60000);
  185. } else {
  186. console.log('offline');
  187. messageReceiver.close();
  188. window.addEventListener('online', init);
  189. }
  190. return;
  191. }
  192. if (ev.proto) {
  193. if (e.name === 'MessageCounterError') {
  194. // Ignore this message. It is likely a duplicate delivery
  195. // because the server lost our ack the first time.
  196. return;
  197. }
  198. var envelope = ev.proto;
  199. var message = initIncomingMessage(envelope.source, envelope.timestamp.toNumber());
  200. message.saveErrors(e).then(function() {
  201. ConversationController.findOrCreatePrivateById(message.get('conversationId')).then(function(conversation) {
  202. conversation.set({
  203. active_at: Date.now(),
  204. unreadCount: conversation.get('unreadCount') + 1
  205. });
  206. var conversation_timestamp = conversation.get('timestamp');
  207. var message_timestamp = message.get('timestamp');
  208. if (!conversation_timestamp || message_timestamp > conversation_timestamp) {
  209. conversation.set({ timestamp: message.get('sent_at') });
  210. }
  211. conversation.save();
  212. conversation.trigger('newmessage', message);
  213. conversation.notify(message);
  214. });
  215. });
  216. return;
  217. }
  218. throw e;
  219. }
  220. function onReadReceipt(ev) {
  221. var read_at = ev.timestamp;
  222. var timestamp = ev.read.timestamp;
  223. var sender = ev.read.sender;
  224. console.log('read receipt ', sender, timestamp);
  225. Whisper.ReadReceipts.add({
  226. sender : sender,
  227. timestamp : timestamp,
  228. read_at : read_at
  229. });
  230. }
  231. // lazy hack
  232. window.receipts = new Backbone.Collection();
  233. function onDeliveryReceipt(ev) {
  234. var pushMessage = ev.proto;
  235. var timestamp = pushMessage.timestamp.toNumber();
  236. console.log(
  237. 'delivery receipt from',
  238. pushMessage.source + '.' + pushMessage.sourceDevice,
  239. timestamp
  240. );
  241. Whisper.DeliveryReceipts.add({
  242. timestamp: timestamp, source: pushMessage.source
  243. });
  244. }
  245. })();