Compare commits

..

524 Commits

Author SHA1 Message Date
akwizgran
33bfef12e4 WIP: Store descriptor in metadata so invite can be deleted. 2018-11-27 12:44:45 +00:00
akwizgran
92163d6a99 WIP: Test effect of deleting private messages on delivery. 2018-11-27 10:07:16 +00:00
Torsten Grote
c09abdb088 Merge branch 'location-permission-sdk-23' into 'master'
Change location permission to uses-permission-sdk-23

See merge request briar/briar!1001
2018-11-22 12:03:07 +00:00
akwizgran
45a11badd5 Change location permission to uses-permission-sdk-23. 2018-11-20 16:16:47 +00:00
akwizgran
fbf8642edb Merge branch '1464-message-status-mixed' into 'master'
[core] fix wrong order of message status flags in conversation headers

Closes #1464

See merge request briar/briar!998
2018-11-16 13:44:39 +00:00
Torsten Grote
ade6a14342 Merge branch 'validation-refactoring' into 'master'
Reorganise validation code

See merge request briar/briar!991
2018-11-15 17:18:15 +00:00
Torsten Grote
d500ff81c3 Merge branch 'require-non-null' into 'master'
Add static requireNonNull() method

See merge request briar/briar!996
2018-11-15 16:50:16 +00:00
Torsten Grote
3053e3cfa7 [core] fix wrong order of message status flags in conversation headers 2018-11-15 14:39:05 -02:00
akwizgran
6964a67ca3 Add static requireNonNull() method. 2018-11-15 11:13:15 +00:00
Torsten Grote
f4b06e1fb3 Merge branch 'load-latest-message-eagerly' into 'master'
Load latest message eagerly

See merge request briar/briar!995
2018-11-14 16:01:59 +00:00
akwizgran
4db075d643 Only consider the latest item for preloading. 2018-11-14 15:13:25 +00:00
akwizgran
78a8ae6b8e Sort headers and eagerly load text of latest message. 2018-11-14 15:01:54 +00:00
Torsten Grote
7866037d02 Merge branch '1460-introduction-request-text' into 'master'
Show correct text when an existing contact is introduced

Closes #1460

See merge request briar/briar!994
2018-11-14 11:23:26 +00:00
akwizgran
35716051fb Show correct text when an existing contact is introduced. 2018-11-14 11:05:46 +00:00
Torsten Grote
6cafea836f Merge branch 'eager-singletons' into 'master'
Singletons that call registration methods must be eager

See merge request briar/briar!993
2018-11-13 18:03:28 +00:00
akwizgran
bd0fd229c6 Merge branch '1242-attachment-input-stream' into 'master'
Attachments will use InputStream rather than ByteBuffer

See merge request briar/briar!992
2018-11-13 17:41:39 +00:00
akwizgran
ea05a5c703 Singletons that call registration methods must be eager. 2018-11-13 17:40:06 +00:00
akwizgran
4103eaf639 Reorganise validation code (no functional changes). 2018-11-13 17:16:47 +00:00
Torsten Grote
753a25bc2a [core] Attachments will use InputStream rather than ByteBuffer 2018-11-13 15:12:34 -02:00
akwizgran
8f4c3c4528 Bump version numbers for 1.1.5 release. 2018-11-13 13:01:01 +00:00
akwizgran
636a7dfe72 Update translations. 2018-11-13 12:59:51 +00:00
akwizgran
08e99edd42 Merge branch 'unpack-tor-binaries' into 'master'
Always unpack and include latest Tor binaries

See merge request briar/briar!987
2018-11-13 12:56:47 +00:00
akwizgran
e28bc475df Merge branch '1242-optional-message-text' into 'master'
Add support for private messages without text

See merge request briar/briar!990
2018-11-13 10:47:52 +00:00
Torsten Grote
88276a4d44 Add support for private messages without text 2018-11-12 18:11:03 -02:00
akwizgran
f9987c89df Merge branch 'disable-tor-connection-padding' into 'master'
Disable Tor's connection padding

See merge request briar/briar!989
2018-11-12 14:03:22 +00:00
Torsten Grote
2c8cb8301f Merge branch '1455-stream-context-may-be-null' into 'master'
Stream context may be null

Closes #1455

See merge request briar/briar!988
2018-11-12 12:50:01 +00:00
akwizgran
c00ee80f0f Update test expectations. 2018-11-12 12:20:04 +00:00
akwizgran
3bfedfdc3d Add action for nullable DB callables. 2018-11-12 12:16:42 +00:00
akwizgran
ecb63d1acb Add interface for DB tasks will nullable results. 2018-11-12 12:13:26 +00:00
akwizgran
b24914408d Stream context may be null. 2018-11-12 11:31:59 +00:00
akwizgran
5ede63edd5 Always unpack and include latest Tor binaries. 2018-11-08 17:48:26 +00:00
akwizgran
4e523c5fbc Merge branch '1242-display-image-attachments' into 'master'
[android] refactor conversation items and view holders

See merge request briar/briar!984
2018-11-08 16:08:58 +00:00
akwizgran
cf79ed5633 IntentFilter may not be thread-safe. 2018-11-08 14:54:53 +00:00
akwizgran
0a0a6a6369 Disable Tor's connection padding on mobile data or battery. 2018-11-08 14:50:36 +00:00
akwizgran
4784980e7b No need to broadcast network status at startup. 2018-11-08 14:50:36 +00:00
akwizgran
3bfa5e2081 [android] Move ConversationListener to top level. 2018-11-08 10:27:36 -02:00
akwizgran
f2b09deac4 [android] Remove type parameter from view holders. 2018-11-08 10:27:29 -02:00
Torsten Grote
ad4729b2f9 [android] refactor conversation items and view holders
This is a preparation for image support.
2018-11-08 10:27:29 -02:00
akwizgran
50cc0a6815 Merge branch '1452-websocket-authentication' into 'master'
[headless] change websocket authentication from basic auth to token message

Closes #1452

See merge request briar/briar!986
2018-11-08 12:26:53 +00:00
Torsten Grote
32c8ac6576 [headless] change websocket authentication from basic auth to token message 2018-11-08 10:15:17 -02:00
akwizgran
c12422d949 Merge branch '1434-android-conversation-package' into 'master'
Move conversation classes into their own package

See merge request briar/briar!978
2018-11-08 11:01:36 +00:00
akwizgran
3841713c18 Merge branch 'upgrade_roboletric_to_401' into 'master'
Upgrade robolectric to 4.0.1

See merge request briar/briar!980
2018-11-08 11:00:08 +00:00
akwizgran
79232eb558 Merge branch 'headless-fixes' into 'master'
Headless fixes

See merge request briar/briar!985
2018-11-08 10:55:28 +00:00
Torsten Grote
d02b30e751 Merge branch 'use-transactional-db-api' into 'master'
Use transactional database API in Bramble

See merge request briar/briar!974
2018-11-07 19:06:26 +00:00
akwizgran
043662a092 Code cleanup. 2018-11-07 18:31:07 +00:00
Torsten Grote
efc85fb88f [headless] don't use putAll for a single field 2018-11-07 15:24:20 -03:00
Torsten Grote
8b3983ef9e [headless] only offload to DatabaseExecutor when needed
when receiving a new conversation message
2018-11-07 15:24:20 -03:00
Torsten Grote
6766fb76b2 [headless] upgrade javalin and mockk 2018-11-07 15:18:46 -03:00
Torsten Grote
7f74bd1c38 [headless] Use --user for websocket example request
The authentication token can contain slashes.
When used as part of the URL, the URL becomes invalid.
Therefore, using curl's user parameter is preferrable.
2018-11-07 15:18:46 -03:00
akwizgran
951ee30b95 Update tests. 2018-11-07 18:18:30 +00:00
akwizgran
c386a0f5eb Replace Maybe with nullable transaction method. 2018-11-07 18:18:30 +00:00
akwizgran
52c778dce3 Reformat code. 2018-11-07 18:18:27 +00:00
akwizgran
e846a13f50 Use transactional database API in Bramble. 2018-11-07 18:14:10 +00:00
akwizgran
23e9b119d1 Merge branch '1434-message-attachments' into 'master'
Add attachment API for sending/retreiving private messages

See merge request briar/briar!976
2018-11-07 18:08:36 +00:00
akwizgran
e6f380296f Merge branch '1451-briar-headless-test-other-modules' into 'master'
[headless] Limit tests in Android Studio to headless package

Closes #1451

See merge request briar/briar!983
2018-11-07 17:47:37 +00:00
Torsten Grote
794fb9686b [headless] Limit tests in Android Studio to headless package 2018-11-07 13:46:49 -03:00
Torsten Grote
bb22b9db10 Merge branch 'remove-hamcrest-dependencies' into 'master'
Remove redundant dependency declarations

See merge request briar/briar!981
2018-11-07 16:37:30 +00:00
Julian Dehm
d4f015d054 Upgrade robolectric to 4.0.1 2018-11-07 17:11:21 +01:00
akwizgran
41e5d8900c Remove redundant dependency declarations. 2018-11-07 16:10:39 +00:00
Torsten Grote
c3cb966009 [android] move conversation classes into their own package 2018-11-07 11:48:20 -03:00
Torsten Grote
f964d1ef07 Fix receivers of ConversationMessageReceivedEvent
These were only listening to private message events, ignoring all others
2018-11-07 11:34:11 -03:00
Torsten Grote
cccaeeda6c [core] Add API to add messages with attachments 2018-11-07 11:34:11 -03:00
Torsten Grote
483106e00c [core] Add MessagingManager#getAttachment() 2018-11-07 11:34:11 -03:00
Torsten Grote
934f14ef31 [core] Add attachment support to private messages 2018-11-07 11:34:09 -03:00
Torsten Grote
e3abff5ad8 Refactor PrivateMessageHeader to ConversationMessageHeader base-class
This is preparation for adding attachments to private messages
2018-11-07 11:33:37 -03:00
Torsten Grote
391732b239 Merge branch 'change-contact-name' into 'master'
Change button text to match name of action

See merge request briar/briar!979
2018-11-07 12:11:22 +00:00
akwizgran
4738bfdd85 Ignore missing translations. 2018-11-07 10:43:13 +00:00
akwizgran
be1ca89309 Change button text to match name of action. 2018-11-07 10:40:59 +00:00
Torsten Grote
866be99179 Merge branch '41-alias-frontend' into 'master'
Add UI for changing contact aliases

Closes #41

See merge request briar/briar!965
2018-11-06 18:09:47 +00:00
akwizgran
48822e2133 Merge branch '1381-introduction-test-fails' into 'master'
Fix non-determinism of Introduction integration tests

Closes #1381

See merge request briar/briar!970
2018-11-06 18:00:48 +00:00
Torsten Grote
6883c5caa9 [android] address last contact aliases review issues 2018-11-06 14:57:39 -03:00
Torsten Grote
8b709969ab [android] pass ContactId via ViewModel to AliasDialogFragment 2018-11-06 13:42:51 -03:00
Torsten Grote
fe94b65b3b [android] Fix double loading of conversation messages when rotating screen 2018-11-06 13:42:51 -03:00
akwizgran
f54df1d787 Reduce visibility, remove unnecessary rethrow. 2018-11-06 13:42:51 -03:00
akwizgran
a7e826ccf5 Remove qualification from java.lang.Runnable. 2018-11-06 13:42:51 -03:00
akwizgran
845eb3262b Use expression lambda. 2018-11-06 13:42:51 -03:00
akwizgran
0a46ad439f Check whether activity is null. 2018-11-06 13:42:51 -03:00
akwizgran
d14d93ea35 Require observed data to be non-null. 2018-11-06 13:42:51 -03:00
akwizgran
12a1cf8f8b Reuse Observer interface. 2018-11-06 13:42:51 -03:00
akwizgran
fb2ab861db Fix some lint warnings. 2018-11-06 13:42:51 -03:00
Torsten Grote
aa15b68d24 [android] Reload conversation when contact name changes 2018-11-06 13:42:51 -03:00
Torsten Grote
7059f376f1 [android] Add UI for changing contact alias
This introduces the first ViewModel to share state between the
ConversationActivity and the AliasDialogFragment.
2018-11-06 13:42:51 -03:00
akwizgran
9313c191c1 Merge branch 'ui-fixes' into 'master'
Small UI fixes

See merge request briar/briar!975
2018-11-05 10:40:09 +00:00
akwizgran
7746364ae9 Merge branch '1437-reversed-emoji' into 'master'
[android] Add new emojis to the beginning of the list of recently used ones

Closes #1437

See merge request briar/briar!977
2018-11-05 10:27:03 +00:00
Torsten Grote
7429857b28 [android] Add new emojis to the beginning of the list of recently used ones
Otherwise the list will be reversed with most recently used at the end.
2018-11-04 11:08:05 -03:00
Torsten Grote
4db64f51a8 [android] Use same color for all messages in private groups 2018-11-02 15:59:49 -03:00
Torsten Grote
78172038ef [android] Always center selectable contacts vertically 2018-11-02 15:38:01 -03:00
Torsten Grote
7d0c418877 [android] Align short incoming messages on the left 2018-11-02 15:37:16 -03:00
Torsten Grote
5ae4f8f6cb [core] Fix non-determism in GroupInvitationIntegrationTest 2018-11-02 14:08:42 -03:00
Torsten Grote
45dd10db9d [core] Fix non-determinism in introduction integration tests 2018-11-02 14:08:42 -03:00
Torsten Grote
5cc8c268ca [core] Re-add message counter and put debug output behind flag 2018-11-02 14:08:42 -03:00
akwizgran
93a6bf2f52 Add logging to debug test failures. 2018-11-02 12:48:23 -03:00
akwizgran
852dd46a1b Utility class for converting BDF to strings.
(cherry picked from commit 9e94917)
2018-11-02 12:48:23 -03:00
Torsten Grote
4a42e767d3 [core] Add a detector for message delivery non-determinism 2018-11-02 12:48:13 -03:00
akwizgran
8547b4dc91 Merge branch 'upgrade-dagger' into 'master'
Upgrade dagger

See merge request briar/briar!973
2018-11-01 14:17:35 +00:00
akwizgran
f6c8a8cec7 Move dagger.gradle to project root. 2018-11-01 14:05:46 +00:00
Torsten Grote
db8796049e gradle: Factor out dagger apt code into its own file 2018-11-01 10:45:59 -03:00
Torsten Grote
e1f31ad381 Remove gradle-apt-plugin since it isn't stricly needed anymore
Reference: 6b2ee87fbf/README.md
2018-10-31 16:01:57 -03:00
Torsten Grote
3a15e47ddd Upgrade Dagger to latest version 2018-10-31 15:57:21 -03:00
Torsten Grote
cf616905d6 Merge branch 'introduction-manager-skip-session-parsing' into 'master'
Avoid some unnecessary session parsing when retrieving introduction messages

See merge request briar/briar!972
2018-10-31 16:36:59 +00:00
akwizgran
d3f774f339 Avoid some unnecessary session parsing. 2018-10-31 16:18:33 +00:00
akwizgran
6c7c488892 Merge branch '41-alias-frontend-base' into 'master'
[android] Show contact aliases in UI

See merge request briar/briar!971
2018-10-31 16:16:38 +00:00
Torsten Grote
3fe7aae97e Contact aliases: address review comments 2018-10-31 13:06:19 -03:00
Torsten Grote
ecf417c93b [android] Show contact alias in remaining places 2018-10-31 13:06:19 -03:00
Torsten Grote
c1785c5b13 [android] Show contact alias in contact lists 2018-10-31 13:06:19 -03:00
Torsten Grote
fb2c321a3d [android] Show contact alias inside private groups and their memberlist 2018-10-31 13:06:19 -03:00
Torsten Grote
6e3adc0874 Show alias for introduction notices in private conversation 2018-10-31 13:06:19 -03:00
Torsten Grote
cdbe2a00f5 [android] Show alias for creator of private group in list of private groups 2018-10-31 11:40:17 -03:00
Torsten Grote
a51dc7e0d5 [android] Show Author alias in AuthorView 2018-10-31 11:40:15 -03:00
Torsten Grote
0ee7465429 Merge branch '41-alias-author-info' into 'master'
Refactor Author.Status into dedicated AuthorInfo class and add alias

See merge request briar/briar!968
2018-10-30 19:33:39 +00:00
Torsten Grote
7c202189a2 [bramble] Implement equals() and hashCode() for AuthorView 2018-10-30 15:21:09 -03:00
akwizgran
da3b2c1591 Merge branch '41-alias-backend' into 'master'
Add backend support for contact aliases

See merge request briar/briar!963
2018-10-30 16:43:52 +00:00
Torsten Grote
6c5e8ce4cf Rename remaining occurrences of status to authorInfo 2018-10-30 13:40:04 -03:00
Torsten Grote
ca700d8d23 [bramble] address review comments 2018-10-30 13:32:56 -03:00
akwizgran
db11dad61e Merge branch 'clean-tor-binaries' into 'master'
Delete Tor binaries when cleaning

See merge request briar/briar!969
2018-10-30 13:59:21 +00:00
akwizgran
69e7366226 Merge branch '1433-illegal-characters' into 'master'
Handle illegal byte sequences safely in BdfReaderImpl

Closes #1433

See merge request briar/briar!967
2018-10-30 13:58:36 +00:00
akwizgran
90b7b4e67f Merge branch '1416-obfs4' into 'master'
Add obfs4proxy and switch to obfs4 bridges

Closes #1417

See merge request briar/briar!964
2018-10-30 13:58:13 +00:00
akwizgran
d29812a42b Delete Tor binaries when cleaning. 2018-10-30 13:06:06 +00:00
Torsten Grote
baf64e1129 [bramble] Add transactionless method for retrieving AuthorInfo to ContactManager 2018-10-29 18:16:34 -03:00
Torsten Grote
88adfabe09 Refactor Author.Status into dedicated AuthorInfo class and add alias 2018-10-29 17:23:45 -03:00
akwizgran
6565172e10 Bump version numbers for 1.1.4 release. 2018-10-29 17:31:09 +00:00
akwizgran
7447468ce5 Update translations. 2018-10-29 17:30:04 +00:00
akwizgran
2db2a1a208 Replace a slow bridge with a faster one. 2018-10-29 17:25:12 +00:00
akwizgran
0d7e4feaf2 Throw AssertionError to make intent clearer. 2018-10-29 17:02:07 +00:00
akwizgran
eb3983f6b2 Use safe ASCII decoding in ModemImpl. 2018-10-29 16:48:18 +00:00
akwizgran
e2ce49c30e Use safe UTF-8 decoding in BdfReaderImpl. 2018-10-29 16:47:55 +00:00
akwizgran
adc6fb2fd5 Add fuzzing test for illegal UTF-8 byte sequences. 2018-10-29 16:44:02 +00:00
Torsten Grote
969150bff0 [bramble] Factor out database type placeholder replacement
to make it available in database schema migrations
2018-10-29 12:50:08 -03:00
Torsten Grote
8fc622f85d [bramble] Add support for contact aliases
Foundation for #41
2018-10-29 12:50:08 -03:00
akwizgran
22eed91019 Merge branch 'javalin-access-manager' into 'master'
[headless] Set up access manager before starting server

See merge request briar/briar!966
2018-10-29 15:35:48 +00:00
akwizgran
fcb88ed58c Merge branch '1147-bluetooth-discovery' into 'master'
Support Bluetooth discovery for adding contacts

See merge request briar/briar!954
2018-10-29 14:35:17 +00:00
Torsten Grote
0d940fc7d7 [headless] Set up access manager before starting server
This became necesary to due an upstream change we missed when bumping
the dependency:

ab19ff91b7
2018-10-29 11:20:48 -03:00
Torsten Grote
ca6dc33cdd Add obfs4 proxy and switch to obfs4 bridges 2018-10-25 09:38:44 -03:00
akwizgran
53da13794f Merge branch '1422-activity-log' into 'master'
Log when activities start and stop

See merge request briar/briar!959
2018-10-24 16:00:52 +00:00
akwizgran
2ab03f48cc Merge branch '1256-remove-contact' into 'master'
briar-headless: Add endpoint for removing a contact

See merge request briar/briar!962
2018-10-24 15:59:39 +00:00
Torsten Grote
436f45554d [briar-headless] update dependencies 2018-10-24 12:41:29 -03:00
Torsten Grote
51209b5eec briar-headless: Add endpoint for removing a contact 2018-10-24 12:12:33 -03:00
akwizgran
822597b4c6 Merge branch '1373-mirror-icons' into 'master'
Fix RTL icon mirroring in DevReportActivity

Closes #1373

See merge request briar/briar!960
2018-10-24 14:05:06 +00:00
akwizgran
7c01bc59c0 Merge branch '1252-dark-theme-system-default' into 'master'
Remove system default theme option on API < 28

Closes #1252

See merge request briar/briar!961
2018-10-24 13:52:20 +00:00
Torsten Grote
825d342f9b Remove system default theme option on API < 27
Closes #1252
2018-10-24 10:40:43 -03:00
Torsten Grote
34955fecbb Fix RTL icon mirroring in DevReportActivity
For some reason, the toolbar icon has a wrong layout direction,
so the autoMirrored attribute doesn't take any effect.
2018-10-22 16:53:17 -03:00
Torsten Grote
5c28b60a6b Log when activities start and stop
Remove BriarRecyclerView log messages
2018-10-22 14:11:36 -03:00
akwizgran
389b2b5b8e Merge branch '1423-check-lifecycle-state' into 'master'
Check lifecycle state before changing fragment

Closes #1423

See merge request briar/briar!958
2018-10-22 14:27:30 +00:00
Torsten Grote
78abfa3698 Check lifecycle state before changing fragment 2018-10-19 16:40:00 -03:00
akwizgran
9c4fb4fd34 Remove unused string. 2018-10-18 17:22:54 +01:00
akwizgran
3d6a336f6d Refactor permissions code, add comments, fix corner cases. 2018-10-18 17:16:49 +01:00
akwizgran
e47d41596a Merge branch '1254-inject-object-mapper' into 'master'
briar-headless: Inject a singleton ObjectMapper for JSON parsing

See merge request briar/briar!957
2018-10-18 15:40:20 +00:00
Torsten Grote
8cf54bcedb briar-headless: Inject a singleton ObjectMapper for JSON parsing 2018-10-18 09:55:34 -03:00
akwizgran
89d5145665 Bump version numbers for 1.1.3 release. 2018-10-17 17:51:11 +01:00
Torsten Grote
0706498b03 Merge branch 'upgrade-android-gradle-plugin' into 'master'
Upgrade Android Gradle plugin to 3.2.1.

See merge request briar/briar!956
2018-10-17 16:36:24 +00:00
akwizgran
b296500e7a Update translations. 2018-10-17 12:41:24 +01:00
akwizgran
60a8b03344 Upgrade Android Gradle plugin to 3.2.1. 2018-10-17 12:34:13 +01:00
Torsten Grote
ae16a93522 Merge branch 'compact-at-startup' into 'master'
Compact the database at startup

See merge request briar/briar!955
2018-10-16 16:02:40 +00:00
Torsten Grote
c9a2ff71ae Merge branch 'tor-v3-hidden-service-addresses' into 'master'
Add support for v3 hidden service addresses

See merge request briar/briar!952
2018-10-16 15:55:34 +00:00
akwizgran
16f4c60a56 Add test for compaction time. 2018-10-16 11:39:06 +01:00
akwizgran
76121eb871 Always compact the DB if migrations have been applied. 2018-10-16 11:24:47 +01:00
akwizgran
47c91a96ae Compact the database at startup. 2018-10-16 11:13:37 +01:00
akwizgran
14befb957b Add support for v3 hidden service addresses. 2018-10-16 10:15:18 +01:00
akwizgran
4b7a81177c Static imports. 2018-10-15 14:46:40 +01:00
Torsten Grote
b464fe1653 Merge branch 'message-terminology' into 'master'
Use "text" to refer to message text

See merge request briar/briar!948
2018-10-15 13:22:31 +00:00
akwizgran
09c6f09805 Merge branch '1420-tor-status-update' into 'master'
Disable TorPlugin before applying changed settings

Closes #1420

See merge request briar/briar!953
2018-10-15 12:54:41 +00:00
Torsten Grote
a93093182d Disable TorPlugin before applying changed settings
The is necessary for two reasons:

1. Since Tor 0.3.4.8, it doesn't reconnect when changing the value of
   UseBridges via the control connection without also resetting
   DisableNetwork
2. The TorPlugin needs to set itself to a disconnected state for the UI
   to properly reflect this new state

Fixes #1420
2018-10-15 09:43:12 -03:00
akwizgran
9515e93857 Cancel discovery after 10 seconds and try to connect. 2018-10-15 11:04:46 +01:00
akwizgran
efe15df940 Remove static import of R's fields. 2018-10-15 11:04:46 +01:00
akwizgran
de611857cf Discover BT devices if no address is provided. 2018-10-15 11:04:46 +01:00
akwizgran
8935ec2c2e Don't wait for state change if BT is already discoverable. 2018-10-15 11:04:45 +01:00
akwizgran
bd00fb1c04 Ask for coarse location permission before adding a contact. 2018-10-15 11:04:45 +01:00
akwizgran
3192015cfd Ask for Bluetooth discoverability before adding a contact. 2018-10-15 11:04:45 +01:00
Torsten Grote
e776ee02b0 Merge branch 'tor-0.3.4.8' into 'master'
Upgrade Tor to 0.3.4.8

See merge request briar/briar!951
2018-10-11 22:44:45 +00:00
akwizgran
c0553ec11f Upgrade Linux Tor binaries to 0.3.4.8. 2018-10-11 15:05:39 +01:00
akwizgran
75a871a2f8 Upgrade Android Tor binaries to 0.3.4.8. 2018-10-11 14:38:18 +01:00
akwizgran
d6d3d5acef Merge branch '1240-no-empty-messages' into 'master'
Don't allow empty message bodies

See merge request briar/briar!949
2018-10-10 14:52:34 +00:00
Torsten Grote
a361a2613c Merge branch 'test-configurations' into 'master'
Update test configurations for Android Studio 3.2

See merge request briar/briar!950
2018-10-10 12:38:19 +00:00
akwizgran
b68dbd6a75 Merge branch 'upgrade-dependencies' into 'master'
Upgrade some of the things

See merge request briar/briar!935
2018-10-10 11:42:45 +00:00
akwizgran
f1e89a3ff4 Don't allow empty message bodies. 2018-10-10 10:57:41 +01:00
akwizgran
056c23167d Update test configurations for Android Studio 3.2. 2018-10-10 10:43:07 +01:00
akwizgran
79d5612645 Use "text" to refer to message text. 2018-10-10 10:40:30 +01:00
akwizgran
a030f92275 Merge branch 'headless' into 'master'
Add Briar headless client that exposes a REST API

See merge request briar/briar!931
2018-10-09 15:43:31 +00:00
Torsten Grote
b3615b4a77 briar-headless: Last round of review comments 2018-10-09 12:19:21 -03:00
akwizgran
8a15fb242a Merge branch 'briar-integration-test-transaction' into 'master'
Remove custom DB transaction code from BriarIntegrationTest

See merge request briar/briar!946
2018-10-09 14:16:23 +00:00
Torsten Grote
e3686186ee Fix closing server with ^C 2018-10-08 18:40:21 -03:00
akwizgran
18ae388137 Merge branch '1395-low-memory-crash' into 'master'
Don't use non-AppCompat theme for AppCompat activities

Closes #1395

See merge request briar/briar!947
2018-10-08 12:03:20 +00:00
Torsten Grote
775031e893 Don't use non-AppCompat theme for AppCompat activities
Fixes #1395
2018-10-05 16:50:11 -03:00
Torsten Grote
9f91b91a4f Remove custom DB transaction code from BriarIntegrationTest 2018-10-05 15:41:29 -03:00
Torsten Grote
280f3ba1fc briar-headless: POST text as JSON in body instead of form parameter 2018-10-05 15:23:31 -03:00
Torsten Grote
66619fd3a4 briar-headless: Next round of review comments 2018-10-05 15:23:31 -03:00
akwizgran
c7eb0cbb6d Include body of private request if present. 2018-10-05 15:23:31 -03:00
akwizgran
1617a95bb9 Only include "body" for headers that can have bodies. 2018-10-05 15:23:31 -03:00
Torsten Grote
6f54718756 Use short type labels in JSON API instead of long Java-like namespaces 2018-10-05 15:23:31 -03:00
Torsten Grote
ea749f2128 Minor improvements to JsonDict output classes 2018-10-05 15:23:31 -03:00
akwizgran
b4b0d3daa6 Allow null values in JsonDict. 2018-10-05 15:23:31 -03:00
akwizgran
609c90f57e Convert Map#put() to assignment. 2018-10-05 15:23:31 -03:00
akwizgran
5cf68fa134 Use JsonDict for blog post headers. 2018-10-05 15:23:31 -03:00
akwizgran
61c9c6b8eb Add visitor to dispatch output() dynamically. 2018-10-05 15:23:31 -03:00
akwizgran
e97608da40 Add test to show that static dispatch won't work. 2018-10-05 15:23:31 -03:00
akwizgran
0bb80b1a15 Add JsonDict class for JSON output. 2018-10-05 15:23:31 -03:00
akwizgran
bda52ea548 Use maps for JSON output. 2018-10-05 15:23:31 -03:00
Torsten Grote
cf033dc29d briar-headless: Address second round of review comments 2018-10-05 15:23:31 -03:00
Torsten Grote
c12cedc371 briar-headless: Address first round of review comments 2018-10-05 15:23:31 -03:00
Torsten Grote
4b5e9bd64f Ensure the use SecureRandom when creating authentication token 2018-10-05 15:23:31 -03:00
Torsten Grote
8d55911dab Add unit test for WebSocketController
Also move the controller into an event package
2018-10-05 15:23:31 -03:00
Torsten Grote
e381f83512 Last code cleanup before submitting merge request 2018-10-05 15:23:31 -03:00
Torsten Grote
e4c7f13832 Add a README.md with API documentation
Also fix some smaller issues found during writing the documentation
2018-10-05 15:23:31 -03:00
Torsten Grote
b089a204d3 Add support for websocket authentication via basic auth
The token should be used as username and the password left empty
2018-10-05 15:23:31 -03:00
Torsten Grote
85fcb34997 Add briar-headless Android Studio run configuration 2018-10-05 15:23:31 -03:00
Torsten Grote
d6d132a9cf Add Bearer Authentication to REST API 2018-10-05 15:23:31 -03:00
Torsten Grote
98d1ea7730 briar-headless: Add more controller tests
Current controller line coverage: 100%
2018-10-05 15:23:31 -03:00
Torsten Grote
159fd34c0c Use Conversation Manager for message retrieval 2018-10-05 15:23:31 -03:00
Torsten Grote
9e7a387ea4 Turn output classes into Kotlin data classes 2018-10-05 15:23:31 -03:00
Torsten Grote
138e520e6c briar-headless: Add command line arguments 2018-10-05 15:23:31 -03:00
Torsten Grote
5783c1dfd8 briar-headless: Add a websocket controller for private message events
Also version API URLs
2018-10-05 15:23:31 -03:00
Torsten Grote
348968018a Migrate REST classes to Kotlin and upgrade Javalin 2018-10-05 15:23:31 -03:00
Torsten Grote
33c509cd1f briar-headless: Add Kotlin and first unit test for blogs with Mockk 2018-10-05 15:23:31 -03:00
Torsten Grote
bea77151bd briar-headless: Add API to list all contacts 2018-10-05 15:23:31 -03:00
Torsten Grote
787e62345f Add simple MessagingController 2018-10-05 15:23:31 -03:00
Torsten Grote
48f6a3b91f Add Tor plugin to headless client and introduce new ConfigurationManager 2018-10-05 15:23:31 -03:00
Torsten Grote
a798e25bf2 Save app data always in $HOME/.briar for now 2018-10-05 15:23:31 -03:00
Torsten Grote
31e4045cf7 Try to shutdown cleanly when server stops or SIGINT is received 2018-10-05 15:23:31 -03:00
Torsten Grote
5334a8c9ca Add basic support for listing and writing blog posts 2018-10-05 15:23:31 -03:00
Torsten Grote
d11f1d2805 Add a poor man's argument to explicitly turn on verbose logging 2018-10-05 15:23:31 -03:00
Torsten Grote
0d1ebddcd2 Allow account creation and reading password from STDIN 2018-10-05 15:23:31 -03:00
Torsten Grote
6c296c1348 Proof-of-Concept Headless Client 2018-10-05 15:23:31 -03:00
akwizgran
87701e5f07 Merge branch 'transactional-db' into 'master'
Transactional DB interface

See merge request briar/briar!945
2018-10-05 15:19:40 +00:00
Torsten Grote
3aae01d152 Merge branch 'panic-app-list' into 'master'
Update list of panic button apps after installing app

Closes #1392

See merge request briar/briar!940
2018-10-05 14:18:44 +00:00
akwizgran
bc298ba68a Remove unnecessary final modifiers. 2018-10-05 09:34:41 +01:00
akwizgran
2623eaa149 Remove unnecessary throwing variants. 2018-10-05 09:32:01 +01:00
akwizgran
7359b6942a Use transactional DB interface for ForumManagerImpl. 2018-10-04 15:59:10 +01:00
akwizgran
3bcc532b4b Add transactional DB interface. 2018-10-04 15:56:21 +01:00
akwizgran
4d08c69779 Revert spurious changes to run configurations. 2018-10-03 13:08:00 +01:00
Torsten Grote
a6cd8937f7 Remove space reserved for icons from preferences
Works around https://issuetracker.google.com/issues/111907042

Might be replacable with a solution from
https://issuetracker.google.com/issues/111907042 in the future.
2018-10-03 12:58:49 +01:00
akwizgran
e8566906ef Update gradle-witness to exclude android.jar from dependencies. 2018-10-03 12:48:29 +01:00
akwizgran
929102ed60 Upgrade build tools to 28.0.3. 2018-10-03 12:48:29 +01:00
akwizgran
3b871f5932 Update ProGuard rules for new OkHttp version. 2018-10-03 12:48:29 +01:00
akwizgran
b972d1fc13 Update ACRA usage for new version. 2018-10-03 12:48:28 +01:00
akwizgran
ccbeee60a7 Upgrade Rome, OkHttp and jsoup libraries. 2018-10-03 12:48:28 +01:00
akwizgran
074b10e177 Upgrade JNA library. 2018-10-03 12:48:28 +01:00
akwizgran
031516ccce Upgrade curve25519-java library. 2018-10-03 12:48:28 +01:00
akwizgran
7d2f1abb94 Upgrade Gradle APT and Animal Sniffer plugins. 2018-10-03 12:48:28 +01:00
akwizgran
00b9c76bb8 Upgrade ACRA. 2018-10-03 12:48:28 +01:00
akwizgran
4d9fab85cb Upgrade zxing, material tap target libraries. 2018-10-03 12:48:28 +01:00
akwizgran
bd2514a299 Upgrade support library to 28.0.0. 2018-10-03 12:48:27 +01:00
akwizgran
e795efc7fc Bump compileSdkVersion for bramble-android. 2018-10-03 12:48:27 +01:00
akwizgran
6691d2164f Upgrade Gradle Android plugin and build tools. 2018-10-03 12:48:27 +01:00
Administrator
a384450c36 Merge branch '1373-format-numbers' into 'master'
Format numbers in locale as well (not all languages use the same)

See merge request briar/briar!943
2018-10-03 11:41:56 +00:00
akwizgran
b375e9873c Merge branch '1409-localize-crash-screen' into 'master'
Localize crash screen in language defined in settings

Closes #1409

See merge request briar/briar!944
2018-10-03 07:53:41 +00:00
Torsten Grote
cb30c3885a Localize crash screen in language defined in settings 2018-10-02 17:56:33 -03:00
Torsten Grote
6ee81eb24c Format numbers in locale as well (not all languages use the same)
Done according to
https://developer.android.com/training/basics/supporting-devices/languages#FormatNumbers
2018-10-02 17:31:23 -03:00
Torsten Grote
c14ebe82ce Merge branch '1365-keep-screen-on' into 'master'
Keep screen on while QR code viewfinder is open

See merge request briar/briar!942
2018-10-02 11:20:46 +00:00
Torsten Grote
00e9f894b1 Merge branch 'remove-tor-patch' into 'master'
Remove unused patches

See merge request briar/briar!941
2018-10-02 11:13:06 +00:00
akwizgran
499c586a59 Keep screen on while scanning QR code. 2018-10-02 12:03:29 +01:00
akwizgran
64f9ce7306 Remove unused patches. 2018-10-02 11:49:29 +01:00
akwizgran
39478a7914 Bump version numbers for 1.1.2 release. 2018-10-01 14:58:45 +01:00
akwizgran
112e71a9cb Bump version numbers for 1.0.2 release. 2018-10-01 14:56:08 +01:00
akwizgran
5650bef310 Update translations. 2018-10-01 14:56:08 +01:00
akwizgran
2a87171c49 Merge branch 'manual-screenshots' into 'master'
Create Screenshot of Conversation for Manual

Closes #1377

See merge request briar/briar!910
2018-10-01 13:41:05 +00:00
akwizgran
071d961ed1 Remove debug logging. 2018-09-28 11:31:22 +01:00
akwizgran
cb9efc5fec Fix lint warnings. 2018-09-28 11:28:47 +01:00
akwizgran
f9e292f734 Update panic app list after installing app. 2018-09-28 11:27:08 +01:00
akwizgran
15cb5409e7 Merge branch '1352-panic-ripple-fdroid' into 'master'
Fix Panic Button bugs

Closes #1109 and #1352

See merge request briar/briar!937
2018-09-28 09:57:18 +00:00
akwizgran
fd07dc006d Update comment. 2018-09-28 09:55:47 +01:00
akwizgran
cc87c4e37d Merge branch '1391-start-end-api15' into 'master'
RTL language layout fixes

Closes #1391

See merge request briar/briar!938
2018-09-28 08:45:17 +00:00
akwizgran
4a10e876f6 Merge branch '1389-notice-shadows' into 'master'
Fix notice shadows

Closes #1389

See merge request briar/briar!939
2018-09-28 08:43:06 +00:00
Torsten Grote
fad0057c4a Fix notice shadows 2018-09-27 20:32:13 -03:00
Torsten Grote
5aabfcea9a Unmirror checkboxes in RTL layouts 2018-09-27 19:09:08 -03:00
Torsten Grote
f7d928c774 Fix start/end margins for API 15
Fixes #1391
2018-09-27 19:07:13 -03:00
Torsten Grote
bd983d9796 Remove non-functional uninstall panic action
Fixes #1109
2018-09-27 18:37:57 -03:00
Torsten Grote
de8d1b7d96 Allow sign out by trusted non-paired panic apps 2018-09-27 18:25:31 -03:00
Torsten Grote
9155f62d0b Remove Amnesty International's key and add F-Droid Ripple key instead
Fixes #1352
2018-09-27 18:17:14 -03:00
akwizgran
86684e228a Merge branch 'slow-bridges' into 'master'
Update bridge list, test for slow bridges

See merge request briar/briar!936
2018-09-27 16:10:22 +00:00
akwizgran
9615eff649 Add new bridges to replace slow ones. 2018-09-27 16:11:52 +01:00
akwizgran
9381d46f51 Remove two bridges that are slow to bootstrap. 2018-09-27 16:08:14 +01:00
akwizgran
e4a3a1ad40 Delete Tor state after testing each bridge. 2018-09-27 16:07:46 +01:00
akwizgran
905dc2a662 Merge branch 'qr-code-version-errors' into 'master'
Show different error message if QR code is too new

See merge request briar/briar!934
2018-09-24 16:42:43 +00:00
Torsten Grote
c2b7f85b8e Remove code from TestDataCreator that breaks encapsulation 2018-09-24 12:37:11 -03:00
Torsten Grote
ae81eb3737 Throw AssertionError when creating an account while a database key is in memory 2018-09-24 12:37:11 -03:00
Torsten Grote
60d949c342 Refactor tests so that all test data is created in the first test 2018-09-24 12:37:11 -03:00
Torsten Grote
1c90e64894 Split up UI and Screenshot tests
Closes #1377
2018-09-24 12:37:06 -03:00
Torsten Grote
f0e2d5281f Create Screenshot of Conversation for Manual 2018-09-24 12:34:26 -03:00
akwizgran
c7522dae1f Show different error message if QR code is too new. 2018-09-24 13:21:45 +01:00
Torsten Grote
097d14b9a1 Merge branch 'private-message-visitor' into 'master'
Use visitor pattern to create conversation items

See merge request briar/briar!933
2018-09-20 19:04:14 +00:00
akwizgran
0491c3cace Use a visitor to create ConversationItems. 2018-09-20 16:53:48 +01:00
akwizgran
cbae13feca Merge branch 'gradle-4.10' into 'master'
Upgrade the gradle wrapper to version 4.10.2

See merge request briar/briar!932
2018-09-20 15:34:33 +00:00
Torsten Grote
b7c8859c82 Upgrade the gradle wrapper to version 4.10.2 2018-09-20 11:52:19 -03:00
akwizgran
2e120f752c Add parameterised return type. 2018-09-20 15:19:22 +01:00
akwizgran
031eac54c5 Add private message visitor. 2018-09-20 14:43:19 +01:00
akwizgran
2c2596afdd Merge branch 'conversation-manager' into 'master'
Use ConversationManager for private message retrieval

See merge request briar/briar!912
2018-09-20 13:01:53 +00:00
akwizgran
d1be14effe Merge branch '1386-app-lock-after-signout' into 'master'
Fix app lock after sign-out bug

Closes #1386

See merge request briar/briar!930
2018-09-20 11:05:37 +00:00
akwizgran
b56e7ab07d Merge branch 'roboelectric-android-http-client' into 'master'
Remove AndroidHttpClient class after Roboelectric update

See merge request briar/briar!929
2018-09-20 11:04:52 +00:00
akwizgran
089e9589ed Merge branch '1378-rtl-support' into 'master'
Add support for right-to-left languages

Closes #1378, #1076, #1078, #964, #1080, and #1079

See merge request briar/briar!918
2018-09-20 10:59:44 +00:00
Torsten Grote
660ba16a14 Fix app lock after sign-out bug
It some cases, it was observered how the app was locked after the user
had signed out.
This commit ensures that set alarms are canceled and that no new ones
will be set after the LockManager service has been stopped.

Fixes #1386
2018-09-19 16:06:13 -03:00
Torsten Grote
b101c4b636 Remove AndroidHttpClient class after Roboelectric update 2018-09-19 15:15:38 -03:00
Torsten Grote
fdfddd2667 Fix small RTL UI glitches in blog post layouts 2018-09-19 14:56:45 -03:00
akwizgran
296546544f Remove auto-generated layout IDs. 2018-09-19 17:42:25 +01:00
akwizgran
ad579a6ba3 Restore max of 50 contacts. 2018-09-19 17:42:09 +01:00
Torsten Grote
90e82357ba Move back to previous way of creating at least one test contact 2018-09-19 11:38:00 -03:00
Torsten Grote
b3b40753d8 RTL support: Address review issues 2018-09-19 11:33:03 -03:00
Torsten Grote
e60df3cece Don't crash when creating test data with 0 contacts
If no contacts exist, at least one will be created
2018-09-19 11:33:03 -03:00
Torsten Grote
da3cb95151 Move TrustIndicator behind date in AuthorView
to prevent it from being pushed off-screen

Fixes #1076
2018-09-19 11:33:03 -03:00
Torsten Grote
c27885072f Ellipzise long contact names in ConversationActivity
Fixes #1078
2018-09-19 11:33:03 -03:00
Torsten Grote
6557d564c9 Add RTL support to remaining layouts 2018-09-19 11:33:03 -03:00
Torsten Grote
53edcaf3e9 Add RTL support to remaining list items
Also fixes several small UI glitches with long texts
2018-09-19 11:33:03 -03:00
Torsten Grote
5122c961b4 Simplify dev reporter and add RTL support 2018-09-19 11:33:03 -03:00
Torsten Grote
f83b9244d4 Clean up threaded discussion screen
Adds RTL support
Fixing cropping bug

Closes #964
2018-09-19 11:33:03 -03:00
Torsten Grote
81292967e0 Add RTL support to conversation message bubbles 2018-09-19 11:33:03 -03:00
Torsten Grote
b72f6b4fc3 Migrate Introduction Screen to ConstraintLayout
Adds RTL support
Fixes issue with long contact names

Closes #1080
2018-09-19 11:33:03 -03:00
Torsten Grote
488be49c93 Convert contact lists to ConstraintLayout
Adds support for RTL languages
Fixes issues with long contact names

Closes #1079
2018-09-19 11:33:03 -03:00
Torsten Grote
90db45817a Add RTL language support to all activities and fragments 2018-09-19 11:33:03 -03:00
akwizgran
81863b9db6 Merge branch '1248-rename-lock-app' into 'master'
Rename "Screen lock" to "Lock app"

Closes #1248 and #1245

See merge request briar/briar!924
2018-09-19 14:28:34 +00:00
akwizgran
da069adb57 Merge branch '1186-remove-lock-screen-notification-setting' into 'master'
Remove lockscreen notification setting

Closes #1186

See merge request briar/briar!925
2018-09-19 14:27:31 +00:00
Torsten Grote
46425b09fa Rename "Screen lock" to "App lock" 2018-09-19 10:22:43 -03:00
akwizgran
41e1a436c9 Merge branch 'centre-decrypting-db-message' into 'master'
Align "decrypting database" message to centre

See merge request briar/briar!926
2018-09-19 11:46:55 +00:00
Torsten Grote
989394d18b Merge branch 'fingerprint-permission' into 'master'
Add obsolete fingerprint permission to satisfy Android Studio

See merge request briar/briar!927
2018-09-19 11:32:58 +00:00
akwizgran
b6b3f9c292 Align "decrypting database" message to centre. 2018-09-19 12:23:13 +01:00
akwizgran
a52547f73b Add obsolete fingerprint permission. 2018-09-19 12:19:33 +01:00
akwizgran
24f823a3ce Remove lock screen notification setting. 2018-09-19 10:50:46 +01:00
akwizgran
a045d7d306 Merge branch '1384-expiry-time' into 'master'
Fix off-by-one error in expiry calculation

Closes #1384

See merge request briar/briar!923
2018-09-18 17:15:54 +00:00
akwizgran
a29d5efd93 Fix off-by-one error in expiry calculation. 2018-09-18 18:01:44 +01:00
akwizgran
37cd1cdddf Merge branch '541-faster-retransmission-eta' into 'master'
Allow retransmission if it will result in faster delivery

Closes #541

See merge request briar/briar!908
2018-09-18 14:26:22 +00:00
akwizgran
4f495bb4d3 Use now + max latency as ETA, add more tests. 2018-09-18 16:05:25 +02:00
goapunk
1a70200b65 Allow retransmission if faster.
* This commit introduces an estimated time of arrival (eta) to the
message status which helps to decide whether a message should be
retransmitted over a faster transport.
2018-09-18 16:05:25 +02:00
akwizgran
6925dfcbdd Merge branch '1240-message-refactoring' into 'master'
Remove raw representation from Message class

See merge request briar/briar!915
2018-09-18 13:30:26 +00:00
Torsten Grote
7d479063a9 ConversationManager: Address review issues 2018-09-18 10:10:21 -03:00
Torsten Grote
2309e73216 Fix bug where available invitations were marked answered
Now an invitiation was answered when it is no longer available
2018-09-18 10:10:21 -03:00
akwizgran
4b325f797b Combine LiveData observers, avoid redundant loads. 2018-09-18 10:10:21 -03:00
Torsten Grote
9be83c3cc7 Refactor ConversationItem creation 2018-09-18 10:10:21 -03:00
Torsten Grote
86f650503b Re-introduce InvitationResponse
This was done, so private responses don't need to include a Nameable already.
Retreiving a nameable is tricky and requires a data migration,
so we just don't do it now.
2018-09-18 10:10:21 -03:00
Torsten Grote
d430b4fd2d Move introduction role into IntroductionResponse 2018-09-18 10:10:21 -03:00
akwizgran
fcf7cf72ea Refactor doesExist() method. 2018-09-18 10:10:21 -03:00
Torsten Grote
b78dfea95f Remove ListenableFutureTask and replace it with LiveData 2018-09-18 10:10:21 -03:00
Torsten Grote
183fe08565 Rename object to nameable 2018-09-18 10:10:21 -03:00
Torsten Grote
7e32697696 Use ConversationManager to retrieve messages
This removes the public method for retrieving messages
from individual conversation clients
and just leaves methods that require a transaction
to be used by the ConversationManager only.
2018-09-18 10:10:21 -03:00
Torsten Grote
29758b174a Unify all events related to private messages 2018-09-18 10:10:21 -03:00
Torsten Grote
61e18f104e Unify all private message responses in one PrivateResponse class
This also adds `Shareable`s to invitation response
which is a precondition for #561
2018-09-18 10:10:21 -03:00
Torsten Grote
ffeca8817f Prepare private message retrieval through ConversationManager 2018-09-18 10:10:21 -03:00
Torsten Grote
59fae2fa3c Unify all private message requests in one PrivateRequest class 2018-09-18 10:10:21 -03:00
Torsten Grote
2d9345c018 Remove unnecessary information from private message classes 2018-09-18 10:10:21 -03:00
akwizgran
817df9c75a Merge branch '1247-flag-secure-warning' into 'master'
Add warning to FLAG_SECURE about app locking implications

Closes #1247

See merge request briar/briar!922
2018-09-17 16:08:43 +00:00
Torsten Grote
745515457e Add warning to FLAG_SECURE about app locking implications 2018-09-17 12:21:16 -03:00
akwizgran
ba5928218a Reduce code duplication in TestMessageFactory. 2018-09-14 17:50:17 +01:00
akwizgran
9476782ced Bump version numbers for 1.1.1 release. 2018-09-14 13:16:17 +01:00
akwizgran
74445acb55 Merge branch '1379-startup-failure-error' into 'master'
Correct startup database failure error messages

Closes #1379

See merge request briar/briar!920
2018-09-14 12:01:52 +00:00
akwizgran
e32771f964 Merge branch '1359-conversation-progress' into 'master'
Fix progress feel over messages in Conversation view

Closes #1359

See merge request briar/briar!911
2018-09-14 11:59:42 +00:00
akwizgran
d7bf1ee374 Merge branch '1367-db-header-corrupt' into 'master'
Fix duplicate actions triggered by hardware keyboard

Closes #1367

See merge request briar/briar!921
2018-09-14 09:09:41 +00:00
Torsten Grote
10bee05856 Only sign-in once when pressing enter 2018-09-13 18:45:24 -03:00
Torsten Grote
fc626d0921 Only create one private group when pressing enter 2018-09-13 18:45:24 -03:00
Torsten Grote
30f87e626a Only create one forum when pressing enter 2018-09-13 18:45:24 -03:00
Torsten Grote
a0d91da569 Add TODO for not allowing double account creation 2018-09-13 18:19:15 -03:00
Torsten Grote
c90a72617e Do not create two accounts when pressing enter for account creation
Fixes #1367
2018-09-13 18:18:30 -03:00
Torsten Grote
8813bc36af Correct startup database failure error messages 2018-09-13 12:35:39 -03:00
akwizgran
049cf3ad27 Merge branch 'optional-tests' into 'master'
Specify optional tests with an environment variable

See merge request briar/briar!916
2018-09-13 14:36:59 +00:00
Torsten Grote
de8a6b23e5 Merge branch '1189-setup-activity' into 'master'
Launch SetupActivity in same task to prevent relaunching from recent apps

Closes #1189

See merge request briar/briar!919
2018-09-13 14:21:24 +00:00
akwizgran
30193a240b Start SetupActivity in same task, finish other activities. 2018-09-13 13:43:01 +01:00
akwizgran
a52ad8b4cc Bump version numbers for 1.1.0 release. 2018-09-12 17:10:52 +01:00
Torsten Grote
6a1a8b6872 Merge branch '1245-enable-pin-lock' into 'master'
Enable sign-in reminder, PIN lock and dark theme for release builds

See merge request briar/briar!917
2018-09-12 11:15:12 +00:00
Torsten Grote
50ad42a0a2 Update translations, adds Hungarian, sets inclusion threshold to 80% 2018-09-12 07:45:02 -03:00
akwizgran
08005bdf56 Enable PIN lock for release builds. 2018-09-12 11:44:27 +01:00
akwizgran
e32cc3af6d Enable dark theme for release builds. 2018-09-12 11:41:54 +01:00
akwizgran
28a68ff625 Enable sign-in reminder for release builds. 2018-09-12 11:39:54 +01:00
akwizgran
2bef2ac828 Merge branch '1249-sign-in-screenshots' into 'master'
Screenshots for account sign-in improvements and Tor settings

See merge request briar/briar!909
2018-09-06 13:40:03 +00:00
akwizgran
b2febbc6e9 Specify optional tests with an environment variable. 2018-09-06 10:34:04 +01:00
Torsten Grote
e12601dd08 Merge branch 'attach-updated-settings-to-event' into 'master'
Attach updated settings to SettingsUpdatedEvent

See merge request briar/briar!913
2018-09-05 11:22:05 +00:00
akwizgran
3388682dda Use updated settings from event. 2018-09-05 12:04:56 +01:00
akwizgran
74e4a9cbdf Remove raw representation from Message class. 2018-09-05 11:23:36 +01:00
akwizgran
8ad3047f87 Merge branch '1247-pin-lock-fingerprint' into 'master'
Implement fingerprint unlocking with BiometricPromptCompat

See merge request briar/briar!882
2018-09-05 08:39:54 +00:00
akwizgran
0cffaf8646 Merge branch 'move-tor-bridge-tests' into 'master'
Move Tor Bridge tests and rename bramble-j2se to bramble-java

See merge request briar/briar!907
2018-09-05 08:35:33 +00:00
akwizgran
7b116f15df Attach updated settings to SettingsUpdatedEvent. 2018-09-05 09:31:12 +01:00
Torsten Grote
ced0f72fba Fix progress feel over messages in Conversation view
Unlike with many other lists,
we are not clearing the list of private messages when restarting the activity.
We still load the messages from the database and add them to the view.
When there are no new message to add,
the usual insert observers do not trigger
and we do not call list.showData() although we should.
Doing so removes the progress bar as soon as messages have been loaded.
2018-09-04 12:31:16 -03:00
Torsten Grote
24c030f06f Remove button from UnlockActivity 2018-09-04 09:32:24 -03:00
Torsten Grote
a3fa15e90e Blank UnlockActivity when not using fingerprint unlock 2018-09-04 09:04:59 -03:00
Torsten Grote
57841be447 Remove BiometricPromptCompat library and limit feature to API 28 2018-09-04 09:04:58 -03:00
Torsten Grote
c5d374af04 ScreenLock: Implement fingerprint unlocking with BiometricPromptCompat 2018-09-04 09:04:33 -03:00
Torsten Grote
8d592ad2ee Take screenshot of Tor settings 2018-09-03 18:03:57 -03:00
Torsten Grote
055c381cc9 Take a screenshot of the Navigation Drawer with lock action 2018-09-03 16:32:39 -03:00
Torsten Grote
1d259bd51c Screenshots for Sign-in improvements
Screenshots for #1249
2018-09-03 16:32:39 -03:00
Torsten Grote
de63141997 Update translations 2018-09-03 15:02:34 -03:00
Torsten Grote
dee8f68477 Do not run Tor bridge test with every CI run 2018-09-03 13:02:54 -03:00
Torsten Grote
59048f106a Move Tor Bridge tests and rename bramble-j2se to bramble-java 2018-09-03 12:58:20 -03:00
akwizgran
da7cf4af28 Rename bramble-j2se to bramble-java. 2018-09-03 16:28:59 +01:00
akwizgran
0d4cf4db68 Merge branch 'java-tor-plugin' into 'master'
Add a LinuxTorPlugin

See merge request briar/briar!902
2018-09-03 15:23:20 +00:00
Torsten Grote
9efd2d113a Ignore file extension when retrieving resources on Android 2018-09-03 11:58:42 -03:00
Torsten Grote
8e6cd12f07 LinuxTorPlugin: Address review comments 2018-09-03 11:52:10 -03:00
Torsten Grote
3a49ca0d97 Add JavaTorPlugin 2018-09-03 11:52:10 -03:00
akwizgran
c03868e800 Merge branch '1343-vanniktech-emoji' into 'master'
Use vanniktech emoji library

Closes #1343, #1314, #940, #930, #749, and #684

See merge request briar/briar!857
2018-09-03 12:12:01 +00:00
akwizgran
d6c129e919 Hide emoji popup when hiding soft keyboard. 2018-08-28 16:45:04 +01:00
akwizgran
271efdd2bc Hide soft keyboard when reblogging post. 2018-08-28 15:57:55 +01:00
akwizgran
ad4e8d51e9 Hide soft keyboard when sending blog post. 2018-08-28 15:55:16 +01:00
akwizgran
eb19c6e08d Remove unused resources. 2018-08-28 15:55:16 +01:00
akwizgran
83bfeb9075 Initialise EmojiManager for UI tests. 2018-08-28 15:55:16 +01:00
akwizgran
428501cf5f Use vanniktech emoji library. 2018-08-28 15:55:16 +01:00
Torsten Grote
d8b04edcd0 Merge branch '1240-avoid-raw-messages' into 'master'
Avoid raw messages

See merge request briar/briar!906
2018-08-27 14:40:54 +00:00
akwizgran
0bc07cd0c1 Rename message length method. 2018-08-24 16:56:24 +01:00
akwizgran
cb3026959a Remove raw messages from SyncRecordWriter interface. 2018-08-24 16:56:24 +01:00
akwizgran
48933637d8 Remove raw messages from DB interface. 2018-08-24 16:56:24 +01:00
akwizgran
5626f3d761 Remove raw message method from DatabaseComponent interface. 2018-08-24 16:56:23 +01:00
akwizgran
0fce224d88 Add method for getting cooked message from DB. 2018-08-24 16:56:23 +01:00
Torsten Grote
3db35f7061 Merge branch 'network-interfaces-may-be-null' into 'master'
Check whether getNetworkInterfaces() returns null

See merge request briar/briar!903
2018-08-24 15:48:22 +00:00
Torsten Grote
751375035d Merge branch 'message-constructor' into 'master'
Minimise use of message constructor

See merge request briar/briar!905
2018-08-24 14:58:57 +00:00
akwizgran
27a169c6e2 Minimise use of message constructor. 2018-08-24 14:17:25 +01:00
akwizgran
d4a4351786 Merge branch '758-db-exception-for-deleted-messages' into 'master'
Throw an exception if a deleted message is requested from the DB

Closes #758

See merge request briar/briar!904
2018-08-24 09:21:05 +00:00
akwizgran
fbd38dbb94 Throw an exception if a raw message has been deleted. 2018-08-23 14:51:56 +01:00
akwizgran
cd4897e6c9 Check whether getNetworkInterfaces() returns null. 2018-08-23 14:16:18 +01:00
akwizgran
d84e176bb4 Merge branch 'fix_performance_test_db' into 'master'
Fix the database performance tests

See merge request briar/briar!893
2018-08-22 15:46:11 +00:00
Torsten Grote
da8b49bec2 Merge branch 'log-relay-names' into 'master'
Log Tor relay names to detect failing bridges

See merge request briar/briar!901
2018-08-22 14:27:58 +00:00
akwizgran
6c8cc79d87 Log Tor relay names to detect failing bridges. 2018-08-22 14:21:41 +01:00
akwizgran
a5271eee29 Merge branch 'switch-preference-android-4' into 'master'
Use Material style for SwitchPreference on Android 4

See merge request briar/briar!897
2018-08-20 19:40:56 +00:00
akwizgran
4dfc96996d Merge branch '1224-show-explanation-when-contact-exchange-fails' into 'master'
Show an error fragment when contact exchange fails

See merge request briar/briar!890
2018-08-20 19:40:36 +00:00
akwizgran
3139f308a2 Merge branch '1349-empty-state-ui' into 'master'
Implement new empty state icons

Closes #1349

See merge request briar/briar!898
2018-08-20 19:39:56 +00:00
Torsten Grote
cc6daffa61 Merge branch 'update-bridges' into 'master'
Replace two failing bridges

See merge request briar/briar!900
2018-08-20 18:36:07 +00:00
Torsten Grote
f08f441f5f Use Material style for SwitchPreference on Android 4 2018-08-20 15:22:55 -03:00
Torsten Grote
83886c78f1 Empty states: Address review comments 2018-08-20 15:14:53 -03:00
Torsten Grote
5ed0e9efec Implement new empty state icons 2018-08-20 15:14:53 -03:00
akwizgran
169c59349e Merge branch '1269-bridge-setting' into 'master'
Refactor Tor settings and add a setting for forcing the use bridges

Closes #1269

See merge request briar/briar!895
2018-08-20 17:56:56 +00:00
akwizgran
764f60b3fe Replace two failing bridges. 2018-08-20 17:57:36 +01:00
Torsten Grote
e51c437a06 Merge branch 'ci-dev-urandom' into 'master'
Use /dev/urandom for CI

See merge request briar/briar!899
2018-08-20 16:24:49 +00:00
akwizgran
9fbf740ba7 Use /dev/urandom for tests. 2018-08-20 17:08:57 +01:00
akwizgran
db7686ea52 Merge branch '1247-pin-lock-activity-timeout' into 'master'
Screen Lock: Lock after customizable inactivity timeout

See merge request briar/briar!887
2018-08-20 13:52:23 +00:00
akwizgran
7fe21e079f Merge branch '1358-message-bubbles' into 'master'
New Design for Message Bubbles

Closes #1358

See merge request briar/briar!896
2018-08-20 12:11:22 +00:00
Torsten Grote
be72e624a3 ContactExchangeErrorFragment: Address review comments 2018-08-16 13:00:02 -03:00
Torsten Grote
d9e9741112 Replace generic ErrorFragment with specific one
when key agreement protocol doesn't match
2018-08-16 12:34:20 -03:00
Torsten Grote
656ca8d67a Contact failure: Add better icon and remove technical error message 2018-08-16 12:34:20 -03:00
Torsten Grote
d3e44358a4 Move feedback trigger and making link clickable to UiUtils 2018-08-16 12:34:20 -03:00
Torsten Grote
920a1d0431 Show an error fragment when contact exchange fails 2018-08-16 12:34:20 -03:00
Torsten Grote
4b9a9771f8 Tor settings: Address review comments 2018-08-16 12:27:26 -03:00
Torsten Grote
d64252aaf3 Screen Lock Timeout: Address review comments 2018-08-16 12:16:45 -03:00
Torsten Grote
825ed451a3 Screen lock: Add a fallback in case alarm manager didn't run during sleep 2018-08-16 12:14:59 -03:00
Torsten Grote
bffd78d404 Use a dedicated summary for 'never lock Briar' for proper English 2018-08-16 12:14:59 -03:00
Torsten Grote
04ffff0953 Screen Lock: Lock after customizable inactivity timeout 2018-08-16 12:14:59 -03:00
Torsten Grote
21f95ed9af Add a stroke for private message bubbles on Android 4 2018-08-16 12:07:54 -03:00
Torsten Grote
c8b516196c Add new private message bubbles, get rid of 9-patch drawables
This reverts commit f8a8c0d8b8.
2018-08-16 10:22:15 -03:00
goapunk
941a0cccc3 Fix a regression in the performance tests causing the db key to be regenerated everytime. 2018-08-16 12:09:33 +02:00
Torsten Grote
9b17836595 Refactor Tor settings and add a setting for forcing to use bridges 2018-08-15 17:32:43 -03:00
akwizgran
e5112ae9ee Merge branch 'gradle-witness' into 'master'
Move gradle witness dependency verification into dedicated files

See merge request briar/briar!892
2018-08-15 15:21:56 +00:00
Torsten Grote
f399ce9290 Use gradle wrapper for updating dependency pinning instead of local gradle 2018-08-15 12:01:13 -03:00
Torsten Grote
30e036c672 Move gradle witness dependency verification into dedicated files
This also adds a script for makes upgrading dependency checksums so much easier
2018-08-14 18:01:34 -03:00
akwizgran
2896700e50 Merge branch 'preference-switches' into 'master'
Replace CheckBoxPreference with the more standard SwitchPreference

See merge request briar/briar!891
2018-08-14 10:21:12 +00:00
akwizgran
987baba3bc Update settings.xml 2018-08-14 10:00:36 +00:00
akwizgran
03191ff08f Merge branch 'master' into 'preference-switches'
# Conflicts:
#   briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java
2018-08-14 09:59:22 +00:00
akwizgran
42031631dd Merge branch '1247-pin-lock' into 'master'
Screen Lock Feature

See merge request briar/briar!870
2018-08-14 09:28:04 +00:00
Torsten Grote
64e30844b8 Screen Lock: Remember when keyguard was shown (for Android 6)
Also automatically unlock if device screenlock was removed.
2018-08-13 14:36:35 -03:00
Torsten Grote
30a070dd13 Replace CheckBoxPreference witht he more standard SwitchPreference 2018-08-13 13:57:28 -03:00
Torsten Grote
4f18303a1f Merge branch 'remove-unused-constants' into 'master'
Remove unused constants

See merge request briar/briar!889
2018-08-10 17:30:16 +00:00
Torsten Grote
5c500fb740 Merge branch 'back-facing-camera-not-required' into 'master'
Make back-facing camera optional in manifest

See merge request briar/briar!888
2018-08-10 16:30:29 +00:00
Torsten Grote
4d63272c04 Prevent activity loops when pressing back button while unlocking
This solution even works when "don't keep activities" is active
2018-08-10 13:28:43 -03:00
akwizgran
16b09b9380 Make back-facing camera optional in manifest. 2018-08-10 16:31:35 +01:00
akwizgran
a1599df712 Remove unused constants. 2018-08-10 15:04:08 +01:00
Torsten Grote
afa3c3a70e Screen Lock: Show verbose unlock message for older APIs 2018-08-10 07:44:10 -03:00
Torsten Grote
0f37a43415 Screen Lock: More changes due to code review 2018-08-10 07:44:10 -03:00
Torsten Grote
ef1d5d3233 Show lock icon when Briar is locked 2018-08-10 07:44:10 -03:00
Torsten Grote
feab825865 Don't show UnlockActivity anymore, might get removed completetly later 2018-08-10 07:44:10 -03:00
Torsten Grote
5d2c96f916 Remove LOCK button from foreground notification
When the user removes the screen lock, the app does not get really
locked. There is no way about getting notified about this. Before users
lock the app without it getting actually locked, we rather remove the
button that was collapsed and not easy to find anyway.
2018-08-10 07:44:10 -03:00
Torsten Grote
02ff37b187 Screen Lock: Second round of addressing review comments 2018-08-10 07:44:10 -03:00
Torsten Grote
6863727646 Upgrade robolectric to get Keyguard support for tests 2018-08-10 07:44:10 -03:00
Torsten Grote
087d6e9931 Screen Lock: Address first round of review comments 2018-08-10 07:44:10 -03:00
Torsten Grote
d79f1b667a Move app locking logic into dedicatd LockManager 2018-08-10 07:44:10 -03:00
Torsten Grote
633f5a8bd7 Adapt foreground notification when locked and show LOCK button 2018-08-10 07:44:10 -03:00
Torsten Grote
90cb9a2fae Disable screen lock setting instead of hiding it when not available 2018-08-10 07:44:10 -03:00
Torsten Grote
fc86319e13 MVP of PIN lock feature
This only shows the settings if a screen lock is available.
If the setting is activated, it shows a drawer item for locking.
Once locked, the screen lock secret needs to be entered to enter the
app again.

First part of #1247
2018-08-10 07:44:10 -03:00
Torsten Grote
af1ed292ae Merge branch '832-android-tor-plugin' into 'master'
Factor out Android-specific code from TorPlugin

Closes #832

See merge request briar/briar!876
2018-08-09 19:36:00 +00:00
Torsten Grote
5393127400 Merge branch 'show-blocked-country-names' into 'master'
Show names of countries where Tor is blocked

See merge request briar/briar!886
2018-08-09 13:21:22 +00:00
akwizgran
0e6c374d0e Show names of countries where Tor is blocked. 2018-08-09 13:55:06 +01:00
akwizgran
52efbcac8a Merge branch '1360-rename-main-flavor' into 'master'
Rename main flavor due to internal conflicts

Closes #1360

See merge request briar/briar!885
2018-08-09 08:58:24 +00:00
Torsten Grote
acf6a45004 Merge branch 'replace-assert-statements' into 'master'
Replace assert statements with AssertionErrors

See merge request briar/briar!877
2018-08-08 19:56:38 +00:00
Torsten Grote
7ffcace228 Rename Main Flavor due to internal conflicts 2018-08-08 16:52:28 -03:00
akwizgran
e157fdfc7b Merge branch '1251-dark-theme-old-message-bubbles' into 'master'
Dark Theme Changes

See merge request briar/briar!884
2018-08-08 15:18:50 +00:00
akwizgran
f8a8c0d8b8 Revert to old message bubbles pending design changes. 2018-08-08 10:35:05 +01:00
Torsten Grote
f53aeef0d6 Merge branch 'logger-names' into 'master'
Use full class names for loggers

See merge request briar/briar!881
2018-08-07 14:27:57 +00:00
akwizgran
f812acb00b Use general-purpose resource provider. 2018-08-07 15:19:46 +01:00
akwizgran
004467e84e Factor out remaining Android code from Tor plugin. 2018-08-07 15:19:43 +01:00
akwizgran
34c0a83e36 Use full class names for loggers. 2018-08-07 15:17:19 +01:00
Torsten Grote
fd0dad8936 Restore old button size and ensure timestamps are not selectable 2018-08-06 14:26:02 -03:00
Torsten Grote
32420a0781 Give names to colors and clean them up 2018-08-06 13:16:53 -03:00
Torsten Grote
b6c85c8bf6 More Dark Theme Changes after designer feedback 2018-08-06 13:16:53 -03:00
Torsten Grote
4163731ec3 New private message bubbles
This gets rid of all those pesky 9-Patch drawables
2018-08-06 13:16:53 -03:00
akwizgran
8e732d880f Merge branch '47-sign-in-reminder' into 'master'
Do not show sign-in reminder once PasswordActivity was opened

Closes #47

See merge request briar/briar!879
2018-08-06 09:38:05 +00:00
Torsten Grote
0b2594a693 Move SignIn reminder code into AndroidNotificationManager and don't show reminder once PasswordActivity was opened 2018-08-03 15:08:57 -03:00
akwizgran
7e009ceaf2 Merge branch '596-espresso' into 'master'
Setup UI Tests with Espresso for Automatic Localized Screenshots

Closes #596

See merge request briar/briar!863
2018-08-03 16:38:57 +00:00
Torsten Grote
b238b28ef9 Remove PasswordActivity test since it doesn't work anyway 2018-08-03 13:09:42 -03:00
Torsten Grote
edb8e8f9d0 Move res values from build.gradle into strings.xml
This fixes an issue where the build type values were overriding the
flavor values.
2018-08-03 13:08:18 -03:00
Torsten Grote
cc6041e90c Rename Component and Screenshot Tests 2018-08-03 11:42:01 -03:00
Torsten Grote
3ff6462899 Refactor Espresso tests to use new AccountManager 2018-08-03 11:20:43 -03:00
Torsten Grote
6f7d0c6f77 Do proper Doze white-listing in UI tests 2018-08-03 11:20:43 -03:00
Torsten Grote
412381f37e Move buildType to flavor and add hashes for pinning of androidTest dependencies 2018-08-03 11:20:33 -03:00
Torsten Grote
05fbb87c06 Add a NavDrawerActivityTest 2018-08-03 11:16:52 -03:00
Torsten Grote
daf5db470f Use demo mode when taking screenshots to clear status bar
https://android.googlesource.com/platform/frameworks/base/+/master/packages/SystemUI/docs/demo_mode.md
2018-08-03 11:16:52 -03:00
Torsten Grote
be2d695150 Setup fastlane
This is great for automatically uploading (localized) screenshots
and app metadata to Google Play.
You can even upload the signed APK releases as well.

For now, this is only useful for running the screenshot Espresso tests
and grabbing the screenshots from the device.
2018-08-03 11:16:52 -03:00
Torsten Grote
d0c2c03057 First prototype of Espresso test infrastructure with automatic screenshoting 2018-08-03 11:16:52 -03:00
Torsten Grote
db11e0101a Merge branch '1355-disable-tor-setting' into 'master'
Add a setting to override location-based disabling of Tor

Closes #1355

See merge request briar/briar!871
2018-08-03 13:35:33 +00:00
akwizgran
25b8932cde Merge branch '47-sign-in-reminder' into 'master'
Don't show sign-in reminder if user is signed-in already

Closes #47

See merge request briar/briar!872
2018-08-03 10:59:25 +00:00
akwizgran
0d658513ba Disable bridges when network is manually enabled. 2018-08-03 11:53:50 +01:00
akwizgran
732bf6d4ec Show countries where Tor is blocked. 2018-08-03 11:53:50 +01:00
akwizgran
53762e7c93 Add setting to override location-based disabling of Tor. 2018-08-03 11:53:47 +01:00
akwizgran
5a145c9eb2 Replace assert statements with AssertionErrors. 2018-08-03 11:14:15 +01:00
akwizgran
d8ce1d75ca Add run configuration for bramble-android tests. 2018-08-03 10:17:36 +01:00
Torsten Grote
77b2fa8acb Merge branch '832-fix-bridge-test' into 'master'
Fix Tor bridge integration test

See merge request briar/briar!875
2018-08-02 15:00:57 +00:00
akwizgran
f9d5873385 Fix Tor bridge test. 2018-08-02 15:51:28 +01:00
Torsten Grote
1de6c863df Merge branch '832-network-manager' into 'master'
Factor network management code out of plugins

See merge request briar/briar!874
2018-08-02 14:36:17 +00:00
akwizgran
8c5c66fa9a Add null-safety and thread-safety annotations. 2018-08-02 15:06:17 +01:00
Torsten Grote
82f939ecd4 Don't show sign-in reminder if user is signed-in already 2018-08-02 09:50:42 -03:00
akwizgran
1a5c02f8a9 Remove extra logging. 2018-08-02 13:22:54 +01:00
akwizgran
16d56535ca Check connectivity after all AP state changes. 2018-08-02 13:22:53 +01:00
akwizgran
dcd6fda046 Check connectivity after entering or leaving doze mode. 2018-08-02 13:22:53 +01:00
akwizgran
2535445831 Factor network management code out of plugins. 2018-08-02 13:22:50 +01:00
Torsten Grote
c0d5a3a5ea Merge branch '1341-account-manager-refactoring' into 'master'
Refactor authentication and account management code

Closes #1341

See merge request briar/briar!866
2018-08-02 11:49:15 +00:00
akwizgran
c1789a8e52 Move identity creation into AccountManager. 2018-08-02 09:51:17 +01:00
akwizgran
2a0ecc3f80 Clean up some tests. 2018-08-01 16:49:14 +01:00
akwizgran
b176ec5844 Add TODO for account creation error handling. 2018-08-01 15:56:53 +01:00
akwizgran
f8df6b88ee Add BriarAccountManager subclass. 2018-08-01 15:52:09 +01:00
akwizgran
55d8f853db Bump version numbers for 1.0.13 release. 2018-07-31 17:34:08 +01:00
Torsten Grote
004853a09b Merge branch '1354-forget-hsforget' into 'master'
Don't try to use missing HSFORGET command

Closes #1354

See merge request briar/briar!869
2018-07-31 16:27:32 +00:00
akwizgran
d815dd6ec9 Don't try to use missing HSFORGET command. 2018-07-31 17:19:11 +01:00
akwizgran
277d045469 Add hashes for test dependencies. 2018-07-27 16:04:57 +01:00
akwizgran
287f3760cd Pass database key into LifecycleManager. 2018-07-27 15:46:48 +01:00
akwizgran
58d09d0742 Add tests for AccountManager and AndroidAccountManager. 2018-07-27 15:29:42 +01:00
akwizgran
adbfa26364 Remove redundant locking. 2018-07-27 14:18:31 +01:00
akwizgran
abaefacb69 Add javadocs. 2018-07-27 13:15:04 +01:00
akwizgran
6ca0339da2 Move DB key management into account manager. 2018-07-27 13:15:03 +01:00
akwizgran
4a9977fa58 Use account manager to check whether account exists. 2018-07-27 13:15:03 +01:00
akwizgran
f9d8c720ec Remove ConfigController. 2018-07-27 13:15:03 +01:00
akwizgran
1edf2bfa75 Move account deletion into AccountManager. 2018-07-27 13:14:58 +01:00
akwizgran
233af69909 Add TODOs. 2018-07-27 13:14:58 +01:00
akwizgran
6f6ba38de1 Remove logic from DatabaseConfig. 2018-07-27 13:14:57 +01:00
akwizgran
f9495b49d6 Move encrypted key, account deletion into AccountManager. 2018-07-27 13:14:57 +01:00
akwizgran
cb29c9bf32 Create minimal AccountManager interface. 2018-07-27 13:14:52 +01:00
akwizgran
8283760e8a Move local author creation into IdentityManager. 2018-07-27 13:14:51 +01:00
831 changed files with 21585 additions and 14636 deletions

1
.gitignore vendored
View File

@@ -23,5 +23,6 @@ local.properties
!.idea/codeStyles
.gradle
build/
captures
*.iml
projectFilesBackup/

View File

@@ -11,8 +11,8 @@ test:
- .gradle/caches
script:
- ./gradlew --no-daemon animalSnifferMain animalSnifferTest
- ./gradlew --no-daemon test
- ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom animalSnifferMain animalSnifferTest
- ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom test --continue
after_script:
# these file change every time but should not be cached

View File

@@ -36,6 +36,9 @@
<option name="JD_ALIGN_PARAM_COMMENTS" value="false" />
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false" />
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<Objective-C-extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
@@ -257,5 +260,11 @@
</rules>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
<option name="PARAMETER_ANNOTATION_WRAP" value="1" />
<option name="VARIABLE_ANNOTATION_WRAP" value="1" />
<option name="ENUM_CONSTANTS_WRAP" value="1" />
</codeStyleSettings>
</code_scheme>
</component>

View File

@@ -0,0 +1,20 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All in briar-headless" type="AndroidJUnit" factoryName="Android JUnit" nameIsGenerated="true">
<module name="briar-headless" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PACKAGE_NAME" value="org.briarproject.briar.headless" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-headless" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<patterns />
<method />
</configuration>
</component>

View File

@@ -21,8 +21,10 @@
<method>
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-api" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-core" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-j2se" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-android" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-java" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-core" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All in briar-headless" run_configuration_type="AndroidJUnit" />
</method>
</configuration>
</component>

View File

@@ -0,0 +1,20 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-android" type="AndroidJUnit" factoryName="Android JUnit">
<module name="bramble-android" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-android" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<patterns />
<method />
</configuration>
</component>

View File

@@ -1,6 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-api" type="AndroidJUnit" factoryName="Android JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="bramble-api" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
@@ -11,12 +10,10 @@
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-api" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method />
</configuration>

View File

@@ -1,6 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-core" type="AndroidJUnit" factoryName="Android JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="bramble-core" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
@@ -11,12 +10,10 @@
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-core" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method />
</configuration>

View File

@@ -1,7 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-j2se" type="AndroidJUnit" factoryName="Android JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="bramble-j2se" />
<configuration default="false" name="All tests in bramble-java" type="AndroidJUnit" factoryName="Android JUnit">
<module name="bramble-java" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PACKAGE_NAME" value="" />
@@ -10,13 +9,11 @@
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea -Djava.library.path=libs" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-j2se" />
<option name="ENV_VARIABLES" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-java" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method />
</configuration>

View File

@@ -1,6 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-android" type="AndroidJUnit" factoryName="Android JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="briar-android" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
@@ -11,12 +10,10 @@
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-android" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method />
</configuration>

View File

@@ -1,6 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-core" type="AndroidJUnit" factoryName="Android JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="briar-core" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
@@ -11,12 +10,10 @@
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-core" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method />
</configuration>

View File

@@ -1,6 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="H2 Performance Test" type="AndroidJUnit" factoryName="Android JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="bramble-core" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
@@ -11,12 +10,10 @@
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method />
</configuration>

View File

@@ -1,6 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="HyperSQL Performance Test" type="AndroidJUnit" factoryName="Android JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="bramble-core" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
@@ -11,12 +10,10 @@
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method />
</configuration>

View File

@@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="briar-headless" type="JetRunConfigurationType" factoryName="Kotlin" singleton="true">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<option name="VM_PARAMETERS" value="" />
<option name="PROGRAM_PARAMETERS" value="-v" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="MAIN_CLASS_NAME" value="org.briarproject.briar.headless.MainKt" />
<option name="WORKING_DIRECTORY" value="" />
<module name="briar-headless" />
<envs />
<method>
<option name="Gradle.BeforeRunTask" enabled="true" tasks="jar" externalProjectPath="$PROJECT_DIR$/briar-headless" vmOptions="" scriptParameters="" />
</method>
</configuration>
</component>

View File

@@ -1,15 +1,18 @@
import com.android.build.gradle.tasks.MergeResources
apply plugin: 'com.android.library'
apply plugin: 'witness'
apply from: 'witness.gradle'
android {
compileSdkVersion 27
buildToolsVersion '27.0.3'
compileSdkVersion 28
buildToolsVersion '28.0.3'
defaultConfig {
minSdkVersion 14
targetSdkVersion 26
versionCode 10012
versionName "1.0.12"
versionCode 10105
versionName "1.1.5"
consumerProguardFiles 'proguard-rules.txt'
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@@ -27,103 +30,41 @@ configurations {
dependencies {
implementation project(path: ':bramble-core', configuration: 'default')
implementation 'org.briarproject:jtorctl:0.3'
tor 'org.briarproject:tor-android:0.2.9.16@zip'
tor 'org.briarproject:tor-android:0.3.4.8@zip'
tor 'org.briarproject:obfs4proxy-android:0.0.7@zip'
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'
compileOnly 'javax.annotation:jsr250-api:1.0'
androidTestImplementation project(path: ':bramble-api', configuration: 'testOutput')
androidTestImplementation project(path: ':bramble-core', configuration: 'testOutput')
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestAnnotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
androidTestCompileOnly 'javax.annotation:jsr250-api:1.0'
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation 'junit:junit:4.12'
testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:2.8.2"
}
dependencyVerification {
verify = [
'com.android.tools.analytics-library:protos:26.1.3:protos-26.1.3.jar:818c9f256f141d9dafec03a1aa2b94d240b2c140acfd7ee31a8b3e6c2b9479e3',
'com.android.tools.analytics-library:shared:26.1.3:shared-26.1.3.jar:7110706c7ada96c8b6f5ca80c478291bc7899d46277de2c48527e045442401a3',
'com.android.tools.analytics-library:tracker:26.1.3:tracker-26.1.3.jar:4155424bf2ce4872da83332579a1707252bc66cbd77c5144fdc4483d0f2e1418',
'com.android.tools.build:apksig:3.1.3:apksig-3.1.3.jar:7e1f8e675a6e768e5b56405e41d6c3cc05befe62e601b04177de1029902c9c89',
'com.android.tools.build:builder-model:3.1.3:builder-model-3.1.3.jar:06ad1c422d679fc698451479cb40ba863849d67bfd1de23f6d2c16d78b024b0b',
'com.android.tools.build:builder-test-api:3.1.3:builder-test-api-3.1.3.jar:4d989f780436794f0f8b2f50e9e079b786571eac90f26c208ab2ae6d4012f389',
'com.android.tools.build:builder:3.1.3:builder-3.1.3.jar:8a1092012c89d0ec1ee2eff09c5708c71ef4482a6862df8d3a44a67fccace01c',
'com.android.tools.build:gradle-api:3.1.3:gradle-api-3.1.3.jar:01e4df521456aef66514336f1d492346730dd1fb8f6433a89f62da834941ed72',
'com.android.tools.build:manifest-merger:26.1.3:manifest-merger-26.1.3.jar:1e4fc7e932adb4607082409800e5e6fccb42e6c5360ae5990094bf522f3ada55',
'com.android.tools.ddms:ddmlib:26.1.3:ddmlib-26.1.3.jar:c54931cd68df5d1ea2923b3b320eae47cd2307a5a916bb8674c0acf93cd1d3cd',
'com.android.tools.external.com-intellij:intellij-core:26.1.3:intellij-core-26.1.3.jar:af67f5535fef2e1a28b1007a4acb8c5deb6a1e33b8afe7b11d012c9e778ebcec',
'com.android.tools.external.com-intellij:kotlin-compiler:26.1.3:kotlin-compiler-26.1.3.jar:c746d2859dc11cc05c84b692b3498d3a621e0929511f8440ee009c6557838fd4',
'com.android.tools.external.org-jetbrains:uast:26.1.3:uast-26.1.3.jar:3f3f6651d0c7685a77ecb22e9c82d6b49fdf24322c17360768dc530678f43265',
'com.android.tools.layoutlib:layoutlib-api:26.1.3:layoutlib-api-26.1.3.jar:10bc73ce706c45629872d6a999dbe12116df64e24f47ff93b7b13121ff57b4b0',
'com.android.tools.lint:lint-api:26.1.3:lint-api-26.1.3.jar:6f97323f9af8deda86278717885b5c927f3766757db89709f52d11d42b6fb751',
'com.android.tools.lint:lint-checks:26.1.3:lint-checks-26.1.3.jar:73c3d53784c9ce3e6d5968506581918e0179645d20809927ca4a001dd766b001',
'com.android.tools.lint:lint-gradle-api:26.1.3:lint-gradle-api-26.1.3.jar:7ca3c4866ec21dc21d53a9d86f752b77ace6f6c610a0c9dc877313856c733d9d',
'com.android.tools.lint:lint-gradle:26.1.3:lint-gradle-26.1.3.jar:db0c354b8f4b6f6637e31f91c564785a59ff896325331fcbc3de7458e0b6c067',
'com.android.tools.lint:lint-kotlin:26.1.3:lint-kotlin-26.1.3.jar:94e2b0f4565a241561cfb8fc1222bb3f132a3b98d2a90421dbb72ee8358e7d68',
'com.android.tools.lint:lint:26.1.3:lint-26.1.3.jar:8d5f32c989c6d191d712e90ad3ca2d1c409313599551d04d834caa44d26c78df',
'com.android.tools:annotations:26.1.3:annotations-26.1.3.jar:c950430b24ac5d58fc97e7283b8f0115f99587e76e08b4e1e2aaa780f2d77323',
'com.android.tools:common:26.1.3:common-26.1.3.jar:7c31a90581a148ab219f615a59667f0dded7fa39b248529784474da3c2274ef2',
'com.android.tools:dvlib:26.1.3:dvlib-26.1.3.jar:0cae87906f53d3f1088366a916ed180a7312b6d9919b90797f238875c8492855',
'com.android.tools:repository:26.1.3:repository-26.1.3.jar:52d4539cc68db91b261e2a33b2c8206b26e05539078758dc28cfb3854adb4f59',
'com.android.tools:sdk-common:26.1.3:sdk-common-26.1.3.jar:1948603ca9ff22c7ebb3178000bffa3a9dd2ca1cc5cb0c793cae08468b8fcfc1',
'com.android.tools:sdklib:26.1.3:sdklib-26.1.3.jar:4adcfaad9514607098d2c51503c39811112d3050f4d1e744c01c7f08f591032b',
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
'com.google.code.gson:gson:2.7:gson-2.7.jar:2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32',
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.errorprone:error_prone_annotations:2.0.18:error_prone_annotations-2.0.18.jar:cb4cfad870bf563a07199f3ebea5763f0dec440fcda0b318640b1feaa788656b',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'com.google.guava:guava:22.0:guava-22.0.jar:1158e94c7de4da480873f0b4ab4a1da14c0d23d4b1902cc94a58a6f0f9ab579e',
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:40ceb7157feb263949e0f503fe5f71689333a621021aa20ce0d0acee3badaa0f',
'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd',
'com.google.protobuf:protobuf-java:3.4.0:protobuf-java-3.4.0.jar:dce7e66b32456a1b1198da0caff3a8acb71548658391e798c79369241e6490a4',
'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
'com.sun.istack:istack-commons-runtime:2.21:istack-commons-runtime-2.21.jar:c33e67a0807095f02a0e2da139412dd7c4f9cc1a4c054b3e434f96831ba950f4',
'com.sun.xml.fastinfoset:FastInfoset:1.2.13:FastInfoset-1.2.13.jar:27a77db909f3c2833c0b1a37c55af1db06045118ad2eed96ce567b6632bce038',
'commons-codec:commons-codec:1.6:commons-codec-1.6.jar:54b34e941b8e1414bd3e40d736efd3481772dc26db3296f6aa45cec9f6203d86',
'commons-logging:commons-logging:1.1.1:commons-logging-1.1.1.jar:ce6f913cad1f0db3aad70186d65c5bc7ffcc9a99e3fe8e0b137312819f7c362f',
'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'javax.xml.bind:jaxb-api:2.2.12-b140109.1041:jaxb-api-2.2.12-b140109.1041.jar:b5e60cd8b7b5ff01ce4a74c5dd008f4fbd14ced3495d0b47b85cfedc182211f2',
'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5',
'net.sf.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2',
'org.apache.commons:commons-compress:1.12:commons-compress-1.12.jar:2c1542faf343185b7cab9c3d55c8ae5471d6d095d3887a4adefdbdf2984dc0b6',
'org.apache.httpcomponents:httpclient:4.2.6:httpclient-4.2.6.jar:362e9324ee7c697e21279e20077b52737ddef3f1b2c1a7abe5ad34b465145550',
'org.apache.httpcomponents:httpcore:4.2.5:httpcore-4.2.5.jar:e5e82da4cc66c8d917bbf743e3c0752efe8522735e7fc9dbddb65bccea81cfe9',
'org.apache.httpcomponents:httpmime:4.1:httpmime-4.1.jar:31629566148e8a47688ae43b420abc3ecd783ed15b33bebc00824bf24c9b15aa',
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
'org.briarproject:jtorctl:0.3:jtorctl-0.3.jar:f2939238a097898998432effe93b0334d97a787972ab3a91a8973a1d309fc864',
'org.briarproject:tor-android:0.2.9.16:tor-android-0.2.9.16.zip:515e33dda6a30853c885a2de2c79ae1ab9ad8b6db44f5db8890333ec2e24f4ae',
'org.codehaus.groovy:groovy-all:2.4.12:groovy-all-2.4.12.jar:6a56af4bd48903d56bec62821876cadefafd007360cc6bd0d8f7aa8d72b38be4',
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
'org.glassfish.jaxb:jaxb-core:2.2.11:jaxb-core-2.2.11.jar:37bcaee8ebb04362c8352a5bf6221b86967ecdab5164c696b10b9a2bb587b2aa',
'org.glassfish.jaxb:jaxb-runtime:2.2.11:jaxb-runtime-2.2.11.jar:a874f2351cfba8e2946be3002d10c18a6da8f21b52ba2acf52f2b85d5520ed70',
'org.glassfish.jaxb:txw2:2.2.11:txw2-2.2.11.jar:272a3ccad45a4511351920cd2a8633c53cab8d5220c7a92954da5526bb5eafea',
'org.jetbrains.kotlin:kotlin-reflect:1.2.0:kotlin-reflect-1.2.0.jar:4f48a872bad6e4d9c053f4ad610d11e4012ad7e58dc19a03dd5eb811f36069dd',
'org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.0:kotlin-stdlib-jre7-1.2.0.jar:c7a20fb951d437797afe8980aff6c1e5a03f310c661ba58ba1d4fa90cb0f2926',
'org.jetbrains.kotlin:kotlin-stdlib-jre8:1.2.0:kotlin-stdlib-jre8-1.2.0.jar:633524eee6ef1941f7cb1dab7ee3927b0a221ceee9047aeb5515f4cbb990c82a',
'org.jetbrains.kotlin:kotlin-stdlib:1.2.0:kotlin-stdlib-1.2.0.jar:05cfd9f5ac0b41910703a8925f7211a495909b27a2ffdd1c5106f1689aeafcd4',
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.jvnet.staxex:stax-ex:1.7.7:stax-ex-1.7.7.jar:a31ff7d77163c0deb09e7fee59ad35ae44c2cee2cc8552a116ccd1583d813fb4',
'org.ow2.asm:asm-analysis:5.1:asm-analysis-5.1.jar:a34658f5c5de4b573eef21131cc32cc25f7b66407944f312b28ec2e56abb1fa9',
'org.ow2.asm:asm-commons:5.1:asm-commons-5.1.jar:97b3786e1f55e74bddf8ad102bf50e33bbcbc1f6b7fd7b36f0bbbb25cd4981be',
'org.ow2.asm:asm-tree:5.1:asm-tree-5.1.jar:c0de2bbc4cb8297419659813ecd4ed1d077ed1dd5c1f5544cc5143e493e84c10',
'org.ow2.asm:asm-util:5.1:asm-util-5.1.jar:ee032c39ae5e3cd099148fbba9a2124f9ed613e5cb93e03ee0fa8808ce364040',
'org.ow2.asm:asm:5.1:asm-5.1.jar:d2da399a9967c69f0a21739256fa79d284222c223082cacadc17372244764b54',
]
}
def torBinariesDir = 'src/main/res/raw'
project.afterEvaluate {
copy {
from configurations.tor.collect { zipTree(it) }
into 'src/main/res/raw'
task cleanTorBinaries {
doLast {
delete fileTree(torBinariesDir) { include '*.zip' }
}
}
clean.dependsOn cleanTorBinaries
task unpackTorBinaries {
doLast {
copy {
from configurations.tor.collect { zipTree(it) }
into torBinariesDir
}
}
dependsOn cleanTorBinaries
}
tasks.withType(MergeResources) {
inputs.dir torBinariesDir
dependsOn unpackTorBinaries
}

View File

@@ -1,126 +0,0 @@
package org.briarproject.bramble.plugin.tor;
import android.content.Context;
import android.support.test.runner.AndroidJUnit4;
import org.briarproject.bramble.DaggerIntegrationTestComponent;
import org.briarproject.bramble.IntegrationTestComponent;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.net.SocketFactory;
import static android.support.test.InstrumentationRegistry.getTargetContext;
import static java.util.Collections.singletonList;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@RunWith(AndroidJUnit4.class)
public class BridgeTest extends BrambleTestCase {
private final static long TIMEOUT = SECONDS.toMillis(23);
private final static Logger LOG =
Logger.getLogger(BridgeTest.class.getSimpleName());
@Inject
EventBus eventBus;
@Inject
BackoffFactory backoffFactory;
@Inject
Clock clock;
private final Context appContext = getTargetContext();
private final CircumventionProvider circumventionProvider;
private final List<String> bridges;
private TorPluginFactory factory;
private volatile int currentBridge = 0;
public BridgeTest() {
super();
circumventionProvider = new CircumventionProvider() {
@Override
public boolean isTorProbablyBlocked(String countryCode) {
return true;
}
@Override
public boolean doBridgesWork(String countryCode) {
return true;
}
@Override
public List<String> getBridges() {
return singletonList(bridges.get(currentBridge));
}
};
bridges = new CircumventionProviderImpl(appContext).getBridges();
}
@Before
public void setUp() {
IntegrationTestComponent component =
DaggerIntegrationTestComponent.builder().build();
component.inject(this);
Executor ioExecutor = Executors.newCachedThreadPool();
ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
LocationUtils locationUtils = () -> "US";
SocketFactory torSocketFactory = SocketFactory.getDefault();
factory = new TorPluginFactory(ioExecutor, scheduler, appContext,
locationUtils, eventBus, torSocketFactory,
backoffFactory, circumventionProvider, clock);
}
@Test
public void testBridges() throws Exception {
assertTrue(bridges.size() > 0);
for (int i = 0; i < bridges.size(); i++) {
testBridge(i);
}
}
private void testBridge(int bridge) throws Exception {
DuplexPlugin duplexPlugin =
factory.createPlugin(new TorPluginCallBack());
assertNotNull(duplexPlugin);
TorPlugin plugin = (TorPlugin) duplexPlugin;
currentBridge = bridge;
LOG.warning("Testing " + bridges.get(currentBridge));
try {
plugin.start();
long start = clock.currentTimeMillis();
while (clock.currentTimeMillis() - start < TIMEOUT) {
if (plugin.isRunning()) return;
clock.sleep(500);
}
if (!plugin.isRunning()) {
fail("Could not connect to Tor within timeout.");
}
} finally {
plugin.stop();
}
}
}

View File

@@ -0,0 +1,11 @@
package org.briarproject.bramble;
import org.briarproject.bramble.battery.AndroidBatteryModule;
import org.briarproject.bramble.network.AndroidNetworkModule;
public interface BrambleAndroidEagerSingletons {
void inject(AndroidBatteryModule.EagerSingletons init);
void inject(AndroidNetworkModule.EagerSingletons init);
}

View File

@@ -1,25 +1,22 @@
package org.briarproject.bramble;
import android.app.Application;
import org.briarproject.bramble.plugin.tor.CircumventionProvider;
import org.briarproject.bramble.plugin.tor.CircumventionProviderImpl;
import org.briarproject.bramble.battery.AndroidBatteryModule;
import org.briarproject.bramble.network.AndroidNetworkModule;
import org.briarproject.bramble.plugin.tor.CircumventionModule;
import org.briarproject.bramble.system.AndroidSystemModule;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module(includes = {
AndroidSystemModule.class
AndroidBatteryModule.class,
AndroidNetworkModule.class,
AndroidSystemModule.class,
CircumventionModule.class
})
public class BrambleAndroidModule {
@Provides
@Singleton
CircumventionProvider provideCircumventionProvider(Application app) {
return new CircumventionProviderImpl(app.getApplicationContext());
public static void initEagerSingletons(BrambleAndroidEagerSingletons c) {
c.inject(new AndroidBatteryModule.EagerSingletons());
c.inject(new AndroidNetworkModule.EagerSingletons());
}
}

View File

@@ -0,0 +1,108 @@
package org.briarproject.bramble.account;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.util.IoUtils;
import java.io.File;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject;
class AndroidAccountManager extends AccountManagerImpl
implements AccountManager {
private static final Logger LOG =
Logger.getLogger(AndroidAccountManager.class.getName());
private static final String PREF_DB_KEY = "key";
protected final Context appContext;
private final SharedPreferences prefs;
@Inject
AndroidAccountManager(DatabaseConfig databaseConfig,
CryptoComponent crypto, IdentityManager identityManager,
SharedPreferences prefs, Application app) {
super(databaseConfig, crypto, identityManager);
this.prefs = prefs;
appContext = app.getApplicationContext();
}
// Locking: stateChangeLock
@Override
@Nullable
protected String loadEncryptedDatabaseKey() {
String key = getDatabaseKeyFromPreferences();
if (key == null) key = super.loadEncryptedDatabaseKey();
else migrateDatabaseKeyToFile(key);
return key;
}
// Locking: stateChangeLock
@Nullable
private String getDatabaseKeyFromPreferences() {
String key = prefs.getString(PREF_DB_KEY, null);
if (key == null) LOG.info("No database key in preferences");
else LOG.info("Found database key in preferences");
return key;
}
// Locking: stateChangeLock
private void migrateDatabaseKeyToFile(String key) {
if (storeEncryptedDatabaseKey(key)) {
if (prefs.edit().remove(PREF_DB_KEY).commit())
LOG.info("Database key migrated to file");
else LOG.warning("Database key not removed from preferences");
} else {
LOG.warning("Database key not migrated to file");
}
}
@Override
public void deleteAccount() {
synchronized (stateChangeLock) {
super.deleteAccount();
SharedPreferences defaultPrefs = getDefaultSharedPreferences();
deleteAppData(prefs, defaultPrefs);
}
}
// Package access for testing
SharedPreferences getDefaultSharedPreferences() {
return PreferenceManager.getDefaultSharedPreferences(appContext);
}
// Locking: stateChangeLock
private void deleteAppData(SharedPreferences... clear) {
// Clear and commit shared preferences
for (SharedPreferences prefs : clear) {
if (!prefs.edit().clear().commit())
LOG.warning("Could not clear shared preferences");
}
// Delete files, except lib and shared_prefs directories
File dataDir = new File(appContext.getApplicationInfo().dataDir);
File[] children = dataDir.listFiles();
if (children == null) {
LOG.warning("Could not list files in app data dir");
} else {
for (File child : children) {
String name = child.getName();
if (!name.equals("lib") && !name.equals("shared_prefs")) {
IoUtils.deleteFileOrDir(child);
}
}
}
// Recreate the cache dir as some OpenGL drivers expect it to exist
if (!new File(dataDir, "cache").mkdir())
LOG.warning("Could not recreate cache dir");
}
}

View File

@@ -0,0 +1,84 @@
package org.briarproject.bramble.battery;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.battery.event.BatteryEvent;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.Service;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import javax.inject.Inject;
import static android.content.Intent.ACTION_BATTERY_CHANGED;
import static android.content.Intent.ACTION_POWER_CONNECTED;
import static android.content.Intent.ACTION_POWER_DISCONNECTED;
import static android.os.BatteryManager.BATTERY_STATUS_CHARGING;
import static android.os.BatteryManager.BATTERY_STATUS_FULL;
import static android.os.BatteryManager.EXTRA_STATUS;
import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger;
class AndroidBatteryManager implements BatteryManager, Service {
private static final Logger LOG =
getLogger(AndroidBatteryManager.class.getName());
private final Context appContext;
private final EventBus eventBus;
private final AtomicBoolean used = new AtomicBoolean(false);
private volatile BroadcastReceiver batteryReceiver = null;
@Inject
AndroidBatteryManager(Application app, EventBus eventBus) {
this.appContext = app.getApplicationContext();
this.eventBus = eventBus;
}
@Override
public boolean isCharging() {
// Get the sticky intent for ACTION_BATTERY_CHANGED
IntentFilter filter = new IntentFilter(ACTION_BATTERY_CHANGED);
Intent i = appContext.registerReceiver(null, filter);
if (i == null) return false;
int status = i.getIntExtra(EXTRA_STATUS, -1);
return status == BATTERY_STATUS_CHARGING ||
status == BATTERY_STATUS_FULL;
}
@Override
public void startService() {
if (used.getAndSet(true)) throw new IllegalStateException();
batteryReceiver = new BatteryReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_POWER_CONNECTED);
filter.addAction(ACTION_POWER_DISCONNECTED);
appContext.registerReceiver(batteryReceiver, filter);
}
@Override
public void stopService() {
if (batteryReceiver != null)
appContext.unregisterReceiver(batteryReceiver);
}
private class BatteryReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context ctx, Intent i) {
String action = i.getAction();
if (LOG.isLoggable(INFO)) LOG.info("Received broadcast " + action);
if (ACTION_POWER_CONNECTED.equals(action))
eventBus.broadcast(new BatteryEvent(true));
else if (ACTION_POWER_DISCONNECTED.equals(action))
eventBus.broadcast(new BatteryEvent(false));
}
}
}

View File

@@ -0,0 +1,27 @@
package org.briarproject.bramble.battery;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class AndroidBatteryModule {
public static class EagerSingletons {
@Inject
BatteryManager batteryManager;
}
@Provides
@Singleton
BatteryManager provideBatteryManager(LifecycleManager lifecycleManager,
AndroidBatteryManager batteryManager) {
lifecycleManager.registerService(batteryManager);
return batteryManager;
}
}

View File

@@ -0,0 +1,142 @@
package org.briarproject.bramble.network;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.network.NetworkStatus;
import org.briarproject.bramble.api.network.event.NetworkStatusEvent;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.system.Scheduler;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject;
import static android.content.Context.CONNECTIVITY_SERVICE;
import static android.content.Intent.ACTION_SCREEN_OFF;
import static android.content.Intent.ACTION_SCREEN_ON;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.logging.Level.INFO;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class AndroidNetworkManager implements NetworkManager, Service {
private static final Logger LOG =
Logger.getLogger(AndroidNetworkManager.class.getName());
// See android.net.wifi.WifiManager
private static final String WIFI_AP_STATE_CHANGED_ACTION =
"android.net.wifi.WIFI_AP_STATE_CHANGED";
private final ScheduledExecutorService scheduler;
private final EventBus eventBus;
private final Context appContext;
private final AtomicReference<Future<?>> connectivityCheck =
new AtomicReference<>();
private final AtomicBoolean used = new AtomicBoolean(false);
private volatile BroadcastReceiver networkStateReceiver = null;
@Inject
AndroidNetworkManager(@Scheduler ScheduledExecutorService scheduler,
EventBus eventBus, Application app) {
this.scheduler = scheduler;
this.eventBus = eventBus;
this.appContext = app.getApplicationContext();
}
@Override
public void startService() {
if (used.getAndSet(true)) throw new IllegalStateException();
// Register to receive network status events
networkStateReceiver = new NetworkStateReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(CONNECTIVITY_ACTION);
filter.addAction(ACTION_SCREEN_ON);
filter.addAction(ACTION_SCREEN_OFF);
filter.addAction(WIFI_AP_STATE_CHANGED_ACTION);
if (SDK_INT >= 23) filter.addAction(ACTION_DEVICE_IDLE_MODE_CHANGED);
appContext.registerReceiver(networkStateReceiver, filter);
}
@Override
public void stopService() {
if (networkStateReceiver != null)
appContext.unregisterReceiver(networkStateReceiver);
}
@Override
public NetworkStatus getNetworkStatus() {
ConnectivityManager cm = (ConnectivityManager)
appContext.getSystemService(CONNECTIVITY_SERVICE);
if (cm == null) throw new AssertionError();
NetworkInfo net = cm.getActiveNetworkInfo();
boolean connected = net != null && net.isConnected();
boolean wifi = connected && net.getType() == TYPE_WIFI;
return new NetworkStatus(connected, wifi);
}
private void updateConnectionStatus() {
eventBus.broadcast(new NetworkStatusEvent(getNetworkStatus()));
}
private void scheduleConnectionStatusUpdate(int delay, TimeUnit unit) {
Future<?> newConnectivityCheck =
scheduler.schedule(this::updateConnectionStatus, delay, unit);
Future<?> oldConnectivityCheck =
connectivityCheck.getAndSet(newConnectivityCheck);
if (oldConnectivityCheck != null) oldConnectivityCheck.cancel(false);
}
private class NetworkStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context ctx, Intent i) {
String action = i.getAction();
if (LOG.isLoggable(INFO)) LOG.info("Received broadcast " + action);
updateConnectionStatus();
if (isSleepOrDozeEvent(action)) {
// Allow time for the network to be enabled or disabled
scheduleConnectionStatusUpdate(1, MINUTES);
} else if (isApEvent(action)) {
// The state change may be broadcast before the AP address is
// visible, so delay handling the event
scheduleConnectionStatusUpdate(5, SECONDS);
}
}
private boolean isSleepOrDozeEvent(@Nullable String action) {
boolean isSleep = ACTION_SCREEN_ON.equals(action) ||
ACTION_SCREEN_OFF.equals(action);
boolean isDoze = SDK_INT >= 23 &&
ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action);
return isSleep || isDoze;
}
private boolean isApEvent(@Nullable String action) {
return WIFI_AP_STATE_CHANGED_ACTION.equals(action);
}
}
}

View File

@@ -0,0 +1,27 @@
package org.briarproject.bramble.network;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.network.NetworkManager;
import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class AndroidNetworkModule {
public static class EagerSingletons {
@Inject
NetworkManager networkManager;
}
@Provides
@Singleton
NetworkManager provideNetworkManager(LifecycleManager lifecycleManager,
AndroidNetworkManager networkManager) {
lifecycleManager.registerService(networkManager);
return networkManager;
}
}

View File

@@ -16,18 +16,27 @@ import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.AndroidUtils;
import java.io.Closeable;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import static android.bluetooth.BluetoothAdapter.ACTION_DISCOVERY_FINISHED;
import static android.bluetooth.BluetoothAdapter.ACTION_DISCOVERY_STARTED;
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED;
import static android.bluetooth.BluetoothAdapter.EXTRA_SCAN_MODE;
@@ -37,8 +46,13 @@ import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERA
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_NONE;
import static android.bluetooth.BluetoothAdapter.STATE_OFF;
import static android.bluetooth.BluetoothAdapter.STATE_ON;
import static android.bluetooth.BluetoothDevice.ACTION_FOUND;
import static android.bluetooth.BluetoothDevice.EXTRA_DEVICE;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@@ -47,8 +61,11 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
private static final Logger LOG =
Logger.getLogger(AndroidBluetoothPlugin.class.getName());
private static final int MAX_DISCOVERY_MS = 10_000;
private final AndroidExecutor androidExecutor;
private final Context appContext;
private final Clock clock;
private volatile boolean wasEnabledByUs = false;
private volatile BluetoothStateReceiver receiver = null;
@@ -58,12 +75,13 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
AndroidBluetoothPlugin(BluetoothConnectionLimiter connectionLimiter,
Executor ioExecutor, AndroidExecutor androidExecutor,
Context appContext, SecureRandom secureRandom, Backoff backoff,
DuplexPluginCallback callback, int maxLatency) {
Context appContext, SecureRandom secureRandom, Clock clock,
Backoff backoff, DuplexPluginCallback callback, int maxLatency) {
super(connectionLimiter, ioExecutor, secureRandom, backoff, callback,
maxLatency);
this.androidExecutor = androidExecutor;
this.appContext = appContext;
this.clock = clock;
}
@Override
@@ -182,6 +200,74 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
}
}
@Override
@Nullable
DuplexTransportConnection discoverAndConnect(String uuid) {
if (adapter == null) return null;
for (String address : discoverDevices()) {
try {
if (LOG.isLoggable(INFO))
LOG.info("Connecting to " + scrubMacAddress(address));
return connectTo(address, uuid);
} catch (IOException e) {
if (LOG.isLoggable(INFO)) {
LOG.info("Could not connect to "
+ scrubMacAddress(address));
}
}
}
LOG.info("Could not connect to any devices");
return null;
}
private Collection<String> discoverDevices() {
List<String> addresses = new ArrayList<>();
BlockingQueue<Intent> intents = new LinkedBlockingQueue<>();
DiscoveryReceiver receiver = new DiscoveryReceiver(intents);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_DISCOVERY_STARTED);
filter.addAction(ACTION_DISCOVERY_FINISHED);
filter.addAction(ACTION_FOUND);
appContext.registerReceiver(receiver, filter);
try {
if (adapter.startDiscovery()) {
long now = clock.currentTimeMillis();
long end = now + MAX_DISCOVERY_MS;
while (now < end) {
Intent i = intents.poll(end - now, MILLISECONDS);
if (i == null) break;
String action = i.getAction();
if (ACTION_DISCOVERY_STARTED.equals(action)) {
LOG.info("Discovery started");
} else if (ACTION_DISCOVERY_FINISHED.equals(action)) {
LOG.info("Discovery finished");
break;
} else if (ACTION_FOUND.equals(action)) {
BluetoothDevice d = i.getParcelableExtra(EXTRA_DEVICE);
String address = d.getAddress();
if (LOG.isLoggable(INFO))
LOG.info("Discovered " + scrubMacAddress(address));
if (!addresses.contains(address))
addresses.add(address);
}
now = clock.currentTimeMillis();
}
} else {
LOG.info("Could not start discovery");
}
} catch (InterruptedException e) {
LOG.info("Interrupted while discovering devices");
Thread.currentThread().interrupt();
} finally {
LOG.info("Cancelling discovery");
adapter.cancelDiscovery();
appContext.unregisterReceiver(receiver);
}
// Shuffle the addresses so we don't always try the same one first
Collections.shuffle(addresses);
return addresses;
}
private void tryToClose(@Nullable Closeable c) {
try {
if (c != null) c.close();
@@ -207,4 +293,18 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
}
}
}
private static class DiscoveryReceiver extends BroadcastReceiver {
private final BlockingQueue<Intent> intents;
private DiscoveryReceiver(BlockingQueue<Intent> intents) {
this.intents = intents;
}
@Override
public void onReceive(Context ctx, Intent intent) {
intents.add(intent);
}
}
}

View File

@@ -11,6 +11,7 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.Clock;
import java.security.SecureRandom;
import java.util.concurrent.Executor;
@@ -33,17 +34,19 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
private final Context appContext;
private final SecureRandom secureRandom;
private final EventBus eventBus;
private final Clock clock;
private final BackoffFactory backoffFactory;
public AndroidBluetoothPluginFactory(Executor ioExecutor,
AndroidExecutor androidExecutor, Context appContext,
SecureRandom secureRandom, EventBus eventBus,
SecureRandom secureRandom, EventBus eventBus, Clock clock,
BackoffFactory backoffFactory) {
this.ioExecutor = ioExecutor;
this.androidExecutor = androidExecutor;
this.appContext = appContext;
this.secureRandom = secureRandom;
this.eventBus = eventBus;
this.clock = clock;
this.backoffFactory = backoffFactory;
}
@@ -65,7 +68,7 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
MAX_POLLING_INTERVAL, BACKOFF_BASE);
AndroidBluetoothPlugin plugin = new AndroidBluetoothPlugin(
connectionLimiter, ioExecutor, androidExecutor, appContext,
secureRandom, backoff, callback, MAX_LATENCY);
secureRandom, clock, backoff, callback, MAX_LATENCY);
eventBus.addListener(plugin);
return plugin;
}

View File

@@ -1,15 +1,16 @@
package org.briarproject.bramble.plugin.tcp;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import org.briarproject.bramble.PoliteExecutor;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.network.event.NetworkStatusEvent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
@@ -20,7 +21,6 @@ import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.logging.Logger;
import javax.annotation.Nullable;
@@ -28,21 +28,13 @@ import javax.net.SocketFactory;
import static android.content.Context.CONNECTIVITY_SERVICE;
import static android.content.Context.WIFI_SERVICE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.wifi.WifiManager.EXTRA_WIFI_STATE;
import static android.os.Build.VERSION.SDK_INT;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static java.util.concurrent.TimeUnit.SECONDS;
@NotNullByDefault
class AndroidLanTcpPlugin extends LanTcpPlugin {
// See android.net.wifi.WifiManager
private static final String WIFI_AP_STATE_CHANGED_ACTION =
"android.net.wifi.WIFI_AP_STATE_CHANGED";
private static final int WIFI_AP_STATE_ENABLED = 13;
class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener {
private static final byte[] WIFI_AP_ADDRESS_BYTES =
{(byte) 192, (byte) 168, 43, 1};
@@ -60,22 +52,20 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
}
}
private final ScheduledExecutorService scheduler;
private final Context appContext;
private final Executor connectionStatusExecutor;
private final ConnectivityManager connectivityManager;
@Nullable
private final WifiManager wifiManager;
@Nullable
private volatile BroadcastReceiver networkStateReceiver = null;
private volatile SocketFactory socketFactory;
AndroidLanTcpPlugin(Executor ioExecutor, ScheduledExecutorService scheduler,
Backoff backoff, Context appContext, DuplexPluginCallback callback,
int maxLatency, int maxIdleTime) {
AndroidLanTcpPlugin(Executor ioExecutor, Context appContext,
Backoff backoff, DuplexPluginCallback callback, int maxLatency,
int maxIdleTime) {
super(ioExecutor, backoff, callback, maxLatency, maxIdleTime);
this.scheduler = scheduler;
this.appContext = appContext;
// Don't execute more than one connection status check at a time
connectionStatusExecutor =
new PoliteExecutor("AndroidLanTcpPlugin", ioExecutor, 1);
ConnectivityManager connectivityManager = (ConnectivityManager)
appContext.getSystemService(CONNECTIVITY_SERVICE);
if (connectivityManager == null) throw new AssertionError();
@@ -89,19 +79,12 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
public void start() {
if (used.getAndSet(true)) throw new IllegalStateException();
running = true;
// Register to receive network status events
networkStateReceiver = new NetworkStateReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(CONNECTIVITY_ACTION);
filter.addAction(WIFI_AP_STATE_CHANGED_ACTION);
appContext.registerReceiver(networkStateReceiver, filter);
updateConnectionStatus();
}
@Override
public void stop() {
running = false;
if (networkStateReceiver != null)
appContext.unregisterReceiver(networkStateReceiver);
tryToClose(socket);
}
@@ -120,7 +103,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
return singletonList(intToInetAddress(info.getIpAddress()));
// If we're running an access point, return its address
if (super.getLocalIpAddresses().contains(WIFI_AP_ADDRESS))
return singletonList(WIFI_AP_ADDRESS);
return singletonList(WIFI_AP_ADDRESS);
// No suitable addresses
return emptyList();
}
@@ -152,21 +135,13 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
return SocketFactory.getDefault();
}
private class NetworkStateReceiver extends BroadcastReceiver {
@Override
public void eventOccurred(Event e) {
if (e instanceof NetworkStatusEvent) updateConnectionStatus();
}
@Override
public void onReceive(Context ctx, Intent i) {
if (!running) return;
if (isApEnabledEvent(i)) {
// The state change may be broadcast before the AP address is
// visible, so delay handling the event
scheduler.schedule(this::handleConnectivityChange, 1, SECONDS);
} else {
handleConnectivityChange();
}
}
private void handleConnectivityChange() {
private void updateConnectionStatus() {
connectionStatusExecutor.execute(() -> {
if (!running) return;
Collection<InetAddress> addrs = getLocalIpAddresses();
if (addrs.contains(WIFI_AP_ADDRESS)) {
@@ -186,11 +161,6 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
socketFactory = getSocketFactory();
if (socket == null || socket.isClosed()) bind();
}
}
private boolean isApEnabledEvent(Intent i) {
return WIFI_AP_STATE_CHANGED_ACTION.equals(i.getAction()) &&
i.getIntExtra(EXTRA_WIFI_STATE, 0) == WIFI_AP_STATE_ENABLED;
}
});
}
}
}

View File

@@ -2,6 +2,7 @@ package org.briarproject.bramble.plugin.tcp;
import android.content.Context;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
@@ -11,7 +12,6 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import javax.annotation.concurrent.Immutable;
@@ -28,15 +28,14 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
private static final double BACKOFF_BASE = 1.2;
private final Executor ioExecutor;
private final ScheduledExecutorService scheduler;
private final EventBus eventBus;
private final BackoffFactory backoffFactory;
private final Context appContext;
public AndroidLanTcpPluginFactory(Executor ioExecutor,
ScheduledExecutorService scheduler, BackoffFactory backoffFactory,
Context appContext) {
public AndroidLanTcpPluginFactory(Executor ioExecutor, EventBus eventBus,
BackoffFactory backoffFactory, Context appContext) {
this.ioExecutor = ioExecutor;
this.scheduler = scheduler;
this.eventBus = eventBus;
this.backoffFactory = backoffFactory;
this.appContext = appContext;
}
@@ -55,7 +54,9 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE);
return new AndroidLanTcpPlugin(ioExecutor, scheduler, backoff,
appContext, callback, MAX_LATENCY, MAX_IDLE_TIME);
AndroidLanTcpPlugin plugin = new AndroidLanTcpPlugin(ioExecutor,
appContext, backoff, callback, MAX_LATENCY, MAX_IDLE_TIME);
eventBus.addListener(plugin);
return plugin;
}
}

View File

@@ -0,0 +1,90 @@
package org.briarproject.bramble.plugin.tor;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.PowerManager;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.util.RenewableWakeLock;
import java.io.IOException;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import javax.net.SocketFactory;
import static android.content.Context.MODE_PRIVATE;
import static android.content.Context.POWER_SERVICE;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
import static java.util.concurrent.TimeUnit.MINUTES;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class AndroidTorPlugin extends TorPlugin {
// This tag may prevent Huawei's power manager from killing us
private static final String WAKE_LOCK_TAG = "LocationManagerService";
private final Context appContext;
private final RenewableWakeLock wakeLock;
AndroidTorPlugin(Executor ioExecutor, ScheduledExecutorService scheduler,
Context appContext, NetworkManager networkManager,
LocationUtils locationUtils, SocketFactory torSocketFactory,
Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Backoff backoff,
DuplexPluginCallback callback, String architecture, int maxLatency,
int maxIdleTime) {
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, batteryManager,
backoff, callback, architecture, maxLatency, maxIdleTime,
appContext.getDir("tor", MODE_PRIVATE));
this.appContext = appContext;
PowerManager pm = (PowerManager)
appContext.getSystemService(POWER_SERVICE);
if (pm == null) throw new AssertionError();
wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK,
WAKE_LOCK_TAG, 1, MINUTES);
}
@Override
protected int getProcessId() {
return android.os.Process.myPid();
}
@Override
protected long getLastUpdateTime() {
try {
PackageManager pm = appContext.getPackageManager();
PackageInfo pi = pm.getPackageInfo(appContext.getPackageName(), 0);
return pi.lastUpdateTime;
} catch (NameNotFoundException e) {
throw new AssertionError(e);
}
}
@Override
protected void enableNetwork(boolean enable) throws IOException {
if (!running) return;
if (enable) wakeLock.acquire();
super.enableNetwork(enable);
if (!enable) wakeLock.release();
}
@Override
public void stop() {
super.stop();
wakeLock.release();
}
}

View File

@@ -3,7 +3,9 @@ package org.briarproject.bramble.plugin.tor;
import android.content.Context;
import android.os.Build;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
@@ -14,6 +16,7 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.util.AndroidUtils;
import java.util.concurrent.Executor;
@@ -25,10 +28,10 @@ import javax.net.SocketFactory;
@Immutable
@NotNullByDefault
public class TorPluginFactory implements DuplexPluginFactory {
public class AndroidTorPluginFactory implements DuplexPluginFactory {
private static final Logger LOG =
Logger.getLogger(TorPluginFactory.class.getName());
Logger.getLogger(AndroidTorPluginFactory.class.getName());
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
private static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds
@@ -39,27 +42,34 @@ public class TorPluginFactory implements DuplexPluginFactory {
private final Executor ioExecutor;
private final ScheduledExecutorService scheduler;
private final Context appContext;
private final NetworkManager networkManager;
private final LocationUtils locationUtils;
private final EventBus eventBus;
private final SocketFactory torSocketFactory;
private final BackoffFactory backoffFactory;
private final ResourceProvider resourceProvider;
private final CircumventionProvider circumventionProvider;
private final BatteryManager batteryManager;
private final Clock clock;
public TorPluginFactory(Executor ioExecutor,
public AndroidTorPluginFactory(Executor ioExecutor,
ScheduledExecutorService scheduler, Context appContext,
LocationUtils locationUtils, EventBus eventBus,
SocketFactory torSocketFactory, BackoffFactory backoffFactory,
NetworkManager networkManager, LocationUtils locationUtils,
EventBus eventBus, SocketFactory torSocketFactory,
BackoffFactory backoffFactory, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider,
Clock clock) {
BatteryManager batteryManager, Clock clock) {
this.ioExecutor = ioExecutor;
this.scheduler = scheduler;
this.appContext = appContext;
this.networkManager = networkManager;
this.locationUtils = locationUtils;
this.eventBus = eventBus;
this.torSocketFactory = torSocketFactory;
this.backoffFactory = backoffFactory;
this.resourceProvider = resourceProvider;
this.circumventionProvider = circumventionProvider;
this.batteryManager = batteryManager;
this.clock = clock;
}
@@ -96,9 +106,10 @@ public class TorPluginFactory implements DuplexPluginFactory {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorPlugin plugin = new TorPlugin(ioExecutor, scheduler, appContext,
locationUtils, torSocketFactory, clock, backoff, callback,
architecture, circumventionProvider, MAX_LATENCY, MAX_IDLE_TIME);
AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, scheduler,
appContext, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, batteryManager,
backoff, callback, architecture, MAX_LATENCY, MAX_IDLE_TIME);
eventBus.addListener(plugin);
return plugin;
}

View File

@@ -0,0 +1,32 @@
package org.briarproject.bramble.system;
import android.app.Application;
import android.content.Context;
import android.content.res.Resources;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.ResourceProvider;
import java.io.InputStream;
import javax.inject.Inject;
@NotNullByDefault
class AndroidResourceProvider implements ResourceProvider {
private final Context appContext;
@Inject
AndroidResourceProvider(Application app) {
this.appContext = app.getApplicationContext();
}
@Override
public InputStream getResourceInputStream(String name, String extension) {
Resources res = appContext.getResources();
// extension is ignored on Android, resources are retrieved without it
int resId =
res.getIdentifier(name, "raw", appContext.getPackageName());
return res.openRawResource(resId);
}
}

View File

@@ -1,9 +1,8 @@
package org.briarproject.bramble.system;
import android.app.Application;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.api.system.SecureRandomProvider;
import javax.inject.Singleton;
@@ -16,18 +15,26 @@ public class AndroidSystemModule {
@Provides
@Singleton
SecureRandomProvider provideSecureRandomProvider(Application app) {
return new AndroidSecureRandomProvider(app);
SecureRandomProvider provideSecureRandomProvider(
AndroidSecureRandomProvider provider) {
return provider;
}
@Provides
LocationUtils provideLocationUtils(Application app) {
return new AndroidLocationUtils(app);
LocationUtils provideLocationUtils(AndroidLocationUtils locationUtils) {
return locationUtils;
}
@Provides
@Singleton
AndroidExecutor provideAndroidExecutor(Application app) {
return new AndroidExecutorImpl(app);
AndroidExecutor provideAndroidExecutor(
AndroidExecutorImpl androidExecutor) {
return androidExecutor;
}
@Provides
@Singleton
ResourceProvider provideResourceProvider(AndroidResourceProvider provider) {
return provider;
}
}

View File

@@ -3,7 +3,6 @@ package org.briarproject.bramble.util;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import android.provider.Settings;
@@ -12,15 +11,12 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.logging.Logger;
import static android.content.Context.MODE_PRIVATE;
import static android.os.Build.VERSION.SDK_INT;
public class AndroidUtils {
private static final Logger LOG =
Logger.getLogger(AndroidUtils.class.getName());
// Fake Bluetooth address returned by BluetoothAdapter on API 23 and later
private static final String FAKE_BLUETOOTH_ADDRESS = "02:00:00:00:00:00";
@@ -29,7 +25,7 @@ public class AndroidUtils {
@SuppressWarnings("deprecation")
public static Collection<String> getSupportedArchitectures() {
List<String> abis = new ArrayList<>();
if (Build.VERSION.SDK_INT >= 21) {
if (SDK_INT >= 21) {
abis.addAll(Arrays.asList(Build.SUPPORTED_ABIS));
} else {
abis.add(Build.CPU_ABI);
@@ -58,30 +54,6 @@ public class AndroidUtils {
&& !address.equals(FAKE_BLUETOOTH_ADDRESS);
}
public static void deleteAppData(Context ctx, SharedPreferences... clear) {
// Clear and commit shared preferences
for (SharedPreferences prefs : clear) {
if (!prefs.edit().clear().commit())
LOG.warning("Could not clear shared preferences");
}
// Delete files, except lib and shared_prefs directories
File dataDir = new File(ctx.getApplicationInfo().dataDir);
File[] children = dataDir.listFiles();
if (children == null) {
LOG.warning("Could not list files in app data dir");
} else {
for (File child : children) {
String name = child.getName();
if (!name.equals("lib") && !name.equals("shared_prefs")) {
IoUtils.deleteFileOrDir(child);
}
}
}
// Recreate the cache dir as some OpenGL drivers expect it to exist
if (!new File(dataDir, "cache").mkdir())
LOG.warning("Could not recreate cache dir");
}
public static File getReportDir(Context ctx) {
return ctx.getDir(STORED_REPORTS, MODE_PRIVATE);
}

View File

@@ -1,8 +0,0 @@
Bridge 131.252.210.150:8081 0E858AC201BF0F3FA3C462F64844CBFFC7297A42
Bridge 67.205.189.122:8443 12D64D5D44E20169585E7378580C0D33A872AD98
Bridge 45.32.148.146:8443 0CE016FB2462D8BF179AE71F7D702D09DEAC3F1D
Bridge 148.251.90.59:7510 019F727CA6DCA6CA5C90B55E477B7D87981E75BC
Bridge 195.91.239.8:9001 BA83F62551545655BBEBBFF353A45438D73FD45A
Bridge 185.165.184.217:6429 64CC94BEC51254E4409AD059192833854CCB95F0
Bridge 45.55.1.74:8443 6F18FEFBB0CAECD5ABA755312FCCB34FC11A7AB8
Bridge 95.85.40.163:9001 40057BE9CF76B6C5BDBE713753468BE0A990DE9C

View File

@@ -0,0 +1,162 @@
package org.briarproject.bramble.account;
import android.app.Application;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.jmock.Expectations;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
import static org.briarproject.bramble.util.StringUtils.toHexString;
public class AndroidAccountManagerTest extends BrambleMockTestCase {
private final SharedPreferences prefs =
context.mock(SharedPreferences.class, "prefs");
private final SharedPreferences defaultPrefs =
context.mock(SharedPreferences.class, "defaultPrefs");
private final DatabaseConfig databaseConfig =
context.mock(DatabaseConfig.class);
private final CryptoComponent crypto = context.mock(CryptoComponent.class);
private final IdentityManager identityManager =
context.mock(IdentityManager.class);
private final SharedPreferences.Editor
editor = context.mock(SharedPreferences.Editor.class);
private final Application app;
private final ApplicationInfo applicationInfo;
private final String encryptedKeyHex = toHexString(getRandomBytes(123));
private final File testDir = getTestDirectory();
private final File keyDir = new File(testDir, "key");
private final File keyFile = new File(keyDir, "db.key");
private final File keyBackupFile = new File(keyDir, "db.key.bak");
private final File dbDir = new File(testDir, "db");
private AndroidAccountManager accountManager;
public AndroidAccountManagerTest() {
context.setImposteriser(ClassImposteriser.INSTANCE);
app = context.mock(Application.class);
applicationInfo = new ApplicationInfo();
applicationInfo.dataDir = testDir.getAbsolutePath();
}
@Before
public void setUp() {
context.checking(new Expectations() {{
allowing(databaseConfig).getDatabaseDirectory();
will(returnValue(dbDir));
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
allowing(app).getApplicationContext();
will(returnValue(app));
}});
accountManager = new AndroidAccountManager(databaseConfig, crypto,
identityManager, prefs, app) {
@Override
SharedPreferences getDefaultSharedPreferences() {
return defaultPrefs;
}
};
}
@Test
public void testDbKeyIsMigratedFromPreferencesToFile() {
context.checking(new Expectations() {{
oneOf(prefs).getString("key", null);
will(returnValue(encryptedKeyHex));
oneOf(prefs).edit();
will(returnValue(editor));
oneOf(editor).remove("key");
will(returnValue(editor));
oneOf(editor).commit();
will(returnValue(true));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
assertEquals(encryptedKeyHex,
accountManager.loadEncryptedDatabaseKey());
assertTrue(keyFile.exists());
assertTrue(keyBackupFile.exists());
}
@Test
public void testDeleteAccountClearsSharedPrefsAndDeletesFiles()
throws Exception {
// Directories 'lib' and 'shared_prefs' should be spared
File libDir = new File(testDir, "lib");
File libFile = new File(libDir, "file");
File sharedPrefsDir = new File(testDir, "shared_prefs");
File sharedPrefsFile = new File(sharedPrefsDir, "file");
// Directory 'cache' should be emptied
File cacheDir = new File(testDir, "cache");
File cacheFile = new File(cacheDir, "file");
// Other directories should be deleted
File potatoDir = new File(testDir, ".potato");
File potatoFile = new File(potatoDir, "file");
context.checking(new Expectations() {{
oneOf(prefs).edit();
will(returnValue(editor));
oneOf(editor).clear();
will(returnValue(editor));
oneOf(editor).commit();
will(returnValue(true));
oneOf(defaultPrefs).edit();
will(returnValue(editor));
oneOf(editor).clear();
will(returnValue(editor));
oneOf(editor).commit();
will(returnValue(true));
oneOf(app).getApplicationInfo();
will(returnValue(applicationInfo));
}});
assertTrue(dbDir.mkdirs());
assertTrue(keyDir.mkdirs());
assertTrue(libDir.mkdirs());
assertTrue(libFile.createNewFile());
assertTrue(sharedPrefsDir.mkdirs());
assertTrue(sharedPrefsFile.createNewFile());
assertTrue(cacheDir.mkdirs());
assertTrue(cacheFile.createNewFile());
assertTrue(potatoDir.mkdirs());
assertTrue(potatoFile.createNewFile());
accountManager.deleteAccount();
assertFalse(dbDir.exists());
assertFalse(keyDir.exists());
assertTrue(libDir.exists());
assertTrue(libFile.exists());
assertTrue(sharedPrefsDir.exists());
assertTrue(sharedPrefsFile.exists());
assertTrue(cacheDir.exists());
assertFalse(cacheFile.exists());
assertFalse(potatoDir.exists());
assertFalse(potatoFile.exists());
}
@After
public void tearDown() {
deleteTestDirectory(testDir);
}
}

View File

@@ -0,0 +1,101 @@
dependencyVerification {
verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.android.tools.analytics-library:protos:26.2.1:protos-26.2.1.jar:2f371f5b1f551e85ab08be4d6a2873471b3d44afd1ebf6aa3298f3b796bf691f',
'com.android.tools.analytics-library:shared:26.2.1:shared-26.2.1.jar:4c1e4e705fa4d45f23aaea230557f6508155012d9c296337787c1d7b26a97f5a',
'com.android.tools.analytics-library:tracker:26.2.1:tracker-26.2.1.jar:4a624ecc976539f755ddb0bb8dfc2dd3d08326cfec59a098dbd70f701ca7fb75',
'com.android.tools.build:aapt2:3.2.1-4818971:aapt2-3.2.1-4818971-linux.jar:f431b6f96c91a2c155144b091a9c97d9805c589fe8efc9c930b6cd346cb60a1e',
'com.android.tools.build:apksig:3.2.1:apksig-3.2.1.jar:2b46f2feffea66037aab29e4261b2433c190194a6ef97b958511eb157f2ccba5',
'com.android.tools.build:apkzlib:3.2.1:apkzlib-3.2.1.jar:c39ad0313905932431fe81c8899c2cf39a4d92ad6c4edcaa4b25432f461452aa',
'com.android.tools.build:builder-model:3.2.1:builder-model-3.2.1.jar:a9f68e6abcec122f9cb5ad352d3f05a3eb03acbcdca95e4d25c16310c2c965ff',
'com.android.tools.build:builder-test-api:3.2.1:builder-test-api-3.2.1.jar:533ac6c2b5884bb54967a33791f2628dfdfac7981af39417a333b43d4379b6be',
'com.android.tools.build:builder:3.2.1:builder-3.2.1.jar:aedcbfd115dbe91d09b4113e66ef50589b558d0aa3b2f133b1d867c9b87fae83',
'com.android.tools.build:gradle-api:3.2.1:gradle-api-3.2.1.jar:57cf0ac5ac1dca8afdb3f62b94265e776e7dcfa641cc3844fb53a05193de208d',
'com.android.tools.build:manifest-merger:26.2.1:manifest-merger-26.2.1.jar:8830573263361035d38cfdcb51e2db94029c93865b21334f5fbf8a27984281a6',
'com.android.tools.ddms:ddmlib:26.2.1:ddmlib-26.2.1.jar:a4bf0a29a19980bf27269465cc782064656750b77c26728f82f9e148b705218b',
'com.android.tools.external.com-intellij:intellij-core:26.2.1:intellij-core-26.2.1.jar:4925ad1892c2687cb1a63427d440ef519c8c59215fefe0dc5d541d5d411fcafe',
'com.android.tools.external.com-intellij:kotlin-compiler:26.2.1:kotlin-compiler-26.2.1.jar:daa064fd708f340ee25fb9823c4c74104ac77f1370b76d907eb9ae6daec0a2ae',
'com.android.tools.external.org-jetbrains:uast:26.2.1:uast-26.2.1.jar:f10f7258d2ab9189562cc0f9ad838c0378fdba439229173390a99de02ebac75b',
'com.android.tools.layoutlib:layoutlib-api:26.2.1:layoutlib-api-26.2.1.jar:ddbf4fca123733fa011595b1cc1f4ac2937ed327b60990711fafc33c775c2ade',
'com.android.tools.lint:lint-api:26.2.1:lint-api-26.2.1.jar:3b57e739de567b98bc9ab56c2c0ee66fc026b4adf5843e8f9804ca0666a6f66e',
'com.android.tools.lint:lint-checks:26.2.1:lint-checks-26.2.1.jar:c86f4cc9aaee722ee4ad70062f7b5af91e9b041914af27adc09f545ab0fb3bc6',
'com.android.tools.lint:lint-gradle-api:26.2.1:lint-gradle-api-26.2.1.jar:2283e7af32e301565f2a797e531f0fc8c648077d457afb3ffdddbee638976c2f',
'com.android.tools.lint:lint-gradle:26.2.1:lint-gradle-26.2.1.jar:8fd90b2f3ec788cbb9801c07ab3e1ea2255aa31a6093157d7ea0ff13d0315ecb',
'com.android.tools.lint:lint-kotlin:26.2.1:lint-kotlin-26.2.1.jar:7a6a5d2b18f69cf1b900d857c2632b4c683713c533295933b8b759f8cab4a877',
'com.android.tools.lint:lint:26.2.1:lint-26.2.1.jar:7848b82ae988b90dee259ae7c7e86e05cbf52db6cd21c8bbd38ce7df08f3f8c5',
'com.android.tools:annotations:26.2.1:annotations-26.2.1.jar:7391c6a1e080174b96e64ceb078dadd31ce4d8a2d2fee0ec65be202126f90f24',
'com.android.tools:common:26.2.1:common-26.2.1.jar:a50aab2d6411ff68f4004a87c7e93d87d8e980a0ec3b352246549897ea2d78e5',
'com.android.tools:dvlib:26.2.1:dvlib-26.2.1.jar:72a83bf2839b1df9b1fbf67ba45d1bfb9f966cd774da4320c762b2be8f1688aa',
'com.android.tools:repository:26.2.1:repository-26.2.1.jar:fa74dae09103faef703df38550ad8fa244c5b6d1bf90d6198be932292b3d9cc1',
'com.android.tools:sdk-common:26.2.1:sdk-common-26.2.1.jar:759d4b292ca69a35cf961fca377b54158fc6c88108978006999442e80a011cf4',
'com.android.tools:sdklib:26.2.1:sdklib-26.2.1.jar:248df7ad5eac4aeb6f96c394c76760de4b7b89ac056e54d0c21a739368b91b45',
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
'com.google.code.gson:gson:2.8.0:gson-2.8.0.jar:c6221763bd79c4f1c3dc7f750b5f29a0bb38b367b81314c4f71896e340c40825',
'com.google.dagger:dagger-compiler:2.19:dagger-compiler-2.19.jar:27a4b202a2de908182edb261f8c0a264e08e5e4733d7514bc7fbf0d31da5c0fc',
'com.google.dagger:dagger-producers:2.19:dagger-producers-2.19.jar:a17663abe0fc38b676026950907d4c5f5e2bf338375415861eaff6e3bdb0b768',
'com.google.dagger:dagger-spi:2.19:dagger-spi-2.19.jar:e7a6379d82c841f6aac2866948ad1eed716528707814602842a8d844ce04e2e1',
'com.google.dagger:dagger:2.19:dagger-2.19.jar:514b6f1e0727c6572e1d65cb27e4ae668b7aeaeb93a29515182965265b609939',
'com.google.errorprone:error_prone_annotations:2.0.18:error_prone_annotations-2.0.18.jar:cb4cfad870bf563a07199f3ebea5763f0dec440fcda0b318640b1feaa788656b',
'com.google.errorprone:error_prone_annotations:2.1.3:error_prone_annotations-2.1.3.jar:03d0329547c13da9e17c634d1049ea2ead093925e290567e1a364fd6b1fc7ff8',
'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30',
'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e',
'com.google.guava:guava:23.0:guava-23.0.jar:7baa80df284117e5b945b19b98d367a85ea7b7801bd358ff657946c3bd1b6596',
'com.google.guava:guava:25.0-jre:guava-25.0-jre.jar:3fd4341776428c7e0e5c18a7c10de129475b69ab9d30aeafbb5c277bb6074fa9',
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:40ceb7157feb263949e0f503fe5f71689333a621021aa20ce0d0acee3badaa0f',
'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd',
'com.google.protobuf:protobuf-java:3.4.0:protobuf-java-3.4.0.jar:dce7e66b32456a1b1198da0caff3a8acb71548658391e798c79369241e6490a4',
'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
'com.sun.istack:istack-commons-runtime:2.21:istack-commons-runtime-2.21.jar:c33e67a0807095f02a0e2da139412dd7c4f9cc1a4c054b3e434f96831ba950f4',
'com.sun.xml.fastinfoset:FastInfoset:1.2.13:FastInfoset-1.2.13.jar:27a77db909f3c2833c0b1a37c55af1db06045118ad2eed96ce567b6632bce038',
'commons-codec:commons-codec:1.9:commons-codec-1.9.jar:ad19d2601c3abf0b946b5c3a4113e226a8c1e3305e395b90013b78dd94a723ce',
'commons-logging:commons-logging:1.2:commons-logging-1.2.jar:daddea1ea0be0f56978ab3006b8ac92834afeefbd9b7e4e6316fca57df0fa636',
'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'javax.xml.bind:jaxb-api:2.2.12-b140109.1041:jaxb-api-2.2.12-b140109.1041.jar:b5e60cd8b7b5ff01ce4a74c5dd008f4fbd14ced3495d0b47b85cfedc182211f2',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5',
'net.sf.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.apache.commons:commons-compress:1.12:commons-compress-1.12.jar:2c1542faf343185b7cab9c3d55c8ae5471d6d095d3887a4adefdbdf2984dc0b6',
'org.apache.httpcomponents:httpclient:4.5.2:httpclient-4.5.2.jar:0dffc621400d6c632f55787d996b8aeca36b30746a716e079a985f24d8074057',
'org.apache.httpcomponents:httpcore:4.4.5:httpcore-4.4.5.jar:64d5453874cab7e40a7065cb01a9a9ca1053845a9786b478878b679e0580cec3',
'org.apache.httpcomponents:httpmime:4.5.2:httpmime-4.5.2.jar:231a3f7e4962053db2be8461d5422e68fc458a3a7dd7d8ada803a348e21f8f07',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
'org.briarproject:obfs4proxy-android:0.0.7:obfs4proxy-android-0.0.7.zip:abdfb5d889d848de9bf214f9276abbf454808a505b870819eccc9a9e985bf617',
'org.briarproject:tor-android:0.3.4.8:tor-android-0.3.4.8.zip:989a0352d9d8d8172cd6c2137654e165e5d2beb10ed1211bab3814e224ad1926',
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'org.codehaus.groovy:groovy-all:2.4.12:groovy-all-2.4.12.jar:6a56af4bd48903d56bec62821876cadefafd007360cc6bd0d8f7aa8d72b38be4',
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
'org.glassfish.jaxb:jaxb-core:2.2.11:jaxb-core-2.2.11.jar:37bcaee8ebb04362c8352a5bf6221b86967ecdab5164c696b10b9a2bb587b2aa',
'org.glassfish.jaxb:jaxb-runtime:2.2.11:jaxb-runtime-2.2.11.jar:a874f2351cfba8e2946be3002d10c18a6da8f21b52ba2acf52f2b85d5520ed70',
'org.glassfish.jaxb:txw2:2.2.11:txw2-2.2.11.jar:272a3ccad45a4511351920cd2a8633c53cab8d5220c7a92954da5526bb5eafea',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.jetbrains.kotlin:kotlin-reflect:1.2.0:kotlin-reflect-1.2.0.jar:4f48a872bad6e4d9c053f4ad610d11e4012ad7e58dc19a03dd5eb811f36069dd',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.2.71:kotlin-stdlib-common-1.2.71.jar:63999687ff2fce8a592dd180ffbbf8f1d21c26b4044c55cdc74ff3cf3b3cf328',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.71:kotlin-stdlib-jdk7-1.2.71.jar:b136bd61b240e07d4d92ce00d3bd1dbf584400a7bf5f220c2f3cd22446858082',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.71:kotlin-stdlib-jdk8-1.2.71.jar:ac3c8abf47790b64b4f7e2509a53f0c145e061ac1612a597520535d199946ea9',
'org.jetbrains.kotlin:kotlin-stdlib:1.2.71:kotlin-stdlib-1.2.71.jar:4c895c270b87f5fec2a2796e1d89c15407ee821de961527c28588bb46afbc68b',
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.jvnet.staxex:stax-ex:1.7.7:stax-ex-1.7.7.jar:a31ff7d77163c0deb09e7fee59ad35ae44c2cee2cc8552a116ccd1583d813fb4',
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm-analysis:6.0:asm-analysis-6.0.jar:2f1a6387219c3a6cc4856481f221b03bd9f2408a326d416af09af5d6f608c1f4',
'org.ow2.asm:asm-commons:6.0:asm-commons-6.0.jar:f1bce5c648a96a017bdcd01fe5d59af9845297fd7b79b81c015a6fbbd9719abf',
'org.ow2.asm:asm-tree:6.0:asm-tree-6.0.jar:887998fb69727c8759e4d253f856822801e33f9fd4caa566b3ac58ee92106215',
'org.ow2.asm:asm-util:6.0:asm-util-6.0.jar:356afebdb0f870175262e5188f8709a3b17aa2a5a6a4b0340b04d4b449bca5f6',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.ow2.asm:asm:6.0:asm-6.0.jar:dd8971c74a4e697899a8e95caae4ea8760ea6c486dc6b97b1795e75760420461',
]
}

View File

@@ -4,46 +4,20 @@ targetCompatibility = 1.8
apply plugin: 'ru.vyarus.animalsniffer'
apply plugin: 'witness'
apply from: 'witness.gradle'
dependencies {
implementation "com.google.dagger:dagger:2.0.2"
implementation "com.google.dagger:dagger:2.19"
implementation 'com.google.code.findbugs:jsr305:3.0.2'
testImplementation 'junit:junit:4.12'
testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:2.8.2"
testImplementation "org.hamcrest:hamcrest-library:1.3"
testImplementation "org.hamcrest:hamcrest-core:1.3"
signature 'org.codehaus.mojo.signature:java16:1.1@signature'
}
dependencyVerification {
verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90',
'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
]
}
// needed to make test output available to bramble-core and briar-core
configurations {
testOutput.extendsFrom(testCompile)

View File

@@ -0,0 +1,10 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface Nameable {
String getName();
}

View File

@@ -0,0 +1,26 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class Pair<A, B> {
private final A first;
private final B second;
public Pair(A first, B second) {
this.first = first;
this.second = second;
}
public A getFirst() {
return first;
}
public B getSecond() {
return second;
}
}

View File

@@ -38,4 +38,18 @@ public abstract class StringMap extends Hashtable<String, String> {
public void putInt(String key, int value) {
put(key, String.valueOf(value));
}
public long getLong(String key, long defaultValue) {
String s = get(key);
if (s == null) return defaultValue;
try {
return Long.valueOf(s);
} catch (NumberFormatException e) {
return defaultValue;
}
}
public void putLong(String key, long value) {
put(key, String.valueOf(value));
}
}

View File

@@ -1,9 +0,0 @@
package org.briarproject.bramble.api;
import java.io.IOException;
/**
* An exception that indicates an unrecoverable version mismatch.
*/
public class UnsupportedVersionException extends IOException {
}

View File

@@ -0,0 +1,70 @@
package org.briarproject.bramble.api.account;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
@NotNullByDefault
public interface AccountManager {
/**
* Returns true if the manager has the database key. This will be false
* before {@link #createAccount(String, String)} or {@link #signIn(String)}
* has been called, and true after {@link #createAccount(String, String)}
* or {@link #signIn(String)} has returned true, until the process exits.
*/
boolean hasDatabaseKey();
/**
* Returns the database key if the manager has it. This will be null
* before {@link #createAccount(String, String)} or {@link #signIn(String)}
* has been called, and non-null after
* {@link #createAccount(String, String)} or {@link #signIn(String)} has
* returned true, until the process exits.
*/
@Nullable
SecretKey getDatabaseKey();
/**
* Returns true if the encrypted database key can be loaded from disk, and
* the database directory exists and is a directory.
*/
boolean accountExists();
/**
* Creates an identity with the given name and registers it with the
* {@link IdentityManager}. Creates a database key, encrypts it with the
* given password and stores it on disk.
* <p/>
* This method does not create the database directory, so
* {@link #accountExists()} will continue to return false until the
* database directory is created.
*/
boolean createAccount(String name, String password);
/**
* Deletes all account state from disk. {@link #accountExists()} will
* return false after this method returns.
*/
void deleteAccount();
/**
* Loads the encrypted database key from disk and decrypts it with the
* given password.
*
* @return true if the database key was successfully loaded and decrypted.
*/
boolean signIn(String password);
/**
* Loads the encrypted database key from disk, decrypts it with the old
* password, encrypts it with the new password, and stores it on disk,
* replacing the old key.
*
* @return true if the database key was successfully loaded, re-encrypted
* and stored.
*/
boolean changePassword(String oldPassword, String newPassword);
}

View File

@@ -0,0 +1,6 @@
package org.briarproject.bramble.api.battery;
public interface BatteryManager {
boolean isCharging();
}

View File

@@ -0,0 +1,19 @@
package org.briarproject.bramble.api.battery.event;
import org.briarproject.bramble.api.event.Event;
/**
* An event that is broadcast when the device starts or stops charging.
*/
public class BatteryEvent extends Event {
private final boolean charging;
public BatteryEvent(boolean charging) {
this.charging = charging;
}
public boolean isCharging() {
return charging;
}
}

View File

@@ -1,7 +1,6 @@
package org.briarproject.briar.client;
package org.briarproject.bramble.api.client;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataParser;
@@ -12,7 +11,7 @@ import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.InvalidMessageException;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.ValidationManager.IncomingMessageHook;
import org.briarproject.bramble.api.sync.validation.IncomingMessageHook;
import javax.annotation.concurrent.Immutable;
@@ -62,5 +61,4 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook {
throw new InvalidMessageException(e);
}
}
}

View File

@@ -9,14 +9,13 @@ import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.InvalidMessageException;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageContext;
import org.briarproject.bramble.api.sync.ValidationManager.MessageValidator;
import org.briarproject.bramble.api.sync.validation.MessageValidator;
import org.briarproject.bramble.api.system.Clock;
import java.util.logging.Logger;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
@Immutable
@@ -49,14 +48,9 @@ public abstract class BdfMessageValidator implements MessageValidator {
throw new InvalidMessageException(
"Timestamp is too far in the future");
}
byte[] raw = m.getRaw();
if (raw.length <= MESSAGE_HEADER_LENGTH) {
throw new InvalidMessageException("Message is too short");
}
try {
BdfList body = clientHelper.toList(raw, MESSAGE_HEADER_LENGTH,
raw.length - MESSAGE_HEADER_LENGTH);
BdfMessageContext result = validateMessage(m, g, body);
BdfList bodyList = clientHelper.toList(m.getBody());
BdfMessageContext result = validateMessage(m, g, bodyList);
Metadata meta = metadataEncoder.encode(result.getDictionary());
return new MessageContext(meta, result.getDependencies());
} catch (FormatException e) {

View File

@@ -16,8 +16,6 @@ import org.briarproject.bramble.api.sync.MessageId;
import java.security.GeneralSecurityException;
import java.util.Map;
import javax.annotation.Nullable;
@NotNullByDefault
public interface ClientHelper {
@@ -32,16 +30,12 @@ public interface ClientHelper {
Message createMessageForStoringMetadata(GroupId g);
@Nullable
Message getMessage(MessageId m) throws DbException;
@Nullable
Message getMessage(Transaction txn, MessageId m) throws DbException;
@Nullable
BdfList getMessageAsList(MessageId m) throws DbException, FormatException;
@Nullable
BdfList getMessageAsList(Transaction txn, MessageId m) throws DbException,
FormatException;

View File

@@ -4,8 +4,12 @@ import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.util.StringUtils.toUtf8;
@Immutable
@NotNullByDefault
public class Contact {
@@ -13,13 +17,21 @@ public class Contact {
private final ContactId id;
private final Author author;
private final AuthorId localAuthorId;
@Nullable
private final String alias;
private final boolean verified, active;
public Contact(ContactId id, Author author, AuthorId localAuthorId,
boolean verified, boolean active) {
@Nullable String alias, boolean verified, boolean active) {
if (alias != null) {
int aliasLength = toUtf8(alias).length;
if (aliasLength == 0 || aliasLength > MAX_AUTHOR_NAME_LENGTH)
throw new IllegalArgumentException();
}
this.id = id;
this.author = author;
this.localAuthorId = localAuthorId;
this.alias = alias;
this.verified = verified;
this.active = active;
}
@@ -36,6 +48,11 @@ public class Contact {
return localAuthorId;
}
@Nullable
public String getAlias() {
return alias;
}
public boolean isVerified() {
return verified;
}

View File

@@ -5,18 +5,21 @@ import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.AuthorInfo;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Collection;
import javax.annotation.Nullable;
@NotNullByDefault
public interface ContactManager {
/**
* Registers a hook to be called whenever a contact is added or removed.
* This method should be called before
* {@link LifecycleManager#startServices(String)}.
* {@link LifecycleManager#startServices(SecretKey)}.
*/
void registerContactHook(ContactHook hook);
@@ -93,6 +96,18 @@ public interface ContactManager {
void setContactActive(Transaction txn, ContactId c, boolean active)
throws DbException;
/**
* Sets an alias name for the contact or unsets it if alias is null.
*/
void setContactAlias(Transaction txn, ContactId c, @Nullable String alias)
throws DbException;
/**
* Sets an alias name for the contact or unsets it if alias is null.
*/
void setContactAlias(ContactId c, @Nullable String alias)
throws DbException;
/**
* Return true if a contact with this name and public key already exists
*/
@@ -105,6 +120,16 @@ public interface ContactManager {
boolean contactExists(AuthorId remoteAuthorId, AuthorId localAuthorId)
throws DbException;
/**
* Returns the {@link AuthorInfo} for the given author.
*/
AuthorInfo getAuthorInfo(AuthorId a) throws DbException;
/**
* Returns the {@link AuthorInfo} for the given author.
*/
AuthorInfo getAuthorInfo(Transaction txn, AuthorId a) throws DbException;
interface ContactHook {
void addingContact(Transaction txn, Contact c) throws DbException;

View File

@@ -0,0 +1,71 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Nullable;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
import static org.briarproject.bramble.util.StringUtils.toHexString;
@NotNullByDefault
public class BdfStringUtils {
public static String toString(@Nullable Object o) throws FormatException {
return toString(o, 0);
}
private static String toString(@Nullable Object o, int indent)
throws FormatException {
if (o == null || o == NULL_VALUE) return "null";
if (o instanceof Boolean) return o.toString();
if (o instanceof Number) return o.toString();
if (o instanceof String) return "\"" + o + "\"";
if (o instanceof Bytes)
return "x" + toHexString(((Bytes) o).getBytes());
if (o instanceof byte[])
return "x" + toHexString((byte[]) o);
if (o instanceof List) {
List<?> list = (List) o;
StringBuilder sb = new StringBuilder();
sb.append("[\n");
int i = 0, size = list.size();
for (Object e : list) {
indent(sb, indent + 1);
sb.append(toString(e, indent + 1));
if (i++ < size - 1) sb.append(',');
sb.append('\n');
}
indent(sb, indent);
sb.append(']');
return sb.toString();
}
if (o instanceof Map) {
Map<?, ?> map = (Map) o;
StringBuilder sb = new StringBuilder();
sb.append("{\n");
int i = 0, size = map.size();
for (Entry e : map.entrySet()) {
indent(sb, indent + 1);
sb.append(toString(e.getKey(), indent + 1));
sb.append(": ");
sb.append(toString(e.getValue(), indent + 1));
if (i++ < size - 1) sb.append(',');
sb.append('\n');
}
indent(sb, indent);
sb.append('}');
return sb.toString();
}
throw new FormatException();
}
private static void indent(StringBuilder sb, int indent) {
for (int i = 0; i < indent; i++) sb.append('\t');
}
}

View File

@@ -2,6 +2,7 @@ package org.briarproject.bramble.api.db;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor;
@@ -18,6 +19,7 @@ import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.MessageStatus;
import org.briarproject.bramble.api.sync.Offer;
import org.briarproject.bramble.api.sync.Request;
import org.briarproject.bramble.api.sync.validation.MessageState;
import org.briarproject.bramble.api.transport.KeySet;
import org.briarproject.bramble.api.transport.KeySetId;
import org.briarproject.bramble.api.transport.TransportKeys;
@@ -27,8 +29,6 @@ import java.util.Map;
import javax.annotation.Nullable;
import static org.briarproject.bramble.api.sync.ValidationManager.State;
/**
* Encapsulates the database implementation and exposes high-level operations
* to other components.
@@ -44,7 +44,8 @@ public interface DatabaseComponent {
* @throws DataTooOldException if the data uses an older schema than the
* current code and cannot be migrated
*/
boolean open(@Nullable MigrationListener listener) throws DbException;
boolean open(SecretKey key, @Nullable MigrationListener listener)
throws DbException;
/**
* Waits for any open transactions to finish and closes the database.
@@ -74,6 +75,27 @@ public interface DatabaseComponent {
*/
void endTransaction(Transaction txn);
/**
* Runs the given task within a transaction.
*/
<E extends Exception> void transaction(boolean readOnly,
DbRunnable<E> task) throws DbException, E;
/**
* Runs the given task within a transaction and returns the result of the
* task.
*/
<R, E extends Exception> R transactionWithResult(boolean readOnly,
DbCallable<R, E> task) throws DbException, E;
/**
* Runs the given task within a transaction and returns the result of the
* task, which may be null.
*/
@Nullable
<R, E extends Exception> R transactionWithNullableResult(boolean readOnly,
NullableDbCallable<R, E> task) throws DbException, E;
/**
* Stores a contact associated with the given local and remote pseudonyms,
* and returns an ID for the contact.
@@ -149,13 +171,13 @@ public interface DatabaseComponent {
throws DbException;
/**
* Returns a batch of raw messages for the given contact, with a total
* length less than or equal to the given length, for transmission over a
* Returns a batch of messages for the given contact, with a total length
* less than or equal to the given length, for transmission over a
* transport with the given maximum latency. Returns null if there are no
* sendable messages that fit in the given length.
*/
@Nullable
Collection<byte[]> generateBatch(Transaction txn, ContactId c,
Collection<Message> generateBatch(Transaction txn, ContactId c,
int maxLength, int maxLatency) throws DbException;
/**
@@ -176,14 +198,14 @@ public interface DatabaseComponent {
throws DbException;
/**
* Returns a batch of raw messages for the given contact, with a total
* length less than or equal to the given length, for transmission over a
* Returns a batch of messages for the given contact, with a total length
* less than or equal to the given length, for transmission over a
* transport with the given maximum latency. Only messages that have been
* requested by the contact are returned. Returns null if there are no
* sendable messages that fit in the given length.
*/
@Nullable
Collection<byte[]> generateRequestedBatch(Transaction txn, ContactId c,
Collection<Message> generateRequestedBatch(Transaction txn, ContactId c,
int maxLength, int maxLatency) throws DbException;
/**
@@ -261,13 +283,22 @@ public interface DatabaseComponent {
*/
Collection<LocalAuthor> getLocalAuthors(Transaction txn) throws DbException;
/**
* Returns the message with the given ID.
* <p/>
* Read-only.
*
* @throws MessageDeletedException if the message has been deleted
*/
Message getMessage(Transaction txn, MessageId m) throws DbException;
/**
* Returns the IDs of all delivered messages in the given group.
* <p/>
* Read-only.
*/
Collection<MessageId> getMessageIds(Transaction txn, GroupId g)
throws DbException;
throws DbException;
/**
* Returns the IDs of any messages that need to be validated.
@@ -295,15 +326,6 @@ public interface DatabaseComponent {
Collection<MessageId> getMessagesToShare(Transaction txn)
throws DbException;
/**
* Returns the message with the given ID, in serialised form, or null if
* the message has been deleted.
* <p/>
* Read-only.
*/
@Nullable
byte[] getRawMessage(Transaction txn, MessageId m) throws DbException;
/**
* Returns the metadata for all delivered messages in the given group.
* <p/>
@@ -351,12 +373,12 @@ public interface DatabaseComponent {
/**
* Returns the IDs and states of all dependencies of the given message.
* For missing dependencies and dependencies in other groups, the state
* {@link State UNKNOWN} is returned.
* {@link MessageState UNKNOWN} is returned.
* <p/>
* Read-only.
*/
Map<MessageId, State> getMessageDependencies(Transaction txn, MessageId m)
throws DbException;
Map<MessageId, MessageState> getMessageDependencies(Transaction txn,
MessageId m) throws DbException;
/**
* Returns the IDs and states of all dependents of the given message.
@@ -365,15 +387,16 @@ public interface DatabaseComponent {
* <p/>
* Read-only.
*/
Map<MessageId, State> getMessageDependents(Transaction txn, MessageId m)
throws DbException;
Map<MessageId, MessageState> getMessageDependents(Transaction txn,
MessageId m) throws DbException;
/**
* Gets the validation and delivery state of the given message.
* <p/>
* Read-only.
*/
State getMessageState(Transaction txn, MessageId m) throws DbException;
MessageState getMessageState(Transaction txn, MessageId m)
throws DbException;
/**
* Returns the status of the given delivered message with respect to the
@@ -487,7 +510,7 @@ public interface DatabaseComponent {
* Removes the given transport keys from the database.
*/
void removeTransportKeys(Transaction txn, TransportId t, KeySetId k)
throws DbException;
throws DbException;
/**
* Marks the given contact as verified.
@@ -500,6 +523,12 @@ public interface DatabaseComponent {
void setContactActive(Transaction txn, ContactId c, boolean active)
throws DbException;
/**
* Sets an alias name for the contact or unsets it if alias is null.
*/
void setContactAlias(Transaction txn, ContactId c, @Nullable String alias)
throws DbException;
/**
* Sets the given group's visibility to the given contact.
*/
@@ -514,7 +543,7 @@ public interface DatabaseComponent {
/**
* Sets the validation and delivery state of the given message.
*/
void setMessageState(Transaction txn, MessageId m, State state)
void setMessageState(Transaction txn, MessageId m, MessageState state)
throws DbException;
/**
@@ -534,7 +563,7 @@ public interface DatabaseComponent {
* Marks the given transport keys as usable for outgoing streams.
*/
void setTransportKeysActive(Transaction txn, TransportId t, KeySetId k)
throws DbException;
throws DbException;
/**
* Stores the given transport keys, deleting any keys they have replaced.

View File

@@ -1,30 +1,15 @@
package org.briarproject.bramble.api.db;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.File;
import javax.annotation.Nullable;
@NotNullByDefault
public interface DatabaseConfig {
boolean databaseExists();
File getDatabaseDirectory();
File getDatabaseKeyDirectory();
void setEncryptionKey(SecretKey key);
@Nullable
SecretKey getEncryptionKey();
void setLocalAuthorName(String nickname);
@Nullable
String getLocalAuthorName();
long getMaxSize();
}

View File

@@ -0,0 +1,9 @@
package org.briarproject.bramble.api.db;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface DbCallable<R, E extends Exception> {
R call(Transaction txn) throws DbException, E;
}

View File

@@ -0,0 +1,9 @@
package org.briarproject.bramble.api.db;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface DbRunnable<E extends Exception> {
void run(Transaction txn) throws DbException, E;
}

View File

@@ -0,0 +1,9 @@
package org.briarproject.bramble.api.db;
/**
* Thrown when a message that has been deleted is requested from the database.
* This exception may occur due to concurrent updates and does not indicate a
* database error.
*/
public class MessageDeletedException extends DbException {
}

View File

@@ -6,6 +6,10 @@ public interface MigrationListener {
* This is called when a migration is started while opening the database.
* It will be called once for each migration being applied.
*/
void onMigrationRun();
void onDatabaseMigration();
/**
* This is called when compaction is started while opening the database.
*/
void onDatabaseCompaction();
}

View File

@@ -0,0 +1,12 @@
package org.briarproject.bramble.api.db;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
@NotNullByDefault
public interface NullableDbCallable<R, E extends Exception> {
@Nullable
R call(Transaction txn) throws DbException, E;
}

View File

@@ -1,5 +1,6 @@
package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.Nameable;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.StringUtils;
@@ -13,11 +14,7 @@ import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_K
*/
@Immutable
@NotNullByDefault
public class Author {
public enum Status {
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES
}
public class Author implements Nameable {
/**
* The current version of the author structure.

View File

@@ -0,0 +1,56 @@
package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class AuthorInfo {
public enum Status {
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES;
public boolean isContact() {
return this == UNVERIFIED || this == VERIFIED;
}
}
private final Status status;
@Nullable
private final String alias;
public AuthorInfo(Status status, @Nullable String alias) {
this.status = status;
this.alias = alias;
}
public AuthorInfo(Status status) {
this(status, null);
}
public Status getStatus() {
return status;
}
@Nullable
public String getAlias() {
return alias;
}
@Override
public int hashCode() {
int hashCode = status.ordinal();
if (alias != null) hashCode += alias.hashCode();
return hashCode;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof AuthorInfo)) return false;
AuthorInfo info = (AuthorInfo) o;
return status == info.status &&
(alias == null ? info.alias == null : alias.equals(info.alias));
}
}

View File

@@ -1,38 +1,39 @@
package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.crypto.CryptoExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author.Status;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface IdentityManager {
/**
* Stores the local pseudonym.
* Creates a local identity with the given name.
*/
void registerLocalAuthor(LocalAuthor a) throws DbException;
@CryptoExecutor
LocalAuthor createLocalAuthor(String name);
/**
* Returns the cached main local identity, non-blocking, or loads it from
* the db, blocking
* Registers the given local identity with the manager. The identity is
* not stored until {@link #storeLocalAuthor()} is called.
*/
void registerLocalAuthor(LocalAuthor a);
/**
* Stores the local identity registered with
* {@link #registerLocalAuthor(LocalAuthor)}, if any.
*/
void storeLocalAuthor() throws DbException;
/**
* Returns the cached local identity or loads it from the database.
*/
LocalAuthor getLocalAuthor() throws DbException;
/**
* Returns the cached main local identity, non-blocking, or loads it from
* the db, blocking, within the given Transaction.
* Returns the cached local identity or loads it from the database.
*/
LocalAuthor getLocalAuthor(Transaction txn) throws DbException;
/**
* Returns the trust-level status of the author
*/
Status getAuthorStatus(AuthorId a) throws DbException;
/**
* Returns the trust-level status of the author
*/
Status getAuthorStatus(Transaction txn, AuthorId a) throws DbException;
}

View File

@@ -3,20 +3,16 @@ package org.briarproject.bramble.api.keyagreement;
public interface KeyAgreementConstants {
/**
* The current version of the BQP protocol. Version number 89 is reserved.
* The version of the BQP protocol used in beta releases. This version
* number is reserved.
*/
byte BETA_PROTOCOL_VERSION = 89;
/**
* The current version of the BQP protocol.
*/
byte PROTOCOL_VERSION = 4;
/**
* The length of the record header in bytes.
*/
int RECORD_HEADER_LENGTH = 4;
/**
* The offset of the payload length in the record header, in bytes.
*/
int RECORD_HEADER_PAYLOAD_LENGTH_OFFSET = 2;
/**
* The length of the BQP key commitment in bytes.
*/
@@ -25,7 +21,7 @@ public interface KeyAgreementConstants {
/**
* The connection timeout in milliseconds.
*/
long CONNECTION_TIMEOUT = 20 * 1000;
long CONNECTION_TIMEOUT = 60_000;
/**
* The transport identifier for Bluetooth.

View File

@@ -0,0 +1,20 @@
package org.briarproject.bramble.api.keyagreement;
import java.io.IOException;
/**
* Thrown when a QR code that has been scanned uses a protocol version that is
* not supported.
*/
public class UnsupportedVersionException extends IOException {
private final boolean tooOld;
public UnsupportedVersionException(boolean tooOld) {
this.tooOld = tooOld;
}
public boolean isTooOld() {
return tooOld;
}
}

View File

@@ -1,13 +1,12 @@
package org.briarproject.bramble.api.lifecycle;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Client;
import java.util.concurrent.ExecutorService;
import javax.annotation.Nullable;
/**
* Manages the lifecycle of the app, starting {@link Client Clients}, starting
* and stopping {@link Service Services}, shutting down
@@ -18,7 +17,7 @@ import javax.annotation.Nullable;
public interface LifecycleManager {
/**
* The result of calling {@link #startServices(String)}.
* The result of calling {@link #startServices(SecretKey)}.
*/
enum StartResult {
ALREADY_RUNNING,
@@ -35,7 +34,8 @@ public interface LifecycleManager {
*/
enum LifecycleState {
STARTING, MIGRATING_DATABASE, STARTING_SERVICES, RUNNING, STOPPING;
STARTING, MIGRATING_DATABASE, COMPACTING_DATABASE, STARTING_SERVICES,
RUNNING, STOPPING;
public boolean isAfter(LifecycleState state) {
return ordinal() > state.ordinal();
@@ -44,28 +44,27 @@ public interface LifecycleManager {
/**
* Registers a {@link Service} to be started and stopped. This method
* should be called before {@link #startServices(String)}.
* should be called before {@link #startServices(SecretKey)}.
*/
void registerService(Service s);
/**
* Registers a {@link Client} to be started. This method should be called
* before {@link #startServices(String)}.
* before {@link #startServices(SecretKey)}.
*/
void registerClient(Client c);
/**
* Registers an {@link ExecutorService} to be shut down. This method
* should be called before {@link #startServices(String)}.
* should be called before {@link #startServices(SecretKey)}.
*/
void registerForShutdown(ExecutorService e);
/**
* Opens the {@link DatabaseComponent}, optionally creates a local author
* with the provided nickname, and starts any registered
* {@link Client Clients} and {@link Service Services}.
* Opens the {@link DatabaseComponent} using the given key and starts any
* registered {@link Client Clients} and {@link Service Services}.
*/
StartResult startServices(@Nullable String nickname);
StartResult startServices(SecretKey dbKey);
/**
* Stops any registered {@link Service Services}, shuts down any

View File

@@ -0,0 +1,9 @@
package org.briarproject.bramble.api.network;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface NetworkManager {
NetworkStatus getNetworkStatus();
}

View File

@@ -0,0 +1,25 @@
package org.briarproject.bramble.api.network;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class NetworkStatus {
private final boolean connected, wifi;
public NetworkStatus(boolean connected, boolean wifi) {
this.connected = connected;
this.wifi = wifi;
}
public boolean isConnected() {
return connected;
}
public boolean isWifi() {
return wifi;
}
}

View File

@@ -0,0 +1,22 @@
package org.briarproject.bramble.api.network.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.network.NetworkStatus;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class NetworkStatusEvent extends Event {
private final NetworkStatus status;
public NetworkStatusEvent(NetworkStatus status) {
this.status = status;
}
public NetworkStatus getStatus() {
return status;
}
}

View File

@@ -0,0 +1,15 @@
package org.briarproject.bramble.api.nullsafety;
import javax.annotation.Nullable;
@NotNullByDefault
public class NullSafety {
/**
* Stand-in for `Objects.requireNonNull()`.
*/
public static <T> T requireNonNull(@Nullable T t) {
if (t == null) throw new NullPointerException();
return t;
}
}

View File

@@ -4,7 +4,8 @@ public interface TorConstants {
TransportId ID = new TransportId("org.briarproject.bramble.tor");
String PROP_ONION = "onion";
String PROP_ONION_V2 = "onion";
String PROP_ONION_V3 = "onion3";
int SOCKS_PORT = 59050;
int CONTROL_PORT = 59051;
@@ -12,11 +13,13 @@ public interface TorConstants {
int CONNECT_TO_PROXY_TIMEOUT = 5000; // Milliseconds
int EXTRA_SOCKET_TIMEOUT = 30000; // Milliseconds
String PREF_TOR_NETWORK = "network";
String PREF_TOR_NETWORK = "network2";
String PREF_TOR_PORT = "port";
String PREF_TOR_MOBILE = "useMobileData";
int PREF_TOR_NETWORK_NEVER = 0;
int PREF_TOR_NETWORK_WIFI = 1;
int PREF_TOR_NETWORK_ALWAYS = 2;
int PREF_TOR_NETWORK_AUTOMATIC = 0;
int PREF_TOR_NETWORK_WITHOUT_BRIDGES = 1;
int PREF_TOR_NETWORK_WITH_BRIDGES = 2;
int PREF_TOR_NETWORK_NEVER = 3;
}

View File

@@ -1,6 +1,7 @@
package org.briarproject.bramble.api.settings;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
@@ -11,6 +12,11 @@ public interface SettingsManager {
*/
Settings getSettings(String namespace) throws DbException;
/**
* Returns all settings in the given namespace.
*/
Settings getSettings(Transaction txn, String namespace) throws DbException;
/**
* Merges the given settings with any existing settings in the given
* namespace.

View File

@@ -2,6 +2,7 @@ package org.briarproject.bramble.api.settings.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.settings.Settings;
import javax.annotation.concurrent.Immutable;
@@ -13,12 +14,18 @@ import javax.annotation.concurrent.Immutable;
public class SettingsUpdatedEvent extends Event {
private final String namespace;
private final Settings settings;
public SettingsUpdatedEvent(String namespace) {
public SettingsUpdatedEvent(String namespace, Settings settings) {
this.namespace = namespace;
this.settings = settings;
}
public String getNamespace() {
return namespace;
}
public Settings getSettings() {
return settings;
}
}

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api.sync;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
public class Message {
@@ -13,17 +13,16 @@ public class Message {
private final MessageId id;
private final GroupId groupId;
private final long timestamp;
private final byte[] raw;
private final byte[] body;
public Message(MessageId id, GroupId groupId, long timestamp, byte[] raw) {
if (raw.length <= MESSAGE_HEADER_LENGTH)
throw new IllegalArgumentException();
if (raw.length > MAX_MESSAGE_LENGTH)
public Message(MessageId id, GroupId groupId, long timestamp, byte[] body) {
if (body.length == 0) throw new IllegalArgumentException();
if (body.length > MAX_MESSAGE_BODY_LENGTH)
throw new IllegalArgumentException();
this.id = id;
this.groupId = groupId;
this.timestamp = timestamp;
this.raw = raw;
this.body = body;
}
/**
@@ -50,15 +49,15 @@ public class Message {
/**
* Returns the length of the raw message in bytes.
*/
public int getLength() {
return raw.length;
public int getRawLength() {
return MESSAGE_HEADER_LENGTH + body.length;
}
/**
* Returns the raw message.
* Returns the message body.
*/
public byte[] getRaw() {
return raw;
public byte[] getBody() {
return body;
}
@Override

View File

@@ -9,5 +9,5 @@ public interface MessageFactory {
Message createMessage(byte[] raw);
Message createMessage(MessageId m, byte[] raw);
byte[] getRawMessage(Message m);
}

View File

@@ -9,7 +9,7 @@ public interface SyncRecordWriter {
void writeAck(Ack a) throws IOException;
void writeMessage(byte[] raw) throws IOException;
void writeMessage(Message m) throws IOException;
void writeOffer(Offer o) throws IOException;

View File

@@ -1,85 +0,0 @@
package org.briarproject.bramble.api.sync;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* Responsible for managing message validators and passing them messages to
* validate.
*/
@NotNullByDefault
public interface ValidationManager {
enum State {
UNKNOWN(0), INVALID(1), PENDING(2), DELIVERED(3);
private final int value;
State(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static State fromValue(int value) {
for (State s : values()) if (s.value == value) return s;
throw new IllegalArgumentException();
}
}
/**
* Registers the message validator for the given client. This method
* should be called before {@link LifecycleManager#startServices(String)}.
*/
void registerMessageValidator(ClientId c, int majorVersion,
MessageValidator v);
/**
* Registers the incoming message hook for the given client. The hook will
* be called once for each incoming message that passes validation. This
* method should be called before
* {@link LifecycleManager#startServices(String)}.
*/
void registerIncomingMessageHook(ClientId c, int majorVersion,
IncomingMessageHook hook);
interface MessageValidator {
/**
* Validates the given message and returns its metadata and
* dependencies.
*/
MessageContext validateMessage(Message m, Group g)
throws InvalidMessageException;
}
interface IncomingMessageHook {
/**
* Called once for each incoming message that passes validation.
*
* @return whether or not this message should be shared
* @throws DbException Should only be used for real database errors.
* If this is thrown, delivery will be attempted again at next startup,
* whereas if an InvalidMessageException is thrown,
* the message will be permanently invalidated.
* @throws InvalidMessageException for any non-database error
* that occurs while handling remotely created data.
* This includes errors that occur while handling locally created data
* in a context controlled by remotely created data
* (for example, parsing the metadata of a dependency
* of an incoming message).
* Throwing this will delete the incoming message and its metadata
* marking it as invalid in the database.
* Never rethrow DbException as InvalidMessageException!
*/
boolean incomingMessage(Transaction txn, Message m, Metadata meta)
throws DbException, InvalidMessageException;
}
}

View File

@@ -3,11 +3,10 @@ package org.briarproject.bramble.api.sync.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.validation.MessageState;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.sync.ValidationManager.State;
/**
* An event that is broadcast when a message state changed.
*/
@@ -17,10 +16,10 @@ public class MessageStateChangedEvent extends Event {
private final MessageId messageId;
private final boolean local;
private final State state;
private final MessageState state;
public MessageStateChangedEvent(MessageId messageId, boolean local,
State state) {
MessageState state) {
this.messageId = messageId;
this.local = local;
this.state = state;
@@ -34,7 +33,7 @@ public class MessageStateChangedEvent extends Event {
return local;
}
public State getState() {
public MessageState getState() {
return state;
}

View File

@@ -0,0 +1,31 @@
package org.briarproject.bramble.api.sync.validation;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.sync.InvalidMessageException;
import org.briarproject.bramble.api.sync.Message;
public interface IncomingMessageHook {
/**
* Called once for each incoming message that passes validation.
*
* @return whether or not this message should be shared
* @throws DbException Should only be used for real database errors.
* If this is thrown, delivery will be attempted again at next startup,
* whereas if an InvalidMessageException is thrown,
* the message will be permanently invalidated.
* @throws InvalidMessageException for any non-database error
* that occurs while handling remotely created data.
* This includes errors that occur while handling locally created data
* in a context controlled by remotely created data
* (for example, parsing the metadata of a dependency
* of an incoming message).
* Throwing this will delete the incoming message and its metadata
* marking it as invalid in the database.
* Never rethrow DbException as InvalidMessageException!
*/
boolean incomingMessage(Transaction txn, Message m, Metadata meta)
throws DbException, InvalidMessageException;
}

View File

@@ -0,0 +1,21 @@
package org.briarproject.bramble.api.sync.validation;
public enum MessageState {
UNKNOWN(0), INVALID(1), PENDING(2), DELIVERED(3);
private final int value;
MessageState(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static MessageState fromValue(int value) {
for (MessageState s : values()) if (s.value == value) return s;
throw new IllegalArgumentException();
}
}

View File

@@ -0,0 +1,16 @@
package org.briarproject.bramble.api.sync.validation;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.InvalidMessageException;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageContext;
public interface MessageValidator {
/**
* Validates the given message and returns its metadata and
* dependencies.
*/
MessageContext validateMessage(Message m, Group g)
throws InvalidMessageException;
}

View File

@@ -0,0 +1,31 @@
package org.briarproject.bramble.api.sync.validation;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientId;
/**
* Responsible for managing message validators and passing them messages to
* validate.
*/
@NotNullByDefault
public interface ValidationManager {
/**
* Registers the {@link MessageValidator} for the given client. This method
* should be called before
* {@link LifecycleManager#startServices(SecretKey)}.
*/
void registerMessageValidator(ClientId c, int majorVersion,
MessageValidator v);
/**
* Registers the {@link IncomingMessageHook} for the given client. The hook
* will be called once for each incoming message that passes validation.
* This method should be called before
* {@link LifecycleManager#startServices(SecretKey)}.
*/
void registerIncomingMessageHook(ClientId c, int majorVersion,
IncomingMessageHook hook);
}

View File

@@ -0,0 +1,11 @@
package org.briarproject.bramble.api.system;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.InputStream;
@NotNullByDefault
public interface ResourceProvider {
InputStream getResourceInputStream(String name, String extension);
}

View File

@@ -2,6 +2,7 @@ package org.briarproject.bramble.api.versioning;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
@@ -25,7 +26,7 @@ public interface ClientVersioningManager {
/**
* Registers a client that will be advertised to contacts. The hook will
* be called when the visibility of the client changes. This method should
* be called before {@link LifecycleManager#startServices(String)}.
* be called before {@link LifecycleManager#startServices(SecretKey)}.
*/
void registerClient(ClientId clientId, int majorVersion, int minorVersion,
ClientVersioningHook hook);

View File

@@ -47,7 +47,7 @@ public class StringUtils {
try {
return s.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
throw new AssertionError(e);
}
}
@@ -63,7 +63,7 @@ public class StringUtils {
try {
return decoder.decode(buffer).toString();
} catch (CharacterCodingException e) {
throw new RuntimeException(e);
throw new AssertionError(e);
}
}

View File

@@ -0,0 +1,42 @@
package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Test;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.NONE;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
public class AuthorInfoTest extends BrambleTestCase {
@Test
public void testEquals() {
assertEquals(
new AuthorInfo(NONE),
new AuthorInfo(NONE, null)
);
assertEquals(
new AuthorInfo(NONE, "test"),
new AuthorInfo(NONE, "test")
);
assertNotEquals(
new AuthorInfo(NONE),
new AuthorInfo(VERIFIED)
);
assertNotEquals(
new AuthorInfo(NONE, "test"),
new AuthorInfo(NONE)
);
assertNotEquals(
new AuthorInfo(NONE),
new AuthorInfo(NONE, "test")
);
assertNotEquals(
new AuthorInfo(NONE, "a"),
new AuthorInfo(NONE, "b")
);
}
}

View File

@@ -0,0 +1,23 @@
package org.briarproject.bramble.test;
import org.briarproject.bramble.api.system.Clock;
public class ArrayClock implements Clock {
private final long[] times;
private int index = 0;
public ArrayClock(long... times) {
this.times = times;
}
@Override
public long currentTimeMillis() {
return times[index++];
}
@Override
public void sleep(long milliseconds) throws InterruptedException {
Thread.sleep(milliseconds);
}
}

View File

@@ -0,0 +1,24 @@
package org.briarproject.bramble.test;
import org.briarproject.bramble.api.system.Clock;
import java.util.concurrent.atomic.AtomicLong;
public class SettableClock implements Clock {
private final AtomicLong time;
public SettableClock(AtomicLong time) {
this.time = time;
}
@Override
public long currentTimeMillis() {
return time.get();
}
@Override
public void sleep(long milliseconds) throws InterruptedException {
Thread.sleep(milliseconds);
}
}

View File

@@ -24,6 +24,7 @@ import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import static java.util.Arrays.asList;
import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
@@ -32,7 +33,6 @@ import static org.briarproject.bramble.api.properties.TransportPropertyConstants
import static org.briarproject.bramble.api.sync.ClientId.MAX_CLIENT_ID_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
public class TestUtils {
@@ -40,6 +40,7 @@ public class TestUtils {
private static final AtomicInteger nextTestDir =
new AtomicInteger((int) (Math.random() * 1000 * 1000));
private static final Random random = new Random();
private static final long timestamp = System.currentTimeMillis();
public static File getTestDirectory() {
int name = nextTestDir.getAndIncrement();
@@ -101,9 +102,8 @@ public class TestUtils {
String name = getRandomString(nameLength);
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
byte[] privateKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
long created = System.currentTimeMillis();
return new LocalAuthor(id, FORMAT_VERSION, name, publicKey, privateKey,
created);
timestamp);
}
public static Author getAuthor() {
@@ -131,14 +131,13 @@ public class TestUtils {
public static Message getMessage(GroupId groupId) {
int bodyLength = 1 + random.nextInt(MAX_MESSAGE_BODY_LENGTH);
return getMessage(groupId, MESSAGE_HEADER_LENGTH + bodyLength);
return getMessage(groupId, bodyLength);
}
public static Message getMessage(GroupId groupId, int rawLength) {
public static Message getMessage(GroupId groupId, int bodyLength) {
MessageId id = new MessageId(getRandomId());
byte[] raw = getRandomBytes(rawLength);
long timestamp = System.currentTimeMillis();
return new Message(id, groupId, timestamp, raw);
byte[] body = getRandomBytes(bodyLength);
return new Message(id, groupId, timestamp, body);
}
public static double getMedian(Collection<? extends Number> samples) {
@@ -174,4 +173,10 @@ public class TestUtils {
Collection<? extends Number> samples) {
return Math.sqrt(getVariance(samples));
}
public static boolean isOptionalTestEnabled(Class testClass) {
String optionalTests = System.getenv("OPTIONAL_TESTS");
return optionalTests != null &&
asList(optionalTests.split(",")).contains(testClass.getName());
}
}

View File

@@ -0,0 +1,24 @@
dependencyVerification {
verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger:2.19:dagger-2.19.jar:514b6f1e0727c6572e1d65cb27e4ae668b7aeaeb93a29515182965265b609939',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90',
'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
]
}

View File

@@ -3,9 +3,10 @@ sourceCompatibility = 1.8
targetCompatibility = 1.8
apply plugin: 'ru.vyarus.animalsniffer'
apply plugin: 'net.ltgt.apt'
apply plugin: 'idea'
apply plugin: 'witness'
apply from: 'witness.gradle'
apply from: '../dagger.gradle'
dependencies {
implementation project(path: ':bramble-api', configuration: 'default')
@@ -13,9 +14,10 @@ dependencies {
implementation 'com.h2database:h2:1.4.192' // The last version that supports Java 1.6
implementation 'org.bitlet:weupnp:0.1.4'
implementation 'net.i2p.crypto:eddsa:0.2.0'
implementation 'org.whispersystems:curve25519-java:0.4.1'
implementation 'org.whispersystems:curve25519-java:0.5.0'
implementation 'org.briarproject:jtorctl:0.3'
apt 'com.google.dagger:dagger-compiler:2.0.2'
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation 'org.hsqldb:hsqldb:2.3.5' // The last version that supports Java 1.6
@@ -23,48 +25,13 @@ dependencies {
testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:2.8.2"
testImplementation "org.hamcrest:hamcrest-library:1.3"
testImplementation "org.hamcrest:hamcrest-core:1.3"
testApt 'com.google.dagger:dagger-compiler:2.0.2'
testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.19'
signature 'org.codehaus.mojo.signature:java16:1.1@signature'
}
dependencyVerification {
verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'net.i2p.crypto:eddsa:0.2.0:eddsa-0.2.0.jar:a7cb1b85c16e2f0730b9204106929a1d9aaae1df728adc7041a8b8b605692140',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90',
'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.hsqldb:hsqldb:2.3.5:hsqldb-2.3.5.jar:6676a6977ac98997a80f827ddbd3fe8ca1e0853dad1492512135fd1a222ccfad',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.whispersystems:curve25519-java:0.4.1:curve25519-java-0.4.1.jar:7dd659d8822c06c3aea1a47f18fac9e5761e29cab8100030b877db445005f03e',
]
}
// needed to make test output available to bramble-j2se
// needed to make test output available to bramble-java
configurations {
testOutput.extendsFrom(testCompile)
}

View File

@@ -8,7 +8,7 @@ import org.briarproject.bramble.lifecycle.LifecycleModule;
import org.briarproject.bramble.plugin.PluginModule;
import org.briarproject.bramble.properties.PropertiesModule;
import org.briarproject.bramble.reporting.ReportingModule;
import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.sync.validation.ValidationModule;
import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.transport.TransportModule;
import org.briarproject.bramble.versioning.VersioningModule;
@@ -31,11 +31,11 @@ public interface BrambleCoreEagerSingletons {
void inject(ReportingModule.EagerSingletons init);
void inject(SyncModule.EagerSingletons init);
void inject(SystemModule.EagerSingletons init);
void inject(TransportModule.EagerSingletons init);
void inject(ValidationModule.EagerSingletons init);
void inject(VersioningModule.EagerSingletons init);
}

View File

@@ -19,6 +19,7 @@ import org.briarproject.bramble.reporting.ReportingModule;
import org.briarproject.bramble.settings.SettingsModule;
import org.briarproject.bramble.socks.SocksModule;
import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.sync.validation.ValidationModule;
import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.transport.TransportModule;
import org.briarproject.bramble.versioning.VersioningModule;
@@ -47,6 +48,7 @@ import dagger.Module;
SyncModule.class,
SystemModule.class,
TransportModule.class,
ValidationModule.class,
VersioningModule.class
})
public class BrambleCoreModule {
@@ -60,9 +62,9 @@ public class BrambleCoreModule {
c.inject(new PluginModule.EagerSingletons());
c.inject(new PropertiesModule.EagerSingletons());
c.inject(new ReportingModule.EagerSingletons());
c.inject(new SyncModule.EagerSingletons());
c.inject(new SystemModule.EagerSingletons());
c.inject(new TransportModule.EagerSingletons());
c.inject(new ValidationModule.EagerSingletons());
c.inject(new VersioningModule.EagerSingletons());
}
}

View File

@@ -0,0 +1,224 @@
package org.briarproject.bramble.account;
import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.util.IoUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.StringUtils.fromHexString;
import static org.briarproject.bramble.util.StringUtils.toHexString;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class AccountManagerImpl implements AccountManager {
private static final Logger LOG =
Logger.getLogger(AccountManagerImpl.class.getName());
private static final String DB_KEY_FILENAME = "db.key";
private static final String DB_KEY_BACKUP_FILENAME = "db.key.bak";
private final DatabaseConfig databaseConfig;
private final CryptoComponent crypto;
private final IdentityManager identityManager;
private final File dbKeyFile, dbKeyBackupFile;
final Object stateChangeLock = new Object();
@Nullable
private volatile SecretKey databaseKey = null;
@Inject
AccountManagerImpl(DatabaseConfig databaseConfig, CryptoComponent crypto,
IdentityManager identityManager) {
this.databaseConfig = databaseConfig;
this.crypto = crypto;
this.identityManager = identityManager;
File keyDir = databaseConfig.getDatabaseKeyDirectory();
dbKeyFile = new File(keyDir, DB_KEY_FILENAME);
dbKeyBackupFile = new File(keyDir, DB_KEY_BACKUP_FILENAME);
}
@Override
public boolean hasDatabaseKey() {
return databaseKey != null;
}
@Override
@Nullable
public SecretKey getDatabaseKey() {
return databaseKey;
}
// Locking: stateChangeLock
@Nullable
protected String loadEncryptedDatabaseKey() {
String key = readDbKeyFromFile(dbKeyFile);
if (key == null) {
LOG.info("No database key in primary file");
key = readDbKeyFromFile(dbKeyBackupFile);
if (key == null) LOG.info("No database key in backup file");
else LOG.warning("Found database key in backup file");
} else {
LOG.info("Found database key in primary file");
}
return key;
}
// Locking: stateChangeLock
@Nullable
private String readDbKeyFromFile(File f) {
if (!f.exists()) {
LOG.info("Key file does not exist");
return null;
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
new FileInputStream(f), "UTF-8"));
String key = reader.readLine();
reader.close();
return key;
} catch (IOException e) {
logException(LOG, WARNING, e);
return null;
}
}
// Locking: stateChangeLock
protected boolean storeEncryptedDatabaseKey(String hex) {
LOG.info("Storing database key in file");
// Create the directory if necessary
if (databaseConfig.getDatabaseKeyDirectory().mkdirs())
LOG.info("Created database key directory");
// If only the backup file exists, rename it so we don't overwrite it
if (dbKeyBackupFile.exists() && !dbKeyFile.exists()) {
if (dbKeyBackupFile.renameTo(dbKeyFile))
LOG.info("Renamed old backup");
else LOG.warning("Failed to rename old backup");
}
try {
// Write to the backup file
writeDbKeyToFile(hex, dbKeyBackupFile);
LOG.info("Stored database key in backup file");
// Delete the old primary file, if it exists
if (dbKeyFile.exists()) {
if (dbKeyFile.delete()) LOG.info("Deleted primary file");
else LOG.warning("Failed to delete primary file");
}
// The backup file becomes the new primary
if (dbKeyBackupFile.renameTo(dbKeyFile)) {
LOG.info("Renamed backup file to primary");
} else {
LOG.warning("Failed to rename backup file to primary");
return false; // Don't overwrite our only copy
}
// Write a second copy to the backup file
writeDbKeyToFile(hex, dbKeyBackupFile);
LOG.info("Stored second copy of database key in backup file");
return true;
} catch (IOException e) {
logException(LOG, WARNING, e);
return false;
}
}
// Locking: stateChangeLock
private void writeDbKeyToFile(String key, File f) throws IOException {
FileOutputStream out = new FileOutputStream(f);
out.write(key.getBytes("UTF-8"));
out.flush();
out.close();
}
@Override
public boolean accountExists() {
synchronized (stateChangeLock) {
return loadEncryptedDatabaseKey() != null
&& databaseConfig.getDatabaseDirectory().isDirectory();
}
}
@Override
public boolean createAccount(String name, String password) {
synchronized (stateChangeLock) {
if (hasDatabaseKey())
throw new AssertionError("Already have a database key");
LocalAuthor localAuthor = identityManager.createLocalAuthor(name);
identityManager.registerLocalAuthor(localAuthor);
SecretKey key = crypto.generateSecretKey();
if (!encryptAndStoreDatabaseKey(key, password)) return false;
databaseKey = key;
return true;
}
}
// Locking: stateChangeLock
private boolean encryptAndStoreDatabaseKey(SecretKey key, String password) {
byte[] plaintext = key.getBytes();
byte[] ciphertext = crypto.encryptWithPassword(plaintext, password);
return storeEncryptedDatabaseKey(toHexString(ciphertext));
}
@Override
public void deleteAccount() {
synchronized (stateChangeLock) {
LOG.info("Deleting account");
IoUtils.deleteFileOrDir(databaseConfig.getDatabaseKeyDirectory());
IoUtils.deleteFileOrDir(databaseConfig.getDatabaseDirectory());
databaseKey = null;
}
}
@Override
public boolean signIn(String password) {
synchronized (stateChangeLock) {
SecretKey key = loadAndDecryptDatabaseKey(password);
if (key == null) return false;
databaseKey = key;
return true;
}
}
// Locking: stateChangeLock
@Nullable
private SecretKey loadAndDecryptDatabaseKey(String password) {
String hex = loadEncryptedDatabaseKey();
if (hex == null) {
LOG.warning("Failed to load encrypted database key");
return null;
}
byte[] ciphertext = fromHexString(hex);
byte[] plaintext = crypto.decryptWithPassword(ciphertext, password);
if (plaintext == null) {
LOG.info("Failed to decrypt database key");
return null;
}
return new SecretKey(plaintext);
}
@Override
public boolean changePassword(String oldPassword, String newPassword) {
synchronized (stateChangeLock) {
SecretKey key = loadAndDecryptDatabaseKey(oldPassword);
return key != null && encryptAndStoreDatabaseKey(key, newPassword);
}
}
}

View File

@@ -0,0 +1,18 @@
package org.briarproject.bramble.account;
import org.briarproject.bramble.api.account.AccountManager;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class AccountModule {
@Provides
@Singleton
AccountManager provideAccountManager(AccountManagerImpl accountManager) {
return accountManager;
}
}

View File

@@ -0,0 +1,19 @@
package org.briarproject.bramble.battery;
import org.briarproject.bramble.api.battery.BatteryManager;
import dagger.Module;
import dagger.Provides;
/**
* Provides a default implementation of {@link BatteryManager} for systems
* without batteries.
*/
@Module
public class DefaultBatteryManagerModule {
@Provides
BatteryManager provideBatteryManager() {
return () -> false;
}
}

View File

@@ -41,7 +41,6 @@ import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_N
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTIES_PER_TRANSPORT;
import static org.briarproject.bramble.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.bramble.util.ValidationUtils.checkLength;
import static org.briarproject.bramble.util.ValidationUtils.checkSize;
@@ -83,13 +82,7 @@ class ClientHelperImpl implements ClientHelper {
@Override
public void addLocalMessage(Message m, BdfDictionary metadata,
boolean shared) throws DbException, FormatException {
Transaction txn = db.startTransaction(false);
try {
addLocalMessage(txn, m, metadata, shared);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
db.transaction(false, txn -> addLocalMessage(txn, m, metadata, shared));
}
@Override
@@ -114,59 +107,31 @@ class ClientHelperImpl implements ClientHelper {
@Override
public Message getMessage(MessageId m) throws DbException {
Message message;
Transaction txn = db.startTransaction(true);
try {
message = getMessage(txn, m);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return message;
return db.transactionWithResult(true, txn -> getMessage(txn, m));
}
@Override
public Message getMessage(Transaction txn, MessageId m) throws DbException {
byte[] raw = db.getRawMessage(txn, m);
if (raw == null) return null;
return messageFactory.createMessage(m, raw);
return db.getMessage(txn, m);
}
@Override
public BdfList getMessageAsList(MessageId m) throws DbException,
FormatException {
BdfList list;
Transaction txn = db.startTransaction(true);
try {
list = getMessageAsList(txn, m);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return list;
return db.transactionWithResult(true, txn -> getMessageAsList(txn, m));
}
@Override
public BdfList getMessageAsList(Transaction txn, MessageId m)
throws DbException, FormatException {
byte[] raw = db.getRawMessage(txn, m);
if (raw == null) return null;
return toList(raw, MESSAGE_HEADER_LENGTH,
raw.length - MESSAGE_HEADER_LENGTH);
return toList(db.getMessage(txn, m).getBody());
}
@Override
public BdfDictionary getGroupMetadataAsDictionary(GroupId g)
throws DbException, FormatException {
BdfDictionary dictionary;
Transaction txn = db.startTransaction(true);
try {
dictionary = getGroupMetadataAsDictionary(txn, g);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return dictionary;
return db.transactionWithResult(true, txn ->
getGroupMetadataAsDictionary(txn, g));
}
@Override
@@ -179,15 +144,8 @@ class ClientHelperImpl implements ClientHelper {
@Override
public BdfDictionary getMessageMetadataAsDictionary(MessageId m)
throws DbException, FormatException {
BdfDictionary dictionary;
Transaction txn = db.startTransaction(true);
try {
dictionary = getMessageMetadataAsDictionary(txn, m);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return dictionary;
return db.transactionWithResult(true, txn ->
getMessageMetadataAsDictionary(txn, m));
}
@Override
@@ -200,15 +158,8 @@ class ClientHelperImpl implements ClientHelper {
@Override
public Map<MessageId, BdfDictionary> getMessageMetadataAsDictionary(
GroupId g) throws DbException, FormatException {
Map<MessageId, BdfDictionary> map;
Transaction txn = db.startTransaction(true);
try {
map = getMessageMetadataAsDictionary(txn, g);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return map;
return db.transactionWithResult(true, txn ->
getMessageMetadataAsDictionary(txn, g));
}
@Override
@@ -225,15 +176,8 @@ class ClientHelperImpl implements ClientHelper {
public Map<MessageId, BdfDictionary> getMessageMetadataAsDictionary(
GroupId g, BdfDictionary query) throws DbException,
FormatException {
Map<MessageId, BdfDictionary> map;
Transaction txn = db.startTransaction(true);
try {
map = getMessageMetadataAsDictionary(txn, g, query);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return map;
return db.transactionWithResult(true, txn ->
getMessageMetadataAsDictionary(txn, g, query));
}
@Override
@@ -251,13 +195,7 @@ class ClientHelperImpl implements ClientHelper {
@Override
public void mergeGroupMetadata(GroupId g, BdfDictionary metadata)
throws DbException, FormatException {
Transaction txn = db.startTransaction(false);
try {
mergeGroupMetadata(txn, g, metadata);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
db.transaction(false, txn -> mergeGroupMetadata(txn, g, metadata));
}
@Override
@@ -269,13 +207,7 @@ class ClientHelperImpl implements ClientHelper {
@Override
public void mergeMessageMetadata(MessageId m, BdfDictionary metadata)
throws DbException, FormatException {
Transaction txn = db.startTransaction(false);
try {
mergeMessageMetadata(txn, m, metadata);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
db.transaction(false, txn -> mergeMessageMetadata(txn, m, metadata));
}
@Override
@@ -364,9 +296,7 @@ class ClientHelperImpl implements ClientHelper {
@Override
public BdfList toList(Message m) throws FormatException {
byte[] raw = m.getRaw();
return toList(raw, MESSAGE_HEADER_LENGTH,
raw.length - MESSAGE_HEADER_LENGTH);
return toList(m.getBody());
}
@Override

View File

@@ -13,7 +13,6 @@ import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.db.ContactExistsException;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
@@ -158,7 +157,8 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
streamWriterFactory.createContactExchangeStreamWriter(out,
alice ? aliceHeaderKey : bobHeaderKey);
RecordWriter recordWriter =
recordWriterFactory.createRecordWriter(streamWriter.getOutputStream());
recordWriterFactory
.createRecordWriter(streamWriter.getOutputStream());
// Derive the nonces to be signed
byte[] aliceNonce = crypto.mac(ALICE_NONCE_LABEL, masterSecret,
@@ -287,19 +287,14 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
private ContactId addContact(Author remoteAuthor, long timestamp,
Map<TransportId, TransportProperties> remoteProperties)
throws DbException {
ContactId contactId;
Transaction txn = db.startTransaction(false);
try {
contactId = contactManager.addContact(txn, remoteAuthor,
return db.transactionWithResult(false, txn -> {
ContactId contactId = contactManager.addContact(txn, remoteAuthor,
localAuthor.getId(), masterSecret, timestamp, alice,
true, true);
transportPropertyManager.addRemoteProperties(txn, contactId,
remoteProperties);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return contactId;
return contactId;
});
}
private void tryToClose(DuplexTransportConnection conn) {

View File

@@ -10,6 +10,9 @@ import org.briarproject.bramble.api.db.NoSuchContactException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.AuthorInfo;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.transport.KeyManager;
@@ -18,21 +21,32 @@ import java.util.Collection;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNKNOWN;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNVERIFIED;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED;
import static org.briarproject.bramble.util.StringUtils.toUtf8;
@ThreadSafe
@NotNullByDefault
class ContactManagerImpl implements ContactManager {
private final DatabaseComponent db;
private final KeyManager keyManager;
private final IdentityManager identityManager;
private final List<ContactHook> hooks;
@Inject
ContactManagerImpl(DatabaseComponent db, KeyManager keyManager) {
ContactManagerImpl(DatabaseComponent db, KeyManager keyManager,
IdentityManager identityManager) {
this.db = db;
this.keyManager = keyManager;
this.identityManager = identityManager;
hooks = new CopyOnWriteArrayList<>();
}
@@ -65,42 +79,21 @@ class ContactManagerImpl implements ContactManager {
public ContactId addContact(Author remote, AuthorId local, SecretKey master,
long timestamp, boolean alice, boolean verified, boolean active)
throws DbException {
ContactId c;
Transaction txn = db.startTransaction(false);
try {
c = addContact(txn, remote, local, master, timestamp, alice,
verified, active);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return c;
return db.transactionWithResult(false, txn ->
addContact(txn, remote, local, master, timestamp, alice,
verified, active));
}
@Override
public Contact getContact(ContactId c) throws DbException {
Contact contact;
Transaction txn = db.startTransaction(true);
try {
contact = db.getContact(txn, c);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return contact;
return db.transactionWithResult(true, txn -> db.getContact(txn, c));
}
@Override
public Contact getContact(AuthorId remoteAuthorId, AuthorId localAuthorId)
throws DbException {
Transaction txn = db.startTransaction(true);
try {
Contact c = getContact(txn, remoteAuthorId, localAuthorId);
db.commitTransaction(txn);
return c;
} finally {
db.endTransaction(txn);
}
return db.transactionWithResult(true, txn ->
getContact(txn, remoteAuthorId, localAuthorId));
}
@Override
@@ -118,14 +111,8 @@ class ContactManagerImpl implements ContactManager {
@Override
public Collection<Contact> getActiveContacts() throws DbException {
Collection<Contact> contacts;
Transaction txn = db.startTransaction(true);
try {
contacts = db.getContacts(txn);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
Collection<Contact> contacts =
db.transactionWithResult(true, db::getContacts);
List<Contact> active = new ArrayList<>(contacts.size());
for (Contact c : contacts) if (c.isActive()) active.add(c);
return active;
@@ -133,13 +120,7 @@ class ContactManagerImpl implements ContactManager {
@Override
public void removeContact(ContactId c) throws DbException {
Transaction txn = db.startTransaction(false);
try {
removeContact(txn, c);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
db.transaction(false, txn -> removeContact(txn, c));
}
@Override
@@ -148,6 +129,23 @@ class ContactManagerImpl implements ContactManager {
db.setContactActive(txn, c, active);
}
@Override
public void setContactAlias(Transaction txn, ContactId c,
@Nullable String alias) throws DbException {
if (alias != null) {
int aliasLength = toUtf8(alias).length;
if (aliasLength == 0 || aliasLength > MAX_AUTHOR_NAME_LENGTH)
throw new IllegalArgumentException();
}
db.setContactAlias(txn, c, alias);
}
@Override
public void setContactAlias(ContactId c, @Nullable String alias)
throws DbException {
db.transaction(false, txn -> setContactAlias(txn, c, alias));
}
@Override
public boolean contactExists(Transaction txn, AuthorId remoteAuthorId,
AuthorId localAuthorId) throws DbException {
@@ -157,15 +155,8 @@ class ContactManagerImpl implements ContactManager {
@Override
public boolean contactExists(AuthorId remoteAuthorId,
AuthorId localAuthorId) throws DbException {
boolean exists;
Transaction txn = db.startTransaction(true);
try {
exists = contactExists(txn, remoteAuthorId, localAuthorId);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return exists;
return db.transactionWithResult(true, txn ->
contactExists(txn, remoteAuthorId, localAuthorId));
}
@Override
@@ -176,4 +167,23 @@ class ContactManagerImpl implements ContactManager {
db.removeContact(txn, c);
}
@Override
public AuthorInfo getAuthorInfo(AuthorId a) throws DbException {
return db.transactionWithResult(true, txn -> getAuthorInfo(txn, a));
}
@Override
public AuthorInfo getAuthorInfo(Transaction txn, AuthorId authorId)
throws DbException {
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
if (localAuthor.getId().equals(authorId))
return new AuthorInfo(OURSELVES);
Collection<Contact> contacts = db.getContactsByAuthorId(txn, authorId);
if (contacts.isEmpty()) return new AuthorInfo(UNKNOWN);
if (contacts.size() > 1) throw new AssertionError();
Contact c = contacts.iterator().next();
if (c.isVerified()) return new AuthorInfo(VERIFIED, c.getAlias());
else return new AuthorInfo(UNVERIFIED, c.getAlias());
}
}

View File

@@ -29,6 +29,7 @@ import static org.briarproject.bramble.data.Types.STRING_16;
import static org.briarproject.bramble.data.Types.STRING_32;
import static org.briarproject.bramble.data.Types.STRING_8;
import static org.briarproject.bramble.data.Types.TRUE;
import static org.briarproject.bramble.util.StringUtils.fromUtf8;
@NotThreadSafe
@NotNullByDefault
@@ -253,7 +254,7 @@ class BdfReaderImpl implements BdfReader {
if (length < 0 || length > maxBufferSize) throw new FormatException();
if (length == 0) return "";
readIntoBuffer(length);
return new String(buf, 0, length, "UTF-8");
return fromUtf8(buf, 0, length);
}
private int readStringLength() throws IOException {

View File

@@ -2,9 +2,11 @@ package org.briarproject.bramble.db;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DataTooNewException;
import org.briarproject.bramble.api.db.DataTooOldException;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.MessageDeletedException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.MigrationListener;
import org.briarproject.bramble.api.identity.Author;
@@ -20,7 +22,7 @@ import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.MessageStatus;
import org.briarproject.bramble.api.sync.ValidationManager.State;
import org.briarproject.bramble.api.sync.validation.MessageState;
import org.briarproject.bramble.api.transport.KeySet;
import org.briarproject.bramble.api.transport.KeySetId;
import org.briarproject.bramble.api.transport.TransportKeys;
@@ -48,7 +50,8 @@ interface Database<T> {
* @throws DataTooOldException if the data uses an older schema than the
* current code and cannot be migrated
*/
boolean open(@Nullable MigrationListener listener) throws DbException;
boolean open(SecretKey key, @Nullable MigrationListener listener)
throws DbException;
/**
* Prevents new transactions from starting, waits for all current
@@ -103,7 +106,7 @@ interface Database<T> {
* @param sender the contact from whom the message was received, or null
* if the message was created locally.
*/
void addMessage(T txn, Message m, State state, boolean shared,
void addMessage(T txn, Message m, MessageState state, boolean shared,
@Nullable ContactId sender) throws DbException;
/**
@@ -111,7 +114,7 @@ interface Database<T> {
* in the given state.
*/
void addMessageDependency(T txn, Message dependent, MessageId dependency,
State dependentState) throws DbException;
MessageState dependentState) throws DbException;
/**
* Records that a message has been offered by the given contact.
@@ -295,14 +298,23 @@ interface Database<T> {
*/
Collection<LocalAuthor> getLocalAuthors(T txn) throws DbException;
/**
* Returns the message with the given ID.
* <p/>
* Read-only.
*
* @throws MessageDeletedException if the message has been deleted
*/
Message getMessage(T txn, MessageId m) throws DbException;
/**
* Returns the IDs and states of all dependencies of the given message.
* For missing dependencies and dependencies in other groups, the state
* {@link State UNKNOWN} is returned.
* {@link MessageState UNKNOWN} is returned.
* <p/>
* Read-only.
*/
Map<MessageId, State> getMessageDependencies(T txn, MessageId m)
Map<MessageId, MessageState> getMessageDependencies(T txn, MessageId m)
throws DbException;
/**
@@ -312,7 +324,7 @@ interface Database<T> {
* <p/>
* Read-only.
*/
Map<MessageId, State> getMessageDependents(T txn, MessageId m)
Map<MessageId, MessageState> getMessageDependents(T txn, MessageId m)
throws DbException;
/**
@@ -371,7 +383,7 @@ interface Database<T> {
* <p/>
* Read-only.
*/
State getMessageState(T txn, MessageId m) throws DbException;
MessageState getMessageState(T txn, MessageId m) throws DbException;
/**
* Returns the status of all delivered messages in the given group with
@@ -409,7 +421,7 @@ interface Database<T> {
* Read-only.
*/
Collection<MessageId> getMessagesToOffer(T txn, ContactId c,
int maxMessages) throws DbException;
int maxMessages, int maxLatency) throws DbException;
/**
* Returns the IDs of some messages that are eligible to be requested from
@@ -426,8 +438,8 @@ interface Database<T> {
* <p/>
* Read-only.
*/
Collection<MessageId> getMessagesToSend(T txn, ContactId c, int maxLength)
throws DbException;
Collection<MessageId> getMessagesToSend(T txn, ContactId c, int maxLength,
int maxLatency) throws DbException;
/**
* Returns the IDs of any messages that need to be validated.
@@ -462,15 +474,6 @@ interface Database<T> {
*/
long getNextSendTime(T txn, ContactId c) throws DbException;
/**
* Returns the message with the given ID, in serialised form, or null if
* the message has been deleted.
* <p/>
* Read-only.
*/
@Nullable
byte[] getRawMessage(T txn, MessageId m) throws DbException;
/**
* Returns the IDs of some messages that are eligible to be sent to the
* given contact and have been requested by the contact, up to the given
@@ -479,7 +482,7 @@ interface Database<T> {
* Read-only.
*/
Collection<MessageId> getRequestedMessagesToSend(T txn, ContactId c,
int maxLength) throws DbException;
int maxLength, int maxLatency) throws DbException;
/**
* Returns all settings in the given namespace.
@@ -613,6 +616,12 @@ interface Database<T> {
void setContactActive(T txn, ContactId c, boolean active)
throws DbException;
/**
* Sets an alias name for a contact.
*/
void setContactAlias(T txn, ContactId c, @Nullable String alias)
throws DbException;
/**
* Sets the given group's visibility to the given contact to either
* {@link Visibility VISIBLE} or {@link Visibility SHARED}.
@@ -628,7 +637,8 @@ interface Database<T> {
/**
* Sets the validation and delivery state of the given message.
*/
void setMessageState(T txn, MessageId m, State state) throws DbException;
void setMessageState(T txn, MessageId m, MessageState state)
throws DbException;
/**
* Sets the reordering window for the given key set and transport in the
@@ -641,14 +651,14 @@ interface Database<T> {
* Marks the given transport keys as usable for outgoing streams.
*/
void setTransportKeysActive(T txn, TransportId t, KeySetId k)
throws DbException;
throws DbException;
/**
* Updates the transmission count and expiry time of the given message
* with respect to the given contact, using the latency of the transport
* over which it was sent.
* Updates the transmission count, expiry time and estimated time of arrival
* of the given message with respect to the given contact, using the latency
* of the transport over which it was sent.
*/
void updateExpiryTime(T txn, ContactId c, MessageId m, int maxLatency)
void updateExpiryTimeAndEta(T txn, ContactId c, MessageId m, int maxLatency)
throws DbException;
/**

View File

@@ -6,9 +6,12 @@ import org.briarproject.bramble.api.contact.event.ContactAddedEvent;
import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
import org.briarproject.bramble.api.contact.event.ContactStatusChangedEvent;
import org.briarproject.bramble.api.contact.event.ContactVerifiedEvent;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.ContactExistsException;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbCallable;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.DbRunnable;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.MigrationListener;
import org.briarproject.bramble.api.db.NoSuchContactException;
@@ -16,6 +19,7 @@ import org.briarproject.bramble.api.db.NoSuchGroupException;
import org.briarproject.bramble.api.db.NoSuchLocalAuthorException;
import org.briarproject.bramble.api.db.NoSuchMessageException;
import org.briarproject.bramble.api.db.NoSuchTransportException;
import org.briarproject.bramble.api.db.NullableDbCallable;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventBus;
@@ -39,7 +43,6 @@ import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.MessageStatus;
import org.briarproject.bramble.api.sync.Offer;
import org.briarproject.bramble.api.sync.Request;
import org.briarproject.bramble.api.sync.ValidationManager.State;
import org.briarproject.bramble.api.sync.event.GroupAddedEvent;
import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
import org.briarproject.bramble.api.sync.event.GroupVisibilityUpdatedEvent;
@@ -51,6 +54,7 @@ import org.briarproject.bramble.api.sync.event.MessageToAckEvent;
import org.briarproject.bramble.api.sync.event.MessageToRequestEvent;
import org.briarproject.bramble.api.sync.event.MessagesAckedEvent;
import org.briarproject.bramble.api.sync.event.MessagesSentEvent;
import org.briarproject.bramble.api.sync.validation.MessageState;
import org.briarproject.bramble.api.transport.KeySet;
import org.briarproject.bramble.api.transport.KeySetId;
import org.briarproject.bramble.api.transport.TransportKeys;
@@ -71,8 +75,8 @@ import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
import static org.briarproject.bramble.api.sync.validation.MessageState.DELIVERED;
import static org.briarproject.bramble.api.sync.validation.MessageState.UNKNOWN;
import static org.briarproject.bramble.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
@@ -103,9 +107,9 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
}
@Override
public boolean open(@Nullable MigrationListener listener)
public boolean open(SecretKey key, @Nullable MigrationListener listener)
throws DbException {
boolean reopened = db.open(listener);
boolean reopened = db.open(key, listener);
shutdown.addShutdownHook(() -> {
try {
close();
@@ -165,6 +169,45 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
for (Event e : transaction.getEvents()) eventBus.broadcast(e);
}
@Override
public <E extends Exception> void transaction(boolean readOnly,
DbRunnable<E> task) throws DbException, E {
Transaction txn = startTransaction(readOnly);
try {
task.run(txn);
commitTransaction(txn);
} finally {
endTransaction(txn);
}
}
@Override
public <R, E extends Exception> R transactionWithResult(boolean readOnly,
DbCallable<R, E> task) throws DbException, E {
Transaction txn = startTransaction(readOnly);
try {
R result = task.call(txn);
commitTransaction(txn);
return result;
} finally {
endTransaction(txn);
}
}
@Override
public <R, E extends Exception> R transactionWithNullableResult(
boolean readOnly, NullableDbCallable<R, E> task)
throws DbException, E {
Transaction txn = startTransaction(readOnly);
try {
R result = task.call(txn);
commitTransaction(txn);
return result;
} finally {
endTransaction(txn);
}
}
private T unbox(Transaction transaction) {
if (transaction.isCommitted()) throw new IllegalStateException();
return txnClass.cast(transaction.unbox());
@@ -306,17 +349,18 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
@Nullable
@Override
public Collection<byte[]> generateBatch(Transaction transaction,
public Collection<Message> generateBatch(Transaction transaction,
ContactId c, int maxLength, int maxLatency) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
Collection<MessageId> ids = db.getMessagesToSend(txn, c, maxLength);
List<byte[]> messages = new ArrayList<>(ids.size());
Collection<MessageId> ids =
db.getMessagesToSend(txn, c, maxLength, maxLatency);
List<Message> messages = new ArrayList<>(ids.size());
for (MessageId m : ids) {
messages.add(db.getRawMessage(txn, m));
db.updateExpiryTime(txn, c, m, maxLatency);
messages.add(db.getMessage(txn, m));
db.updateExpiryTimeAndEta(txn, c, m, maxLatency);
}
if (ids.isEmpty()) return null;
db.lowerRequestedFlag(txn, c, ids);
@@ -332,9 +376,11 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
Collection<MessageId> ids = db.getMessagesToOffer(txn, c, maxMessages);
Collection<MessageId> ids =
db.getMessagesToOffer(txn, c, maxMessages, maxLatency);
if (ids.isEmpty()) return null;
for (MessageId m : ids) db.updateExpiryTime(txn, c, m, maxLatency);
for (MessageId m : ids)
db.updateExpiryTimeAndEta(txn, c, m, maxLatency);
return new Offer(ids);
}
@@ -355,18 +401,18 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
@Nullable
@Override
public Collection<byte[]> generateRequestedBatch(Transaction transaction,
public Collection<Message> generateRequestedBatch(Transaction transaction,
ContactId c, int maxLength, int maxLatency) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
Collection<MessageId> ids = db.getRequestedMessagesToSend(txn, c,
maxLength);
List<byte[]> messages = new ArrayList<>(ids.size());
Collection<MessageId> ids =
db.getRequestedMessagesToSend(txn, c, maxLength, maxLatency);
List<Message> messages = new ArrayList<>(ids.size());
for (MessageId m : ids) {
messages.add(db.getRawMessage(txn, m));
db.updateExpiryTime(txn, c, m, maxLatency);
messages.add(db.getMessage(txn, m));
db.updateExpiryTimeAndEta(txn, c, m, maxLatency);
}
if (ids.isEmpty()) return null;
db.lowerRequestedFlag(txn, c, ids);
@@ -456,6 +502,15 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
return db.getLocalAuthors(txn);
}
@Override
public Message getMessage(Transaction transaction, MessageId m)
throws DbException {
T txn = unbox(transaction);
if (!db.containsMessage(txn, m))
throw new NoSuchMessageException();
return db.getMessage(txn, m);
}
@Override
public Collection<MessageId> getMessageIds(Transaction transaction,
GroupId g) throws DbException {
@@ -486,16 +541,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
return db.getMessagesToShare(txn);
}
@Nullable
@Override
public byte[] getRawMessage(Transaction transaction, MessageId m)
throws DbException {
T txn = unbox(transaction);
if (!db.containsMessage(txn, m))
throw new NoSuchMessageException();
return db.getRawMessage(txn, m);
}
@Override
public Map<MessageId, Metadata> getMessageMetadata(Transaction transaction,
GroupId g) throws DbException {
@@ -534,7 +579,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
}
@Override
public State getMessageState(Transaction transaction, MessageId m)
public MessageState getMessageState(Transaction transaction, MessageId m)
throws DbException {
T txn = unbox(transaction);
if (!db.containsMessage(txn, m))
@@ -574,8 +619,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
}
@Override
public Map<MessageId, State> getMessageDependencies(Transaction transaction,
MessageId m) throws DbException {
public Map<MessageId, MessageState> getMessageDependencies(
Transaction transaction, MessageId m) throws DbException {
T txn = unbox(transaction);
if (!db.containsMessage(txn, m))
throw new NoSuchMessageException();
@@ -583,8 +628,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
}
@Override
public Map<MessageId, State> getMessageDependents(Transaction transaction,
MessageId m) throws DbException {
public Map<MessageId, MessageState> getMessageDependents(
Transaction transaction, MessageId m) throws DbException {
T txn = unbox(transaction);
if (!db.containsMessage(txn, m))
throw new NoSuchMessageException();
@@ -655,7 +700,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
merged.putAll(s);
if (!merged.equals(old)) {
db.mergeSettings(txn, s, namespace);
transaction.attach(new SettingsUpdatedEvent(namespace));
transaction.attach(new SettingsUpdatedEvent(namespace, merged));
}
}
@@ -829,6 +874,16 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
transaction.attach(new ContactStatusChangedEvent(c, active));
}
@Override
public void setContactAlias(Transaction transaction, ContactId c,
@Nullable String alias) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
db.setContactAlias(txn, c, alias);
}
@Override
public void setGroupVisibility(Transaction transaction, ContactId c,
GroupId g, Visibility v) throws DbException {
@@ -855,14 +910,15 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
if (!db.containsMessage(txn, m))
throw new NoSuchMessageException();
if (db.getMessageState(txn, m) != DELIVERED)
throw new IllegalArgumentException("Shared undelivered message");
throw new IllegalArgumentException(
"Shared undelivered message");
db.setMessageShared(txn, m);
transaction.attach(new MessageSharedEvent(m));
}
@Override
public void setMessageState(Transaction transaction, MessageId m,
State state) throws DbException {
MessageState state) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsMessage(txn, m))
@@ -879,7 +935,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
T txn = unbox(transaction);
if (!db.containsMessage(txn, dependent.getId()))
throw new NoSuchMessageException();
State dependentState = db.getMessageState(txn, dependent.getId());
MessageState dependentState =
db.getMessageState(txn, dependent.getId());
for (MessageId dependency : dependencies) {
db.addMessageDependency(txn, dependent, dependency, dependentState);
}
@@ -913,7 +970,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
T txn = unbox(transaction);
for (KeySet ks : keys) {
TransportId t = ks.getTransportKeys().getTransportId();
if (db.containsTransport(txn, t)) db.updateTransportKeys(txn, ks);
if (db.containsTransport(txn, t))
db.updateTransportKeys(txn, ks);
}
}
}

View File

@@ -2,6 +2,8 @@ package org.briarproject.bramble.db;
import org.briarproject.bramble.api.settings.Settings;
import static java.util.concurrent.TimeUnit.DAYS;
interface DatabaseConstants {
/**
@@ -23,4 +25,16 @@ interface DatabaseConstants {
*/
String SCHEMA_VERSION_KEY = "schemaVersion";
/**
* The {@link Settings} key under which the time of the last database
* compaction is stored.
*/
String LAST_COMPACTED_KEY = "lastCompacted";
/**
* The maximum time between database compactions in milliseconds. When the
* database is opened it will be compacted if more than this amount of time
* has passed since the last compaction.
*/
long MAX_COMPACTION_INTERVAL_MS = DAYS.toMillis(30);
}

View File

@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.ShutdownManager;
import org.briarproject.bramble.api.sync.MessageFactory;
import org.briarproject.bramble.api.system.Clock;
import java.sql.Connection;
@@ -18,8 +19,9 @@ public class DatabaseModule {
@Provides
@Singleton
Database<Connection> provideDatabase(DatabaseConfig config, Clock clock) {
return new H2Database(config, clock);
Database<Connection> provideDatabase(DatabaseConfig config,
MessageFactory messageFactory, Clock clock) {
return new H2Database(config, messageFactory, clock);
}
@Provides

Some files were not shown because too many files have changed in this diff Show More