As a chrome packaged app, we have to keep at least one window open in
order to maintain our websocket connection in the background page.
This change replaces the system window frame with custom buttons in the
inbox header, such that the 'close' button merely hides the window
rather than unloading it.
Fixes#237
FREEBIE
In a multi device world, it's possible to receive a receipt for a sync
message before the sync message actually arrives. In this case we need
to keep the receipt around and the process it when the message shows up.
My current version of chromium inexplicably exposes a crippled version
of chrome.browserAction even though we are now a packaged app and should
not have that functionality exposed to us anymore. This results in some
errors to the tune of "property 'foo' of undefined".
It also doesn't support the innerBounds property for window creation,
only the older (deprecated) bounds property.
Also make it accessible by providing a mode argument to the install
function. Previously developers could just edit the url but we no longer
have the address bar as an app window, so now they must close the
default installer and run the following from the background page
console: `extension.install('standalone')`.
In the production build, this should result in an error since it is not
supported / the register page is not included there.
Appify tabs, windows, browserAction
Port the extension.windows.focus function to new window api and
generalize its error handling in the case where the requested window
does not exist. An error will be passed to the callback.
Port extension.browserAction and rename it to the more generic
extension.onLaunched.
Use of the id option when opening a window ensures that attempting to
open a duplicate window merely focuses the existing window.
Finally, after registration, close the options window and open the
inbox.
Port extension.remove
Add window.storage to the background page, which loads all data from the
'items' store in indexeddb, caching them in memory for synchronous
access, then override textsecure storage to use that in memory store.
Storing multiple sessions in a single indexeddb record is prone to
clobbering data due to races between requests to update multiple device
sessions for the same number, since you have to read the current state
of the device->session map and update it. Splitting the records up makes
it so that those updates can be made in parallel. Selecting all the
sessions for a given number can still be done efficiently thanks to
indexeddb range queries.
* Session records are now opaque strings, so treat them that way:
- no more cross checking identity key and session records
- Move hasOpenSession to axolotl wrapper
- Remote registration ids must be fetched async'ly via protocol wrapper
* Implement async AxolotlStore using textsecure.storage
* Add some db stores and move prekeys and signed keys to indexeddb
* Add storage tests
* Rename identityKey storage key from libaxolotl25519KeyidentityKey to
simply identityKey, since it's no longer hardcoded in libaxolotl
* Rework registration and key-generation, keeping logic in libtextsecure
and rendering in options.js.
* Remove key_worker since workers are handled at the libaxolotl level
now
Encapsulate the websocket resources and socket setup process in a
friendly OO class. The MessageReceiver constructor expects an instance
of EventTarget on which to fire message events asynchronously. The
provider of the EventTarget can then add/remove listeners as desired.
Ground work for a smoother registration flow. Overall UX still needs
some polish but at least now we can have a progress gif or animation or
whatever. Also adds the phonenumber-confirmation step as a simple alert
box, which will be replaced with a nice dialogue in a later commit.
Creating a group with a member who's identity key has changed would
previously fail silently. Now, we catch and save the error, allowing the
same conflict resolution process as with regular messages.
Fixes#205
Previously there was a long pause between confirming the group details
and opening the conversation. Fix by first saving/opening the
conversation, rather than waiting for the initial group update to finish
transmitting.
This reverts commit 31e7d285e3.
This seemed like a nice feature, but the popup bubble isn't very
conducive to nontrivial user inputs, e.g. file inputs.
Fixes#211
Clicking on a key conflict message opens the message detail view,
which displays the contact(s) in this conversation. If the message
contains a key conflict with any of these contacts, a button is
displayed which attempts to resolve that conflict and any other
conflicts in the conversation that are related to that contact.
We'd like to live in a world where we can retry all the pending
conflicts in a conversation as a batch, which means we don't want to
wipe the identity key before processing each message. Thus, remove that
step from these handlers and encapsulate in a method on the conversation
model.
Ensure that both tryAgain functions return promises, allowing the
application to take appropriate action in the result of success or
failure. This lets us remove all dependency from libtextsecure on
app-level constructs like message objects/ids and the `extenion.trigger`
function.
Corresponding frontend changes to follow in another commit.
1. Return the value returned by the registered function, to expose the
underlying promise to the caller.
2. Stop accepting extra arguments to the replay function. The caller
should be able to do what they want with the returned promise instead.
3. Add a timestamp argument to the outgoing case, needed to re-try
sending a message.
Rather than opening the inbox in its own window, let it appear as a
browser action popup by default, but allow promotion to its own window
if requested.
Let libaxolotl throw a generic error instead of a replayable error, and
add an helper function in libtextsecure's axolotl_wrapper to catch and
convert from the generic error to the replayable one. This allows the
ReplayableError to remain a libtextsecure-level concept only.
Somewhat unrelatedly, but nearby, fix some whitespace and add missing
semicolon.
`emoji.init_colons` creates and populates `emoji.map.colons`, a global
map from common names to emoji code points. It's safe to call
repeatedly, but unecessary.
Now with actual malloc/free implementations. Had to drop back to -O1
optimization because the ed25519 signature test broke with -O2. :(
Closes#153
The toolchain install and build process, for reference:
```
wget https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz
tar xvfz emsdk-portable.tar.gz
cd emsdk-portable
./emsdk update
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh
cd ../TextSecure-Browser
grunt build
```
I had some trouble with the registration..
Quickly checked TextSecure Server API and found the problems:
number has to be valid PSTN. (Including regionCode, precisely what validateNumber() returns)
verificationCode has to be all numbers, no dashes or spaces
Closes#193
Update unreadCounts per-conversation on incoming messages. Render unread
conversations with font-weigh: bold in the inbox view.
To ensure that the inbox and conversation views remain in sync, the
background page now ensures that the same models objects are used for
both views.
Turns out we can get ABNORMAL_CODE (1006) for disconnects where (for
instance) we pause the background page too long. However, in these cases
there is no preceeding ErrorEvent. In contrast, when we have bad
authentication credentials, there is an ErrorEvent. Thus, this change
ensures that we only reconnect if there was no Error.