Compare commits

..

995 Commits

Author SHA1 Message Date
Michael Rogers
050191f0ef Bumped version number for beta release. 2017-08-01 12:31:47 +01:00
akwizgran
4b5a19ce5d Merge branch 'update-translations' into 'master'
Update translations, add Turkish and Russian

See merge request !575
2017-08-01 09:28:17 +00:00
akwizgran
7c4dd991b9 Merge branch '1016-reblog-runtime-error' into 'master'
Runtime error fix due to window requests

Closes #1016 and #1007

See merge request !576
2017-08-01 09:25:39 +00:00
Ernir Erlingsson
8455569e88 moved window requests above onCreate 2017-07-30 22:42:03 +02:00
Torsten Grote
d25676559c Update translations, add Turkish and Russian 2017-07-29 11:03:51 -03:00
Michael Rogers
a9437f7985 Bumped version number for beta release. 2017-07-28 18:01:19 +01:00
akwizgran
8141a97fc9 Merge branch '1015-recent-emoji-crash' into 'master'
Prevent a crash caused by empty emoji

Closes #1015

See merge request !571
2017-07-28 16:59:02 +00:00
Torsten Grote
db842bd7e4 Prevent a crash caused by empty emoji
The crash happens because the serialization of recently used emoji uses
';' to separate the emojis.
One of the ASCII emojis however has a ';' in the beginning.
When this one is used by the user,
it causes an empty string to be returned when deserializing.

This commit prevents the crash by changing the separator to a tab.
It uses a different settings string to store the emoji,
so users will lose the list of recently used emoji when they update to
this version.

PS. That wasn't my idea ;)
2017-07-28 13:49:51 -03:00
Torsten Grote
6dbec3a864 Merge branch 'enable-logging-for-beta-builds' into 'master'
Enable logging for beta builds

See merge request !573
2017-07-28 15:58:01 +00:00
akwizgran
29f658cf4d Merge branch '1006-blog-crash' into 'master'
Prevent crash in blog by ensuring a listener always exists

Closes #1006

See merge request !574
2017-07-28 15:53:43 +00:00
akwizgran
ca83744a84 Merge branch 'close-feed-stream' into 'master'
Close InputStream from RSS feed and prevent NPE

See merge request !572
2017-07-28 15:48:01 +00:00
Torsten Grote
d91a9e2be4 Prevent crash in blog by ensuring a listener always exists 2017-07-28 12:42:56 -03:00
akwizgran
8408c3f467 Enable logging for beta builds.
Some devices were logging and others not, due to the log level being set in the SplashScreenActivity constructor.
2017-07-28 16:41:24 +01:00
Torsten Grote
544c83a64c Close InputStream from RSS feed and prevent NPE 2017-07-28 10:38:01 -03:00
Michael Rogers
3800cd5e4f Bumped version number for beta release. 2017-07-28 11:17:09 +01:00
akwizgran
259f2cd419 Merge branch '993-fix-full-text-blog-posts' into 'master'
Show blog posts with full text when clicked

Closes #993

See merge request !570
2017-07-26 11:01:38 +00:00
Torsten Grote
20eb022c36 Show blog posts with full text when clicked
This fixes a regression that was introduced in !551.
2017-07-25 15:50:04 -03:00
akwizgran
531e555b52 Bumped version number for beta release. 2017-07-25 18:43:19 +01:00
akwizgran
a9024aa34b Merge branch '955-shared-with-update' into 'master'
Fix "shared with" counter not being updated

Closes #955

See merge request !569
2017-07-25 17:40:40 +00:00
akwizgran
d4e3b7842c Merge branch 'blog-sharing-tests' into 'master'
Add unit tests for BlogSharingManager

See merge request !567
2017-07-25 17:40:29 +00:00
Torsten Grote
167fddfbcc Add unit tests for BlogSharingManager 2017-07-25 12:45:36 -03:00
Torsten Grote
a48d642648 Fix UI bug in CreateForumActivity and adapt group creation 2017-07-25 12:32:53 -03:00
Torsten Grote
9a70f054c7 Use proper GroupId when reacting to accepted invitations
Fixes #955
2017-07-25 10:03:13 -03:00
Torsten Grote
ca43d13bd6 Merge branch 'inject-properties-module-eager-singletons' into 'master'
Inject properties module's eager singletons

See merge request !568
2017-07-25 12:55:59 +00:00
akwizgran
5b71004179 Inject properties module's eager singletons. 2017-07-25 13:49:15 +01:00
akwizgran
63befccdbf Bumped expiry time and version number for beta release. 2017-07-21 11:52:09 +01:00
akwizgran
4ecf7c02d0 Merge branch '979-duplicate-blog-session' into 'master'
Fix Blog Sharing Sessions

Closes #979

See merge request !566
2017-07-21 10:27:21 +00:00
Torsten Grote
f25badc18c Move responsibility for pre-sharing blogs to sharing manager
to have all the code related to that in one place,
so it is easier to maintain and to spot bugs.

This also checks that only blogs without an existing sharing session
are shared and initialized again.
It extends an existing test to catch the missing check.

This removes some debugging information from the previous commit
to not leak private information via the sharing sessions.

Fixes #979
2017-07-17 14:07:47 -03:00
akwizgran
6e931e9ba5 Bump version number and expiry date for beta release. 2017-07-17 10:32:46 +01:00
akwizgran
7e749124bf Merge branch '617-protocol-versioning' into 'master'
Protocol versioning for BTP

See merge request !557
2017-07-17 09:24:35 +00:00
akwizgran
5822eb7808 Remove 'this'. 2017-07-17 10:16:50 +01:00
Torsten Grote
7a7e086541 Merge branch '982-name-not-found-exception' into 'master'
Use fully-qualified class names in manifest

Closes #982

See merge request !565
2017-07-14 12:19:50 +00:00
akwizgran
abab3167c2 Use fully-qualified class names in manifest.
This prevents a crash on Android 4 when the package name in build.gradle differs from the name in the manifest.
2017-07-14 12:01:55 +01:00
Torsten Grote
8d08570568 Merge branch '977-crash-when-opening-rss-blog' into 'master'
Create correct shareable for RSS blogs

Closes #977

See merge request !564
2017-07-07 17:42:54 +00:00
akwizgran
2007078f13 Added test for sharing an RSS blog. 2017-07-07 18:02:15 +01:00
akwizgran
dfb71a7978 Merge branch '942-block-blog-notifications' into 'master'
Block blog notifications when viewing combined feed

See merge request !563
2017-07-07 16:32:07 +00:00
akwizgran
480b0e3a03 Create correct shareable for RSS blogs.
Also removed "personal blog" wording that doesn't apply to RSS blogs.
2017-07-07 17:30:44 +01:00
akwizgran
8f8751f4ac Block blog notifications when viewing combined feed. 2017-07-07 15:34:00 +01:00
akwizgran
de2ea112ee Merge branch '933-beta-warning' into 'master'
Show Beta Expiry Warning

Closes #933

See merge request !559
2017-07-07 12:19:04 +00:00
Torsten Grote
6f99a53fd9 Show beta expiry warning in main activity 2017-07-07 09:12:07 -03:00
akwizgran
a8a9b9032d Merge branch 'warn_on_extra_translation' into 'master'
Show a warning instead of throwing an error for unused translations

See merge request !561
2017-07-07 12:01:23 +00:00
goapunk
6b15fb89de Show a warning instead of throwing an error for unused translations
Signed-off-by: goapunk <noobie@goapunks.net>
2017-07-07 12:19:44 +02:00
Torsten Grote
a711d6b8a1 Merge branch '106-fix-package-name' into 'master'
Set applicationId to match app_package

See merge request !560
2017-07-05 13:46:30 +00:00
akwizgran
5678f8aaa4 Update Robolectric tests so they can find resources. 2017-07-05 14:40:03 +01:00
akwizgran
2fe37f6c26 Set applicationId to match app_package. 2017-07-05 14:17:35 +01:00
Torsten Grote
a879747968 Translation Update 2017-07-05 09:50:14 -03:00
akwizgran
95e8fd7ee0 Merge branch 'notify_more_agressively' into 'master'
Notify more aggressively

See merge request !555
2017-07-05 11:36:37 +00:00
goapunk
4416aaaa4c Notify more aggressively
* Add setting to show notification on the lockscreen
* Don't block notifications in the contact-/-group/-forum/-bloglist

Signed-off-by: goapunk <noobie@goapunks.net>
2017-07-05 13:05:21 +02:00
Torsten Grote
500d5f0efe Merge branch '822-group-creation-workflow' into 'master'
Revisit private group creation workflow

Closes #822

See merge request !553
2017-07-04 17:19:11 +00:00
akwizgran
fc8978fd90 Create forum when button is clicked. 2017-07-04 16:17:59 +01:00
akwizgran
73df126bd4 Create and share private groups separately, as with forums. 2017-07-04 16:17:58 +01:00
akwizgran
9146488c7d Use same layout and behaviour for creating groups and forums. 2017-07-04 16:17:58 +01:00
akwizgran
613a7fe376 Merge branch '962-removing-contacts' into 'master'
Add test where two contacts remove each other

Closes #962

See merge request !558
2017-07-04 15:14:27 +00:00
akwizgran
ecb62f00d4 Code cleanup. 2017-07-04 16:09:32 +01:00
akwizgran
c4540a03cd Protocol versioning for BTP. 2017-07-04 16:09:32 +01:00
akwizgran
3e31da99b5 Merge branch '106-beta-namespace' into 'master'
Change app name and package name for beta release

Closes #106

See merge request !545
2017-07-04 14:40:47 +00:00
Torsten Grote
098c1d0b1e Add test where two contacts remove each other 2017-07-04 11:30:17 -03:00
akwizgran
178e908c86 Use a different package name and app name for beta builds. 2017-07-03 18:20:05 +01:00
akwizgran
ecf7cf14ae Merge branch '957-rss-url-case-sensitivity' into 'master'
Handle RSS URLs case-insensitively

Closes #957

See merge request !544
2017-07-03 16:22:52 +00:00
akwizgran
09e2a15a73 Merge branch '951-remove-visibility-indicators' into 'master'
Remove visibility indicators from private group join messages

Closes #951

See merge request !546
2017-07-03 16:22:31 +00:00
akwizgran
ab387860a6 Removed visibility indicators from private group member list. 2017-07-03 16:37:29 +01:00
akwizgran
f63fc94f2b Removed visibility indicators from private group join messages. 2017-07-03 16:37:29 +01:00
Michael Rogers
41e5928cca Validate and normalise RSS URLs. 2017-07-03 16:36:50 +01:00
Torsten Grote
8303175494 Merge branch 'use-f-droid-base-docker-image' into 'master'
Use F-Droid's base Docker image

See merge request !556
2017-07-03 15:35:28 +00:00
akwizgran
151eb6935b Use F-Droid's base Docker image. 2017-07-03 16:17:03 +01:00
akwizgran
6a419c0c7b Merge branch '968-downgrade-h2' into 'master'
Downgrade H2 to 1.4.192

Closes #968

See merge request !550
2017-07-03 11:51:35 +00:00
akwizgran
1795b32121 Downgrade H2 to 1.4.192. 2017-07-03 12:36:45 +01:00
akwizgran
01971768ce Merge branch '970_settings_use_summaries' into 'master'
Split notification settings into title and summary.

Closes #970

See merge request !554
2017-07-03 11:19:15 +00:00
akwizgran
ef7483ab01 Merge branch '787-tapping-blog-author-opens-same-blog' into 'master'
Don't reopen the same blog when the author is tapped

Closes #787

See merge request !551
2017-07-03 10:43:15 +00:00
akwizgran
527d11473d Merge branch '805-introduction-message-layout' into 'master'
Use smaller layout for introduction message screen

Closes #805

See merge request !552
2017-07-03 10:40:10 +00:00
akwizgran
775dadc9a0 Merge branch '904-notify-tor-controller' into 'master'
Notify Tor controller if Tor has crashed

Closes #904

See merge request !543
2017-07-03 09:29:04 +00:00
akwizgran
800b10a988 Merge branch '956-tap-protection-ux' into 'master'
Don't show tap protection dialog until it's needed

Closes #956

See merge request !548
2017-07-03 09:22:31 +00:00
akwizgran
c977bf047d Removed overrides of showScreenFilterWarning. 2017-07-03 10:08:36 +01:00
goapunk
660a25f21d Split notification settings into title and summary.
Signed-off-by: goapunk <noobie@goapunks.net>
2017-07-03 09:27:07 +02:00
Torsten Grote
e7fd6d23af Merge branch '962-check-blog-subscription-when-removing-contact' into 'master'
Check personal blog subscription when removing contact

See merge request !549
2017-06-30 20:57:52 +00:00
Torsten Grote
46982897f0 Merge branch '963-load-thread-list-messages-on-start' into 'master'
Load messages each time activity starts

See merge request !547
2017-06-30 20:53:13 +00:00
Torsten Grote
d24de68d64 Merge branch '574-upgrade-tor' into 'master'
Upgrade Tor to 0.2.9

Closes #574

See merge request !542
2017-06-30 20:36:22 +00:00
akwizgran
7514c46a3f Use smaller layout for introduction message screen. 2017-06-30 16:23:16 +01:00
akwizgran
6632c0f8e3 Don't reopen the same blog when the author is tapped. 2017-06-30 14:24:32 +01:00
akwizgran
79aafcda69 Fixed a test, added a regression test. 2017-06-30 12:58:44 +01:00
akwizgran
05af21e8dc Check personal blog subscription when removing contact. 2017-06-30 12:04:34 +01:00
akwizgran
0dc62cbbdc Fixed a test. 2017-06-30 10:01:35 +01:00
akwizgran
f3a084cfd2 Removed option to remember shown overlay apps. 2017-06-29 18:47:36 +01:00
akwizgran
8b32f82566 Don't show tap protection dialog until it's needed. 2017-06-29 18:18:39 +01:00
akwizgran
d598b6ed44 Load messages each time activity starts. 2017-06-26 16:21:25 +01:00
akwizgran
f5dc6f24b9 Bumped expiry date to 1 September 2017. 2017-06-26 14:50:58 +01:00
akwizgran
37454392da Update Tor binaries to 0.2.9.11. 2017-06-23 22:06:00 +01:00
akwizgran
de7f9111d3 Update Tor patch to 0.2.9.11. 2017-06-23 15:23:26 +01:00
akwizgran
96d2889a6c Notify Tor controller if Tor has crashed. 2017-06-23 14:57:00 +01:00
Torsten Grote
f6412d1e9a Merge branch 'spongy-castle-1-56' into 'master'
Upgrade Spongy Castle and some other dependencies

See merge request !541
2017-06-15 17:37:22 +00:00
akwizgran
b377cd6b1c Upgrade Spongy Castle and some other dependencies. 2017-06-12 17:44:08 +01:00
Ernir Erlingsson
f6cdbda5bb Merge branch 'master' of https://code.briarproject.org/akwizgran/briar 2017-05-29 11:06:16 +02:00
Ernir Erlingsson
855c600a3e hotfix list restore NPE for user testing 2017-05-29 11:05:46 +02:00
akwizgran
ea6e8303b0 Merge branch '954_dont_show_on_startup_failure' into 'master'
Don't show screenfilter warning in StartupFailureActivity

See merge request !539
2017-05-29 09:05:18 +00:00
goapunk
d4934040d9 Don't show screenfilter warning in StartupFailureActivity
Signed-off-by: goapunk <noobie@goapunks.net>
2017-05-22 12:40:33 +02:00
akwizgran
3449677b24 Bumped version number and expiry date. 2017-05-19 12:07:29 +01:00
akwizgran
1ad3a6646e Merge branch '941-store-correct-parent-id' into 'master'
Store correct original parent ID when rewrapping blog posts

See merge request !534
2017-05-12 09:53:27 +00:00
akwizgran
2d10f6b2bd Merge branch '884-emoji-text-view-layout-bug' into 'master'
Remove ellipsizing support from EmojiTextView

Closes #884

See merge request !533
2017-05-12 09:35:33 +00:00
akwizgran
5b05424d83 Merge branch 'master' into '941-store-correct-parent-id'
# Conflicts:
#   briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerImplTest.java
2017-05-12 09:34:24 +00:00
akwizgran
0826022d82 Merge branch 'bring_annotations_in_line' into 'master'
Bring nullable annotation imports in line

See merge request !536
2017-05-12 09:33:00 +00:00
akwizgran
a901bfb9cb Merge branch '948-vector-crash' into 'master'
Remove scientific notation from vector drawables to prevent crashes

Closes #948

See merge request !537
2017-05-12 09:28:59 +00:00
akwizgran
03cdce122a Merge branch '947-bluetooth-address-crash' into 'master'
Don't crash on empty bluetooth addresses

See merge request !538
2017-05-12 09:26:57 +00:00
goapunk
f2e0e16969 Bring nullable annotation imports in line
Signed-off-by: goapunk <noobie@goapunks.net>
2017-05-12 10:06:56 +02:00
Torsten Grote
0c441e2ff3 Don't crash on empty bluetooth addresses 2017-05-10 15:06:09 -03:00
Torsten Grote
21302304a5 Remove scientific notation from vector drawables to prevent crashes
Details: http://stackoverflow.com/a/40829348
2017-05-10 14:56:59 -03:00
Torsten Grote
6839d8b844 Merge branch 'wifi-manager-memory-leak' into 'master'
Use application context to get WifiManager

See merge request !535
2017-05-10 17:01:52 +00:00
Torsten Grote
aee65a716c Merge branch '798-remove-contact-blogs' into 'master'
Allow to remove pre-shared blogs of our contacts

Closes #798

See merge request !529
2017-05-10 16:58:38 +00:00
Torsten Grote
6a07d8f2c9 Allow to remove pre-shared blogs of our contacts 2017-05-10 13:50:07 -03:00
Ernir Erlingsson
3c1ea81cd0 Merge branch '853-disabled-menu-items' into 'master'
Remove theme default color override

Closes #853

See merge request !527
2017-05-06 20:26:15 +00:00
Ernir Erlingsson
025f417bc7 Merge branch '894-list-position-restore' into 'master'
save and restore list position for threaded lists

Closes #894 and #946

See merge request !528
2017-05-06 19:37:02 +00:00
Ernir Erlingsson
c9dcd906c9 final pre-merge fixes 2017-05-06 21:36:25 +02:00
Ernir Erlingsson
7024e04d15 fixed final akwizgran comments 2017-05-06 21:31:53 +02:00
akwizgran
0b8ac947db Use application context to get WifiManager. 2017-05-05 15:43:27 +01:00
Ernir Erlingsson
948410a064 fixed unread buttons for threaded lists and akwizgran's comments 2017-05-05 14:49:53 +02:00
akwizgran
2841339cac Merge branch '468-ci' into 'master'
Set up basic CI

Closes #468

See merge request !530
2017-05-05 09:11:06 +00:00
Torsten Grote
e8e82bd805 Update Translations 2017-05-04 10:26:49 -03:00
Ernir Erlingsson
6876f40a0e Merge branch 'fix_groupname_validation' into 'master'
Fix groupname validation

See merge request !531
2017-05-04 07:26:55 +00:00
Ernir Erlingsson
5f4e1ecdfd improvements after code review #1
fix
2017-05-02 11:42:55 +02:00
Ernir Erlingsson
044719432a list position save and restore now implemented for threaded lists 2017-05-02 11:42:55 +02:00
Ernir Erlingsson
d1a929da85 bumped expire date 2017-05-02 11:42:15 +02:00
goapunk
2a8978a60d fix group name validation
Signed-off-by: goapunk <noobie@goapunks.net>
2017-04-29 16:49:37 +02:00
Torsten Grote
c0afad7a26 Set up basic CI 2017-04-28 13:24:41 -03:00
akwizgran
37281c6c23 Remove ellipsizing support from EmojiTextView.
This is a workaround for a layout bug.
2017-04-28 15:39:24 +01:00
Ernir Erlingsson
6de539a62d Merge branch '791-permanent-input' into 'master'
Show text input permanently in threaded conversations

Closes #791

See merge request !526
2017-04-27 10:38:58 +00:00
Ernir Erlingsson
34704ec04d Merge branch '874-tree-indicator' into 'master'
Darken thread indicator

Closes #874

See merge request !525
2017-04-26 08:38:52 +00:00
akwizgran
9fd6d46583 Merge branch '871-increase-socket-timeout' into 'master'
Increase socket timeout for Tor sockets

See merge request !519
2017-04-19 16:53:59 +00:00
akwizgran
76a5e25656 Added tests for wrapping and rewrapping blog posts. 2017-04-19 12:16:18 +01:00
akwizgran
3575b74837 Store correct original parent ID when rewrapping blog posts. 2017-04-19 12:15:34 +01:00
Torsten Grote
f1c7996960 Remove theme default color override 2017-04-18 09:14:00 -03:00
Torsten Grote
920f3581fa Show text input permanently in threaded conversations 2017-04-17 16:22:24 -03:00
Torsten Grote
45e7af31fe Darken thread indicator 2017-04-17 16:14:26 -03:00
Torsten Grote
67d5d8cdf1 Merge branch '941-reblogged-rss-post-has-wrong-icon' into 'master'
Store RSS flag for wrapped blog posts

Closes #941

See merge request !524
2017-04-17 18:23:41 +00:00
Torsten Grote
9d8cadb7a9 Merge branch 'use-original-timestamp-for-rss-posts' into 'master'
Use original timestamp for RSS posts, if available

See merge request !523
2017-04-17 18:22:10 +00:00
Torsten Grote
6425c49d04 Merge branch 'remove-single-top-flag' into 'master'
Don't use single top and clear top flags together

See merge request !522
2017-04-17 18:20:46 +00:00
Torsten Grote
68d98b50f2 Merge branch '938-ignore-play-services-overlay-permission' into 'master'
When checking for overlay apps, ignore Play Services

Closes #938

See merge request !521
2017-04-17 18:19:46 +00:00
akwizgran
84986d393f Added a test for #941, fixed some broken tests. 2017-04-13 17:28:45 +01:00
akwizgran
115d488bc3 Clamp the imported timestamp within reasonable limits. 2017-04-13 16:21:00 +01:00
akwizgran
2eeb2213e3 Store RSS flag for wrapped blog posts. 2017-04-13 15:23:08 +01:00
akwizgran
1b48d661e8 Use original timestamp for RSS posts, if available. 2017-04-13 14:43:43 +01:00
akwizgran
49ba66dee9 Don't use single top and clear top flags together. 2017-04-13 13:56:20 +01:00
akwizgran
46920f3bce Merge branch '892-separate-rss-blog' into 'master'
Separate RSS posts from personal blog posts

Closes #892

See merge request !520
2017-04-13 10:15:00 +00:00
Torsten Grote
4b955809f7 Address review comments 2017-04-12 15:18:27 -03:00
akwizgran
57d4d6546a When checking for overlay apps, ignore Play Services. 2017-04-12 14:24:37 +01:00
Torsten Grote
9bfb58a764 Show blog posts from RSS feeds with a dedicated icon
This adds a field to the post headers and some more tests.
2017-04-12 08:43:24 -03:00
Torsten Grote
0256ec0b8c Show reblog icon only for reblogged posts 2017-04-12 08:43:23 -03:00
Torsten Grote
b0b4a85d15 Add integration test for FeedManager
Attention: This factors out a DnsModule to be able to make actual
non-Tor DNS lookups for testing.
2017-04-12 08:43:23 -03:00
Torsten Grote
d40a058ef5 Change blog descriptor format to include RSS feed flag
This now also handles the case where an RSS blog is deleted via the blog
deletion option and not the feed management.
2017-04-12 08:43:22 -03:00
Torsten Grote
58b9efb24c Open feed's blog when clicking it in 'manage activity' 2017-04-12 08:43:22 -03:00
Torsten Grote
17de785c12 Remove blog as well when removing RSS feed
This also adds a confirmation dialog to the removal process.
2017-04-12 08:43:21 -03:00
Torsten Grote
c7ff1ba974 Store RSS feeds in a separate dedicated blog
A fake LocalAuthor is created for this new blog and stored in the feed's metadata.
2017-04-12 08:43:21 -03:00
akwizgran
d17669f131 Increase socket timeout for Tor sockets. 2017-04-11 14:53:03 +01:00
akwizgran
9755cd9ab4 Merge branch '891-messages-not-acked' into 'master'
Fix MessageId calculation for deprecated MessageQueue

Closes #891

See merge request !514
2017-04-11 12:49:44 +00:00
akwizgran
6d2b18facc Merge branch '799-explain-content-visibility' into 'master'
Show explanation about visibility in member lists

Closes #799

See merge request !516
2017-04-07 14:54:41 +00:00
Torsten Grote
f8cf7034db Show explanation about visibility in member lists 2017-04-07 11:38:33 -03:00
akwizgran
a1e65c9fa7 Merge branch '893-double-introduction-accept' into 'master'
Prevent conversation actions from being executed twice

Closes #893

See merge request !512
2017-04-07 14:03:40 +00:00
Torsten Grote
499d2fe677 Prevent conversation actions from being executed twice 2017-04-07 10:00:55 -03:00
Torsten Grote
fe963edd9d Merge branch '829-new-launcher-icon' into 'master'
Use the new launcher icon

Closes #829

See merge request !515
2017-04-07 12:59:35 +00:00
akwizgran
96f006068f Use the new launcher icon. 2017-04-07 13:57:13 +01:00
akwizgran
74f1fa5690 Merge branch '932-panic-button-terminate-process' into 'master'
Terminate the process after handling a panic trigger

Closes #932

See merge request !513
2017-04-07 12:49:52 +00:00
Torsten Grote
85c17b4cb0 Fix MessageId calculation for deprecated MessageQueue
This was preventing introduction messages from getting ACKed.
The introduction tests were modified to check for this.
2017-04-07 09:45:35 -03:00
akwizgran
6b3a1fd6d4 Merge branch 'fix-test-configuration' into 'master'
Fix "all tests" configuration

See merge request !509
2017-04-07 10:19:01 +00:00
akwizgran
bcabcfce8c Merge branch '925_panic_app_market' into 'master'
Refine the panic app list tap behavior

Closes #925

See merge request !511
2017-04-07 10:17:48 +00:00
goapunk
db0a3bf380 Refine the panic app list behavior
* Only open if a market is installed

Signed-off-by: goapunk <noobie@goapunks.net>
2017-04-07 12:07:10 +02:00
akwizgran
d5d9436e28 Terminate the process after handling a panic trigger. 2017-04-07 10:54:51 +01:00
Torsten Grote
0827b067ec Harmonize position of boolean message variables 2017-04-06 15:42:12 -03:00
akwizgran
9d0dbe9210 Merge branch '885_store_only_four_lan_ip' into 'master'
Store only 4 ip addresses because 5 exceed the maximum length.

Closes #885

See merge request !510
2017-04-06 14:38:49 +00:00
akwizgran
1f7d1bf515 Merge branch '675-polite-executor' into 'master'
Use a polite executor for validation tasks

Closes #675

See merge request !507
2017-04-06 14:37:59 +00:00
akwizgran
fb85ecf07b Added note about number of available processors changing. 2017-04-06 15:34:39 +01:00
akwizgran
a931e6b316 Merge branch '906_tapjacking' into 'master'
Add tapjacking protection

Closes #906

See merge request !502
2017-04-06 14:31:10 +00:00
akwizgran
3aa4644339 If we have multiple cores, leave one free from crypto tasks. 2017-04-06 11:36:02 +01:00
goapunk
9a638c804a Store only 4 ip addresses because 5 exceed the maximum length.
Signed-off-by: goapunk <noobie@goapunks.net>
2017-04-06 12:35:44 +02:00
akwizgran
df3254c634 Fix "all tests" configuration.
The last (empty) stage of this configuration used to
complain about not finding any tests. I replace the last
stage with a copy of the briar-android configuration
and removed briar-android from the list of prerequisites,
so all stages now contain tests.
2017-04-06 10:18:42 +01:00
akwizgran
ba353b9f2b List of wifi configs can be null. 2017-04-06 10:11:59 +01:00
goapunk
04c4e70dd1 Add tapjacking protection
* Set filterTouchesWhenObscured for all views
* Warn the user if Apps using the SYSTEM_ALERT_WINDOW permission are installed
* Warn the user if an App using the permission is installed while Briar is running

Signed-off-by: goapunk <noobie@goapunks.net>
2017-04-05 23:25:57 +02:00
akwizgran
d381e25e86 Limit the number of validation tasks on the crypto executor. 2017-04-05 17:34:21 +01:00
akwizgran
0c085f139a Added "polite" delegating executor. 2017-04-05 17:34:20 +01:00
akwizgran
4123f4a5ce Log time spent queueing and executing crypto and DB tasks. 2017-04-05 17:34:15 +01:00
akwizgran
7bc269fda4 Merge branch '914-simpler-secure-random' into 'master'
Remove Fortuna generator, fix Android SecureRandom bug

Closes #914

See merge request !500
2017-04-05 10:55:25 +00:00
akwizgran
a22931bae6 Merge branch '928-move-html-sanitation-to-dbthread' into 'master'
Move HTML Sanitation to DbThread

Closes #928

See merge request !506
2017-04-04 16:54:21 +00:00
akwizgran
403f886110 Merge branch '910-fix-intent-hijacking' into 'master'
Fix possible intent hijacking for implicit pending intents

Closes #910

See merge request !499
2017-04-04 16:34:38 +00:00
Torsten Grote
b7866be38d Move HTML Sanitation to DbThread 2017-04-04 13:27:06 -03:00
akwizgran
a1b415330e Merge branch '926-class-cast-exception' into 'master'
Don't cast Context to BaseActivity

Closes #926

See merge request !505
2017-04-04 12:44:38 +00:00
Torsten Grote
58318bb79f Remove pending intents for clearning notification counters
These counters are already reset when the user clicks the notification
or vists the area of the app the notifications are for.

This also removes a potential intent hijacking vulnerability.
2017-04-04 09:02:38 -03:00
akwizgran
10bb30e190 Don't assume Context is a BaseActivity. 2017-04-03 12:22:52 +01:00
akwizgran
199a2ffc46 Merge branch '909-prevent-multiple-password-screens' into 'master'
Prevent multiple instances of PasswordActivity

Closes #909

See merge request !504
2017-03-31 13:42:04 +00:00
akwizgran
f6ad2992f2 Prevent multiple instances of PasswordActivity. 2017-03-31 12:55:38 +01:00
akwizgran
f039bd1239 Merge branch '909-restrict-access-to-panic-prefs' into 'master'
Don't allow other apps to open the panic prefs activity

See merge request !503
2017-03-31 08:25:21 +00:00
Torsten Grote
da22d91ef3 Update expiry date and translations 2017-03-30 15:35:02 -03:00
Torsten Grote
cd360ec877 Merge branch '909-restrict-access-to-settings-activity' into 'master'
Require a system permission to open the settings activity

See merge request !501
2017-03-30 12:58:07 +00:00
akwizgran
8e1ada4cdc Don't allow other apps to open the panic prefs activity. 2017-03-30 12:26:33 +01:00
akwizgran
ac063b4c79 Require a system permission to open the settings activity. 2017-03-30 12:00:35 +01:00
akwizgran
10e6163e94 Merge branch '915-fix-forumactivitytest' into 'master'
Fix ForumActivityTest

Closes #915

See merge request !496
2017-03-30 08:19:30 +00:00
Torsten Grote
ebc3402307 Merge branch '912-validate-stream-encrypter-args' into 'master'
Validate arguments to StreamEncrypter#writeFrame()

Closes #912

See merge request !497
2017-03-29 16:52:54 +00:00
akwizgran
d9c63bbcfe Remove Fortuna generator, fix Android SecureRandom bug. 2017-03-29 16:31:59 +01:00
akwizgran
9c89e83c20 Merge branch '913-simpler-password-strength-estimation' into 'master'
Simpler password strength estimation

Closes #913

See merge request !495
2017-03-29 15:01:44 +00:00
akwizgran
adc9bdeb68 Merge branch 'run-configurations' into 'master'
Run configurations for tests

See merge request !498
2017-03-29 08:18:05 +00:00
akwizgran
ff7f0bdc63 Added run configurations for tests to git. 2017-03-28 15:36:18 +01:00
Torsten Grote
c5f6980c69 Fix ForumActivityTest 2017-03-28 09:34:42 -03:00
akwizgran
2574354997 Merge branch '905_set_testing_constant_on_debug' into 'master'
Set TESTING from BuildConfig

Closes #905

See merge request !494
2017-03-28 12:30:00 +00:00
akwizgran
c4e42949cf Simpler password strength estimation. 2017-03-28 13:27:04 +01:00
goapunk
1c5897f1cc Set TESTING from BuildConfig
Signed-off-by: goapunk <noobie@goapunks.net>
2017-03-27 23:39:39 +02:00
akwizgran
510f99c7da Validate arguments to StreamEncrypter#writeFrame(). 2017-03-27 16:26:49 +01:00
akwizgran
1918346ae8 Merge branch '911-link-sanitation' into 'master'
Sanitize all HTML before displaying it

Closes #911

See merge request !493
2017-03-27 09:45:17 +00:00
akwizgran
2a59515c72 Merge branch '907-panic-signout' into 'master'
Require a panic app to be set before executing any panic actions

Closes #907

See merge request !492
2017-03-27 09:43:30 +00:00
akwizgran
7161152b41 Merge branch '903_replace_Runtime_with_ProcessBuilder' into 'master'
Use ProcessBuilder instead of Runtime to start tor

See merge request !487
2017-03-27 09:37:00 +00:00
akwizgran
b42660edab Merge branch 'emoji-soft-reference' into 'master'
Fix potential NPE when getting soft reference

See merge request !490
2017-03-27 09:28:30 +00:00
akwizgran
b405bbf98e Merge branch 'setting-to-disable-tor' into 'master'
Add a setting to disable Tor

See merge request !489
2017-03-27 09:27:56 +00:00
akwizgran
c167938b61 Use constants for Tor network setting values. 2017-03-27 10:26:10 +01:00
Torsten Grote
24b531e6b2 Sanitize all HTML before displaying it 2017-03-24 16:45:36 -03:00
Torsten Grote
9cffff715a Require a panic app to be set before executing any panic actions 2017-03-24 16:19:09 -03:00
Torsten Grote
804e912e19 Merge branch 'remove-placeholder-tests' into 'master'
Remove placeholder tests

See merge request !491
2017-03-24 18:12:13 +00:00
akwizgran
d67e3900e3 Removed placeholder tests.
Evidently this way of nagging myself to write tests doesn't work.
2017-03-24 15:18:37 +00:00
akwizgran
e682f31898 Added a setting to disable Tor.
Also fixed a bug with settings namespaces.
2017-03-24 14:56:30 +00:00
akwizgran
a9053808b4 Merge branch '908-rss-import-dns-leak' into 'master'
Don't make DNS lookups during RSS import

Closes #908

See merge request !488
2017-03-24 10:02:19 +00:00
akwizgran
d9a62a0431 Merge branch 'print_tor_errors' into 'master'
Make Tor boot more verbose

See merge request !486
2017-03-24 10:01:29 +00:00
akwizgran
15ba73276d Merge branch '900-remove-error-state' into 'master'
Remove error state and reset session on error instead

Closes #900

See merge request !484
2017-03-24 09:57:03 +00:00
Torsten Grote
720dda784e Remove error state and reset session on error instead 2017-03-23 14:14:23 -03:00
akwizgran
0ae55404f5 Merge branch '900-simplify-sharing-client-state-machine' into 'master'
Remove REMOTE_LEFT state from sharing client state machine

See merge request !483
2017-03-23 16:13:44 +00:00
akwizgran
9c41437870 Prevent OkHttp from making local DNS lookups. 2017-03-23 15:13:15 +00:00
akwizgran
da9cde083f Include description of SOCKS error in exception. 2017-03-23 15:13:15 +00:00
goapunk
ce3156c9fe Use ProcessBuilder instead of Runtime to start tor
* ProcessBuilder copies the ENV from the current proc
  and preserves ANDROID_ROOT and ANDROID_DATA

Signed-off-by: goapunk <noobie@goapunks.net>
2017-03-18 09:46:24 +01:00
goapunk
be3752bf2f Set Android env vars
Signed-off-by: goapunk <noobie@goapunks.net>

(cherry picked from commit e26f663)
2017-03-17 16:00:34 +00:00
noobie
ef74db65aa Make Tor boot more verbose
Signed-off-by: noobie <noobie@goapunks.net>
2017-03-13 12:19:14 +01:00
Torsten Grote
867a233b6f Update expiry 2017-03-06 18:46:15 +01:00
Torsten Grote
36f02b36d9 Update expiry and translations 2017-02-01 11:17:53 -02:00
Torsten Grote
59af25b2cd Remove REMOTE_LEFT state from sharing client state machine 2017-01-12 15:19:28 -02:00
akwizgran
2fb11fba2a Merge branch '877-save-invitation-outcome-to-invitation-message-and-make-available-to-ui' into 'master'
Store invitation outcome in metadata and make it available to the UI

This MR is based on !479 and should only be merged after that one has been merged as well.

It stores the invitation outcome in the message metadata  and includes it in the `canBeOpened()` calculation for private groups and sharables.

Closes #877

See merge request !480
2017-01-06 16:06:19 +00:00
akwizgran
1d11857e75 Merge branch '476-blog-sharing-protocol-modifies-state-external-to-session' into 'master'
Migrate blog sharing to new sharing client infrastructure

This MR contains a second small commit that fixes #816 and adds a test for it.

Closes #476, #701

See merge request !479
2017-01-06 16:04:17 +00:00
Torsten Grote
04508a7431 Store invitation outcome in metadata
and include in canBeOpened calculation for private groups and sharables.
2017-01-06 13:29:21 -02:00
Torsten Grote
5653c6d650 Address review comments 2017-01-06 13:25:13 -02:00
Torsten Grote
ab100ad19b Properly remove the blog when deleting a contact and inform all peers
Fixes #816
2017-01-06 13:01:37 -02:00
Torsten Grote
c13eafef14 Migrate blog sharing to new sharing client infrastructure 2017-01-06 13:01:34 -02:00
akwizgran
d5443e9651 Merge branch '889-select-navdrawer-item-when-coming-from-notification' into 'master'
Check the blog item in NavDrawer when opening a blog via notification

There are three scenarios where the selected item in the NavDrawer changes:
1. The user selects an item -> the item is checked automatically.
2. The user pressed back -> already handled in onBackPressed (needs to be extended with #606)
3. The user touched a notification -> handled by this commit.
   
Signed-off-by: goapunk <noobie@goapunks.net>

Closes #889

See merge request !481
2017-01-06 14:59:21 +00:00
akwizgran
d5f9a3280d Merge branch 'briar-recycler-view-log' into 'master'
Stop periodic list update only once

When testing the forum unread code, I noticed the recycler view is detaching twice. Once because the stop method is called and once because the view detaches from the window. Wouldn't it be safe to null the refresher when the updates are stopped?

See merge request !478
2017-01-06 14:15:48 +00:00
goapunk
09b2ecaecf Check the corresponding NavDrawer item when coming from a notification
Signed-off-by: goapunk <noobie@goapunks.net>
2017-01-06 15:12:40 +01:00
Torsten Grote
dc6a6f27ab Fix MessageTreeImplTest 2017-01-04 16:27:49 -02:00
Torsten Grote
8d9ddeeeee Stop periodic list update only once 2017-01-04 11:15:19 -02:00
Torsten Grote
baed2b8483 Merge branch '879-remove-thread-collapsing-unread-count' into 'master'
Remove code for collapsing threads and for reply count

Besides removing lots of code, this MR also improves the encapsulation between adapter and view holders.

Closes #478, #502, #526, #682,  #683,  #835,  #836

See merge request !477
2017-01-04 13:00:16 +00:00
Torsten Grote
b3d3230549 Remove code for collapsing threads and for reply count 2017-01-04 10:58:31 -02:00
akwizgran
deb8787668 Merge branch '879-threaded-unread-messages' into 'master'
Threaded Unread Handling

![unread](/uploads/457c3bc36c897d683ff8161b4f3a344c/unread.mp4)

This leaves in the collapsing code for now and just hides the UI element for collapsing. The code can be removed in a second pass to simplify the adapter.

Closes #879

See merge request !476
2017-01-04 11:12:24 +00:00
Torsten Grote
7034ea28f3 Merge branch '475-new-sharing-client' into 'master'
New Forum Sharing Client

This is very similar to how the private group invitations work and I am sure there's still some tiny bugs that I didn't catch.

All existing integration tests either pass or have been modified to pass.

Once this has been merged, the code should be usable for blog sharing as well.

Closes #475

See merge request !467
2017-01-03 19:30:48 +00:00
Torsten Grote
51b78cf9b1 Address review comments for new sharing client 2017-01-03 17:25:45 -02:00
Torsten Grote
b4c669243b Add UnreadMessageButton to threaded conversations 2017-01-03 13:25:31 -02:00
Torsten Grote
694e662028 New Forum Sharing Client 2017-01-03 11:23:02 -02:00
Torsten Grote
409e0fb5a5 ForumSharingValidator 2017-01-03 11:23:00 -02:00
Torsten Grote
279f4d668a Add new UnreadMessageButton class 2017-01-02 16:30:00 -02:00
akwizgran
d2608e28ac Merge branch '881-forumactivitytest-fails-due-to-custom-toolbar' into 'master'
Fix ForumActivityTest and get rid of redundant theme definition

Closes #881

See merge request !474
2017-01-02 14:22:27 +00:00
akwizgran
8cf02c5f0e Merge branch '851-refresher-memory-leak' into 'master'
Fix memory leaks caused by periodic view refreshing tasks

This branch implements @goapunk's suggested solution to #851. Credit goes to @ernir for finding the bug and the initial solution, and @goapunk for the improved solution - I just did a quick implementation so we can get this fixed as quickly as possible.

Closes #851

See merge request !473
2017-01-02 14:10:32 +00:00
Torsten Grote
c5df2100da Fix ForumActivityTest and get rid of redundant theme definition 2017-01-02 11:57:45 -02:00
akwizgran
a6999a8197 Merge branch '710-conversationactivity-uses-uninitialised-field-as-format-string-argument' into 'master'
Make sure contact name is initialized when needed

This uses a Listenable Future and unfortunately requires 4 basically identical methods to handle the incoming events. Any suggestions for improving that are welcome.

Closes #710

See merge request !472
2017-01-02 11:11:41 +00:00
akwizgran
da89f11419 Merge branch '882-feedmanagerimpl-logs-rss-feed-urls' into 'master'
Do not log information from RSS feeds

Closes #882

See merge request !475
2017-01-02 10:52:04 +00:00
Torsten Grote
a9663875f4 Update expiry date and translations 2016-12-30 12:13:43 -02:00
Torsten Grote
804966ede6 Do not log information from RSS feeds 2016-12-29 13:07:18 -02:00
Torsten Grote
f0f22b42e5 Make sure contact name is initialized when needed 2016-12-29 12:29:32 -02:00
akwizgran
59316ae3c4 Fix memory leaks caused by periodic view refreshing tasks. 2016-12-28 15:23:21 +00:00
akwizgran
79c78518fb Fix potential NPE when getting soft reference. 2016-12-28 13:47:33 +00:00
Torsten Grote
460b524e4b Merge branch 'record-reading-tests' into 'master'
Unit tests for record readers

I thought we should have some tests for the new logic that skips unrecognised record types.

See merge request !471
2016-12-21 17:14:16 +00:00
akwizgran
48e949c9f8 Merge branch '742-use-unique-request-ids-across-the-app' into 'master'
Use unique request codes across the app

Closes #742

See merge request !470
2016-12-21 15:33:03 +00:00
Torsten Grote
924398c829 Use unique request codes across the app 2016-12-21 12:52:11 -02:00
akwizgran
8619b044ce Merge branch '469-handle-background-errors' into 'master'
Add a handleDbException() method to BaseActivity

This adds a `handleDbException()` method to BaseActivity and a corresponding method for fragments that calls through to the activity.
For now, the method just finishes the activity
and NavDrawerActivity overrides it to do nothing,
and all the error places marked with TODO that finish the activity call the method instead.

That gives us zero functional improvement over the status quo,
but it allows us to change the default behaviour easily,
and then we can start thinking about which cases should have non-default behaviour.

First part of #469

See merge request !469
2016-12-21 14:46:53 +00:00
akwizgran
3c3731a562 Merge branch '876-group-invitation-not-marked-unavailable' into 'master'
Mark invitation unavailable to answer when creator dissolved the group after the invitation.

Closes #876

See merge request !468
2016-12-21 14:43:38 +00:00
akwizgran
b54984b542 Unit tests for RecordReaderImpl. 2016-12-21 14:39:56 +00:00
akwizgran
2390f767f5 Unit tests for KeyAgreementTransport. 2016-12-21 14:08:21 +00:00
Torsten Grote
0a9840997f This adds a handleDbException() method to BaseActivity
and a corresponding method for fragments that calls through to the activity.
For now, the method just finishes the activity
and NavDrawerActivity overrides it to do nothing,
and all the error places marked with TODO that finish the activity call the method instead.

That gives us zero functional improvement over the status quo,
but it allows us to change the default behaviour easily,
and then we can start thinking about which cases should have non-default behaviour.
2016-12-21 12:06:20 -02:00
Torsten Grote
6a94785d9a Mark invitation unavailable to answer when creator dissolved the group
after the invitation.

Closes #876
2016-12-21 11:24:08 -02:00
akwizgran
79fc41477c Merge branch '628-bring-protocols-into-line-with-spec' into 'master'
Bring protocols in line with spec

Closes #628

See merge request !465
2016-12-21 12:52:43 +00:00
Torsten Grote
efb89adf41 Merge branch '793-show-open-button-after-accepting-invitations' into 'master'
Show open button in private conversation after accepting invitations

To keep the implementation simple, the Open button does appear where the Accept button had been previously.

In order to make the Open button functional, I had to make the `GroupId` of the invitation target available to the UI. Most code in this MR is due to that.

![device-2016-12-13-105228](/uploads/d0f27fc02f1411596458d9203a0810d2/device-2016-12-13-105228.png)

Closes #793

See merge request !457
2016-12-20 14:07:13 +00:00
Torsten Grote
c04580e321 Don't open unsubscribed shareables 2016-12-20 12:00:01 -02:00
Torsten Grote
2ef9b8f4b6 Show open button in private conversation after accepting invitations 2016-12-20 08:47:27 -02:00
akwizgran
d63d15329c Merge branch '814-enable-QrScanner-after-QrCode-was-created' into 'master'
Ignore QR code results until local QR code is created

* Make scanning only possible after we are "ready" (= our QrCode was created and set).

Signed-off-by: goapunk <noobie@goapunks.net>

Closes #814

See merge request !454
2016-12-19 19:28:14 +00:00
Torsten Grote
5345db0b6b Address review comments 2016-12-19 11:15:53 -02:00
Torsten Grote
501980d8fe Bring protocols in line with spec 2016-12-19 10:26:48 -02:00
akwizgran
cc5c000278 Merge branch '738-older-devices-show-overflow-icon-on-some-screens-but-not-others' into 'master'
Also show overflow icon on devices with menu key by using Toolbar

Closes #738

See merge request !463
2016-12-16 11:58:18 +00:00
akwizgran
3ce0131b8c Merge branch '828-update-briar-logo-in-app' into 'master'
Update all logos

The launcher icons are now in mipmap folders which is the recommended practice, because on a low-res device, the high res drawables are stripped from the app. This is bad when the user decides to show the app icons really big on the launcher and the high-res drawables are not available anymore.

The old launcher icon seemed to have some sort of 3D effect.
![device-2016-12-13-134037](/uploads/84db532df3821ad74ba57719f0763b7b/device-2016-12-13-134037.png)

Navigation Drawer Old:
![device-2016-12-13-124112](/uploads/465b817d2e0bbbd50b461ea32686c933/device-2016-12-13-124112.png)
Navigation Drawer New:
![device-2016-12-13-132428](/uploads/3c3530bfc515525dd8f66abfa52d1142/device-2016-12-13-132428.png)

Closes #828

See merge request !459
2016-12-15 23:25:40 +00:00
akwizgran
008e4f760a Merge branch '795-use-different-notification-icons-for-different-features' into 'master'
Use different notification icons for different features

![device-2016-12-13-151008](/uploads/2c9aa33c230738b5ea20a76ac5e3b214/device-2016-12-13-151008.png)
![device-2016-12-13-150954](/uploads/85acd46fc6afd3aebcc1fcd015b041d7/device-2016-12-13-150954.png)

Closes #795

See merge request !460
2016-12-15 23:16:36 +00:00
akwizgran
fc44268b22 Removed translations of unused strings. 2016-12-15 23:12:24 +00:00
akwizgran
de0a7c75ed Merge branch '697-include-commit-id-in-crash-reports-and-feedback' into 'master'
Include Commit ID in crash reports and feedback

Closes #697

See merge request !461
2016-12-15 23:06:24 +00:00
Torsten Grote
1c6be2fb78 Include Commit ID in crash reports and feedback 2016-12-15 15:40:52 -02:00
Torsten Grote
09b0a8b161 Use different notification icons for different features
and use the primary color for the notification.
2016-12-15 15:29:48 -02:00
Torsten Grote
a6d053a0ea Update all logos 2016-12-15 15:19:38 -02:00
akwizgran
e7a26c42a4 Merge branch '285-plugins-should-throw-exceptions-for-startup-errors' into 'master'
Plugins throw exceptions for startup errors

Please review carefully as I don't know much about the code I have touched here.

Closes #285

See merge request !462
2016-12-15 14:33:35 +00:00
akwizgran
bb5fc35e17 Removed translations of unused strings. 2016-12-15 10:56:04 +00:00
Torsten Grote
ea4e2f09c8 Revert dagger update 2016-12-14 16:52:38 -02:00
Torsten Grote
ffc9fdbb92 Plugins throw exceptions for startup errors 2016-12-14 16:35:23 -02:00
akwizgran
074f5c2faf Fix imports in HashTest. 2016-12-14 17:09:15 +00:00
goapunk
7666b210e4 Ignore results from the QrScanner if task is not ready
* Ignore results until the KeyAgreementTask is ready and returned the local payload

Signed-off-by: goapunk <noobie@goapunks.net>
2016-12-14 17:28:01 +01:00
akwizgran
ab3fcb6219 Merge branch 'add-crypto-hash-test' into 'master'
Add Unit tests for CryptoComponent#hash()

See merge request !464
2016-12-14 16:14:18 +00:00
akwizgran
b7e35ff780 Merge branch '778-move-unit-tests-into-their-respective-modules' into 'master'
Move all unit tests to their modules and remove briar-tests

There are now tests in these modules:
* bramble-api
* bramble-core
* bramble-j2se
* briar-core
* briar-android

In order to run all -core tests together, the following AS run configuration can be used:
![Screenshot_2016-12-12_16-37-53](/uploads/8c706406f015ecd9e2371ebc28e6b34c/Screenshot_2016-12-12_16-37-53.png)

Closes #778

See merge request !456
2016-12-14 15:57:45 +00:00
akwizgran
3c2428449d Moved test utility classes into test package. 2016-12-14 15:42:52 +00:00
Torsten Grote
25a4caec2a Add Unit tests for CryptoComponent#hash() 2016-12-14 13:15:44 -02:00
Torsten Grote
db71472501 Also show overflow icon on devices with menu key by using Toolbar 2016-12-14 11:17:04 -02:00
Torsten Grote
1081a08ea9 Move all unit tests to their modules and remove briar-tests 2016-12-13 17:22:24 -02:00
akwizgran
32be148c7a Merge branch '646-shared-with-subtitle-groups' into 'master'
Add sharing information to private group ActionBar subtitle

![device-2016-12-12-114533](/uploads/b31fc37643ef6e817a80a4ddd767fe98/device-2016-12-12-114533.png)

Closes #646

See merge request !455
2016-12-13 18:01:48 +00:00
Torsten Grote
78000375df Merge branch '155-notification-icon' into 'master'
Make notification icon less similar to superuser icon

Closes #155

See merge request !458
2016-12-13 17:24:05 +00:00
akwizgran
66f8978bb6 Make notification icon less similar to superuser icon. 2016-12-13 17:20:48 +00:00
Torsten Grote
45b5040254 Add sharing information to private group ActionBar subtitle 2016-12-12 13:55:35 -02:00
Torsten Grote
378a8f0a10 Merge branch '813-add-online-status-and-creator-information-to-group-memberlist' into 'master'
Add creator and online information to group member list

![device-2016-12-06-102258](/uploads/90e19a6ca31aaf91c6ebf3ea8e218b3f/device-2016-12-06-102258.png)
![device-2016-12-06-110113](/uploads/3fd62f7cdfe75419a07262356d27b952/device-2016-12-06-110113.png)

Closes #813

See merge request !448
2016-12-12 15:36:02 +00:00
Torsten Grote
562866494b Add creator and online information to group member list 2016-12-12 13:33:23 -02:00
akwizgran
c9cb085a0a Merge branch '777-move-integration-tests-into-their-respective-modules' into 'master'
Move integration tests to their proper packages

Closes #777

See merge request !453
2016-12-12 15:08:26 +00:00
Torsten Grote
97d4c68f43 Move integration tests to their proper packages 2016-12-12 10:27:41 -02:00
Torsten Grote
4226ba40c2 Merge branch '570-consistent-use-of-animations' into 'master'
Make animations more consistent

![animations6](/uploads/0ac694d3561515e04fbb9032d31f183c/animations6.mp4)

Closes #570, #621

See merge request !439
2016-12-09 16:49:26 +00:00
Torsten Grote
3df3d19a07 Address review comments 2016-12-09 14:40:20 -02:00
Torsten Grote
e3dcc62509 Use back transition when backing out of creating private group 2016-12-09 14:22:05 -02:00
Torsten Grote
db3c3eee44 Move OnBlogPostClickListener from activity to fragment 2016-12-09 14:22:03 -02:00
Torsten Grote
5a522d64df Don't show splash screen when signed in
This also removes the BriarFragmentActivity that was only really used by
the NavDrawerActivity.
2016-12-09 14:14:47 -02:00
Torsten Grote
68b216d580 Make animations more consistent 2016-12-09 14:13:18 -02:00
Torsten Grote
d5c6fcc85b Fix merge accident after renaming event 2016-12-09 14:12:27 -02:00
Torsten Grote
a099104d08 Merge branch '646-shared-with-subtitle-forums' into 'master'
Add sharing info to ForumActivity action bar subtitle

This indirectly does also most of the work for adding the same information to private groups. However, completing this is blocked by !448.

![device-2016-12-07-152915](/uploads/5bb42f2e78a87931b0307e7597ba72c5/device-2016-12-07-152915.png)

Second part of #646

See merge request !451
2016-12-09 16:06:21 +00:00
akwizgran
787b3399f7 Merge branch '646-shared-with-subtitle' into 'master'
Add blog sharing information to toolbar subtitle

This MR introduces a new `SharingController` which is supposed to be used in activities that show blogs, groups and forums. Feedback on this approach is welcome before this is used to add "Shared with" support to other parts of the UI.

The toolbar subtitle shows information about how many contacts the current shareable is shared with and how many of those are online.

So far this is implemented for blogs:

![device-2016-12-05-180207](/uploads/13afb4c7c5d10ad29c414865ee02670d/device-2016-12-05-180207.png)

One part of #646

See merge request !447
2016-12-09 16:04:04 +00:00
Torsten Grote
4e159bbb1f Add sharing info to ForumActivity action bar subtitle 2016-12-09 14:02:42 -02:00
Torsten Grote
7c6232db9d Address review comments (rename event, fix annotations, final field) 2016-12-09 13:54:39 -02:00
Torsten Grote
6cf1480d2d Merge branch '766-unit-tests-for-peer-protocol-engine' into 'master'
Add unit tests for PeerProtocolEngine

Although not all classes have unit tests, this

Closes #766

See merge request !450
2016-12-08 16:14:34 +00:00
Torsten Grote
2679e6932f Add unit tests for PeerProtocolEngine 2016-12-08 14:13:00 -02:00
akwizgran
17e149e517 Merge branch '766-unit-tests-for-invitee-protocol-engine' into 'master'
Add unit tests for InviteeProtocolEngine

Next part of #766

See merge request !444
2016-12-08 15:42:05 +00:00
Torsten Grote
d04dda1566 Add sharing information to toolbar subtitle of blogs
The toolbar subtitle shows information about how many contacts the
current blog is shared with and how many of those are online.
2016-12-07 15:16:44 -02:00
Torsten Grote
5588855667 Fix intent of some CreatorProtocolEngine unit tests 2016-12-07 15:07:01 -02:00
Torsten Grote
7df6abbcbe Merge branch '810-fix-sharing-status-screens' into 'master'
Fix Sharing Status screens

* Remove distinction between "shared with" and "shared by"
* Show all contacts a blog is shared with
* Show online status of contacts in sharing screen

![device-2016-12-05-142949](/uploads/703fbd2d52815374e57edd89f754bf6c/device-2016-12-05-142949.png)

Closes #810

See merge request !445
2016-12-07 16:52:29 +00:00
Torsten Grote
001f5faeaa Two small review details: comment and initializing boolean 2016-12-07 14:49:57 -02:00
Torsten Grote
ba1a19d236 Address review issues 2016-12-07 14:31:24 -02:00
Torsten Grote
b7ce7de42a Add unit tests for InviteeProtocolEngine 2016-12-07 14:31:23 -02:00
akwizgran
3f6a8f9341 Merge branch '808-introduction-client-logs-contact-names' into 'master'
Remove verbose logging from introduction client

Closes #808

See merge request !449
2016-12-07 15:49:14 +00:00
akwizgran
9495163016 Merge branch 'onboarding-dialog-style' into 'master'
Introduce Dialog Theme for Onboarding

Currently onboarding dialogs and confirmation dialogs look the same. This MR introduces a new dialog theme for onboarding dialogs that looks like the tap target onboarding, so that the user can immediately spot the purpose of the dialog.

![device-2016-12-06-085539](/uploads/6d75b17c0f20028bb7ffac65e6fba03a/device-2016-12-06-085539.png)

See merge request !446
2016-12-07 15:47:12 +00:00
Torsten Grote
7f5a5d40dc Remove verbose logging from introduction client 2016-12-06 15:36:54 -02:00
Torsten Grote
98dd8ec7f7 Fix Sharing Status screens
* Remove distinction between "shared with" and "shared by"
* Show all contacts a blog is shared with
* Show online status of contacts in sharing screen
2016-12-06 10:53:50 -02:00
akwizgran
27c2ee8d89 Merge branch '548-require-a-label-for-hashing' into 'master'
Require a label for hashing

* Add a string label argument to `CryptoComponent#hash()`
* Convert `DoubleDigest` from implementing `MessageDigest`
  to implementing `org.spongycastle.crypto.Digest`
  (we need to keep `DoubleDigest` for `FortunaGenerator`)
* Convert all other uses of `MessageDigest` to `CryptoComponent#hash()`
* Remove `CryptoComponent#getMessageDigest()`, `MessageDigest` and `DigestWrapper`

Closes #548

See merge request !442
2016-12-06 11:07:58 +00:00
Torsten Grote
b98ab93e77 Merge branch '283-die-bluetooth-die' into 'master'
Ensure key agreement tasks finish if they ignore interrupts

The problem here was that `BluetoothSocket#connect()` was throwing an IOException when the task was interrupted - the task treated this like any other connection failure and retried, so the task never finished.

The fix is to check whether the timeout has expired before retrying, so the task eventually finishes even if it ignores the original interrupt.

Closes #283

See merge request !443
2016-12-06 11:02:19 +00:00
Torsten Grote
81337fe7ad Introduce Dialog Theme for Onboarding 2016-12-05 14:54:39 -02:00
akwizgran
cdd234dfe3 Ensure key agreement tasks finish if they ignore interrupts. 2016-12-05 12:38:45 +00:00
Torsten Grote
062ed4ef4b Require a label for hashing
* Add a string label argument to CryptoComponent#hash()
* Convert DoubleDigest from implementing MessageDigest
  to implementing org.spongycastle.crypto.Digest
  (we need to keep DoubleDigest for FortunaGenerator)
* Convert all other uses of MessageDigest to CryptoComponent#hash()
* Remove CryptoComponent#getMessageDigest(), MessageDigest and DigestWrapper
2016-12-05 09:57:18 -02:00
akwizgran
9c22ea8434 Merge branch '766-unit-tests-for-creator-protocol-engine' into 'master'
Add unit tests for CreatorProtocolEngine

See merge request !441
2016-12-05 09:59:40 +00:00
Torsten Grote
9458b185f8 Add unit test for CreatorProtocolEngine 2016-12-02 10:57:00 -02:00
akwizgran
c2b06536ad Merge branch 'identity-manager-unit-tests' into 'master'
Add missing IdentityManager unit tests

See merge request !440
2016-12-02 10:35:15 +00:00
akwizgran
878b52ef2c Merge branch '771-create-bramble-modules' 2016-12-01 21:48:03 +00:00
Torsten Grote
a9ddb0019e Add missing IdentityManager unit tests 2016-12-01 13:21:09 -02:00
akwizgran
2d7cb7b279 Updated Transifex config. 2016-12-01 10:19:24 +00:00
akwizgran
f25d33b0c8 Move stray resources to the right place. 2016-12-01 10:18:42 +00:00
akwizgran
906dd1bd06 Added .gitignore files for new modules. 2016-12-01 10:08:46 +00:00
akwizgran
ad6016d428 Updated java.library.path. 2016-11-30 18:10:49 +00:00
akwizgran
f6d23b4d1a Merge branch '705-blog-pager-race-conditions' into 'master'
Remove blog pagers

I set out to fix potential race conditions in the blog pagers (the screens you reach by tapping the body of a blog post, that allow you to swipe left and right through the posts in the combined feed or a single blog). The race conditions here are similar to those addressed by !356, but the adapters don't inherit from BriarAdapter so they need to be fixed separately.

While I was looking into this I found a few minor problems with the pagers:
* The feed pager wasn't responding to events - this was fixed in !398
* The feed pager finishes NavDrawerActivity when any blog is removed
* The feed isn't updated when a blog is added (this applies to the list view as well as the pager)
* Posts aren't removed from the feed pager when a blog is removed

The last problem is quite serious - the feed pager's adapter contains posts that are no longer in the DB, so they'll fail to load. To fix that problem, the adapter needs to be cleared in onStop() and repopulated in onStart(). This is the same approach we use for other adapters where items can be removed from the underlying dataset. Unfortunately, FragmentStatePagerAdapter has some odd behaviour when you clear and repopulate it:

1. When reselecting the previously selected item after clearing and repopulating the adapter, the item slides into view instead of just appearing, which makes it look like you've accidentally swiped.
2. Items are sometimes duplicated when clearing and repopulating the adapter, so swiping left or right shows another copy of the same post.

These problems only seem to happen if the adapter is cleared - adding new posts works fine on master, although I think there might be some luck involved - FragmentStatePagerAdapter doesn't seem to be designed to support items changing positions.

I spent a lot of time trying to resolve these problems before concluding that maybe it wasn't worth it, and we should just remove the pagers. That's what's currently implemented in this branch. Tapping the body of a post will show the full-length post, but you won't be able to swipe left or right.

The swiping functionality was nice to have, so if you have ideas for fixing the bugs I'd love to hear them. But I'd rather remove this functionality than keep it in a buggy state with no plan for how to fix it.

Closes #705

See merge request !400
2016-11-30 11:21:03 +00:00
akwizgran
aa064e853a Merge branch '760-integration-tests-for-private-group-invitation-protocol' into 'master'
Add integration tests for GroupInvitationManager

This MR is based on !433. It adds some integration tests for the private group invitation protocol. One of those tests fails at the moment.

It does not yet cover all corner cases, so it does not fully address #760, but addresses a part of it. Suggestions for more scenarios to test are welcome.

[Wording changed to prevent #760 from being closed automatically based on the description.]

See merge request !434
2016-11-30 11:19:05 +00:00
akwizgran
8a139eaf5d Tightened up test expectations. 2016-11-30 11:17:57 +00:00
akwizgran
d51f73151f Fixed a bug in the group invitation protocol, added tests. 2016-11-30 11:12:04 +00:00
akwizgran
6c90204c6e Fixed a broken unit test. 2016-11-30 11:07:30 +00:00
akwizgran
f8266d8a02 Tightened up some tests. 2016-11-30 10:23:43 +00:00
akwizgran
f245b04726 Fixed a failing test. 2016-11-30 10:23:43 +00:00
Torsten Grote
67d9f3a7c2 Add integration tests for GroupInvitationManager 2016-11-30 10:23:35 +00:00
akwizgran
24d68c4f5b Merge branch '727-refactor-integration-tests' into 'master'
Refactor Integration Tests

This is quite a massive MR (currently 1763 additions and 3482 deletions). However, there's not so much happening. The only thing I did was moving redundant code from the various protocol integration tests to the `BriarIntegrationTest` class.

All integration tests are still passing.

Closes #727

See merge request !433
2016-11-29 18:28:11 +00:00
akwizgran
edbd7f4eeb Addressed review comments. 2016-11-29 18:27:19 +00:00
akwizgran
2f7830e73f Merge branch '766-unit-tests-for-group-validators' into 'master'
Add unit tests for group validators

Part of #766

See merge request !436
2016-11-29 18:13:43 +00:00
akwizgran
a82fdca3d4 Added more private group invitation validation tests. 2016-11-29 18:12:32 +00:00
akwizgran
050111a994 Added some more private group validation tests, found a bug. 2016-11-29 17:46:46 +00:00
akwizgran
a22d1d811f Merge branch '766-unit-tests-for-group-invitation-client' into 'master'
Add unit tests for group invitation client

Part of #766

See merge request !429
2016-11-29 11:51:17 +00:00
akwizgran
90124e00ca Addressed review comments. 2016-11-29 11:50:20 +00:00
akwizgran
04323856de Merge branch '782-wrong-item-selected-in-navdrawer-onBackPressed' into 'master'
Fix Contacts Item always beeing selected if Back is pressed in the NavMenu

Signed-off-by: goapunk <noobie@goapunks.net>

Closes #782

See merge request !438
2016-11-28 17:07:24 +00:00
goapunk
cfcd36f21a Fix Contacts Item always beeing selected if Back is pressed in the NavMenu
Signed-off-by: goapunk <noobie@goapunks.net>
2016-11-28 16:29:41 +01:00
Ernir Erlingsson
2b9ccb4c42 Merge branch '782-wrong-item-selected-in-navdrawer-onBackPressed' into 'master'
Select the correct MenuItem when Back is pressed in NawDrawer

Signed-off-by: goapunk <noobie@goapunks.net>

Closes #782

See merge request !437
2016-11-28 08:37:53 +00:00
Ernir Erlingsson
6436e6688d Merge branch '477-private-messaging-text-bubble-and-header-overlap' into 'master'
Bring back the toolbar shadow

![device-2016-11-21-180111](/uploads/7cd5e6a1e7a4b79b6d7cf81377b148a0/device-2016-11-21-180111.png)

Closes #477

See merge request !431
2016-11-27 21:55:24 +00:00
Torsten Grote
8c7a532e2e Update translations before user testing 2016-11-27 13:38:26 -02:00
goapunk
47171f3e18 Select the correct MenuItem when Back is pressed in NawDrawer
Signed-off-by: goapunk <noobie@goapunks.net>
2016-11-26 23:09:07 +01:00
Torsten Grote
6fc42f7296 Update also Malaysian translation (removes unused strings) 2016-11-23 21:08:51 -02:00
Torsten Grote
55af22ca04 Update translations and expiry date 2016-11-23 21:05:06 -02:00
Torsten Grote
b37a7531ca Add unit tests for group validators 2016-11-23 18:53:03 -02:00
akwizgran
6ab8219394 Merge branch '666-transport-icons-overlap-navigation-items' into 'master'
Make navigation drawer scrollable

![device-2016-11-22-095642](/uploads/bcd5f68d40816ed2e44c3194eb977695/device-2016-11-22-095642.png)![device-2016-11-22-095658](/uploads/da1807e981632936ba04db24dc7b8ae7/device-2016-11-22-095658.png)

Closes #666

See merge request !432
2016-11-23 15:11:43 +00:00
akwizgran
7d1ddb6d65 Merge branch '504-define-and-design-primary-and-secondary-actions' into 'master'
Make dialog actions consistent

Closes #504

See merge request !430
2016-11-23 15:08:58 +00:00
akwizgran
f1371f1db8 Merge branch '774-adding-contacts-via-bluetooth-only-fails' into 'master'
Use uuid created from the commitment/payload instead of the uuid returned from getUuid()

Signed-off-by: goapunk <noobie@goapunks.net>

Closes #774

See merge request !435
2016-11-23 15:06:16 +00:00
goapunk
491e0adc9c Use uuid created from the commitment/payload instead of the uuid returned from getUuid()
Signed-off-by: goapunk <noobie@goapunks.net>
2016-11-23 10:07:47 +01:00
Torsten Grote
2850763ec6 Refactor Integration Tests 2016-11-22 13:31:58 -02:00
Torsten Grote
f10ac13350 Make navigation drawer scrollable 2016-11-22 09:59:42 -02:00
Torsten Grote
e69139bc24 Bring back the toolbar shadow 2016-11-21 18:32:29 -02:00
Torsten Grote
38f46a9c60 Make dialog actions consistent 2016-11-21 17:42:23 -02:00
Torsten Grote
b0b932a01c Add unit tests for group invitation client 2016-11-21 16:57:28 -02:00
Torsten Grote
20de6f1aa5 Merge branch '747-remove-injected-field-from-unit-test' into 'master'
Remove injected field from unit test

Getting this off my todo list...

Closes #747

See merge request !428
2016-11-21 16:43:49 +00:00
akwizgran
cbdeb0ad32 Replace unused injected field with a mock. 2016-11-21 16:41:01 +00:00
akwizgran
a60414517c Merge branch '639-reblogger-and-author-look-similar-their-roles-are-unclear' into 'master'
Make original author look like commenter when reblogged

This wasn't as simple as changing the persona in the XML,
because the same layout is used for a post whether reblogged or not.
So the persona needs to be changed programmatically for reblogged posts.
For this, the `AuthorView#setPersona()` method has been made public and
was changed to always set all views into the desired state to support
usage in a RecyclerView.

![device-2016-11-21-094221](/uploads/e508937ad2d2d84f97f5be29bdeaac2e/device-2016-11-21-094221.png)

Closes #639

See merge request !426
2016-11-21 15:51:43 +00:00
akwizgran
988c3e4b58 Merge branch '768-keyagreementconnector-regression-unsupportedoperationexception' into 'master'
Fix KeyAgreement after regression

Closes #768

See merge request !427
2016-11-21 12:34:33 +00:00
Torsten Grote
b0098fb054 Fix KeyAgreement after regression 2016-11-21 10:32:06 -02:00
Torsten Grote
a7c28f04de Make original author look like commenter when reblogged
This wasn't as simple as changing the persona in the XML,
because the same layout is used for a post whether reblogged or not.
So the persona needs to be changed programmatically for reblogged posts.
For this, the `AuthorView#setPersona()` method has been made public and
was changed to always set all views into the desired state to support
usage in a RecyclerView.
2016-11-21 09:43:22 -02:00
akwizgran
4eec29a631 Merge branch '762-textinput_does_not_increase' into 'master'
make TextInputView resizable again

* TextInputView can resize up to 3 lines again

Signed-off-by: goapunk <noobie@goapunks.net>

Closes #762

See merge request !425
2016-11-21 10:11:00 +00:00
goapunk
76504387ff make TextInputView resizable again
* TextInputView can resize up to 3 lines again

Signed-off-by: goapunk <noobie@goapunks.net>
2016-11-18 18:05:31 +01:00
Torsten Grote
ea0ad08f57 Merge branch '763-remove-signature-api' into 'master'
Remove old signature class from API

I decided not to remove the SignatureImpl class, as it's not a trivial wrapper around the Bouncy Castle class, but I moved the interface into briar-core and made it  package-private.

Closes #763

See merge request !424
2016-11-18 16:23:01 +00:00
akwizgran
e4676517ef Merge branch '524-check-that-acra-is-catching-all-uncaught-exceptions' into 'master'
Introduce a @Scheduler annotation

and make sure work is offloaded to an executor, so exceptions can be caught.

Closes #524

See merge request !422
2016-11-18 16:00:22 +00:00
akwizgran
dbbeb37485 Merge branch '757-remove-deviceid-code' into 'master'
Remove Device ID

Closes #757

See merge request !423
2016-11-18 15:54:28 +00:00
akwizgran
89a7f41a07 Remove old signature class from API. 2016-11-18 15:30:18 +00:00
akwizgran
936ee5e95b Merge branch '549-require-a-label-for-signing' into 'master'
Require a label for signing

This adds a sign() and a verify() method to the CryptoComponent
that take a mandatory label argument to ensure that signatures can't be
repurposed.

Closes #549

See merge request !419
2016-11-18 15:16:41 +00:00
Torsten Grote
1697c2af04 Remove Device ID 2016-11-18 12:30:25 -02:00
Torsten Grote
cb8e0beea9 Fix Transport IDs 2016-11-18 12:29:57 -02:00
Torsten Grote
98cb077dd9 Migrate all custom signature code to new methods and add test 2016-11-18 12:19:03 -02:00
akwizgran
e6a8ad5d49 Merge branch '754-add-visibility-information-to-group-member-list' into 'master'
Add visibility information to group member list

![device-2016-11-17-120740](/uploads/f16dd42c3637e0030722559bace9c391/device-2016-11-17-120740.png)![device-2016-11-17-121008](/uploads/a83fe1f27cd3a505cf45a94fec76cdcf/device-2016-11-17-121008.png)

Closes #754

See merge request !418
2016-11-18 13:19:45 +00:00
akwizgran
5e4116efa0 Merge branch '761-keyboard_doesnt_close_on_userinteraction' into 'master'
use SHOW_IMPLICIT when showing the softkeyboard, otherwise it won't auto hide

* remove the forced hiding in ThreadListActivity as it should no longer be required

Signed-off-by: goapunk <noobie@goapunks.net>

Closes #761

See merge request !421
2016-11-18 13:14:51 +00:00
akwizgran
a01eeafe4e Merge branch '752-refactor-android-dagger-module' into 'master'
Activity module refactor

Broke the Activity module into numerous modules to be able to make numerous controller's package visible

Closes #752

See merge request !417
2016-11-18 13:13:12 +00:00
Torsten Grote
c86d971166 Require a label for signing
This adds a sign() and a verify() method to the CryptoComponent
that take a mandatory label argument to ensure that signatures can't be
repurposed.
2016-11-18 11:05:19 -02:00
Torsten Grote
d5f8808597 Add visibility information to group member list 2016-11-18 11:02:54 -02:00
goapunk
e98f4901f5 use SHOW_IMPLICIT when showing the softkeyboard, otherwise it won't auto hide
* remove the forced hiding in ThreadListActivity as it should no longer be required

Signed-off-by: goapunk <noobie@goapunks.net>
2016-11-18 13:50:04 +01:00
akwizgran
9b09b64ad3 Merge branch '558-use-namespaced-strings-for-transport-ids' into 'master'
Use namespaced strings for Transport IDs

Closes #558

See merge request !420
2016-11-18 12:49:57 +00:00
Torsten Grote
20708bc156 Introduce a @Scheduler annotation
and make sure work is offloaded to an executor, so exceptions can be
caught.
2016-11-18 10:48:20 -02:00
akwizgran
0814458cb9 Merge branch '759-introduction-responses-are-not-marked-as-read' into 'master'
Do not track incoming positive introduction responses

Positive introduction responses are not shown in the UI (for introducees) and are therefore not marked as read. If they would be tracked, the unread message count would be higher than it actually is and would never decrease.

This is a minimal fix that could be better, but I didn't bother to refactor anything, because we need to rewrite the introduction client eventually anyway once more.

Closes #759

See merge request !416
2016-11-18 12:20:40 +00:00
Torsten Grote
e32313c30b Use namespaced strings for Transport IDs 2016-11-17 17:06:26 -02:00
Torsten Grote
593152e7cd Do not track incoming positive introduction responses
because they are not shown in the UI and are therefore not marked as
read. This fixes the unread message count.
2016-11-17 10:59:20 -02:00
Ernir Erlingsson
ab91520813 refactored the activity module 2016-11-17 13:57:02 +01:00
Torsten Grote
37e61c97ea Merge branch 'remove-unmodifiable-wrappers' into 'master'
Remove unnecessary unmodifiable collection wrappers

Part of #379.

See merge request !414
2016-11-16 18:02:34 +00:00
Torsten Grote
303fcc9ece Merge branch 'validator-unit-tests' into 'master'
Unit tests for some validators

See merge request !413
2016-11-16 17:44:08 +00:00
akwizgran
e2bbe7429b Moved some boilerplate into a field. 2016-11-16 17:00:53 +00:00
akwizgran
eaf17c054f Moved common fields to superclass. 2016-11-16 16:39:30 +00:00
Torsten Grote
f97f30ce42 Merge branch '756-avoid-lost-messages' into 'master'
Use new group visibility state to avoid lost messages

Depends on !410. Closes #756.

See merge request !411
2016-11-16 16:22:30 +00:00
akwizgran
f4c26d9cc7 Remove unnecessary unmodifiable collection wrappers. 2016-11-16 16:19:47 +00:00
akwizgran
68abf8ba1a Merge branch '756-group-visibility' into 'master'
Add third group visibility state

This branch adds a third group visibility state: each group is either invisible, visible, or shared with respect to each contact.

Invisible means that the contact doesn't see any sign that we subscribe to the group. Visible means that the contact can send us messages in the group, but we won't send the contact messages in the group. Shared means that the contact can send us messages in the group and we'll send the contact any shared messages in the group.

This is a preparatory step for #756. I'll put up another MR with the changes that close that ticket.

See merge request !410
2016-11-16 15:56:37 +00:00
akwizgran
58f6af513d Use new group visibility state to avoid lost messages. #756 2016-11-16 15:50:07 +00:00
akwizgran
c9170fa5a0 Removed unnecessary use of unmodifiable collections. 2016-11-16 15:48:08 +00:00
akwizgran
ec1f4dccdb Added third group visibility state. 2016-11-16 15:40:51 +00:00
akwizgran
8c3b598ab2 Unit tests for ForumSharingValidator. 2016-11-16 15:35:27 +00:00
akwizgran
bd3bba6e8a Unit tests for ForumPostValidator. 2016-11-16 14:36:22 +00:00
akwizgran
11fcad89c6 Unit tests for BdfMessageValidator. 2016-11-16 14:32:22 +00:00
Torsten Grote
007df4288b Merge branch '709-track-private-group-invitation-messages' into 'master'
Use MessageTracker for private group invitation messages

Depends on !405.

See merge request !412
2016-11-16 14:14:48 +00:00
Torsten Grote
9798654c23 Merge branch 'message-tracker-refactoring' into 'master'
Factor MessageTracker out of BdfIncomingMessageHook

The branch moves the MessageTracker implementation from BdfIncomingMessageHook to a separate class. This will allow the private group invitation client to track messages from classes other than the one that implements the delivery hook.

I've also fixed a couple of bugs, removed some redundant code from the validation manager, and added null-safety annotations (which is how I noticed the bugs).

See merge request !405
2016-11-16 14:04:14 +00:00
akwizgran
7b58d003a1 Merge branch '732-reveal-contacts-ui-join-notices' into 'master'
Add visibility and OPTIONS button to private group join notices

![device-2016-11-11-180658](/uploads/e00d175a1e1f34307c5f0d80fa0d1cdf/device-2016-11-11-180658.png)
![device-2016-11-11-181325](/uploads/0f6010094d529a4f151db8ebce974885/device-2016-11-11-181325.png)

Closes #732

See merge request !408
2016-11-16 13:44:32 +00:00
akwizgran
b60f6b0789 Merge branch '755-group-message-timestamp' into 'master'
Made private group timestamp greater than that of latest message

I did not change `getPreviousMsgId()` to `getPreviousMsgHeader()` because there doesn't seem to be a need for it anymore.

Closes #755

See merge request !409
2016-11-16 13:29:59 +00:00
Torsten Grote
914b72505a Made private group timestamp greater than that of latest message 2016-11-16 11:20:25 -02:00
Torsten Grote
24dd4fda69 Address review issues 2016-11-16 11:08:00 -02:00
akwizgran
52eb261a11 Unit tests for PrivateMessageValidator. 2016-11-16 11:49:49 +00:00
Torsten Grote
980a6d18bb Add visibility and OPTIONS button to private group join notices 2016-11-16 09:25:22 -02:00
akwizgran
c4a152b543 Merge branch '732-reveal-contacts-ui-onboarding' into 'master'
Add onboarding dialog for revealing contacts screen

This MR is based on !406.

![device-2016-11-11-162417](/uploads/8df831905eebf41ecdbe368890cdd429/device-2016-11-11-162417.png)

See merge request !407
2016-11-14 12:44:41 +00:00
Torsten Grote
ed728e816e Add onboarding dialog for revealing contacts screen 2016-11-14 09:14:30 -02:00
akwizgran
efbce95399 Merge branch '732-reveal-contacts-ui' into 'master'
Add UI for revealing contacts within a private group

This addresses one part of #732. Join notices and onboarding will follow in separate MRs.

Although this MR is technically not based on !402, it does require it to be merged first to compile.

![device-2016-11-11-160454](/uploads/8cb6d8bdd0f3761657875024739e730a/device-2016-11-11-160454.png)

See merge request !406
2016-11-14 10:48:42 +00:00
akwizgran
98c81f71b4 Merge branch '709-reveal-relationships' into 'master'
Mark relationship visible when syncing group with peer

This branch updates the private group invitation protocol to use @grote's new method for marking a contact relationship visible to the group.

I've changed the method slightly because the protocol state machine allows us to leave and re-enter the BOTH_JOINED state (see diagram on #659), so the relationship may already be visible when the method is called. In that case the visibility isn't updated, so we stick with whichever of revealed-by-us and revealed-by-contact happened first.

See merge request !402
2016-11-14 10:32:56 +00:00
akwizgran
da543c1004 Added javadocs, removed redundant exception. 2016-11-14 10:30:38 +00:00
akwizgran
7ab4d12d83 Track private group invitation messages. 2016-11-14 10:10:14 +00:00
Torsten Grote
59964c5087 Add UI for revealing contacts within a private group 2016-11-11 15:40:02 -02:00
Torsten Grote
b885e49ba2 Don't indicate that we are sharing with ourselves in group memberlist 2016-11-11 15:40:01 -02:00
akwizgran
63da860681 Merge branch '732-reveal-contacts-ui-preparation' into 'master'
Prepare UI for revealing contacts

This changes the visibility of some methods (that need to be accessed from another package), removes unnecessary abstractions and fixes erroneous static import of GroupId constant.

See merge request !404
2016-11-11 17:33:54 +00:00
akwizgran
aa210fc555 Factor MessageTracker out of BdfIncomingMessageHook. 2016-11-11 16:59:10 +00:00
Torsten Grote
68f0e91f32 Prepare UI for revealing contacts
This changes the visibility of some methods, removes unnecessary
abstractions and fixes static import of GroupId constant.
2016-11-11 14:49:26 -02:00
akwizgran
3a2205123f Added a method for revealing a contact to a private group. 2016-11-11 13:49:49 +00:00
akwizgran
2837bde774 Removed blog post pagers 2016-11-11 13:38:04 +00:00
akwizgran
411549dc0a Code cleanup, use correct fragment class. 2016-11-11 13:37:32 +00:00
akwizgran
ab16ee7465 Merge branch 'exception-handler' into 'master'
Add new Exception handler

While working on #732 I again needed to use a `UiResultExceptionHandler`  when I actually don't need to return a result. We have some other places in the code like this. So I introduced a `UiExceptionHandler` without the result part and used it where appropriate. While I was touching some classes, I also added the new annotations.

This MR includes another small commit that notifies only on local group messages. Joining a group is a message as well and without this change, you are notified about a new message when you yourself joined your newly created group.

See merge request !403
2016-11-11 13:34:09 +00:00
Torsten Grote
eb66924e21 Do not show notification for local group messages 2016-11-11 10:03:03 -02:00
Torsten Grote
563d897651 Introduce Exception handler for when no result needs to be returned
Also add NotNull annotation to classes that were touched
2016-11-11 10:03:02 -02:00
akwizgran
98cf6b5bba Mark relationship visible when syncing group with peer. 2016-11-11 11:29:55 +00:00
akwizgran
ade7e50f65 Merge branch 'contact-selector-controller' into 'master'
Add a controller for contact selection lists

See merge request !401
2016-11-11 10:54:07 +00:00
Torsten Grote
ccc9d53ac7 Address review comments 2016-11-10 16:49:20 -02:00
Torsten Grote
d232529eb3 Add a controller for contact selection lists 2016-11-10 15:33:53 -02:00
akwizgran
a532f03784 Merge branch '732-reveal-backennd' into 'master'
Add support for revealing contacts to the PrivateGroupManager

This also adds three integration tests and improves some small details here and there in the private group client.

Prerequisite for #732.

See merge request !396
2016-11-10 17:00:31 +00:00
Torsten Grote
5e5bf7ec05 Add ContactRelationshipRevealedEvent and address review comments 2016-11-10 13:56:42 -02:00
akwizgran
7414abd1ce Merge branch '748-qr-code-payload-order' into 'master'
Preserve the order of descriptors in QR code payloads

This fixes a regression caused by my recent changes to the Payload class.

Closes #748

See merge request !399
2016-11-10 12:21:36 +00:00
Torsten Grote
dc76ce2be2 Merge branch '720-camera-surface-illegal-state-exception' into 'master'
Don't crash if camera is reopened or surface is recreated

This branch fixes the crash is described in #720, which can be reproduced easily by scanning a QR code and failing to connect (for example, scan a screenshot of a QR code from a device that's no longer listening). When the camera view becomes visible again after trying to connect, its surfaceCreated() callback is called again with the same surface. An IllegalStateException added in !340 causes the crash.

Closes #720

See merge request !397
2016-11-10 11:12:24 +00:00
Torsten Grote
3eed0bfe81 Add visibility of contact relationship to JoinMessageHeader 2016-11-09 16:35:27 -02:00
Torsten Grote
ec8982438a Add support for revealing contacts to the PrivateGroupManager
This also adds two integration tests and improves some small details
2016-11-09 16:34:58 -02:00
akwizgran
501c2dab31 Preserve the order of descriptors in QR code payloads. 2016-11-09 15:57:41 +00:00
akwizgran
2fe69af6d8 Don't try to get parameters after releasing camera. 2016-11-09 14:51:05 +00:00
Torsten Grote
b20c107010 Merge branch 'feed-pager-events' into 'master'
Make the feed pager respond to events, block notifications

This branch fixes a bug I found while working on #705: FeedPostPagerFragment doesn't start or stop the controller, so it doesn't load newly received posts or block notifications, unlike FeedFragment.

See merge request !398
2016-11-09 14:16:57 +00:00
akwizgran
f410e4eddd Make the feed pager respond to events, block notifications. 2016-11-09 13:24:44 +00:00
akwizgran
bb82bd70e2 Don't crash if camera is reopened or surface is recreated. 2016-11-09 12:43:33 +00:00
akwizgran
138a6e11a7 Merge branch '346-smaller-qr-codes' into 'master'
Encode transport properties more compactly in QR codes

The [original BQP spec](https://code.briarproject.org/akwizgran/briar/wikis/BQP) described a compact encoding for transport properties, with the goal of making the QR code as small as possible. At some point during the implementation, I asked @str4d to use TransportIds and TransportProperties instead, as described in the [current spec](https://code.briarproject.org/akwizgran/briar-spec/blob/master/protocols/BQP.md). That was a mistake.

Using the original format reduces the payload from 60 to 34 bytes (43% smaller) for Bluetooth only, and from 96 to 49 bytes (49% smaller) for Bluetooth and LAN. This makes it easier to scan codes from low-resolution screens using fixed-focus and/or low-resolution cameras. Using this branch I can exchange codes between the Sony Xperia Tipo (320x480 screen, fixed focus, 640x480 preview size) and the Huawei Ascend Y300 (480x800 screen, infinity focus, 1280x720 preview size).

This also removes an obstacle to implementing #558, as TransportIds are no longer included in QR codes.

Closes #346.

See merge request !394
2016-11-08 17:32:26 +00:00
akwizgran
178d72114b Merge branch '709-private-group-invitation-protocol' into 'master'
Private group invitation protocol

This branch implements the private group invitation protocol. The implementation is something of an experiment with a new way of writing client protocols.

We start with a role enum that lists the roles in the protocol, and a state enum for each role, which lists the states in the role's state machine. Then there's a session class, parameterised by the state class and therefore by the role, which represents the session information held by that role. Then there's an engine interface, parameterised by the session class and therefore by the role, which encapsulates the protocol logic for the role. Most of this stuff can be created pretty mechanically from the state machine diagrams.

The engine interface has a method for each type of message and each local action. I started out with one method for all messages and another for all local actions, but that turned out to be a bad design - the information about what kind of message was being handled was lost when the message was passed to the engine, and had to be recovered using an instanceof ladder.

Each engine method takes a message or an action and a session, and returns an updated session. A transaction is passed in so the engine can send messages, attach events, and do any other work it needs to do (such as changing the visibility of groups, in the case of this protocol). This removes the need to run tasks outside the engine, so the protocol logic is better encapsulated inside the engine.

Parsing and encoding of messages and sessions is separated from protocol logic. MessageParser, MessageEncoder and the validator are the only classes that know how messages and their metadata are formatted, and likewise SessionParser and SessionEncoder are the only classes that know how sessions are formatted. The metadata keys are declared in a package-private interface.

It's common knowledge that I never make mistakes, so to keep things interesting I've hidden 114 deliberate mistakes in this code. See how many you can spot!

Needs tests before #709 is closed.

See merge request !382
2016-11-08 17:22:00 +00:00
Torsten Grote
c1f1eb7dfa Merge branch '709-preliminaries' into 'master'
Preliminaries for private group invitation protocol

As promised, here's the preliminary stuff for #709 as a separate MR.

See merge request !395
2016-11-08 17:02:45 +00:00
akwizgran
d2a3804cfe Added null safety annotations to plugin interfaces. 2016-11-08 16:59:56 +00:00
akwizgran
fb095c1f4d Broadcast events for private group invitations. 2016-11-08 16:08:51 +00:00
akwizgran
f89d8cbe38 Updated peer state machine for automatic join response. 2016-11-08 16:08:50 +00:00
akwizgran
d2434123a9 Private group invitation protocol. 2016-11-08 16:08:50 +00:00
akwizgran
edbf5ff5b4 Preliminaries for private group invitation protocol. 2016-11-08 15:45:04 +00:00
akwizgran
32f0b53d15 Increase test timeouts to avoid spurious failures. 2016-11-08 15:17:08 +00:00
akwizgran
55ecdd9a13 Merge branch '557-use-namespaced-strings-for-client-ids' into 'master'
Use namespaced strings for client IDs

Closes #557

See merge request !393
2016-11-08 13:25:41 +00:00
akwizgran
e47e3242a6 Merge branch '196-mark-messages-read' into 'master'
Mark private messages read properly

Depends on !386.

This branch uses the same approach as forums to mark messages read, i.e. each message is marked read when it becomes visible, rather than marking all messages read in a batch when the activity finishes. This fixes two problems: messages not being marked read when isFinishing() is false, for example when leaving the activity via the home button, and a race condition between updating and loading the group count when leaving the activity, resulting in a stale unread message count in the contact list.

Closes #196.

See merge request !388
2016-11-08 13:25:00 +00:00
Torsten Grote
4387bfc5bd Merge branch '733-incoming-messages-aren-t-added-to-private-group-conversation' into 'master'
Broadcast GroupMessageAddedEvent for the UI to update when received

Closes #733

See merge request !390
2016-11-08 13:24:20 +00:00
Torsten Grote
d11ee5e43b Broadcast GroupMessageAddedEvent for the UI to update when received 2016-11-08 11:23:52 -02:00
akwizgran
ce53589c33 Merge branch '736-private-group-list-is-not-updated-when-group-is-dissolved' into 'master'
Create GroupDissolvedEvent and react to it

This MR also makes the private group list react to incoming group invitations (once they are implemented).

![device-2016-11-07-155240](/uploads/84ed51cf72bf2c7c597a0fd68b5d868c/device-2016-11-07-155240.png)
![device-2016-11-07-155302](/uploads/446c98d70d674d0bcd79bfb7682dfed5/device-2016-11-07-155302.png)

Closes #736, #737

See merge request !392
2016-11-08 13:20:28 +00:00
Torsten Grote
e96b3a8c68 Use namespaced strings for client IDs 2016-11-08 11:17:52 -02:00
Torsten Grote
62040d45b8 Create GroupDissolvedEvent and react to it
Also react to incoming group invitations
2016-11-08 10:28:54 -02:00
akwizgran
1809943f1d Merge branch '734-notifications-for-private-group-messages' into 'master'
Show Notifications for Group Messages

Closes #734

See merge request !391
2016-11-08 12:06:15 +00:00
akwizgran
d204757395 Merge branch '735-back-button-in-invite-members-screen-returns-to-group-list' into 'master'
Return to group after not inviting new members

This MR also closes the keyboard when returning from the message fragment.

Closes #735

See merge request !389
2016-11-08 11:55:36 +00:00
akwizgran
c640ee8e51 Merge branch '714-asynchronous-context-leaks' into 'master'
Fixed asynchronous Activity leaks in Fragments

If a Fragment has been detached its `getActivity()` method will return null, providing numerous crash possibilities within the app.

My approach to fixing this is to make Fragments use their own `runOnUiThreadUnlessDestroyed` method, which also checks if the Fragment has been detached before running the Runnable

Closes #714

See merge request !387
2016-11-08 11:49:45 +00:00
akwizgran
04d4ecad05 Encode transport properties more compactly in QR codes. 2016-11-08 11:28:44 +00:00
Ernir Erlingsson
c36bb3e60e created runOnUiThreadUnlessDestroyed fragment wrapper 2016-11-07 17:11:57 +01:00
akwizgran
7327029fca Log the QR code payload length. 2016-11-07 16:04:07 +00:00
Torsten Grote
81d341374d Show Notifications for Group Messages 2016-11-07 13:52:59 -02:00
Torsten Grote
7b884d2425 Return to group after not inviting new members
Also close keyboard when returning from message fragment
2016-11-07 10:44:22 -02:00
Torsten Grote
fbcf334941 Merge branch 'use-contact-id-as-conversation-id' into 'master'
Use contact ID rather than messaging group ID to identify conversation

We originally used the private messaging group ID to identify the private conversation, but now that the conversation includes messages from multiple clients it's more appropriate to use the contact ID.

This refactoring isn't urgent - I've had the branch lying around for a while, but I'm putting it up for review because #734 will touch some of the same code.

See merge request !386
2016-11-07 11:24:11 +00:00
akwizgran
238100bcac Mark messages read properly in private conversation. 2016-11-07 10:43:24 +00:00
akwizgran
7c3805260d Merge branch '643-allow-messages-to-be-deleted-in-the-delivery-hook' into 'master'
Allow messages to be deleted in delivery hook

Closes #643

See merge request !385
2016-11-04 16:14:44 +00:00
akwizgran
51bcf7b1b8 Don't use messaging group ID as proxy for contact ID. 2016-11-04 15:50:44 +00:00
Torsten Grote
719a53dc94 Address review comments 2016-11-04 12:58:12 -02:00
Torsten Grote
3f9a254a0b Allow messages to be deleted in delivery hook 2016-11-04 12:52:33 -02:00
akwizgran
e810a1265a Merge branch '205-unit-tests-for-keymanagerimpl-and-transportkeymanager' into 'master'
Add unit tests for KeyManagerImpl

This also creates a `TransportKeyManager` interface and a factory for that to be able to test things separately.

Closes #205

See merge request !380
2016-11-04 14:29:21 +00:00
Torsten Grote
c36f5c795b Address review comments for TransportKeyManagerImplTest 2016-11-04 11:04:44 -02:00
Torsten Grote
f52186ac8c Add unit tests for KeyManagerImpl and create TransportKeyManager
interface and a factory for that.
2016-11-04 10:54:56 -02:00
akwizgran
e0f4be931d Merge branch '708-private-group-fixup' into 'master'
Let only the creator invite new members to private groups

A little bug I noticed when reviewing the implementation of the invitation protocol.

See merge request !383
2016-11-04 09:33:50 +00:00
akwizgran
7536c00a34 Merge branch '708-private-group-remove-new-member-announcement' into 'master'
Remove new member announcement and add signature to join message



See merge request !384
2016-11-04 09:32:40 +00:00
akwizgran
847b6e4179 Added comments to integration test. 2016-11-04 09:32:21 +00:00
Torsten Grote
58793068c3 Address review comments 2016-11-03 17:26:37 -02:00
Torsten Grote
7125248677 Remove new member announcement and add signature to invitation 2016-11-03 17:24:31 -02:00
Torsten Grote
4bad7076e7 Merge branch '674-ending-a-transaction-can-throw-an-exception-in-a-finally-block' into 'master'
Replace transaction.setComplete() by database.commitTransaction()

Closes #674

See merge request !374
2016-11-03 19:23:16 +00:00
akwizgran
2bb16bb75f Merge branch '348-testers-did-not-understand-qr-code-workflow' into 'master'
Improve QR code workflow slightly

* Improve wording so contacts know they need meet up to scan
  and scan each other's codes
* Use consistent progress bar styles

Closes #348

See merge request !381
2016-11-03 15:56:19 +00:00
Torsten Grote
b5a427f876 Let only the creator invite new members to private groups 2016-11-02 17:40:33 -02:00
Torsten Grote
b34b4623ed Replace transaction.setComplete() by database.commitTransaction() 2016-11-02 13:04:31 -02:00
Torsten Grote
f3b9214702 Improve QR code workflow slightly
* Improve wording so contacts know they need meet up to scan
  and scan each other's codes
* Use consistent progress bar styles
2016-11-02 12:43:41 -02:00
akwizgran
36f087c512 Merge branch '724-unit-tests-for-clienthelperimpl' into 'master'
Add Unit Tests for ClientHelper

Closes #724

See merge request !379
2016-11-02 11:04:07 +00:00
akwizgran
0c30f16d7e Merge branch '731-bdf-reader-open-lists-and-dictionaries' into 'master'
Don't throw IllegalStateException if BDF input is incomplete

Closes #731

See merge request !378
2016-11-01 17:40:13 +00:00
akwizgran
4d8a84a48d Don't throw IllegalStateException if BDF input is incomplete. 2016-11-01 17:38:23 +00:00
akwizgran
2650f3114e Merge branch '518-limit-the-depth-of-nested-bdf-structures' into 'master'
Limit the depth of nested BDF structures

Closes #518

See merge request !375
2016-11-01 17:30:50 +00:00
Torsten Grote
dfdde9799f Add Unit Tests for ClientHelper 2016-11-01 15:28:28 -02:00
akwizgran
114a2dc8f2 Merge branch '427-local-author-caching' into 'master'
Cache the local author and load before the db latch is released

Closes #427, #588 

See merge request !354
2016-11-01 17:21:14 +00:00
akwizgran
642fa7df18 Removed unused field, renamed nickname methods. 2016-11-01 17:17:40 +00:00
akwizgran
c85767d2a0 Nickname is all one word. 2016-11-01 17:12:30 +00:00
Torsten Grote
55af1b954e Limit the depth of nested BDF structures 2016-11-01 14:52:00 -02:00
Ernir Erlingsson
88272c5d61 improvements after dev comments 2016-11-01 13:33:12 +01:00
Ernir Erlingsson
eaa393a7ed added a cache to the IdentityManager, changed its signature, modified when and where the author is stored
made the author creation single-threaded again in the LifecycleManager, removed redundant code
2016-11-01 12:51:49 +01:00
akwizgran
19080ad957 Merge branch '723-unit-tests-for-contactmanagerimpl' into 'master'
Add Unit tests for ContactManager

Closes #723

See merge request !376
2016-11-01 11:50:47 +00:00
Torsten Grote
7eeeb5f1ed Add Unit tests for ContactManager 2016-11-01 09:40:05 -02:00
akwizgran
d55503ee92 Merge branch '722-implement-ux-design-for-inviting-new-members-to-a-group' into 'master'
Implement UX design for inviting new members to a group

Closes #722

See merge request !373
2016-11-01 11:38:29 +00:00
Torsten Grote
8448d27d20 Implement UX design for inviting new members to a group 2016-11-01 09:27:23 -02:00
akwizgran
47d6fc526f Merge branch '678-implement-ux-for-viewing-the-membership-of-a-private-group' into 'master'
Implement UX for viewing the membership of a private group

This MR is the second and last MR to address #678. The first part is in !377.

![device-2016-10-26-112000](/uploads/8cbdee65c123a6d5329e208d9983d0b0/device-2016-10-26-112000.png)

Closes #678

See merge request !364
2016-11-01 11:12:21 +00:00
Torsten Grote
3da879cfd9 Address review comments for group member list 2016-11-01 09:09:22 -02:00
Torsten Grote
8fdce5ba51 Group Member List UI 2016-11-01 09:09:20 -02:00
akwizgran
f759a7506f Merge branch '600-remove-content-type-from-private-messages' into 'master'
Remove content-type and parentId from private messages

and turn them into a regular string.

Closes #600

See merge request !372
2016-11-01 11:05:30 +00:00
akwizgran
0b11aea7a2 Merge branch '672-implement-ux-for-dissolving-a-group' into 'master'
Implement UX for when a group has been dissolved

This MR is based on !367.

Closes #672

See merge request !369
2016-11-01 11:02:27 +00:00
akwizgran
aa954cee63 Merge branch '671-implement-ux-for-leaving-a-group' into 'master'
Implement UX for leaving a group

This MR also includes the creator's part of the UX for dissolving a group since it is almost the same.

![device-2016-10-26-185615](/uploads/8689a1ee103fcee23105a469b37c59de/device-2016-10-26-185615.png)

Closes #671

See merge request !367
2016-11-01 10:57:33 +00:00
akwizgran
68024c264e Merge branch '700-update-blog-backend-to-match-current-usage' into 'master'
Update blog backend to match current usage

Closes #700

See merge request !371
2016-11-01 10:56:02 +00:00
Torsten Grote
78740a6942 Remove content-type and parentId from private messages
and turn them into a regular string.
2016-11-01 08:39:15 -02:00
Torsten Grote
9e553ef9c8 Update blog backend to match current usage 2016-11-01 08:34:29 -02:00
Torsten Grote
1147b8ffaf Disable group before loading messages 2016-11-01 08:26:40 -02:00
Torsten Grote
67866dbe66 Implement UX for when a group has been dissolved 2016-11-01 07:41:55 -02:00
Torsten Grote
8dac2d1ca6 Implement UI for dissolving and leaving group 2016-11-01 07:40:56 -02:00
Torsten Grote
b0a5a69b81 Remove group from database in PrivateGroupManager 2016-11-01 07:39:35 -02:00
akwizgran
a18317e912 Merge branch '681-convert-forum-post-bodies-to-strings-remove-content-type' into 'master'
Remove forum content type and change bodies to string

Also removes support for anonymous forum posts.

This MR depends on !360.

Closes #698, #681

See merge request !370
2016-10-31 21:34:24 +00:00
akwizgran
ad7d0d8e74 Merge branch '678-private-group-hooks-and-membership' into 'master'
Add methods and hooks to PrivateGroupManager related to members and removal

This MR is the first of two MRs related to #678.

See merge request !377
2016-10-31 16:27:15 +00:00
akwizgran
fe79131f4a Merge branch '678-contact-list-refactoring' into 'master'
Refactor contact lists, their adapters and items

This was supposed to be a preparation for #678 to make the contacts lists cleaner and easier to re-use for different use-cases. Turns out #678 can't use this work, but it is probably nice to have anyway.

During this work, support for multiple identities has been removed from the various contact lists.

See merge request !363
2016-10-31 15:39:48 +00:00
Torsten Grote
cb61d91074 Add methods and hooks to PrivateGroupManager related to members and removal 2016-10-31 13:23:03 -02:00
akwizgran
399a4890de Merge branch '708-implement-protocol-for-private-group-messaging' into 'master'
Implement protocol for private group messaging

Closes #708

See merge request !360
2016-10-31 15:17:51 +00:00
Torsten Grote
656a947f5a Last minor review comments addressed 2016-10-31 13:13:59 -02:00
Torsten Grote
7191967092 Refactor contact lists, their adapters and items 2016-10-31 10:29:53 -02:00
Torsten Grote
5ce8b1978d Remove forum content type and move bodies to string
Also removes support for anonymous forum posts.
Closes #698
2016-10-31 10:25:12 -02:00
Torsten Grote
c0aa255bb6 Address review comments 2016-10-31 10:16:48 -02:00
Torsten Grote
c79ce61f6d Add PrivateGroupManager integration tests 2016-10-31 10:13:21 -02:00
Torsten Grote
0caabda303 Do additional validation on incoming private group messages 2016-10-31 10:13:21 -02:00
Torsten Grote
679b54b2b4 Show join messages properly in the threaded conversation 2016-10-31 10:13:20 -02:00
Torsten Grote
349a34ffd8 Return actual private group message headers and bodies to the UI 2016-10-31 10:12:26 -02:00
Torsten Grote
2c8aaa215c Posting group messages takes previous message into account 2016-10-31 10:11:35 -02:00
Torsten Grote
4f4f1956eb Creator automatically joins the group after creating it 2016-10-31 10:11:33 -02:00
Torsten Grote
e06726b2f9 Implement New Member and Join Announcements in GroupMessageFactory 2016-10-31 10:10:14 -02:00
Torsten Grote
a6e3827127 Implement first prototype of GroupMessageValidator 2016-10-31 10:09:17 -02:00
Torsten Grote
8dc529cc3f Move validator's signature verification into ClientHelper 2016-10-31 10:08:26 -02:00
akwizgran
1e36f21cc8 Merge branch '707-implement-ux-for-showing-and-answering-private-group-invitations' into 'master'
Implement UX for showing and answering private group invitations

As usual, this MR contains several logically separate commits that could be split out into smaller MRs if desired. It consists of two main parts:
* Showing open invitations in the list of private groups with a snackbar
* Showing invitations and responses in the private conversation

For both parts, the existing code was refactored to allow for a smooth implementation and to leave maintainable code behind.

![device-2016-10-18-101549](/uploads/66582dbe97736fdcd2498e87e1c7dfd1/device-2016-10-18-101549.png)
![device-2016-10-18-101612](/uploads/8c25eff8171f330796a55cb27cdb2552/device-2016-10-18-101612.png)
![device-2016-10-18-101534](/uploads/ebba4c0a2c0f727dcadac8c2ec57b48f/device-2016-10-18-101534.png)

Closes #707

See merge request !357
2016-10-31 12:02:22 +00:00
Torsten Grote
2cc650d85f Address review comments 2016-10-28 15:29:47 -02:00
akwizgran
3407d0c0a8 Merge branch 'protocol-state-exception' into 'master'
ProtocolStateException for client protocols

Methods that implement local actions in a client protocol (for example, accepting an invitation) can throw this exception to indicate that the action wasn't taken because the action isn't applicable to the current state. This can happen if the protocol state machine is updated by an incoming message and the user takes an action before the UI has been updated.

See merge request !368
2016-10-27 15:46:03 +00:00
akwizgran
ca8d3babaa Added ProtocolStateException for client protocols. 2016-10-27 11:57:36 +01:00
Torsten Grote
7b627bb427 Remove PartialItem interface and the need for casting ConversationItems 2016-10-27 08:22:52 -02:00
Torsten Grote
f027b832d4 Address review issues 2016-10-27 08:14:33 -02:00
Torsten Grote
42175dca7a Show group invitations and responses in private conversation 2016-10-27 08:14:33 -02:00
Torsten Grote
5ffcdc4e46 Refactor ConversationAdapter and its ConversationItems 2016-10-27 08:14:32 -02:00
Torsten Grote
e00219c15f Allow responding to sharing invitations based on SessionId 2016-10-27 08:14:32 -02:00
Torsten Grote
96666273d3 Show group invitations in group list 2016-10-27 08:14:32 -02:00
Torsten Grote
a92f7e1c9f Controllerize invitation activities 2016-10-27 08:14:31 -02:00
Torsten Grote
02a39f5694 Refactor events based on InvitationRequestReceivedEvent 2016-10-27 08:14:31 -02:00
Torsten Grote
a33d7d1663 Add a stub for a GroupInvitationManager 2016-10-27 08:14:30 -02:00
Ernir Erlingsson
8eeaf4e347 Merge branch '688-proguard-warns-about-missing-descriptor-classes' into 'master'
Fix proguard notes about unkept descriptor classes

Closes #688

See merge request !366
2016-10-26 20:32:43 +00:00
Torsten Grote
835bd86346 Fix proguard notes about unkept descriptor classes 2016-10-26 15:57:52 -02:00
akwizgran
84b2a171ab Merge branch '718-creating-a-group-without-having-contacts-can-cause-crash' into 'master'
Fix crash when navigating back in contact selector

Closes #718

See merge request !365
2016-10-26 17:08:07 +00:00
Torsten Grote
1df00f5702 Fix crash when navigating back in contact selector 2016-10-26 14:49:45 -02:00
akwizgran
292e1c3e8e Merge branch '715-long-posts-aren-t-rendered' into 'master'
Disable EmojiTextView software layer rendering when cache is too small

This needs to be tested if it works as intended on several devices.

See merge request !362
2016-10-26 15:09:56 +00:00
akwizgran
c8c0281efc Merge branch '686-crash-when-transitioning-out-of-reblogactivity' into 'master'
Limit scene transition animations to API 23 and above

to work-around [android bug #224270](https://code.google.com/p/android/issues/detail?id=224270).
This is only necessary if the transitioning view might not be available anymore when the exit transition is made.

Closes #686

See merge request !361
2016-10-26 10:11:32 +00:00
akwizgran
e8c48ccf8d Merge branch '661-implement-ux-for-creating-a-private-group' into 'master'
Implement UX for creating a private group

This MR allows the user to create a new private group and select contacts to be invited into the group.

There are currently 6 commits starting with some small refactoring for code reuse and making more functionality available in the backend. Each commit could be split up into a dedicated MR if desired.

![create-groups](/uploads/5229f102ee2611c05d5e9d1e2aac510d/create-groups.gif)

Closes #661

See merge request !353
2016-10-26 09:32:34 +00:00
Torsten Grote
09baa2ebe1 Add own constant for maximum group invitation message length 2016-10-26 07:28:51 -02:00
Torsten Grote
1176741ea4 Address actual review issues 2016-10-25 15:22:11 -02:00
Torsten Grote
e6def70030 Pre-address potential review issues 2016-10-25 14:58:50 -02:00
Torsten Grote
1a812f1327 UI for creating private groups 2016-10-25 14:58:47 -02:00
Torsten Grote
8dc3bd2c4c Implement private group creation and fetching in PrivateGroupManager 2016-10-25 14:57:43 -02:00
Torsten Grote
c934ec30aa Move Up button handling into BaseFragment 2016-10-25 14:57:43 -02:00
Torsten Grote
d5f6e71cba Create a reusable ContactSelectorActivity 2016-10-25 14:57:41 -02:00
Torsten Grote
feed2581c9 Factor out a reuseable MessageFragment 2016-10-25 14:56:25 -02:00
Torsten Grote
bd1f3fc2bd Make ContactSelectorFragment reusable 2016-10-25 14:52:27 -02:00
akwizgran
d25f4d1fbe Merge branch 'string-truncation' into 'master'
Truncate all messages to valid length before sending



See merge request !358
2016-10-25 15:52:35 +00:00
Torsten Grote
e84d1c5996 Update translations and expiry date 2016-10-25 08:19:15 -02:00
Torsten Grote
06831bafc3 Disable EmojiTextView software layer rendering when cache is too small 2016-10-24 17:20:57 -02:00
Torsten Grote
9284167a2e Limit scene transition animations to API 23 and above
to work-around android bug #224270.
This is only necessary if the transitioning view might not be available
anymore when the exit transition is made.
2016-10-24 15:34:24 -02:00
akwizgran
df44015ccb Merge branch '705-adapter-revisions' into 'master'
Fix race conditions when updating UI from events (again)

This is my second attempt at fixing race conditions caused by updating the UI from events while background tasks are loading data from the DB. Unlike my first attempt, this one is pretty simple and doesn't require too much reasoning about possible races.

The first commit fixes a few list loading bugs I found while working on this problem, and moves the lifecycle callbacks from resume/pause to start/stop, closing #609. The second commit contains the fix for #705, which works as follows:

* Each BriarAdapter has a revision counter
* Before making a change to the adapter that could be overwritten by a background task, increment the revision
* Before starting a background task that could overwrite other changes, get the current revision
* Before applying changes from a background task that could overwrite other changes, check whether the revision has changed
* If the revision has changed, restart the background task
* Otherwise apply the changes

Closes #609. #705 remains open because the PagerAdapters for blogs need to be updated.

See merge request !356
2016-10-21 10:28:02 +00:00
akwizgran
c4716ca457 BlogFragment doesn't need to use adapter revisions.
All changes to the adapter are cumulative.
2016-10-20 14:21:10 +01:00
akwizgran
9bb16b424f Moved revision counter methods into their own interface. 2016-10-20 12:44:09 +01:00
akwizgran
e8ebdc2884 Don't finish nav drawer fragments on error. 2016-10-20 11:55:39 +01:00
akwizgran
2140a290e4 Avoid race conditions when updating the UI from events. 2016-10-20 11:28:03 +01:00
akwizgran
50a70f7649 Use start/stop lifecycle callbacks rather than pause/resume.
Also fixed a couple of bugs.
2016-10-20 10:40:10 +01:00
akwizgran
b3e5d1ff85 Finished renaming entry to item, reduced some visibility. 2016-10-19 20:49:45 +01:00
Torsten Grote
690142ce07 Merge branch '712-bdf-list-out-of-bounds' into 'master'
Throw FormatException if BdfList index is out of bounds

Closes #712

See merge request !359
2016-10-19 17:49:14 +00:00
akwizgran
82eea6bb77 Throw FormatException if BdfList index is out of bounds. 2016-10-19 18:11:31 +01:00
Torsten Grote
3ad3332649 Merge branch '663-implement-ux-for-displaying-message-threads-in-private-groups' into 'master'
Private Group Threaded Conversation

This MR refactors the forum activity, its controller, its adapter and view holder so *most* of the code can be re-used for private groups by making heavy use of generics.

The refactoring has 1383 additions and 1087 deletions, so just grows the code-base slightly and adding the private group conversation just takes an additional 400 lines.

The MR also includes one commit that moves post/message creation more into clients, so the UI doesn't need to keep track of timestamps. This commit can of course be split out into a separate MR if desired.

Closes #662, #663 

See merge request !350
2016-10-19 16:42:24 +00:00
Torsten Grote
5a0fa5dcc7 Last round of addressing review issues 2016-10-19 14:38:11 -02:00
akwizgran
97223cce97 Fixed a typo in a constant. 2016-10-19 15:14:07 +01:00
akwizgran
08b191d72e Fixed a typo in a comment in a test. URGENT STUFF! 2016-10-19 15:04:24 +01:00
akwizgran
06335c2c30 Truncate all messages to valid length before sending. 2016-10-19 14:49:09 +01:00
Torsten Grote
8f882dc910 Addressing second round of review issues 2016-10-19 10:43:02 -02:00
Torsten Grote
0523c4e718 Address issues found in code review 2016-10-19 10:43:01 -02:00
Torsten Grote
7bf4aebdaf Move post/message creation into clients
This way the forum and private group client do not need to keep track of
message timestamps themselves and do not need to interact with
post/message factories.
2016-10-19 10:43:01 -02:00
Torsten Grote
6db59ffce5 Parsing and retrieval of private groups in PrivateGroupManager 2016-10-19 10:43:01 -02:00
Torsten Grote
e0835ad460 Add "Created by" to ActionBar 2016-10-19 10:43:00 -02:00
Torsten Grote
c83d4bbb39 Implement first prototype of private group message threads 2016-10-19 10:43:00 -02:00
Torsten Grote
65b47bb5d2 Refactor Forum Controller, so it can be used by private groups 2016-10-19 10:42:59 -02:00
Torsten Grote
9ce95d6de7 Refactor Forum Activity and adapters to be re-used for private groups 2016-10-19 10:42:59 -02:00
akwizgran
9d2c56e75f Upgraded Gradle plugin to 2.2.1. 2016-10-19 12:24:22 +01:00
akwizgran
32c4f61e68 Merge branch '670-uncaught-exceptions-do-not-print-a-stack-trace-in-introductionintegrationtest' into 'master'
Print stack trace for uncaught exceptions during tests for easier debugging

Closes #670

See merge request !355
2016-10-14 12:14:05 +00:00
Torsten Grote
6e04664915 Print stack trace for uncaught exceptions during tests for easier debugging 2016-10-14 08:44:47 -03:00
akwizgran
5674ee2d88 Converted group list controller to constructor injection. 2016-10-12 17:28:44 +01:00
akwizgran
8637faf858 Merge branch '704-constructor-injection' into 'master'
Use constructor injection for controllers

Also made some listeners volatile.

This is part of #704 - if I don't find any other classes that need constructor injection I'll close the ticket.

See merge request !351
2016-10-12 16:02:53 +00:00
akwizgran
970cbbf557 Merge branch 'not-null-by-default' into 'master'
Null safety annotations

The @NotNullByDefault annotation marks all fields, methods and parameters in a class or package @NotNull, so Android Studio will warn if values that may be null are used. Please use this annotation for new classes, and specify @Nullable for any fields, methods and parameters that may be null.

Injected fields are initialised to null, so injected classes should use @MethodsNotNullByDefault and @ParametersNotNullByDefault, or specify @Nullable for injected fields.

See merge request !349
2016-10-12 16:00:54 +00:00
akwizgran
57ac4a5374 Removed Maven Central repo. 2016-10-12 17:00:03 +01:00
akwizgran
2b91631ba5 Use constructor injection for controllers.
Also made some listeners volatile.
2016-10-11 12:31:21 +01:00
akwizgran
b327122255 Merge branch '660-implement-ux-for-the-list-of-private-groups' into 'master'
Private Group List UI

This MR implements the UI for the list of private groups.

It reacts to three types of events to refresh the displayed data:
* new group message received
* private group added
* private group removed

Missing from final implementation:
* entering groups
* adding new groups
* reacting to a future group dissolved event
* actually removing a dissolved group

![device-2016-09-29-180741](/uploads/666f04e8c9e2c81bdfe7f5648c14e71d/device-2016-09-29-180741.png)
![device-2016-10-03-141200](/uploads/5d0a54ea5a31d64404591c03ccf1e3b6/device-2016-10-03-141200.png)
![groups](/uploads/3eba757e21837739a129aab15100c06a/groups.gif)

Closes #660

See merge request !335
2016-10-11 10:22:26 +00:00
akwizgran
0b3ec9aa4c Merge branch '676-keyboard-isn-t-shown-when-forum-text-entry-field-gets-focus' into 'master'
Always show the keyboard when asked for it

The main fix is maintaining the internal keyboard state when the entire view gets hidden, because `onMeasure()` isn't called anymore in that case and can't update it itself.

Closes #676

See merge request !348
2016-10-11 09:47:27 +00:00
Torsten Grote
154e02723f Always show the keyboard when asked for it
and maintain keyboard state when hiding view.
2016-10-10 13:53:53 -03:00
Torsten Grote
b09e30a95f Private Group List 2016-10-10 13:48:34 -03:00
akwizgran
3ea36bbd40 Merge branch '551-destroyable-context' into 'master'
Always check whether the context has been destroyed

#551 has the same root cause as #610, which is that when a background operation completes, we need to check whether the activity or fragment that started the operation has been destroyed before doing anything with the UI. 

DestroyableActivity has been renamed to DestroyableContext because it's now implemented by some fragments as well. Various existing listener interfaces now extend DestroyableContext.

I also modified the ActivityLifecycleController interface so the activity is passed into the onActivityCreate() method rather than being injected - @ernir please check I haven't broken anything!

Closes #551

See merge request !341
2016-10-10 15:00:15 +00:00
akwizgran
cb983f02c2 Always check whether context has been destroyed. 2016-10-10 15:54:08 +01:00
akwizgran
f1730aa7d9 Merge branch '696-npe-key-agreement-task' into 'master'
Fix NPE when stopping KeyAgreementTask, improve thread safety

This branch fixes #696 and improves the thread safety of the camera code, mostly by adding @UiThread annotations and occasionally by moving stuff onto the UI thread that might have happened on other threads before.

Closes #696

See merge request !345
2016-10-10 14:46:25 +00:00
akwizgran
857665db79 Merge branch '373-slow-contact-list' into 'master'
Use new group metadata for showing lists

What was supposed to be a minimal change turned into a rather large MR. I did my best to keep things in separate commits, so I can still split this into smaller MRs if desired.

While making use of the new group metadata in the contact and forum list, I noticed some other things in need of improvement to get rid of needing to load all messages:
* Refactor `SharingManager` so its events provide message headers that can be used to update list items
* Add `GroupId` to conversation items, so the metadata of the respective group can be updated as well when marking the items read
* Create a very basic `ConversationManager` so the GroupCount for the various clients can be queried in one go without needing to know all their groups per contact
* Fix a nasty bug that caused forum and blog invitation to not update their read state
* Fix some bugs related to displaying the forum list with proper unread count

Some casual measurements with just a few contacts and messages showed a reduction of the contact list load time by one third.

See merge request !343
2016-10-10 14:00:36 +00:00
Torsten Grote
7f2db71160 Address review comments 2016-10-10 10:46:30 -03:00
akwizgran
60dee5c4cb Added null safety annotations. 2016-10-10 14:32:26 +01:00
Torsten Grote
784561144a Use new GroupCount to display Forum List
Fixes #531, #532
2016-10-10 08:00:17 -03:00
Torsten Grote
70d39d03bc Use group metadata from ConversationManager for showing contact lists
Fixes #373
2016-10-10 08:00:17 -03:00
Torsten Grote
48a3db46bc Properly pass message read state for sharing invitations and responses
Fixes #350
2016-10-10 08:00:16 -03:00
Torsten Grote
f52819f4ca Create a basic ConversationManager for querying GroupCount
This is also lays the groundwork for #384
2016-10-10 08:00:16 -03:00
Torsten Grote
457c30f3f2 Add GroupId to conversation items 2016-10-10 08:00:15 -03:00
Torsten Grote
1731369d7a Refactor SharingManager so its events provide message header 2016-10-10 08:00:12 -03:00
akwizgran
064b920626 Merge branch '687-refactor-adapters' into 'master'
Refactor existing adapters into a generic superclass

This MR also moves various blog classes into their own packages and makes the required visibility changes.

Closes #687

See merge request !346
2016-10-10 10:15:13 +00:00
Torsten Grote
b2fa039474 Refactor existing adapters into a generic superclass
This commit also moves various blog classes into their own packages and
makes the required visibility changes.
2016-10-06 11:30:10 -03:00
akwizgran
9112d17a4b Merge branch '611-body-cache-thread-safety' into 'master'
Make body cache thread-safe, reduce visibility of classes

Closes #611

See merge request !347
2016-10-06 13:43:09 +00:00
akwizgran
86fbb89637 Make body cache thread-safe, reduce visibility of classes. 2016-10-06 14:41:55 +01:00
akwizgran
b3bea1f945 Merge branch 'fix-introduction-unit-tests' into 'master'
Fix IntroductionManager unit tests

I forgot to run the unit tests after changing the `GroupCount` serialization in response to a review comment. This MR fixes the tests.

See merge request !344
2016-10-06 10:59:27 +00:00
akwizgran
543304973e Fixed an NPE, improved thread safety of camera code. 2016-10-06 11:53:07 +01:00
akwizgran
fc38738428 Merge branch '598-remove-unused-code' into 'master'
Remove unused UI code and layouts

If we ever need this code, it will be in the git history.

Closes #598

See merge request !342
2016-10-06 08:55:33 +00:00
Torsten Grote
d661fa0661 Fix IntroductionManager unit tests 2016-10-05 18:51:03 -03:00
akwizgran
e2eda8fef0 Merge branch '584-store-latest-timestamp-and-unread-count-in-group-metadata-for-private-messaging' into 'master'
Store message count, unread count and timestamp of latest message in group metadata

This is to eventually address #373 and slowness of other lists. The group metadata is not yet used, but if this MR isn't merged fast, another commit that actually uses it and thus takes care of the slowness will be added.

Closes #584, #585, #586

See merge request !336
2016-10-05 16:20:32 +00:00
akwizgran
604542c19b Remove unused UI code and layouts. 2016-10-05 17:09:16 +01:00
Torsten Grote
a727a0817e Store message count, unread count and timestamp of latest message
in group metadata to be able to speed up group listings.

Closes #584, #586, #585
2016-10-05 12:34:37 -03:00
Torsten Grote
3fa84ec7a8 Merge branch '680-release-camera-surface' into 'master'
Release camera surface to work around Android bug #54285

Closes #680

See merge request !340
2016-10-05 14:41:19 +00:00
Torsten Grote
e5f5511112 Merge branch 'identicon-cleanup' into 'master'
Clean up identicon code, remove unused classes

I noticed some debug-level logging coming from the identicon code, went in there to remove it, and realised half the code was unused, so I removed that too.

No functional changes except that the logging is gone and the opacity is now OPAQUE rather than UNKNOWN, which wasn't valid in this context.

See merge request !339
2016-10-05 14:38:17 +00:00
akwizgran
16ecb2ce8d Release surface to work around Android bug #54285. 2016-10-05 14:47:23 +01:00
akwizgran
c49c888f9f Merge branch '644-missing-header' into 'master'
Remove loading callbacks from fragment listener

Now fragments are responsible for their own Progress bars.

Closes #642

See merge request !316
2016-10-05 13:34:09 +00:00
Ernir Erlingsson
6b3db67ef5 removed fragment progress callback and fixed missing header 2016-10-05 14:21:14 +02:00
akwizgran
293c06fd61 Merge branch '92-emoticons' into 'master'
Emoji Support for all user input

All text that can be generated by users will show emoji from the shipped sprites by using the `EmojiTextView` instead of the normal `TextView`.

For all messages and posts, the custom emoji keyboard is now available as well. For this, a new `LargeTextInputView` has been introduced that is a sub-class of `TextInputView`. In order for the emoticon keyboard to work properly the existing views had to be modified heavily, sometimes resulting in new behavior such as scroll views now being above the fixed input field. Actual testing on a device (preferably with a tiny screen) is recommended to make sure this still works as expected. Screenshots will be included at the end of this post.

This MR also disables menu actions rather than hiding them and it includes a fix for a regression that was not showing the keyboard automatically in forums.

![device-2016-09-28-104914](/uploads/8ce9c8f61b32dc5a46b89a3a2cf1e6a4/device-2016-09-28-104914.png)
![device-2016-09-28-105026](/uploads/96ef9c40547c7a44fbc4517c87637a7e/device-2016-09-28-105026.png)
![device-2016-09-28-105041](/uploads/a0d1ed23ccb66e8bf9541737407142e3/device-2016-09-28-105041.png)
![device-2016-09-28-105440](/uploads/fb76ed2adc87600cfb0fc33c3962d4a6/device-2016-09-28-105440.png)
![device-2016-09-28-105515](/uploads/51f845d697cee3df38d1b9eef3c0ddfc/device-2016-09-28-105515.png)

Closes #92

See merge request !329
2016-10-05 11:01:12 +00:00
akwizgran
1c55fae704 Merge branch '695-introduction-failure' into 'master'
Fix regression in IntroduceeManager

This was happening when the remote response arrives before the local
response is made and thus the local response needs to be send with the
ACK following. The problem was that we ACK was sent before the response
which is not allowed and resulted in the session being aborted by the
introducee. This was happening, because recursion is hard ;)

The fix is only restarting another protocol engine to send the ACK
after the first run has been completed.

An integration test was added to prevent such regression in the future
and to test this code path.

Closes #695

See merge request !338
2016-10-04 21:38:48 +00:00
Torsten Grote
95670937c3 Fix regression in IntroduceeManager
This was happening when the remote response arrives before the local
response is made and thus the local response needs to be send with the
ACK following. The problem was that we ACK was sent before the response
which is not allowed and resulted in the session being aborted by the
introducee. This was happening, because recursion is hard ;)

The fix is only restarting another protocol engine to send the ACK
after the first run has been completed.

An integration test was added to prevent such regression in the future
and to test this code path.
2016-10-04 17:44:47 -03:00
Ernir Erlingsson
165deebb40 Merge branch '690-introduction-onboarding-is-shown-again-if-it-s-dismissed' into 'master'
Don't show introduction onboarding again no matter how dismissed

Closes #690

See merge request !337
2016-10-04 20:30:08 +00:00
Torsten Grote
0b0cae06ae Don't show introduction onboarding again no matter how dismissed 2016-10-04 14:51:37 -03:00
Torsten Grote
f8e0441de8 Emoji Support for all user input
All text that can be generated by users will show emoji from the
shipped sprites.

For all messages and posts, the custom emoji keyboard is now available.

This also disables menu actions rather than hiding them and thus
closes #677

Included is a fix for a regression that was not showing the keyboard
automatically in forums and thus
closes #676
2016-10-04 14:12:17 -03:00
akwizgran
a422c626b3 Merge branch '673-privategroupmanager-facade' into 'master'
Create PrivateGroupManager Facade and stub implementation

Some classes were renamed and new base classes introduced in the process. I suggest to expand the "Changed files" before reviewing to get an overview over the changes.

Closes #673

See merge request !332
2016-10-03 19:46:55 +00:00
Torsten Grote
6ece398a21 Create PrivateGroupManager Facade and stub implementation 2016-09-30 12:05:35 -03:00
akwizgran
8b50cb1461 Merge branch 'fix-integration-tests' into 'master'
Fix integration tests

First problem was a race condition with message delivery and the second
one due to the fact that we no longer plan to allow adding of additional
blogs, so the test for that has simply been removed.

See merge request !333
2016-09-29 16:43:56 +00:00
Torsten Grote
f28bc691a5 Merge branch '685-teaser-length' into 'master'
Check length of text after spanning

Closes #685

See merge request !334
2016-09-29 14:12:10 +00:00
akwizgran
42056720fa Check length of text after spanning. #685 2016-09-29 15:06:50 +01:00
Torsten Grote
0861ee1f10 Fix integration tests
First problem was a race condition with message delivery and the second
one due to the fact that we no longer plan to allow adding of additional
blogs, so the test for that has simply been removed.
2016-09-29 11:02:44 -03:00
akwizgran
a30de6309d Removed translated strings that were causing lint errors.
The app _name string is marked as non-translatable and the new_identity_item string no longer exists.
2016-09-29 12:47:29 +01:00
akwizgran
d112b42d20 Fixed obsolete ID in layout. 2016-09-29 12:45:56 +01:00
akwizgran
fd6719301a Merge branch '556-thread-safety-blocking-issues' into 'master'
Forum controller thread safety and tree safety

This branch solves the concurrent forum issues by code restructure and refactoring.

Closes #556 
Closes #552 

See merge request !262
2016-09-29 09:30:51 +00:00
Ernir Erlingsson
92f2e7b0fc merge with master and fixes after comments 2016-09-29 01:30:13 +02:00
akwizgran
ee98900613 Merge branch '644-missing-header-only' into 'master'
Remove toolbar animation to fix the missing toolbar on first start

Closes #644

See merge request !331
2016-09-28 17:03:55 +00:00
akwizgran
747553f577 Cleaned up identicon code, removed unused classes. 2016-09-28 17:34:12 +01:00
Torsten Grote
8a4c162bba Remove toolbar animation to fix the missing toolbar on first start 2016-09-28 13:33:09 -03:00
akwizgran
7e806c8cf2 Merge branch '679-own-personal-blogs-can-be-removed' into 'master'
Prevent personal blogs from being removed

This also adds unit tests to prevent regressions like this in the future.

Closes #679

See merge request !330
2016-09-28 16:22:46 +00:00
akwizgran
e466ed580c Merge branch '589-when-a-message-is-shared-share-its-transitive-dependencies' into 'master'
When a message is shared, share its transitive dependencies

Like other recursive operations on the dependency graph, this is
not done in a single transaction to prevent an attacker from creating
arbitrary large transactions.

So at startup, the `ValidationManager` finds and resumes any
unfinished operations, by looking for unshared messages with shared
dependents.

Closes #589

See merge request !325
2016-09-28 16:19:43 +00:00
Torsten Grote
d058172429 When a message is shared, share its transitive dependencies
Like other recursive operations on the dependency graph, this is
not done in a single transaction to prevent an attacker from creating
arbitrary large transactions.

So at startup, the `ValidationManager` finds and resumes any
unfinished operations, by looking for shared messages with unshared
dependencies.
2016-09-28 13:17:11 -03:00
Torsten Grote
1f0b305139 Prevent personal blogs from being removed
This also adds unit tests to prevent regressions like this in the
future.
2016-09-28 13:12:20 -03:00
Torsten Grote
7a0db798d1 bump expiry date and update translations 2016-09-28 11:56:55 -03:00
Torsten Grote
7e6a522eee Merge branch '346-camera-parameters' into 'master'
Try harder to find suitable camera parameters

This branch fixes QR code scanning on the Galaxy Nexus running Cyanogen Mod 12.1 (Android 5.1.1), without breaking QR code scanning on any of the other test devices.

The problem on the Galaxy Nexus was that the selected scene mode was overriding the selected focus mode, so we asked for continuous picture mode but got macro mode. Macro mode requires startAutoFocus() to be called, but we weren't calling it because we'd asked for continuous picture mode.

The fix for that problem is to query the focus mode after applying the parameters and call startAutoFocus() based on the actual mode rather than the requested mode.

But then I discovered another problem: barcode scene mode was setting the flash to auto, so in low light the flash was turning on and off while trying to scan QR codes. That might work well for printed QR codes, but it's terrible when scanning from a screen.

The fix for the new problem is to select barcode scene mode, then try to disable the flash, and if that fails, reset the scene mode. Then we pick the best available video stabilisation, focus mode and preview size.

On the Galaxy Nexus with CM 12.1, that means we use continuous picture mode instead of barcode scene mode, which works fine. All the other test devices pick the same settings as before.

See merge request !321
2016-09-28 14:40:56 +00:00
akwizgran
33795e7046 Use compareAndSet() instead of locking. 2016-09-27 23:02:54 +02:00
Ernir Erlingsson
2d59b9095c Fixing concurrency issues and refactoring code 2016-09-27 23:02:44 +02:00
Torsten Grote
8fb820c967 Merge branch 'check-if-listfiles-returns-null' into 'master'
Check whether File#listFiles() returns null

The docs say this can happen if there's an I/O error. Also fixed a throw-in-finally-block warning and renamed an IoUtils method to make its contract clearer.

See merge request !328
2016-09-27 16:17:09 +00:00
akwizgran
53d0b8b21e Check whether File#listFiles() returns null.
The docs say this can happen for a directory if there's an I/O error.
2016-09-27 15:52:57 +01:00
akwizgran
d389f79a48 Merge branch '346-remove-base32-todos' into 'master'
Remove base32 TODOs, fix a potential NPE

I thought we'd be able to get higher data density in QR codes by using base32 instead of base64, allowing the QR code to use alphanumeric mode instead of byte mode. But I tried it, and although the QR code does use alphanumeric mode, it comes out at exactly the same size (see the 346-use-base32-for-qr-codes branch). So this MR removes the TODOs and fixes a potential NPE I spotted while working on the other branch.

See merge request !327
2016-09-27 14:19:45 +00:00
akwizgran
b278c7d9cb Remove base32 TODOs - base64 is just as good. 2016-09-27 13:31:07 +01:00
Torsten Grote
a85043efb5 Merge branch 'recreate-cache-dir' into 'master'
Recreate cache directory after deleting app data

This fixes a warning on the Moto G:
```
E/libEGL: error creating cache file /data/data/org.briarproject/cache/com.android.opengl.shaders_cache: No such file or directory (2)
```

@grote might possibly be related to hardware rendering issues.

See merge request !326
2016-09-27 12:07:43 +00:00
akwizgran
133722dd2c Code cleanup. 2016-09-27 11:51:24 +01:00
akwizgran
9e3db12ea2 Recreate the cache dir after deleting app data. 2016-09-27 11:44:14 +01:00
akwizgran
f461ec4ab0 Merge branch '627-tests-for-introduction-security-properties' into 'master'
Add more introduction tests for fake MAC and modified timestamp

Closes #627, #669

See merge request !315
2016-09-26 17:09:56 +00:00
Torsten Grote
e87c301e3a Add more introduction tests for fake MAC and modified timestamp 2016-09-26 13:31:00 -03:00
akwizgran
17bacc1116 Merge branch '357-introduction-feature-is-not-very-visible' into 'master'
Add first onboarding screen

When the user enters a private conversation after adding her second
contact, an onboarding screen will be shown highlighting the possibility
of introducing the contacts to each other.

![intro2](/uploads/b2cd4377f39974ca1fbd95649558e487/intro2.gif)

Closes #357

See merge request !324
2016-09-26 14:30:45 +00:00
Torsten Grote
401abf2c0c Add first onboarding screen
When the user enters a private conversation after adding her second
contact, an onboarding screen will be shown highlighting the possibility
of introducing the contacts to each other.
2016-09-26 10:42:20 -03:00
akwizgran
a4d08f4cf1 Try harder to find suitable camera parameters. #346 2016-09-26 12:14:23 +01:00
akwizgran
eb6189150f Merge branch '92-emoticons' into 'master'
Emoji

This MR introduces a custom Emoji implementation to Briar for devices that do not support Emoji sufficiently. It is heavily based on Signal's implementation. Hence, the license for the Android part has been changed to GPLv3.

So far, emoji input is only supported for forums and private conversations that both rely on the same `TextInputView`.

![emoji2](/uploads/f69af031e72efb0bd6f0f67a9574d11f/emoji2.gif)

See merge request !317
2016-09-23 16:31:38 +00:00
akwizgran
c917110e6a Emoji: minor bug fixes, code cleanup, logging, visibility, 2016-09-23 17:18:21 +01:00
Torsten Grote
d5beca5351 Port Signal's emoji implementation to Briar
Add functionality to save and restore recently used Emojis

Update emoji and add new categories based on AOSP's XML file
2016-09-23 17:18:18 +01:00
akwizgran
1fdbe65dde Fixed a broken test. 2016-09-23 11:34:02 +01:00
Torsten Grote
1583163f88 Merge branch '538-recipient-offers-message-to-sender' into 'master'
Don't offer messages back to the sender

Closes #538

See merge request !323
2016-09-22 15:02:06 +00:00
akwizgran
ee35110167 Merge branch '625-avoid-repeated-author-status-lookups' into 'master'
Avoid repeated author status lookups

Closes #625

See merge request !322
2016-09-22 13:18:45 +00:00
akwizgran
72bf701345 Mark a received message as seen by the sender. 2016-09-22 11:31:32 +01:00
Torsten Grote
fd4dbdc081 Avoid repeated author status lookups 2016-09-21 17:26:24 -03:00
akwizgran
97937428bb Merge branch '329-btp-header' into 'master'
Include stream number in stream header nonce

See the corresponding change in the BTP spec for an explanation:
388e1d23c0

Closes #329

See merge request !320
2016-09-21 08:58:36 +00:00
akwizgran
4be1c1bb7d Include stream number in stream header nonce. 2016-09-20 15:27:01 +01:00
Torsten Grote
89ab4dd04e Merge branch '665-android-executor-npe' into 'master'
Fix potential NPE in AndroidExecutorImpl

Always wait for the startup latch to ensure the background thread's Handler is initialised before using it.

Closes #665.

See merge request !319
2016-09-19 16:15:41 +00:00
akwizgran
f3ea731565 Always wait for latch before using background handler. 2016-09-19 10:46:25 +01:00
Torsten Grote
bf023874f0 Merge branch '664-no-delivery-hook' into 'master'
Don't throw an exception if the client has no delivery hook

Closes #664.

See merge request !318
2016-09-16 23:41:53 +00:00
akwizgran
16ac73d002 Don't throw an exception if the client has no delivery hook. 2016-09-16 22:02:04 +01:00
akwizgran
cc439aa74f Merge branch '569-convert-html-to-plain-text-safely-and-readably' into 'master'
Clean HTML from RSS feeds with Jsoup and Show Link Warning

This adds HTML cleaning with the Jsoup library based on a whitelist. The resulting HTML is then used to create a `Spannable` in Android. This spannable is traversed and URLs are replaced by a custom dialog fragment that shows the following warning.

![device-2016-09-07-154936](/uploads/87a9800bde2676b0f2ddf5a894aa04eb/device-2016-09-07-154936.png)

Closes #569

See merge request !311
2016-09-15 10:29:39 +00:00
Torsten Grote
7a1003178d Introduce new MovementMethod for text selection and link clicks 2016-09-13 15:02:27 -03:00
Torsten Grote
cab667ef6a Show all apps that can open links and dismis dialog after click 2016-09-13 14:47:52 -03:00
Torsten Grote
7035d8063c Clean HTML from RSS feeds with Jsoup and show Link Warning 2016-09-13 14:47:51 -03:00
Torsten Grote
2fbbb663a3 Merge branch '619-validation-transactions' into 'master'
Refactor ValidationManager and fix some bugs

The validation manager uses a pattern of throwing an exception from within a transaction, then trying to ensure that the transaction gets committed anyway by setting it complete in a finally block. This is a bad idea - if the intentional exception isn't thrown but a later method throws an unintentional exception, the changes up to that point will be committed instead of rolled back.

I reworked the control flow to remove this pattern, and in the process realised that the validation manager was doing a lot of work to provide objects to attach to MessageStateChangedEvents, which are only used by tests these days. So I fixed that and a couple of other issues.

The VALID state is no longer needed and has been removed.

Closes #619

See merge request !313
2016-09-13 15:18:16 +00:00
akwizgran
b4714b5360 Removed redundant message state check. 2016-09-12 12:09:21 +01:00
akwizgran
8a3e5bfb50 Refactor ValidationManager and fix some bugs. #619 2016-09-09 18:03:14 +01:00
akwizgran
fd4275733f Merge branch 'fix-master-ui-handlers' into 'master'
Introduce a DestroyableActivity for UI result handlers



See merge request !314
2016-09-08 14:52:07 +00:00
Torsten Grote
af5b246d7b Introduce a DestroyableActivity for UI result handlers 2016-09-08 11:25:02 -03:00
akwizgran
49e9ee2b6d Merge branch '637-effect-of-touching-a-post-is-inconsistent' into 'master'
Resolve Outstanding Blog Issues

This MR has several commits which fix individual small issues. The biggest commit is a refactoring of the `BlogActivity`, so its `ViewPager` can be used also for the Blog feed.

Closes #637

See merge request !309
2016-09-08 11:57:18 +00:00
akwizgran
1a611d55be Merge branch '610-result-handlers-can-return-results-to-destroyed-activities-fragments' into '637-effect-of-touching-a-post-is-inconsistent'
Check if activity is still alive before returning results to it

Closes #610

See merge request !312
2016-09-08 11:45:52 +00:00
Torsten Grote
7c5945de01 Check if activity is still alive before returning results to it 2016-09-07 17:44:07 -03:00
Torsten Grote
ccc49df08e Address review issues 2016-09-07 14:24:19 -03:00
Torsten Grote
ac325d4423 remove unused resources 2016-09-07 12:51:43 -03:00
Torsten Grote
0a0e1b4280 Always replace current blog activity when new one opened
Fixes #635
2016-09-07 12:51:42 -03:00
Torsten Grote
cb64740916 Set blog title when opening blog
Fixes #634
2016-09-07 12:51:42 -03:00
Torsten Grote
73bc86df4a show only a teaser for blog posts in lists 2016-09-07 12:51:41 -03:00
Torsten Grote
307e124ee8 Make the blog post pager usable for the feed and individual blogs 2016-09-07 12:51:41 -03:00
Torsten Grote
60b4c5649a Make blog post text clickable
by making it only selectable in detail view
2016-09-07 12:51:40 -03:00
akwizgran
e0e46a726e Merge branch '641-rss-feed-entry-comparator-wrongly-assumes-existing-date' into 'master'
Don't crash if an RSS entry has no date

Closes #641

See merge request !310
2016-09-07 14:06:06 +00:00
akwizgran
668eaf45f6 Merge branch '636-blogpostfragment-should-use-the-same-layout-as-the-blog-feed' into 'master'
Show Blog Posts always in the same design

This also adds comments to the blog post detail screen that were previously missing.
It re-uses the existing `BlogPostViewHolder` and its `bind()` methods effectively reducing the amount of code necessary.

Closes #636

See merge request !307
2016-09-07 13:12:25 +00:00
akwizgran
fb9d743d11 Merge branch '627-tests-for-introduction-security-properties' into 'master'
Add one introduction test for modified response message

This is only the first part of #627, but I am putting it up for review already, since the second part will be very similar and issues found here will likely apply to both.

See merge request !306
2016-09-07 13:08:34 +00:00
akwizgran
fc2213c042 Merge branch '633-blog-posts-from-other-users-sometimes-have-bold-nicknames' into 'master'
Fix view recycling issue with author name typeface

Closes #633

See merge request !305
2016-09-07 12:43:08 +00:00
akwizgran
34f9311f43 Merge branch '638-illegalstateexception-when-navigating-out-of-combined-feed-and-back-in' into 'master'
Allow Blog Controller listener to re-attach

Closes #638

See merge request !304
2016-09-07 12:39:04 +00:00
akwizgran
28fd84b261 Merge branch '632-badtokenexception-if-rss-error-dialog-is-show-after-activity-is-destroyed' into 'master'
Only show RSS Feed Import Failed Dialog when Activity lives

Closes #632

See merge request !303
2016-09-07 12:36:12 +00:00
Torsten Grote
448bf86379 don't crash if an RSS entry has no date 2016-09-06 15:55:53 -03:00
Torsten Grote
91e529a9e9 Merge branch 'socks-socket' into 'master'
Fetch RSS feeds via Tor

This patch replaces jsocks with our own minimal SOCKS 5 implementation, which is compatible with Android's OpenSSL hacks (see discussion on #599 for the horrifying details). This allows us to use OkHttp over Tor to fetch RSS feeds.

It turns out that SOCKS 5 without authentication is a really simple protocol: https://tools.ietf.org/html/rfc1928

Closes #599.

See merge request !308
2016-09-06 18:37:38 +00:00
akwizgran
74f9a0dd73 Use our own SOCKS implementation to talk to Tor. 2016-09-05 19:59:22 +01:00
Torsten Grote
54290bc374 Show Blog Posts always in the same design
This also adds comments to the blog post detail screen that were
previously missing.
2016-09-05 13:33:44 -03:00
Torsten Grote
3e39ad8a68 Add one introduction test for modified response message 2016-09-02 11:49:10 -03:00
Torsten Grote
07445ada41 Fix view recycling issue with author name typeface 2016-09-02 11:38:44 -03:00
Torsten Grote
5281d8b468 Allow Blog Controller listener to re-attach 2016-09-02 11:25:17 -03:00
Torsten Grote
0deac1d1b6 Only show RSS Feed Import Failed Dialog when Activity lives 2016-09-02 11:12:24 -03:00
akwizgran
387e44d114 Merge branch '496-implement-ui-for-reblogging-and-blog-comments' into 'master'
UI for reblogging and blog comments

This MR wraps all blog posts inside a `CardView` and adds a reblog button to blog posts. When this button is pressed, a new activity opens that shows the blog post again and allows the user to reblog it into their own blog. An optional comment can be added.

Also a new compound view `AuthorView` is introduced to display authors and their trust level in a consistent way.

The `BlogController` has been refactored, so the `FeedController` can share most code through an abstract base class.

![reblog2](/uploads/ce4764851c4cbe39684c95a3b427e3a2/reblog2.gif)

Closes #496, #437 

See merge request !300
2016-09-02 11:16:28 +00:00
akwizgran
bb00412187 Added @UiThread annotations, minor code cleanups. 2016-09-02 11:53:16 +01:00
Torsten Grote
bb0a2a5b32 Add a scene transition animation when reblogging a blog post 2016-09-02 11:53:16 +01:00
Torsten Grote
6d7e0aab07 Reblogging and Comment UI 2016-09-02 11:53:08 +01:00
Torsten Grote
da08072409 Make the user's own identities visually distinct
Closes #593
2016-09-02 11:52:34 +01:00
Torsten Grote
9664aea520 Introduce and use CardView and AuthorView for Blog Posts 2016-09-02 11:52:34 +01:00
akwizgran
636b587b9c Merge branch '605-add-database-method-for-retrieving-a-contact-by-local-and-remote-author-ids' into 'master'
Add database method for retrieving a contact by local and remote author IDs

Closes #605

See merge request !302
2016-09-01 20:00:27 +00:00
akwizgran
0afab09fdf Merge branch '616-continue-button-is-off-screen-when-adding-a-contact' into 'master'
Scroll down Adding Contact screen

Normally, you would introduce a new layout only for small screens, but in this case it is easier and has less maintenance overhead to just scroll down the screen, so the button is always visible after loading.

While I was at it, I also replaced `getLocalAuthors()` by the new `getLocalAuthor()`.

Closes #616

See merge request !294
2016-09-01 19:54:31 +00:00
Torsten Grote
fe4f71fe0f Remove lots of unused code for identity selection 2016-09-01 16:13:55 -03:00
Torsten Grote
6f0ffa8439 Add database method for retrieving a contact by author ID
and use it for retreiving the status of an author faster.
Also add tests for both.
2016-09-01 14:06:38 -03:00
Torsten Grote
69dd399bd2 Scroll down Adding Contact screen
Closes #616
2016-09-01 12:16:26 -03:00
akwizgran
8b7304f4cb Merge branch '599-fetch-rss-feeds-via-tor' into 'master'
Factor out Tor Socks Port

This MR factors out the local Tor port, so other clients can listen to an `TransportEnabledEvent` for Tor and start tasks as soon as Tor becomes available. This would also enable client to pass traffic through Tor's local SOCKS proxy.

See merge request !301
2016-09-01 11:57:13 +00:00
Torsten Grote
e023e5d8fc Start RSS Feed Fetcher only after TransportEnabledEvent for Tor 2016-09-01 12:55:25 +01:00
akwizgran
042050453a Merge branch '359-introduction-message-can-be-overlooked' into 'master'
Attach optional messages to invitations in Conversation view

![device-2016-08-29-115823](/uploads/e819324046b8a37ff06da7300046369c/device-2016-08-29-115823.png)![device-2016-08-29-115834](/uploads/051b4b64938bfa6f3ed610db28909865/device-2016-08-29-115834.png)

Closes #359

See merge request !299
2016-09-01 11:43:18 +00:00
akwizgran
1c15e690e1 Merge branch '352-conversation-screen-has-too-much-padding' into 'master'
Improve conversation screen graphics with less padding

This is how the conversation screen looks with this MR:

![1](https://code.briarproject.org/akwizgran/briar/uploads/3078636c93f7edc6b07034ad808ffc7c/device-2016-08-26-105325.png)
![2](https://code.briarproject.org/akwizgran/briar/uploads/fe0dcd3b1cbc6593aabed6faab1801d7/device-2016-08-26-105425.png)

This MR also replaces more raster graphics with vector graphics.

Closes #352

See merge request !298
2016-09-01 11:37:10 +00:00
Torsten Grote
61c05c1dd4 Fix tests broken by latest merges! 2016-08-31 11:32:53 -03:00
akwizgran
d8a9d83caf Merge branch '494-implement-backend-for-reblogging-and-blog-comments' into 'master'
Add support for comments and reblogging to Blog Client

Comments and reblogs need to depend on the post they refer to.
Since message dependencies are limited to one group,
the post and also the comments need to be wrapped
when commented on or reblogged to another blog (and group).

For this reason, in addition to comments, two new wrapping message types
are introduced. They retain all data of the original messages and allow
for reconstruction and signature verification.

This MR breaks backwards compatibility with old blog posts.
It removes the content type, title and parent ID from the post.

Furthermore, it includes one commit that replaces the `Message` in `MessageSharedEvent` with a `MessageId`.

Closes #494

See merge request !285
2016-08-30 23:09:31 +00:00
akwizgran
70a44e8a27 Merge branch '364-introduction-responses-should-be-signed' into 'master'
Sign Introduction Information to be able to discover MITM attack

The local introducee doesn't know whether each piece of information received from the introducer originates from the remote introducee or has been replaced by the introducer, i.e. whether the introducer is carrying out a man-in-the-middle attack.

The introduction protocol doesn't aim to detect or prevent man-in-the-middle attacks. We only aim to establish that if the remote identity public key is not replaced then the remote ephemeral public key, transport properties and timestamp are not replaced either. This MR adds a MAC and a signature to the introduction protocol's ACK message to fulfill that aim. See #364 for the detailed security argument.

Later, when the local introducee verifies that the remote identity public key belongs to a particular person (#513), she can also be sure that the remote ephemeral public key, transport properties and timestamp originated from that person.

Closes #364

See merge request !297
2016-08-30 23:05:25 +00:00
Torsten Grote
fc5a7290e3 Calculate and verify signature and MAC for Introduction ACKs
Before the introducee sends her ACK,
she derives a master key from the ephemeral shared secret as before.

Two nonces and a MAC key are then derived from the master key.
The local introducee signs one of the nonces and calculates a MAC
over her own identity public key, ephemeral public key,
transport properties and timestamp.
The local introducee includes the signature and MAC in her ACK.

On receiving the remote introducee's ACK,
the local introducee verifies the signature and MAC.
Should the verification fail, an ABORT is sent to the introducer and
the remote introducee that was added as inactive is deleted again.
2016-08-30 19:58:54 -03:00
Torsten Grote
7db0e4472a Introduction Client: Add MAC and signature to ACK message
The MAC and signature are not yet generated and verified.
This will happen in a later commit.
2016-08-30 19:25:53 -03:00
Torsten Grote
65bdd5558e Address bugs and comments from reblogging code review 2016-08-30 18:52:33 -03:00
Torsten Grote
3dd3a18694 Add support for comments and reblogging to Blog Client
Comments and reblogs need to depend on the post they refer to.
Since message dependencies are limited to one group,
the post and also the comments need to be wrapped
when commented on or reblogged to another blog.

For this reason, in addition to comments, two new wrapping message types
are introduced. They retain all data of the original messages and allow
for reconstruction and signature verification.

This commit breaks backwards compatibility with old blog posts.
It removes the content type, title and parent ID from the post
message structure.
2016-08-29 13:37:20 -03:00
Torsten Grote
743fc7dd1f Do not require an entire Message for the MessageSharedEvent 2016-08-29 13:36:09 -03:00
akwizgran
eb3da2aac9 Merge branch '539-564-568-notification-overhaul' into 'master'
Fix various notification bugs

Fixes #539, #564, #568.

Depends on !276.

See merge request !286
2016-08-29 16:27:47 +00:00
Torsten Grote
4518f59a54 Improving notices with messages attached in conversation view 2016-08-29 12:01:51 -03:00
Torsten Grote
11c0cb667f Improve conversation screen graphics with less padding
Also replace more raster graphics with vector graphics.
2016-08-29 10:02:15 -03:00
Torsten Grote
132a03d0a9 Merge branch '364-add-mac-to-crypto-component' into 'master'
Add MAC function to crypto component



See merge request !295
2016-08-26 13:34:56 +00:00
Torsten Grote
c666b0493c Merge branch '618-bdf-dictionary-iteration-order' into 'master'
Define iteration order of BdfDictionary

Closes #618

See merge request !296
2016-08-26 13:29:06 +00:00
akwizgran
625276067a Define iteration order of BdfDictionary. 2016-08-26 10:57:57 +01:00
akwizgran
30f2c192c6 Added MAC function to crypto component. 2016-08-26 10:06:24 +01:00
Torsten Grote
55602ed76a Merge branch '614-dev-reporter-does-not-close-stream' into 'master'
Use Briar's IoUtils.copy(), not H2's IOUtils.copy()

Our implementation closes both streams, H2's implementation leaves them open.

Closes #614.

See merge request !293
2016-08-25 13:11:54 +00:00
akwizgran
4ad0df2640 Use Briar's IoUtils, not H2's IOUtils. 2016-08-25 11:57:21 +01:00
Torsten Grote
d93f59b4ef Merge branch '555-blog-controller' into 'master'
Blog controller thread safety

This patch removes the mutable list of posts from the blog controller to make it thread-safe, and adds a cache of message bodies to speed up reloads.

Closes #555.

See merge request !276
2016-08-24 19:36:06 +00:00
akwizgran
c5f0272621 Merge branch '597-gradle-connectedcheck-fails-due-to-method-limit' into 'master'
Cleanup Gradle and Proguard to fix connectedCheck

Closes #597

See merge request !284
2016-08-24 17:22:30 +00:00
akwizgran
419aa2e97e Merge branch '311-audit-crash-report-and-feedback-fields-for-sensitive-or-identifying-information' into 'master'
Remove sensitive information from crash and feedback reports

This depends on MR !290 and removes also the crash report settings.

Closes #311

See merge request !291
2016-08-24 17:20:49 +00:00
akwizgran
015e45752e Merge branch '592-scrub-addresses-before-logging-them' into 'master'
Scrub addresses before logging them

MAC, IP and onion addresses are now scrubbed before logging to ensure we don't leave any sensitive information in plaintext on the device or send it in crash reports or feedback.

* Bluetooth MAC addresses keep the first and last octets
* IPv4 addresses keep the first and last octets
* IPv6 addresses should be scrubbed completely (couldn't test)
* Onion addresses keep the first three characters

If an address is invalid it will not be scrubbed to enable debugging, because it is most likely not sensitive.

Closes #592

See merge request !290
2016-08-24 17:18:48 +00:00
Torsten Grote
743053930a Remove crash report settings
Closes #311
2016-08-24 13:33:03 -03:00
Torsten Grote
cc7602e566 Remove sensitive information from crash and feedback reports 2016-08-24 13:24:12 -03:00
Torsten Grote
8b56e082b3 Scrub IP addresses before logging 2016-08-24 13:22:28 -03:00
akwizgran
b4889fe293 Merge branch '483-design-ux-for-importing-an-rss-feed' into 'master'
Add feed title to imported entries

Also fixes one bug where a new feed was not saved and improved HTML stripping a bit.

Closes #483

See merge request !287
2016-08-24 16:15:14 +00:00
Torsten Grote
ca094620d8 Scrub Bluetooth MAC addresses before logging 2016-08-24 12:47:20 -03:00
Torsten Grote
83be5c766e Scrub onion addresses from log 2016-08-24 12:47:20 -03:00
Torsten Grote
72fb4e9bc7 Post RSS entries within one transaction
This also fixes a bug where new feeds was not added properly.
2016-08-24 12:39:04 -03:00
Torsten Grote
e10f68b496 Add feed title to imported entries
Also fixes one bug where a new feed was not saved and
improved HTML stripping a bit.
2016-08-24 11:20:45 -03:00
Torsten Grote
22e7ec5b27 Merge branch 'gradle-2.14.1' into 'master'
Upgrade gradle to 2.14.1 and gradle plugin to 2.1.3.



See merge request !292
2016-08-24 13:44:47 +00:00
akwizgran
3bccdfa947 Upgraded gradle to 2.14.1 and gradle plugin to 2.1.3. 2016-08-24 11:06:49 +01:00
akwizgran
ef02908082 Improved blog controller's caching. 2016-08-23 23:34:33 +01:00
akwizgran
3aa3811d1b Fix progress bar issues. 2016-08-23 17:04:48 +01:00
Torsten Grote
00240bfa57 Merge branch '573-hidden-service-address' into 'master'
Add hidden service address for dev reports

Closes #573

See merge request !289
2016-08-23 13:14:35 +00:00
akwizgran
1f5de42844 Added hidden service address for dev reports. 2016-08-23 10:54:21 +01:00
akwizgran
17f9972a56 Merge branch '573-hidden-service-for-crash-reports-and-feedback' into 'master'
Server-side code for accepting crash reports and feedback

* Moved some shared code for copying InputStreams to OutputStreams into a utility class
* Modified the  dev report sender to send one report per connection
  * Easier to handle on the server side
  * If the connection fails after sending any reports, they don't need to be resent
  * Tor will reuse the circuit, so it's cheap
* Added server-side code for accepting dev reports
  * We need to protect the server's resources from DoS attacks
  * Reports can't be larger than 1 MB
  * Connections are limited to an average rate of one per minute
  * The rate limiter uses a token bucket to allow bursts of up to 1,000 connections
  * If the rate limit is exceeded, connection attempts will fail - clients will retry next time they sign in
  * The limits can be raised when we move to a bigger server (and when we have some users)


See merge request !288
2016-08-22 20:09:46 +00:00
akwizgran
18dd7d7aa9 Use socket timeout to limit number of open sockets. 2016-08-22 18:11:04 +01:00
Torsten Grote
bc6557e82d Merge branch '566-raise-api-level' into 'master'
Stop supporting Gingerbread

Closes #566

See merge request !278
2016-08-22 16:52:41 +00:00
akwizgran
5f86dd0207 Simple rate-limited server for saving dev reports. 2016-08-22 17:35:23 +01:00
Torsten Grote
659cf85ca1 really bump the expiry date 2016-08-22 12:56:42 -03:00
Torsten Grote
294bc0bdd2 update translations and bump expiry date 2016-08-22 12:23:21 -03:00
akwizgran
be84afc543 System.lineSeparator() doesn't exist in Java 6. 2016-08-22 16:20:38 +01:00
akwizgran
c6c62cab6c Use one connection per dev report.
This allows simpler server-side code, and a failure part-way through sending won't require restarting from the beginning next time.
2016-08-22 16:12:57 +01:00
akwizgran
d24e18a5d9 Use IoUtils.copy() in Tor plugin. 2016-08-22 16:05:15 +01:00
akwizgran
34a4a3f3c6 Renamed FIleUtils to IoUtils, added copy() method. 2016-08-22 15:29:13 +01:00
Ernir Erlingsson
48e1a65a24 raised api level and made necessary code changes 2016-08-22 00:08:47 +02:00
akwizgran
28be7d5de3 Added UI thread methods to AndroidExecutor. 2016-08-20 18:41:05 +01:00
akwizgran
dbdf567d4e Overhaul notifications to fix various bugs.
Fixes #539, #564 and #568.
2016-08-20 18:40:59 +01:00
akwizgran
98337a16ec Make BlogController thread-safe. #555 2016-08-20 16:07:04 +01:00
akwizgran
d34afa5f30 Merge branch '583-npe-org-briarproject-android-util-qrcodeutils-createqrcode' into 'master'
Fix two crashes when scanning QR codes

One crash was two due the `Context` being `null` and the other due to the camera being opened within an `AsyncTask`.

Closes #583

See merge request !282
2016-08-19 19:32:24 +00:00
akwizgran
746fce1b95 Merge branch '580-introduced-contacts-have-status-verified' into 'master'
Add introduced contacts as UNVERIFIED

This MR **breaks** the database schema requiring you to create a new account.

Closes #580

See merge request !280
2016-08-19 16:18:35 +00:00
Torsten Grote
c3a14d9275 Add a new event that is broadcasted when a contact is verified
Also, don't support unverifying contacts.
2016-08-19 12:41:10 -03:00
Torsten Grote
e690bcb3cc Add introduced contacts as UNVERIFIED
Closes #580
2016-08-19 12:31:00 -03:00
akwizgran
70b311db13 Merge branch '591-add-new-message-types-to-blogvalidator' into 'master'
Validate New Messages for Reblogging and Comments of Blog Posts

Closes #591

See merge request !279
2016-08-19 14:50:27 +00:00
Torsten Grote
caee7fe61b Validate New Messages for Reblogging and Comments of Blog Posts
Also includes unit tests for the new message types.

Closes #591
2016-08-15 14:28:17 -03:00
akwizgran
84d4bf2205 Merge branch '595-clients-should-decide-whether-to-share-messages' into 'master'
Let clients decide whether to share messages or not

Before this MR, the `ValidationManager` was sharing all messages after they had been delivered. Now, it is within the client's responsibility whether to share messages or not. So far, only the Blog and the Forum client are sharing incoming messages.

Closes #595

See merge request !283
2016-08-15 15:03:59 +00:00
Torsten Grote
bcf7488afd Cleanup Gradle and Proguard to fix connectedCheck 2016-08-11 14:54:31 -03:00
Torsten Grote
71196e3494 Let clients decide whether to share messages or not 2016-08-11 12:19:10 -03:00
Torsten Grote
9defb099dd Merge branch '342-organise-strings-xml-to-make-life-easier-for-translators' into 'master'
Group strings and remove unused resources

Before I grouped the strings, I removed unused resources as well to not group things that are not being used anymore.

The grouping tries to follow a normal usage lifecycle of the app where the user works their way down the navigation drawer and explores all features in one area.

Closes #342

See merge request !277
2016-08-11 14:28:19 +00:00
Torsten Grote
b3d6e7d12d Open Camera in UI Thread to prevent crash on some devices
Also properly handle back navigation when trying to add contacts.
2016-08-10 20:00:01 -03:00
Torsten Grote
739e8b4511 Fix one crash when showing QR Code 2016-08-10 18:44:55 -03:00
akwizgran
cb9a85eb88 Merge branch '447-lan-ports' into 'master'
Don't try to reuse already bound ports for key agreement

This is one cause of #447, but probably not the only one.

See merge request !281
2016-08-10 21:12:02 +00:00
akwizgran
7e086d0f4e Don't try to reuse already bound ports for key agreement. 2016-08-10 18:06:07 +01:00
akwizgran
dccc2e6ded Merge branch '587-java-lang-illegalstateexception-no-group-in-intent' into 'master'
Don't crash when pressing Up button in WriteBlogPostActivity

Closes #587

See merge request !275
2016-08-10 10:13:04 +00:00
Torsten Grote
72906acaee Group strings and remove unused resources
Closes #342
2016-08-09 15:06:11 -03:00
Torsten Grote
6fc7e69849 Harmonize Text Color of Blog Posts in Detail View 2016-08-08 13:00:25 -03:00
Torsten Grote
30092550c7 Don't crash when pressing Up button in WriteBlogPostActivity
Closes #587
2016-08-08 13:00:11 -03:00
Torsten Grote
b17fbcb135 Merge branch '582-tor-assets' into 'master'
Update Tor assets if they're older than the APK

Extract the Tor binary, GeoIP database and config file from the APK if they haven't been extracted since the APK was last updated.

On the Galaxy Nexus, skipping extraction of the binary if it's already up to date shaves about 1.5 seconds off the Tor plugin's startup time.

Closes #582.

Depends on !272.

See merge request !273
2016-08-08 14:47:24 +00:00
Ernir Erlingsson
060860bea5 Merge branch 'care_for_lint' into 'master'
Care for lint errors

No more general disabling of abortOnError
Resolved all *errors* beside language ones  MissingTranslation & ImpliedQuantity
Issue context: #567

See merge request !274
2016-08-08 14:35:07 +00:00
Torsten Grote
f8337d09ae Merge branch '578-tor-ports' into 'master'
Don't connect to Tor if it's already running

For some time now we've had a reliable way of shutting down the Tor process (the __OwningControllerProcess command line argument combined with the TAKEOWNERSHIP command), but TorPlugin#start() still assumes that Tor may already be running. This allows another app to bind the Tor control and SOCKS ports and collect confidential data from Briar (#578). It also allows two Briar instances running on the same device to try to communicate with the same Tor process, which prevents proper shutdown (#572).

This patch prevents the Tor plugin from starting unless it's able to start its own Tor process with the expected control and SOCKS ports. If two Briar instances are running on the same device, only one of them will be able to use Tor. The other should fail to start its Tor plugin and then function normally without Tor access, including normal shutdown.

Fixes #572, #578. Open another ticket if you want two Briar instances on the same device to have their own Tor processes. :-)

See merge request !272
2016-08-08 14:27:28 +00:00
ligi
4055bbfcd4 Care for lint errors
No more general disabling of abortOnError
Resolved all *errors* beside language ones  MissingTranslation & ImpliedQuantity
Issue context: #567
2016-08-07 17:12:27 +02:00
akwizgran
44d13ef28e Merge branch '579-unsubscribe-from-shared-blogs' into 'master'
Allow unsubscribing from shared blogs

Only personal blogs from non-contacts can be removed.
This also adds integration tests that check the conditions under which blogs can actually be removed.

Closes #579

See merge request !268
2016-08-05 17:36:36 +00:00
Torsten Grote
1ec56fa3ef Allow unsubscribing from shared blogs
Only personal blogs from non-contacts can be removed.
This also adds integration tests that check if blogs can actually be removed.

Closes #579
2016-08-05 14:08:09 -03:00
akwizgran
fce104487a Merge branch '470-second-invitation-doesn-t-disappear-from-available-forums' into 'master'
Return proper Invitation objects in SharingManager

Fixes #470

See merge request !265
2016-08-05 16:46:27 +00:00
Torsten Grote
17db03d40a Return proper Invitation objects in SharingManager
Fixes #470
2016-08-05 13:07:16 -03:00
akwizgran
3bbc8dcc4e Merge branch '429-explain-that-qr-codes-can-not-be-scanned-remotely' into 'master'
Show Explanatory Graphic Before Scanning QR Codes

![device-2016-08-04-182045](/uploads/9d6a5fea975d55e86dfe6d9bdbacb51c/device-2016-08-04-182045.png)
![device-2016-08-04-182058](/uploads/3ce86635f37ce2b903144a842d814d15/device-2016-08-04-182058.png)

Closes #429

See merge request !270
2016-08-05 15:55:46 +00:00
akwizgran
930194accf Merge branch '514-npe-crash-when-adding-contacts-in-emulator' into 'master'
Fix crashes when no Bluetooth or no Camera is available

Briar crashed when run in a device without bluetooth or without camera
such as an emulator.

Closes #514

See merge request !269
2016-08-05 15:51:32 +00:00
Torsten Grote
b04bde4f41 Fix crashes when no Bluetooth or no Camera is available
Briar crashed when run in a device without bluetooth or without camera
such as an emulator.

Closes #514
2016-08-05 12:30:57 -03:00
akwizgran
054a0d467c Merge branch '576-empty-state-messages-are-briefly-shown-when-they-shouldn-t' into 'master'
Prevent empty state messages from showing briefly

When we clear a list in `onPause()`, the proper behavior is that the empty state
message is shown, because the list is indeed empty.

However, we will reload the list content again in `onResume()`,
so the fix chosen in this MR is to force showing the progress bar
right after clearing the list.

Closes #576

See merge request !267
2016-08-05 15:02:52 +00:00
akwizgran
adc85dab7e Merge branch '575-fix-sharerleavesbeforeresponse-test' into 'master'
Fix SharerLeavesBeforeResponse Integration Test

Closes #575

See merge request !266
2016-08-05 15:01:10 +00:00
akwizgran
55b7e95d35 Update Tor assets if they're older than the APK. #582 2016-08-05 15:37:39 +01:00
akwizgran
36d15358a1 Don't connect to Tor if it's already running.
Fixes #572, #578.
2016-08-05 13:59:25 +01:00
akwizgran
d15d82ccec Merge branch '565-forums-sometimes-appear-empty' into 'master'
Fix regression where forum entries were not shown

Closes #565

See merge request !271
2016-08-05 09:12:49 +00:00
Torsten Grote
7be17668c1 Fix regression where forum entries were not shown
Closes #565
2016-08-04 19:07:30 -03:00
Torsten Grote
f8f1c7f0d4 Show Explanatory Graphic Before Scanning QR Codes
Closes #429
2016-08-04 18:22:48 -03:00
Torsten Grote
dd0d23359b Prevent empty state messages from showing briefly
When we clear a list in onPause(), the proper behavior is that the empty state
message is shown, because the list is indeed empty.

However, we will reload the list content again in onResume(),
so the fix chosen in this commit is to force showing the progress bar
right after clearing the list.

Closes #576
2016-08-03 19:12:53 -03:00
Torsten Grote
1a32458783 Merge branch '498-implement-ui-for-sharing-blogs' into 'master'
UI for sharing blogs

Not posting any screenshots, because the UI is the same as for forums.

This does not yet offer the possibility to unsubscribe from blogs again. Should be done in a different MR as this one is big enough already.

Closes #498,  #497

See merge request !263
2016-08-03 21:47:02 +00:00
Torsten Grote
a4cf91fba5 Use Inheritence for shared Forum and Blog Sharing Code 2016-08-03 18:46:20 -03:00
Torsten Grote
16da3f2cab Fix SharerLeavesBeforeResponse Integration Test
Closes #575
2016-08-03 18:15:14 -03:00
Torsten Grote
a3b2358164 Show Sharing Status for Blogs
This refactors the current SharingStatusActivity
so it can be used for forums and blogs.
2016-08-03 13:01:25 -03:00
Torsten Grote
e4f5d8e6e7 Show Blog Invitations
This refactors the forum invitation code,
so it can be used by both: forums and blogs.
2016-08-03 13:01:25 -03:00
Torsten Grote
a69a4028b0 Fix Blog Sharing Backend and Add Blog Sharing Integration Tests 2016-08-03 13:01:24 -03:00
Torsten Grote
a552d1b6a6 Show blog invitation requests and responses in private conversation 2016-08-03 13:01:24 -03:00
Torsten Grote
2f7d188a07 UI for Sharing Blogs
This commit refactors the code for sharing forums,
so it can be used for sharing blogs as well.

It does not yet include code for responding to blog invitations.
2016-08-03 13:01:23 -03:00
akwizgran
4a4366078a Moved briar-android tests into their respective packages. 2016-08-03 14:46:15 +01:00
akwizgran
9a32a13767 Merge branch '571-npe-in-feedfragment' into 'master'
Fix two Blog NPEs

Closes #571

See merge request !264
2016-08-03 13:44:21 +00:00
Torsten Grote
50d2742cae Fix two Blog NPEs
Closes #571
2016-08-03 10:38:45 -03:00
akwizgran
747ed023e4 Merge branch '517-simple-ui-for-managing-rss-feeds' into 'master'
Simple UI for Managing and Importing RSS Feeds

Please note that this does not yet include the reblogging style for displaying imported RSS entries.

![device-2016-07-26-170732](/uploads/e7f53f72e955d0c37518e0d552121105/device-2016-07-26-170732.png)
![device-2016-07-26-170755](/uploads/b8e0c91ed496b618d330364e840458dc/device-2016-07-26-170755.png)
![device-2016-07-26-171519](/uploads/fae5c16255d5a67673a4bd9be73c165f/device-2016-07-26-171519.png)

Closes #517

See merge request !251
2016-08-03 09:42:51 +00:00
akwizgran
e8c398e996 Merge branch '486-convert-rss-feed-entries-into-briar-blog-posts' into 'master'
Post new RSS entries into the user's personal blog

Closes #486

See merge request !250
2016-08-03 09:36:55 +00:00
akwizgran
85c9b48196 Merge branch '485-extract-new-entries-from-rss-feed' into 'master'
Keep track of which RSS entries have been seen

This is done by remembering the time of the latest entry.
All entries newer than that are considered new and will be posted.

Closes #485

See merge request !249
2016-08-03 09:25:45 +00:00
akwizgran
2a2966bd6c Merge branch '484-implement-background-task-for-fetching-rss-feeds' into 'master'
Implement background task for fetching RSS feeds

* Implemented in briar-core as a `ScheduledExecutorService`
  that gets started when the app starts
* The briar-api has a `FeedManager` interface
  that the UI can use to register and unregister feeds
* In this first iteration, feeds are fetched via HTTP(S), not Tor

Closes #484

See merge request !247
2016-08-03 09:23:07 +00:00
Torsten Grote
62c1c3e08d Simple UI for Managing and Importing RSS Feeds
Closes #517
2016-08-02 20:21:54 -03:00
Torsten Grote
6454acdaa5 Post new RSS entries into the user's personal blog
Closes #486
2016-08-02 20:02:40 -03:00
Torsten Grote
8d1a26ba72 Keep track of which RSS entries have been seen
This is done by remembering the time of the latest entry.
All entries newer than that are considered new and will be posted.

Closes #485
2016-08-02 19:19:48 -03:00
Torsten Grote
e527e30712 Implement background task for fetching RSS feeds
* Implemented in briar-core as a `ScheduledExecutorService`
  that gets started when the app starts
* The briar-api has a `FeedManager` interface
  that the UI can use to register and unregister feeds
* In this first iteration, feeds are fetched via HTTP(S), not Tor

Closes #484
2016-08-02 19:18:55 -03:00
akwizgran
4af5dbb45b Merge branch '562-npe-in-contactlistfragment' into 'master'
Fix NPE in ContactListFragment

Closes #562

See merge request !261
2016-08-02 09:32:59 +00:00
akwizgran
7132c88644 Merge branch '335-report-ui-improvements' into 'master'
UX improvements for crash reports and feedback

(The background color of the first screenshot is white, but I now changed it to use the same background color like everywhere)
![device-2016-08-01-174433](/uploads/a457489f61a7f0af48d4ebf8e3a10bf0/device-2016-08-01-174433.png)![device-2016-08-01-174500](/uploads/5275bff37db5a35e9ac9ad5038c06142/device-2016-08-01-174500.png)![device-2016-08-01-174532](/uploads/d0281156feff94262789102bd420ffeb/device-2016-08-01-174532.png)![device-2016-08-01-180330](/uploads/ed2d2d35b465df22b717cb84567a555f/device-2016-08-01-180330.png)

Closes #335

See merge request !246
2016-08-02 09:26:42 +00:00
Torsten Grote
a452060b41 Address issues found in code review 2016-08-01 18:08:05 -03:00
str4d
60a381430e Use full-screen overlay with microcopy instead of dialog to request report 2016-08-01 16:30:37 -03:00
str4d
827fd0aebb Move send action from FAB into toolbar 2016-08-01 16:30:37 -03:00
str4d
23eb5acafa Use AppCompatDelegate to add AppCompat support to BaseCrashReportDialog subclass
This enables the toolbar to be used as an action bar, and tinting of UI elements
like checkboxes.
2016-08-01 16:30:36 -03:00
str4d
2170d291a2 Hide debug report by default for both crash reports and feedback 2016-08-01 16:30:36 -03:00
Torsten Grote
31cd6e8958 Fix NPE in ContactListFragment
Closes #562
2016-08-01 16:26:01 -03:00
akwizgran
a51d2f47af Send messages in ascending order of timestamp.
The old behaviour was a leftover from the days of limited retention periods. The new behaviour will interact better with dependencies and message queues.
2016-08-01 18:49:24 +01:00
akwizgran
0d9cbb2793 Merge branch '543-flicker-when-forum-invitation-is-removed-from-list' into 'master'
Remove forum invitations from list instead of reloading

Closes #543

See merge request !255
2016-08-01 17:16:25 +00:00
Torsten Grote
c17ef86968 Clear Forum Invitation adapter only when invitations could be removed 2016-08-01 12:55:56 -03:00
akwizgran
ff28ae296e Merge branch '559-show-elapsed-time-in-blog-feeds-and-individual-blog-posts' into 'master'
Show Blog Post times with new timestamp and update it periodically

Closes #559

See merge request !260
2016-08-01 15:44:04 +00:00
Torsten Grote
ce2cb01558 Show Blog Post times with new timestamp and update it periodically
Closes #559
2016-08-01 12:37:14 -03:00
akwizgran
d096c1fead Merge branch '472-forum-no-message-for-the-inviter-if-an-invitee-accepts-or-declines' into 'master'
Show Responses to Forum Invitations in Private Conversation

Closes #472

See merge request !257
2016-08-01 13:46:30 +00:00
akwizgran
36dd9c30f8 Merge branch '553-pause-periodic-list-refresh-when-view-is-not-visible' into 'master'
Pause Periodic List Refresh when View is not Visible

This MR also sneaks in a second commit which stops the cevron in the forum list to sometimes lose its blue color. I noticed this when testing this MR with short refresh intervals. This is not as nice of specifying the color as a tint, but unfortunately tints are not yet ready for primetime on Android.

Closes #553

See merge request !259
2016-08-01 13:45:00 +00:00
akwizgran
2c993b62c2 Made the logger and a constant static. 2016-08-01 14:38:58 +01:00
akwizgran
737f0dac1e Initialise adapter in onCreate() to avoid double refreshing. 2016-08-01 14:38:55 +01:00
Torsten Grote
5a2fd2018f Fix Chevron in Forum sometimes losing its Blue Color 2016-08-01 14:35:52 +01:00
Torsten Grote
15d139afd4 Pause Periodic List Refresh when View is not Visible
Closes #553
2016-08-01 14:35:51 +01:00
akwizgran
2577b2ab2a Merge branch '488-show-notifications-for-new-blog-posts' into 'master'
Show notifications for new blog posts

This also adds a setting allowing people to turn blog post notifications off.

As instructed, this does not yet improve upon the current notification mechanism, but rather follows it, leaving the improvements for  #289.

Closes #488

See merge request !258
2016-08-01 12:36:16 +00:00
Torsten Grote
04af39f567 Show notifications for new blog posts
This also adds a setting allowing people to turn blog post notifications off.

Closes #488
2016-08-01 13:21:12 +01:00
Torsten Grote
64b596d0f9 Show Responses to Forum Invitations in Private Conversation
Closes #472
2016-08-01 12:13:51 +01:00
akwizgran
8bbb2184ff Merge branch '415-blog-activity-for-viewing-list-of-blog-posts' into 'master'
Show Personal Blog When Clicking On Post in Combined Blog Feed

This is your own personal blog when clicking on your own posts. Note how you can also write posts from that screen and no trust indicator is shown for the posts:
![device-2016-07-28-164921](/uploads/92993d579e26307ee0c6172cfd67bcd8/device-2016-07-28-164921.png)

This is somebody else's blog on a dedicated screen after clicking on a blog post:
![device-2016-07-28-164949](/uploads/d6c18d5b2ea81fd16b0300ae7b76aac5/device-2016-07-28-164949.png)

Closes #415

See merge request !256
2016-08-01 11:10:08 +00:00
Torsten Grote
bca12bb0e5 Show Personal Blog When Clicking On Post in Combined Blog Feed
Closes #415
2016-08-01 11:26:53 +01:00
akwizgran
32578e2cab Merge branch '535-formatexception-when-loading-contact-list-after-receiving-invitation' into 'master'
Use Client Layer Events in ContactListFragment

This prevents trying to access the same group metadata in different groups.
Also, the conversation does not need to be reloaded once introduction messages arrive.

Closes #535

See merge request !254
2016-08-01 10:21:31 +00:00
akwizgran
0ffbc28792 Validator should call getMessageMetadataForValidator(). 2016-08-01 11:16:22 +01:00
akwizgran
38979ef504 Controllers should depend on ResultHandler not its impl. 2016-07-31 15:21:15 +01:00
akwizgran
5c186db4e4 Fixed a test that was broken by validation changes. 2016-07-31 15:18:14 +01:00
akwizgran
49437522f6 Fixed a test that was broken by my code cleanup. 2016-07-31 14:15:23 +01:00
akwizgran
6511c13752 Merge branch '544-persistentdata-classes-aren-t-thread-safe' into 'master'
Remove PersistentData classes as they aren't thread-safe

This MR depends on !244 and does not claim to resolve *all* issues with the ForumActivity.

Closes #544

See merge request !253
2016-07-30 15:52:19 +00:00
akwizgran
1bfa1016b4 Code cleanup, added FIXMEs for bigger issues. 2016-07-30 16:43:15 +01:00
akwizgran
f3d0ffa09f Merge branch '310-client-layer-events-for-forums' into 'master'
Introduce client layer events for forums

The forum UI depended on sync layer events such as `MessageStateChangedEvent`.
Now, the forum client broadcasts its own high-level event (`ForumPostReceivedEvent`)
with the information the UI needs (`ForumPostHeader`).

Closes #310

See merge request !244
2016-07-30 14:34:17 +00:00
Torsten Grote
d8272d875b Remove ForumPersistentData 2016-07-29 15:36:15 -03:00
Torsten Grote
e782e699fe Remove BlogPersistentData 2016-07-29 15:29:04 -03:00
Torsten Grote
bdb876552d Allow Validator to access metadata for pending messages
Database queries for metadata only returned it for messages that were delivered already.
However, there are cases (e.g. a pending message needs to be delivered) where
the validator needs to retrieve the metadata from the database.

For these cases, a special database query has been introduced.
2016-07-29 15:17:18 -03:00
Torsten Grote
e1bdede4f5 Introduce client layer events for forums
The forum UI depended on sync layer events such as MessageStateChangedEvent.
Now, the forum client broadcasts its own high-level event (`ForumPostReceivedEvent`)
with the information the UI needs (`ForumPostHeader`).

Closes #310
2016-07-29 15:16:52 -03:00
akwizgran
9ff4758683 Merge branch '533-explain-why-forum-can-t-be-shared-with-contact' into 'master'
Explain why forum can't be shared with contact

Closes #533

See merge request !252
2016-07-29 17:33:17 +00:00
akwizgran
fa0639d220 Overlay background colour as an alternative to setAlpha(). 2016-07-29 18:29:14 +01:00
Torsten Grote
cf6aa01905 Remove forum invitations from list instead of reloading
Closes #543
2016-07-28 15:30:48 -03:00
Torsten Grote
3d22d43868 Use Client Layer Events in ContactListFragment
This prevents trying to access the same group metadata in different groups.
Also, the conversation does not need to be reloaded once introduction messages arrive.

Closes #535
2016-07-28 14:30:18 -03:00
Torsten Grote
bbf12ca0c4 Explain why forum can't be shared with contact
Closes #533
2016-07-28 11:21:34 -03:00
Ernir Erlingsson
04d2ede2e1 Merge branch '515-starting-intent-from-preferences-does-not-work-with-different-app-id' into 'master'
Allow different package IDs (for preference intents)

Closes #515

See merge request !248
2016-07-27 19:34:41 +00:00
Torsten Grote
c47171c06e Update translations and expiry date 2016-07-27 15:09:25 -03:00
Torsten Grote
7318aa562e Allow different package IDs (for preference intents)
Closes #515
2016-07-25 13:15:57 -03:00
str4d
ddbac36913 Merge branch '410-my-blogs-tab-with-option-to-add-new-blogs' into 'master'
Micro Blogs UI

**Attention:** This MR includes several other commits which are supposed to end up in separate MRs. I suggest that you review **per commit**. Once the first two commits have green light, I can split out the other commits into other MRs. This way I don't have to work myself through a long rebase chain every time I make a change to the bottom MR.

This MR is full of commits that introduce features that we will not be using initially. The last commit implements the Micro Blogs UI on top of the framework the first commits establish and hides/disables all future features for now.

I suggest we merge this as is and clean things up later when we have a clearer idea what features we will be doing eventually.

![device-2016-06-23-135016](/uploads/600fc7c28c0c6c4a60d8273ffb55f30a/device-2016-06-23-135016.png)
![device-2016-06-22-181934](/uploads/e57cfbc162150bcd01d4683d4164406e/device-2016-06-22-181934.png)
![device-2016-06-23-142422](/uploads/5814f1e13b6d2230f2e4c12a8c5cd599/device-2016-06-23-142422.png)
![device-2016-06-23-142506](/uploads/d3ac268082b98bbcd068f3d6fe0c6712/device-2016-06-23-142506.png)
![device-2016-06-22-181913](/uploads/f5dcc1ed9a40ec5fa8f634864903f4cc/device-2016-06-22-181913.png)

Closes #436 

See merge request !214
2016-07-17 03:35:36 +00:00
str4d
c019d8ecf0 Address review comments 2016-07-17 03:33:25 +00:00
Ernir Erlingsson
c12c60d000 Merge branch '356-make-it-clearer-who-will-be-introduced' into 'master'
Make it clearer who will be introduced

Show contact names under avatars before sending introduction to make it clearer who will be introduced.

![device-2016-07-08-121836](/uploads/de13f6e75b9a573e561e9c810bbdb08b/device-2016-07-08-121836.png)

Closes #356

See merge request !242
2016-07-13 18:47:09 +00:00
str4d
8504cfa88b Re-enable UI if blog post fails to publish 2016-07-13 03:16:59 +00:00
str4d
dd1eed5aa7 Cleanup after review 2016-07-13 03:08:37 +00:00
str4d
39d91e026b Update introduction message text colours 2016-07-12 23:45:36 +00:00
str4d
67aa7c3269 Merge branch '461-forum-invitation-can-not-be-accepted-if-forum-already-added' into 'master'
Show all Forum Invitations, not only the first one to prevent cut-offs and forks

This MR solves the problems outlined in #461 by always showing forum invitations, even if the user already subscribed to the forum.

Available Forums have been renamed to Forum Invitations in the UI:

![device-2016-07-07-144141](/uploads/9c8d06decdd19117250e3faca0c38192/device-2016-07-07-144141.png)
![device-2016-07-07-144150](/uploads/9803f567c962a721b24d79359974a29f/device-2016-07-07-144150.png)

Closes #461

See merge request !241
2016-07-12 23:34:22 +00:00
str4d
85f96d8865 Update forum-exists text 2016-07-12 23:32:48 +00:00
str4d
89469f9d35 Merge branch '459-remove-step-string' into 'master'
Improved the contact addition header

Closes #459

See merge request !245
2016-07-12 12:34:40 +00:00
Ernir Erlingsson
55601bc2c3 removed step string 2016-07-12 12:21:50 +02:00
Ernir Erlingsson
9a4bf598ae Merge branch '346-some-cameras-can-t-focus-on-qr-codes' into 'master'
Set focus mode properly when scanning QR codes

This simple fix contributed by @m8r-v9bo74 fixed the issue on my Xperia
Pro that could never focus on the QR code before. Focusing and scanning
still works on my other test devices.

Closes #346

See merge request !243
2016-07-12 08:37:48 +00:00
str4d
ee68e35b36 Merge branch '360-feedback-for-introducer-when-introduction-request-is-sent' into 'master'
Show Snackbar after introduction request has been sent

Closes #360

See merge request !239
2016-07-12 05:33:09 +00:00
Ernir Erlingsson
8f02cf8307 Merge branch '151-explain-what-account-creation-means-on-first-run' into 'master'
Improve Account Setup Screen

* Explain what "account creation" means on first run (#151)
* Use hints instead of dedicated text views
* Move password strength meter up into the user's view
* Always move user's view to current input field
* Improve "Forgot Password" dialog

![Screenshot_20160627-142116](/uploads/7fadc812f62c5f22f6ba73735d139064/Screenshot_20160627-142116.png)
![Screenshot_20160627-142127](/uploads/da27fb864bbe34168665a51b60747181/Screenshot_20160627-142127.png)
![Screenshot_20160627-142135](/uploads/19ddb247a043f56f9429a98e9655cd9f/Screenshot_20160627-142135.png)
![Screenshot_20160627-142153](/uploads/5d859e029a9584598a5cd6a391e697d3/Screenshot_20160627-142153.png)
![Screenshot_20160627-142204](/uploads/f59a79fc30528a17aece31f2c45d4638/Screenshot_20160627-142204.png)
![Screenshot_20160627-142241](/uploads/a493df940ae69b7ae1eecba598b4d378/Screenshot_20160627-142241.png)

Please note that the dialog button colors will be changed in !214 to the official design. Here they have the old colors.

Closes #151, #207

See merge request !229
2016-07-11 08:36:25 +00:00
Torsten Grote
193cdc42d9 Set focus mode properly when scanning QR codes
This simple fix contributed by @m8r-v9bo74 fixed the issue on my Xperia
Pro that could never focus on the QR code before. Focusing and scanning
still works on my other test devices.

Closes #346
2016-07-08 13:12:32 -03:00
Torsten Grote
91492c3068 Improve Account Setup Screen
* Explain what "account creation" means on first run
* Use hints instead of dedicated text views
* Move password strength meter up into the user's view
* Always move user's view to current input field
* Improve "Forgot Password" dialog

Closes #151
2016-07-08 12:55:04 -03:00
Torsten Grote
412bf162ce Show contact names under avatars before sending introduction
to make it clearer who will be introduced.
2016-07-08 12:39:26 -03:00
Ernir Erlingsson
3a3d717884 Merge branch '327-empty-state-design' into 'master'
Simple Empty State Messages

This MR implements very basic and simple empty state messages for the
current features.

This is how it looks (note that the contact add FAB will be removed soon):

![Screenshot_20160629-125146](/uploads/4c6a8be041cc48b0aba165dd507453d5/Screenshot_20160629-125146.png)
![device-2016-06-29-130834](/uploads/821677074d7d3e6435574a0711f3a0a7/device-2016-06-29-130834.png)
![Screenshot_20160629-125138](/uploads/a39a465db51f8e009ab0b6ee34d4a7e7/Screenshot_20160629-125138.png)
![Screenshot_20160629-125853](/uploads/1dab114bbe7ba379b20a5d298c8fa25c/Screenshot_20160629-125853.png)

Closes #327

See merge request !236
2016-07-08 08:50:10 +00:00
Torsten Grote
6301b2a9a2 Change Available Forums into Forum Invitations 2016-07-07 14:48:28 -03:00
Torsten Grote
c577efacbe Show all Forum Invitations, not only the first 2016-07-07 14:48:28 -03:00
Torsten Grote
fa5304c145 Add tests to ensure Forum Posts are synchronized both ways
even after re-sharing an existing forum.
2016-07-07 14:48:06 -03:00
Torsten Grote
f0a784b4af Merge branch '449-contact-fab' into 'master'
Removed the Fab and moved the icon into the toolbar

Closes #449

See merge request !240
2016-07-07 14:09:22 +00:00
Ernir Erlingsson
b2b97f31f3 Removed the Fab and moved the icon into the toolbar 2016-07-07 15:40:44 +02:00
Ernir Erlingsson
e9789435cc Merge branch '452-hide-identities-initially' into 'master'
Hide Identity Selector When Adding Contact

Closes #452

See merge request !233
2016-07-06 20:29:18 +00:00
Ernir Erlingsson
ba86690ce0 Merge branch '455-update-timestamps-of-messages-every-minute' into 'master'
Update Timestamps Every Minute

Yes by using `notifyDataSetChanged()` I am invalidating everything, but view binding is very fast and the RecyclerView is smart about it. I could parse the dataset and use `notifyItemChanged()` only on the elements that matter, but this is not generic and a lot more code which is not necessarily faster. I suggest we go with my simple and generic approach for now and optimize when we actually notice a performance problem.

Closes #455

See merge request !238
2016-07-06 20:25:35 +00:00
Torsten Grote
db2d965006 Show Snackbar after introduction request has been sent
Closes #360
2016-07-06 13:58:20 -03:00
Torsten Grote
b99650b070 Hide Identity Selector When Adding Contact
Closes #452
2016-07-06 13:09:41 -03:00
Torsten Grote
bc0b226fff Update Timestamps Every Minute
Closes #455
2016-07-06 11:33:25 -03:00
Ernir Erlingsson
3ae3fdab63 Merge branch '450-blog-client-unit-tests' into 'master'
Blog Client Unit and Integration Tests

Closes #450

See merge request !230
2016-07-06 09:55:16 +00:00
Torsten Grote
d8b5710a42 Blog Feed: Show 'Scroll To' link only if scrolling possible 2016-07-04 16:28:57 -03:00
Torsten Grote
fd7278b488 Combined Blog Feed
This commit addes a combined blog feed that shows all posts of all
subscribed blogs in the order the blog posts have been received.

For now, this commit also hides other blog functionality like adding
additional blogs and browsing individual blogs.

Closes #417
2016-07-04 14:37:23 -03:00
Torsten Grote
e0d2d09bdd UI for Deleting a Blog
Closes #418
2016-07-04 14:37:22 -03:00
Torsten Grote
761525ad85 Extend BlogActivity to also show individual posts
This allows for swiping left/right to read other posts by using
a ViewPager.

This hasn't been done as a separate activity, but with
fragments, so both can share the `BlogPersistentData` without
needing to reload it.

Closes #428
2016-07-04 14:35:09 -03:00
Torsten Grote
f7d5c1f63c Add an activity to write blog posts
Closes #411
2016-07-04 14:35:09 -03:00
Torsten Grote
365fbb45ad Add a BlogActivity that shows a list of blog posts
This commit lays the groundwork for #415
2016-07-04 14:35:08 -03:00
Torsten Grote
d05237d2c1 My Blogs tab: Show all blogs the user created
This does not yet support multiple identities. It just shows blogs
created by the first identity, but can easily be adapted for
multi-identity support.

Closes #410
2016-07-04 14:35:08 -03:00
Torsten Grote
4c4f4ad2d5 Add a My Blogs tab with option to add new blogs
Clicking the plus in the toolbar open the `CreateBlogActivity` which
allows the user to create a new blog. Only the first identity is
considered, but support for more identities can be easily added later.

The actual list of blogs in the My Blogs tab will be done in the next
commit.
2016-07-04 14:35:07 -03:00
Torsten Grote
37a5d884b8 Simple Empty State Messages
This implements very basic and simple empty state messages for the
current features.

Closes #327
2016-07-04 14:15:52 -03:00
str4d
759b1c7448 Merge branch '333-font-color' into 'master'
Font Colors and Separate Themes

Once applied this commit will change the font colors according to the
design and move all themes into a dedicated file.

Closes #333

See merge request !228
2016-07-03 00:07:03 +00:00
Ernir Erlingsson
57ce7e3f63 Merge branch '397-remove-unused-java-layout-helpers' into 'master'
Remove unused Java layout helpers

Closes #397

See merge request !232
2016-07-01 13:13:16 +00:00
Torsten Grote
f84bba5d79 Remove unused Java layout helpers
Closes #397
2016-06-30 12:03:12 -03:00
Torsten Grote
bb6e249980 Merge branch '230-make-timestamps-prettier-and-more-useful' into 'master'
Make timestamps prettier and more useful

Here's some example timestamps I have been testing with. That's how it will look like when this MR is merged:

![device-2016-06-28-184748](/uploads/c082ac0f54b50c27f9a1c5ef8865998b/device-2016-06-28-184748.png)

Closes #230

See merge request !235
2016-06-30 14:16:07 +00:00
Torsten Grote
d8df9c9955 Make timestamps prettier and more useful 2016-06-30 11:14:12 -03:00
Ernir Erlingsson
ebe80c773d Merge branch '326-trim-leading-and-trailing-whitespace-when-displaying-messages' into 'master'
Trim leading and trailing whitespace when displaying messages

Closes #326

See merge request !234
2016-06-29 21:24:37 +00:00
Torsten Grote
123f59cd96 Trim leading and trailing whitespace when displaying messages
Closes #326
2016-06-28 17:01:41 -03:00
Torsten Grote
f7965edc71 Add Blog Manager Integration Test 2016-06-28 14:43:55 -03:00
Torsten Grote
66a1f85859 Font Colors and Separate Themes
Once applied this commit will change the font colors according to the
design and move all themes into a dedicated file.

Closes #333
2016-06-28 12:16:57 -03:00
Torsten Grote
7a9290e3a6 Blog Client Unit Tests
Closes #450
2016-06-27 18:04:19 -03:00
Torsten Grote
f270624f39 Merge branch '365-contact-exchange-protocol' into 'master'
Deduplicate contact exchange protocol

`ContactExchangeTask` was originally extracted from the Bluetooth invitation task; this completes the refactoring.

Closes #365.

See merge request !199
2016-06-27 16:06:38 +00:00
Torsten Grote
94927c2f60 Bumped expiry date to 1 August 2016. 2016-06-27 11:39:43 -03:00
Torsten Grote
ecbf5621f2 Merge branch '448-make-use-of-existing-translations' into 'master'
Make use of Existing Translations

Adds first translations to source code and sets up transifex config
file. Pull more translations later with:

```bash
 cd briar-android
 tx pull --mode=developer
```
Closes #448

![device-2016-06-23-145337](/uploads/14c557adf185dce516ca94295b4db965/device-2016-06-23-145337.png)

See merge request !226
2016-06-27 14:35:04 +00:00
Torsten Grote
4d3a333915 Make use of Existing Translations
Adds first translations to source code and sets up transifex config
file. Pull more translations later with:

 cd briar-android
 tx pull --mode=developer

Closes #448
2016-06-27 11:31:42 -03:00
Ernir Erlingsson
9ac1a13711 Merge branch '442-author-s-identicon-nickname-and-status-are-separated-in-forum-post-layout' into 'master'
Separate Date and Author Name in Forum Posts

This also fixes the issue there the trust indicator was shown at the top on some devices.

![device-2016-06-23-152315](/uploads/62786502942bbccadf809fedd72cedd1/device-2016-06-23-152315.png)

Closes #442

See merge request !227
2016-06-27 10:09:54 +00:00
Ernir Erlingsson
946d7cb3e7 Merge branch '446-addidentityhook-sometimes-not-run-for-first-identity' into 'master'
Fix IdentityManager hooks

This commit makes sure that there is only one identity manager that is
initialized early enough so hooks can be added properly.

Closes #446

See merge request !225
2016-06-27 10:00:31 +00:00
str4d
b71a303bf8 Deduplicate contact exchange protocol
ContactExchangeTask was originally extracted from the Bluetooth invitation
task; this completes the refactoring.
2016-06-25 13:41:58 +12:00
Torsten Grote
a9996b4fb1 Separate Date and Author Name in Forum Posts
Closes #442
2016-06-23 15:24:21 -03:00
Torsten Grote
9c2250277b Fix IdentityManager hooks
This commit makes sure that there is only one identity manager that is
initialized early enough so hooks can be added properly.

Closes #446
2016-06-23 14:04:25 -03:00
Torsten Grote
4176f592df Merge branch '436-automatic-personal-blogs-backend' into 'master'
Backend for Automatic Micro Blogs

This MR introduces automatic personal blogs to the Blog client. When a contact is added, her personal blog will also be added automatically. Also, when a new identity is added, a personal blog for that identity is created.

The first commit changes the blog paradigm to short-form blogs and introduces other things that will be useful later in the UI (!214) such as a BlogPostAdded event and the possibility to delete/remove blogs (not the personal ones).

This MR is based on !224 to prevent crashes that are fixed by it. So please review and merge !224 first.

See merge request !223
2016-06-23 15:05:46 +00:00
Torsten Grote
91aa81041e Store and expose time a blog post was received
This is useful when sorting blog posts in the combined feed. It ensures
you do not miss older posts that were just synced to you.
2016-06-23 11:58:25 -03:00
Torsten Grote
a8f51fcb8a Backend for Automatic Personal Blogs
When a contact is added, her personal blog will also be added automatically.
Also, when a new identity is added, a personal blog for that identity is created.

Part of #436
2016-06-23 11:58:25 -03:00
Torsten Grote
30fe9f6e2a Change Blog Paradigm to Short-Form
Removes teaser and makes body mandatory.

It also adds support for deleting blogs and
introduces a getAuthorStatus() method to the IdentityManager
that takes a running transaction.
2016-06-23 10:47:44 -03:00
str4d
5a9615265e Merge branch '441-group-descriptor-can-be-too-long-causes-crash' into 'master'
Remove MAX_GROUP_DESCRIPTOR_LENGTH

Closes #441

See merge request !224
2016-06-23 09:27:48 +00:00
Torsten Grote
59320f02b7 Remove MAX_GROUP_DESCRIPTOR_LENGTH
Closes #441
2016-06-22 11:47:38 -03:00
Torsten Grote
3e4be038f2 Merge branch '426-forum-improvements' into 'master'
Forum improvements

Forum Activity improvements:

* Orientation changes now restore the activity properly, e.g. input text and state is retained
* Snack bar is now, when appropriate, clickable
* The bottom divider is no longer visible for the bottom entry
* Code refactoring for improved simplicity and less redundancy
* Timestamp check to ensure that new posts are not older than the latest post

Closes #426 
Closes #423 
Closes #424 

See merge request !218
2016-06-22 14:45:44 +00:00
Ernir Erlingsson
a2a5b746c5 Forum improvements 2016-06-22 13:50:12 +02:00
Torsten Grote
08cc5500ef Merge branch 'nav-drawer-instance-restore-fix' into 'master'
Fixing fragment instance restore

Alas, it turns out that my neat way of integrating the Fragments into the dependency graph was not without problems. Me and @grote discovered that this presented us with a lot of problems on orientation changes as the Activity is re-created, and therefore parts of the dependency graph. The simplest solution was simply to abandon the idea, i.e. with this branch Fragments are no longer part of the dependency graph. 

See merge request !215
2016-06-21 13:59:56 +00:00
Torsten Grote
ee0c4c07a7 Merge branch '354-private-chat-input-field' into 'master'
synched conversation and forum input

Closes #354

See merge request !219
2016-06-21 12:10:35 +00:00
Ernir Erlingsson
ac8c1c0eee synched conversation and forum input 2016-06-21 13:47:33 +02:00
Ernir Erlingsson
8a29207bd0 Fixing fragment instance restore 2016-06-20 21:56:50 +02:00
Torsten Grote
192ee41600 Merge branch '403-blog-sharing-client' into 'master'
Implement Blog Sharing Client

Closes #403

See merge request !220
2016-06-20 17:16:45 +00:00
str4d
13e3eec6b3 Implement BlogSharingManager 2016-06-18 19:02:52 +12:00
str4d
9ae64124d3 Factor out generic sharing code from ForumSharingManger 2016-06-18 19:02:48 +12:00
Ernir Erlingsson
5df2776dc2 Merge branch '78-fix-test' into 'master'
Fix test broken by #78



See merge request !221
2016-06-17 08:31:35 +00:00
str4d
19fdf3ffd0 Fix test broken by #78 2016-06-17 04:48:13 +00:00
Ernir Erlingsson
e7dce02709 Merge branch '402-blog-client-implementation' into 'master'
Blog Client with Factories and Validator

This implements a simple initial blog client that covers the basic blog actions, but no deletion/removal of blogs, yet.

Classes for Blogs and Blog Post Headers have been introduced along with the associated factories.

A `BlogPostValidator` has been added that validates incoming blog posts.

Closes #402
Closes #404

See merge request !212
2016-06-15 20:26:35 +00:00
Ernir Erlingsson
f823b8ba4c Merge branch '78-trust-indicators' into '402-blog-client-implementation'
New Trust Level Indicator Replaces The Stars

This implements a generic `TrustIndicatorView` with a `setTrustLevel()`
method which updates the drawable according to the `Author.State`.

It also removes unused files from the repo.

This is based on !212 and should only be merged after it.

Closes #78

See merge request !217
2016-06-15 20:17:59 +00:00
Torsten Grote
dc048187f5 New Trust Level Indicator Replaces The Stars
This implements a generic `TrustIndicatorView` with a `setTrustLevel()`
method which updates the drawable according to the `Author.State`.

Closes #78
2016-06-15 12:41:43 -03:00
Torsten Grote
da68ef78f1 Blog Client with Factory and Validator
This implements a simple initial blog client that covers the basic blog
actions, but no deletion/removal of blogs, yet.

Classes for Blogs and Blog Post Headers have been introduced along with
the associated factories.

A `BlogPostValidator` has been added that validates incoming blog posts.

Closes #402
Closes #404
2016-06-15 11:16:28 -03:00
Torsten Grote
bbed673150 Merge branch '433-forum-persistance' into 'master'
fix persistance

Closes #433

See merge request !216
2016-06-15 14:11:42 +00:00
Ernir Erlingsson
69b0bec033 fix persistance 2016-06-14 23:53:05 +02:00
str4d
a11e30c2b3 Merge branch '390-change-password' into 'master'
Add a UI for changing the password

Closes #390

See merge request !213
2016-06-11 22:51:24 +00:00
str4d
c5708ee3ce Add a UI for changing the password 2016-06-11 22:49:45 +00:00
Torsten Grote
e96838e731 Merge branch '430-npe-in-forumsharingstatusactivity' into 'master'
Fix NPE in ForumSharingStatusActivity by only accessing group in contact list

Only access group in contact list where it is guaranteed to exist.

Closes #430

See merge request !211
2016-06-08 13:49:09 +00:00
Torsten Grote
6697b06530 Fix NPE in ForumSharingStatusActivity
by checking if a group ID exists.

Closes #430
2016-06-08 10:47:47 -03:00
Torsten Grote
1bb17a3979 Merge branch '309-client-layer-events-for-messaging' into 'master'
Client layer events for messaging

Adds and uses a new `PrivateMessageReceivedEvent` and eliminate the need for an event for adding local messages. Both done in separate commits.

This addresses part of #309

See merge request !208
2016-06-08 13:37:34 +00:00
Torsten Grote
9d826631e9 Add private message to list right away, so eliminate need for an event 2016-06-08 10:31:26 -03:00
Torsten Grote
b26acdf228 Introduce a PrivateMessageReceivedEvent and use it in the Android app 2016-06-08 10:31:26 -03:00
Torsten Grote
69fba1aa17 Merge branch '388-forum-sharing-race-condition' into 'master'
Address Race-Condition in Forum Sharing

When Two Contacts Share Same Forum with each other at the same time a race condition causes them both to delete each other's invitation. This is solved by an Alice/Bob test as suggested in #388.

See merge request !205
2016-06-08 13:29:12 +00:00
Torsten Grote
1a1dd80810 Merge branch '408-forum-list-unread-posts-badges' into 'master'
Adds badges to the forum list that indicate unread posts

This MR adds  badges to the forum list that indicate unread posts. It does so by extending the compound view `TextAvatarView` and provides convenient setters that take care of the required UI changes. The new badge can also be used to indicate a problem with the forum.

![device-2016-06-02-134048](/uploads/133f365f5654be304f590a4f5b667d06/device-2016-06-02-134048.png)![device-2016-06-02-134453](/uploads/423a88f6306a558828181f0c539aa1cb/device-2016-06-02-134453.png)

I decided not to check if the forum is shared from someone or with someone and indicate a problem in this case, because this requires iterating two times over all contacts and their group metadata for each forum. If someone considers it important to check for this information, we can create a ticket for doing this within the forum and not in the forum list.

See merge request !207
2016-06-07 14:36:42 +00:00
Ernir Erlingsson
02f432c04e Merge branch '409-blog-fragment-in-navigation-drawer-with-tabs' into 'master'
Blog Fragment in Navigation Drawer with Tabs

This replaces the custom layouts in the navigation drawer with a
`NavigationView` and adds a menu entry for Blogs.

A Main Blogs fragment is added that holds a `TabLayout` and a
`ViewPager`. Five tabs are already added, but they just have a single
placeholder fragment that is to be replaced by the actual fragments.

Please note that the header in the navigation drawer is just provisional. I am sure @Megalox can design a better one.

![device-2016-06-02-191101](/uploads/ddffee792f67fad01158d7adc7ca904d/device-2016-06-02-191101.png)
![device-2016-06-02-191048](/uploads/a5e6def118646a02c6bcbf17e0398484/device-2016-06-02-191048.png)

Closes #409

See merge request !210
2016-06-06 09:48:08 +00:00
Torsten Grote
3f838b0472 Blog Fragment in Navigation Drawer with Tabs
This replaces the custom layouts in the navigation drawer with a
`NavigationView` and adds a menu entry for Blogs.

A Main Blogs fragment is added that holds a `TabLayout` and a
`ViewPager`. Five tabs are already added, but they just have a single
placeholder fragment that is to be replaced by the actual fragments.

Closes #409
2016-06-03 13:51:31 -03:00
Torsten Grote
5d06f42000 This commit adds badges to the forum list that indicate unread posts.
It does so by extending the compound view `TextAvatarView` and provides
convienient setters that take care of the required UI changes.
The new badge can also be used to indicate a problem with the forum.

Closes #408
2016-06-03 12:44:03 -03:00
Torsten Grote
4acb59b22a Address Race-Condition when Two Contacts Share Same Forum
with each other at the same time.

Closes #388
2016-06-02 14:02:32 -03:00
str4d
bba7083660 Merge branch '422-forum-subtree-duplicates' into 'master'
fixed sub-tree duplicate bug

Closes #422

See merge request !206
2016-06-02 00:27:08 +00:00
Ernir Erlingsson
e3fc015ec3 fixed sub-tree duplicate bug and also wrong reply count 2016-06-01 23:32:19 +02:00
Ernir Erlingsson
441fce8500 fixed forum crash bug 2016-05-31 23:12:33 +02:00
Ernir Erlingsson
a58fb72ab1 Merge branch '122-threaded-discussion-ui' into 'master'
122 threaded discussions

This branch contains the complete code for the nested forums (UI & back-end).

* This branch has an optional randomized set of dummy test data, uncomment one line in ForumActivity.java and then open up any forum.


See merge request !201
2016-05-31 16:06:22 +00:00
Ernir Erlingsson
86039b81c0 Forum, nested discussions front end UI/UX, rev 2 2016-05-30 23:57:01 +02:00
str4d
661140f623 Merge branch '382-message-dependencies-2' into 'master'
Message Dependencies

This MR adds a new table to the database to hold message dependencies.
It introduces two more message states  (pending and delivered) and completely changes the validation and message delivery logic.

Since this is a **very invasive** change, please **review carefully**. It is better to catch issues now than having to debug things later. If you notice an area without tests, please let me know. I tried to have tests for all changes.

Unfortunately, this MR turned out rather large, but most of it are actually tests and you can review one commit after the other without needing to see the full changelog.

In order to reflect the new states, things that were previously true for `VALID` messages have been changed to now be true for `DELIVERED` messages. This might have changed the semantics in some places and can have unindented side-effects.

The `DatabaseComponent` was extended with methods for:
* adding dependencies
* getting dependencies and states of a message
* getting messages that depend on a message (dependents) and their states
* getting messages to be delivered (by startup hook)
* getting pending messages to be possibly delivered (by startup hook)

The `valid` column in the database was renamed to `state` along with the associated methods to better reflect its new extended meaning.

Since pending messages should not be available to clients, many database queries have been modified to only return results for delivered messages. I might have missed some. Please check carefully. Also you might want to think about how you could create arbitrarily large transactions by sending malicious messages.

Please note that the database version was bumped in this MR.

Closes #382

See merge request !198
2016-05-28 00:20:39 +00:00
str4d
19b6afa69f Move new methods in Database interface to match existing alphabetic sorting 2016-05-28 00:17:17 +00:00
str4d
7ac7fae30e Update comments 2016-05-28 00:16:24 +00:00
Torsten Grote
d3b83a50a6 Let the ForumValidator return parent posts as dependency
and add integration tests that make sure that dependencies are handled
properly.
2016-05-26 13:49:59 -03:00
Torsten Grote
5561532c5d Implement new message validation logic
that handles message dependencies reported from clients.

The MessageValidatedEvent has been renamed into a MessageDeliveredEvent
since there were no real use cases for the former any more.
2016-05-26 13:49:59 -03:00
Torsten Grote
b03d0a206b Add Message Dependencies to Database
This adds a new table to the database to hold message dependencies.
It introduces two more message states: pending and delivered
The valid column in the database was renamed to state to better reflect
its new extended meaning.

The DatabaseComponent was extended with three methods for:
* adding dependencies
* getting dependencies of a message
* getting messages that depend on a message (dependents)
* getting messages to be delivered (by startup hook)
* getting pending messages to be possibly delivered (by startup hook)

In order to reflect the new states, things that were previously true for
VALID messages have been changed to now be true for DELIVERED messages.

Since pending messages should not be available to clients, many database
queries have been modified to only return results for delivered
messages.

All added methods and changes should come with updated unit tests.

Please note that the database version was bumped in this commit.
2016-05-26 13:49:03 -03:00
Ernir Erlingsson
512940e82b Merge branch '393-message-tree' into 'master'
Sort threaded messages generic

Constructed a generic that we can use to sort threaded messages.

Closes #393

See merge request !203
2016-05-26 11:13:06 +00:00
Ernir Erlingsson
d2ba7c9b7f generic sorted message tree 2016-05-25 22:12:20 +02:00
Torsten Grote
a652f1a5d7 Merge branch '122-forum-manager' into 'master'
added parent id to metadata and a unit test

The parent id, a necessary attribute for nested forums, was not being added to the metadata in the forum manager. Additionally, a simple forum manager unit was created.

See merge request !202
2016-05-24 18:13:15 +00:00
Ernir Erlingsson
21b237a629 ForumManager: Added parent id to metadata and a unit test 2016-05-24 15:12:37 -03:00
Torsten Grote
2a7990f5c4 Merge branch '334-nav-menu-button-crash' into 'master'
android.support.v7.widget.AppCompatButton -> Button to use AppCompat inflater

Fixes the following crash that occurs after upgrading to support 23.3.0:
https://code.google.com/p/android/issues/detail?id=174871

Closes #334.

See merge request !200
2016-05-20 14:12:11 +00:00
str4d
92d3e02c82 android.support.v7.widget.AppCompatButton -> Button to use AppCompat inflater
Fixes the following crash that occurs after upgrading to support 23.3.0:
https://code.google.com/p/android/issues/detail?id=174871
2016-05-20 03:30:10 +00:00
1751 changed files with 80969 additions and 32296 deletions

7
.gitignore vendored
View File

@@ -9,15 +9,18 @@ Thumbs.db
.DS_Store
# Eclipse project files
#.classpath
#.project
.classpath
.project
.settings
# Local configuration file (sdk path, etc)
local.properties
# Android Studio
.idea/*
!.idea/runConfigurations/
!.idea/codeStyleSettings.xml
.gradle
build/
*.iml
projectFilesBackup/

20
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,20 @@
image: registry.gitlab.com/fdroid/ci-images-base:latest
cache:
paths:
- .gradle/wrapper
- .gradle/caches
before_script:
- export GRADLE_USER_HOME=$PWD/.gradle
# - export ANDROID_COMPILE_SDK=`sed -n 's,.*compileSdkVersion\s*\([0-9][0-9]*\).*,\1,p' app/build.gradle`
# - echo y | android --silent update sdk --no-ui --filter android-${ANDROID_COMPILE_SDK}
test:
script:
- ./gradlew test
after_script:
# this file changes every time but should not be cached
- rm -f $GRADLE_USER_HOME/caches/modules-2/modules-2.lock
- rm -fr $GRADLE_USER_HOME/caches/*/plugin-resolution/

View File

@@ -31,6 +31,8 @@
</value>
</option>
<option name="RIGHT_MARGIN" value="100" />
<option name="JD_ALIGN_PARAM_COMMENTS" value="false" />
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false" />
<AndroidXmlCodeStyleSettings>
<option name="USE_CUSTOM_SETTINGS" value="true" />
</AndroidXmlCodeStyleSettings>
@@ -68,6 +70,12 @@
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
</XML>
<codeStyleSettings language="Groovy">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true" />
<option name="SMART_TABS" value="true" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="RIGHT_MARGIN" value="80" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />

28
.idea/runConfigurations/All_tests.xml generated Normal file
View File

@@ -0,0 +1,28 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests" 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" />
<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$/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>
<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 briar-core" run_configuration_type="AndroidJUnit" />
</method>
</configuration>
</component>

View File

@@ -0,0 +1,23 @@
<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" />
<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-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>
</component>

View File

@@ -0,0 +1,23 @@
<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" />
<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-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>
</component>

View File

@@ -0,0 +1,23 @@
<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" />
<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 -Djava.library.path=libs" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-j2se" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method />
</configuration>
</component>

View File

@@ -0,0 +1,23 @@
<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" />
<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$/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>
</component>

View File

@@ -0,0 +1,23 @@
<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" />
<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$/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>
</component>

View File

@@ -13,23 +13,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-------------------------------------------------------------------------
All files under the directories briar-android/src, briar-api/src,
briar-core/src, briar-desktop/src and briar-test/src are licensed
under the Apache License, version 2.0 (the "License"); you may not
use these files except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the License for the specific language governing
permissions and limitations under the License.
-------------------------------------------------------------------------
GNU GENERAL PUBLIC LICENSE

View File

@@ -1,5 +1,5 @@
bin
gen
build
local.properties
.settings
src/main/res/raw/*.zip

View File

@@ -0,0 +1,104 @@
import de.undercouch.gradle.tasks.download.Download
import de.undercouch.gradle.tasks.download.Verify
apply plugin: 'com.android.library'
apply plugin: 'witness'
apply plugin: 'de.undercouch.download'
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
versionCode 14
versionName "0.14"
consumerProguardFiles 'proguard-rules.txt'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
dependencies {
compile project(':bramble-core')
compile fileTree(dir: 'libs', include: '*.jar')
provided 'javax.annotation:jsr250-api:1.0'
}
def torBinaryDir = 'src/main/res/raw'
task downloadTorGeoIp(type: Download) {
src 'https://briarproject.org/build/geoip-2017-05-02.zip'
dest "$torBinaryDir/geoip.zip"
onlyIfNewer true
}
task downloadTorBinaryArm(type: Download) {
src 'https://briarproject.org/build/tor-0.2.9.11-arm.zip'
dest "$torBinaryDir/tor_arm.zip"
onlyIfNewer true
}
task downloadTorBinaryArmPie(type: Download) {
src 'https://briarproject.org/build/tor-0.2.9.11-arm-pie.zip'
dest "$torBinaryDir/tor_arm_pie.zip"
onlyIfNewer true
}
task downloadTorBinaryX86(type: Download) {
src 'https://briarproject.org/build/tor-0.2.9.11-x86.zip'
dest "$torBinaryDir/tor_x86.zip"
onlyIfNewer true
}
task downloadTorBinaryX86Pie(type: Download) {
src 'https://briarproject.org/build/tor-0.2.9.11-x86-pie.zip'
dest "$torBinaryDir/tor_x86_pie.zip"
onlyIfNewer true
}
task verifyTorGeoIp(type: Verify, dependsOn: 'downloadTorGeoIp') {
src "$torBinaryDir/geoip.zip"
algorithm 'SHA-256'
checksum '51f4d1272fb867e1f3b36b67a584e2a33c40b40f62305457d799fd399cd77c9b'
}
task verifyTorBinaryArm(type: Verify, dependsOn: 'downloadTorBinaryArm') {
src "$torBinaryDir/tor_arm.zip"
algorithm 'SHA-256'
checksum '1da6008663a8ad98b349e62acbbf42c379f65ec504fa467cb119c187cd5a4c6b'
}
task verifyTorBinaryArmPie(type: Verify, dependsOn: 'downloadTorBinaryArmPie') {
src "$torBinaryDir/tor_arm_pie.zip"
algorithm 'SHA-256'
checksum 'eb061f880829e05f104690ac744848133f2dacef04759d425a2cff0df32c271e'
}
task verifyTorBinaryX86(type: Verify, dependsOn: 'downloadTorBinaryX86') {
src "$torBinaryDir/tor_x86.zip"
algorithm 'SHA-256'
checksum 'f5308aff8303daca082f82227d02b51ddedba4ab1d1420739ada0427ae5dbb41'
}
task verifyTorBinaryX86Pie(type: Verify, dependsOn: 'downloadTorBinaryX86Pie') {
src "$torBinaryDir/tor_x86_pie.zip"
algorithm 'SHA-256'
checksum '889a6c81ac73d05d35ed610ca5a913cee44d333e4ae1749c2a107f2f7dd8197b'
}
project.afterEvaluate {
preBuild.dependsOn {
[
'verifyTorGeoIp',
'verifyTorBinaryArm',
'verifyTorBinaryArmPie',
'verifyTorBinaryX86',
'verifyTorBinaryX86Pie'
]
}
}

Binary file not shown.

View File

@@ -0,0 +1,15 @@
-keep,includedescriptorclasses class org.briarproject.** { *; }
-keep class org.h2.** { *; }
-dontwarn org.h2.**
-dontnote org.h2.**
-keep class dagger.** { *; }
-dontwarn dagger.**
-dontnote dagger.**
-dontwarn sun.misc.Unsafe
-dontnote com.google.common.**
# UPnP library isn't used
-dontwarn org.bitlet.weupnp.**

View File

@@ -0,0 +1,24 @@
<manifest
package="org.briarproject.bramble"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-feature android:name="android.hardware.bluetooth"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_LOGS"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<!-- Since API 23, this is needed to add contacts via Bluetooth -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application
android:allowBackup="false"
android:label="@string/app_name"
android:supportsRtl="true">
</application>
</manifest>

View File

@@ -0,0 +1,13 @@
package org.briarproject.bramble;
import org.briarproject.bramble.plugin.AndroidPluginModule;
import org.briarproject.bramble.system.AndroidSystemModule;
import dagger.Module;
@Module(includes = {
AndroidPluginModule.class,
AndroidSystemModule.class
})
public class BrambleAndroidModule {
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.android.api;
package org.briarproject.bramble.api.system;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
@@ -13,10 +13,21 @@ public interface AndroidExecutor {
* Runs the given task on a background thread with a message queue and
* returns a Future for getting the result.
*/
<V> Future<V> submit(Callable<V> c);
<V> Future<V> runOnBackgroundThread(Callable<V> c);
/**
* Runs the given task on a background thread with a message queue.
*/
void execute(Runnable r);
void runOnBackgroundThread(Runnable r);
/**
* Runs the given task on the main UI thread and returns a Future for
* getting the result.
*/
<V> Future<V> runOnUiThread(Callable<V> c);
/**
* Runs the given task on the main UI thread.
*/
void runOnUiThread(Runnable r);
}

View File

@@ -0,0 +1,65 @@
package org.briarproject.bramble.plugin;
import android.app.Application;
import android.content.Context;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginConfig;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
import org.briarproject.bramble.api.reporting.DevReporter;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.plugin.droidtooth.DroidtoothPluginFactory;
import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory;
import org.briarproject.bramble.plugin.tor.TorPluginFactory;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.Executor;
import javax.net.SocketFactory;
import dagger.Module;
import dagger.Provides;
@Module
public class AndroidPluginModule {
@Provides
PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor,
AndroidExecutor androidExecutor, SecureRandom random,
SocketFactory torSocketFactory, BackoffFactory backoffFactory,
Application app, LocationUtils locationUtils, DevReporter reporter,
EventBus eventBus) {
Context appContext = app.getApplicationContext();
DuplexPluginFactory bluetooth = new DroidtoothPluginFactory(ioExecutor,
androidExecutor, appContext, random, backoffFactory);
DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, appContext,
locationUtils, reporter, eventBus, torSocketFactory,
backoffFactory);
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
backoffFactory, appContext);
final Collection<DuplexPluginFactory> duplex =
Arrays.asList(bluetooth, tor, lan);
@NotNullByDefault
PluginConfig pluginConfig = new PluginConfig() {
@Override
public Collection<DuplexPluginFactory> getDuplexFactories() {
return duplex;
}
@Override
public Collection<SimplexPluginFactory> getSimplexFactories() {
return Collections.emptyList();
}
};
return pluginConfig;
}
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.plugins.droidtooth;
package org.briarproject.bramble.plugin.droidtooth;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -9,21 +9,26 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import org.briarproject.android.api.AndroidExecutor;
import org.briarproject.android.util.AndroidUtils;
import org.briarproject.api.TransportId;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.crypto.PseudoRandom;
import org.briarproject.api.keyagreement.KeyAgreementConnection;
import org.briarproject.api.keyagreement.KeyAgreementListener;
import org.briarproject.api.keyagreement.TransportDescriptor;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
import org.briarproject.api.properties.TransportProperties;
import org.briarproject.util.StringUtils;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.crypto.PseudoRandom;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
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.PluginException;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.util.AndroidUtils;
import org.briarproject.bramble.util.StringUtils;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.security.SecureRandom;
@@ -36,6 +41,7 @@ import java.util.Map.Entry;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
@@ -44,6 +50,8 @@ import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import javax.annotation.Nullable;
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;
@@ -57,23 +65,25 @@ 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.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PREF_BT_ENABLE;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_ADDRESS;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_UUID;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.UUID_BYTES;
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class DroidtoothPlugin implements DuplexPlugin {
// Share an ID with the J2SE Bluetooth plugin
static final TransportId ID = new TransportId("bt");
private static final Logger LOG =
Logger.getLogger(DroidtoothPlugin.class.getName());
private static final int UUID_BYTES = 16;
private static final String FOUND =
"android.bluetooth.device.action.FOUND";
private static final String DISCOVERY_FINISHED =
"android.bluetooth.adapter.action.DISCOVERY_FINISHED";
private static final String PROP_ADDRESS = "address";
private static final String PROP_UUID = "uuid";
private final Executor ioExecutor;
private final AndroidExecutor androidExecutor;
private final Context appContext;
@@ -120,26 +130,28 @@ class DroidtoothPlugin implements DuplexPlugin {
}
@Override
public boolean start() throws IOException {
public void start() throws PluginException {
if (used.getAndSet(true)) throw new IllegalStateException();
// BluetoothAdapter.getDefaultAdapter() must be called on a thread
// with a message queue, so submit it to the AndroidExecutor
try {
adapter = androidExecutor.submit(new Callable<BluetoothAdapter>() {
@Override
public BluetoothAdapter call() throws Exception {
return BluetoothAdapter.getDefaultAdapter();
}
}).get();
adapter = androidExecutor.runOnBackgroundThread(
new Callable<BluetoothAdapter>() {
@Override
public BluetoothAdapter call() throws Exception {
return BluetoothAdapter.getDefaultAdapter();
}
}).get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("Interrupted while getting BluetoothAdapter");
LOG.warning("Interrupted while getting BluetoothAdapter");
throw new PluginException(e);
} catch (ExecutionException e) {
throw new IOException(e);
throw new PluginException(e);
}
if (adapter == null) {
LOG.info("Bluetooth is not supported");
return false;
throw new PluginException();
}
running = true;
// Listen for changes to the Bluetooth state
@@ -153,7 +165,7 @@ class DroidtoothPlugin implements DuplexPlugin {
bind();
} else {
// Enable Bluetooth if settings allow
if (callback.getSettings().getBoolean("enable", false)) {
if (callback.getSettings().getBoolean(PREF_BT_ENABLE, false)) {
wasEnabledByUs = true;
if (adapter.enable()) LOG.info("Enabling Bluetooth");
else LOG.info("Could not enable Bluetooth");
@@ -161,7 +173,6 @@ class DroidtoothPlugin implements DuplexPlugin {
LOG.info("Not enabling Bluetooth");
}
}
return true;
}
private void bind() {
@@ -172,7 +183,7 @@ class DroidtoothPlugin implements DuplexPlugin {
String address = AndroidUtils.getBluetoothAddress(appContext,
adapter);
if (LOG.isLoggable(INFO))
LOG.info("Local address " + address);
LOG.info("Local address " + scrubMacAddress(address));
if (!StringUtils.isNullOrEmpty(address)) {
// Advertise the Bluetooth address to contacts
TransportProperties p = new TransportProperties();
@@ -182,7 +193,8 @@ class DroidtoothPlugin implements DuplexPlugin {
// Bind a server socket to accept connections from contacts
BluetoothServerSocket ss;
try {
ss = InsecureBluetooth.listen(adapter, "RFCOMM", getUuid());
ss = adapter.listenUsingInsecureRfcommWithServiceRecord(
"RFCOMM", getUuid());
} catch (IOException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
@@ -214,7 +226,7 @@ class DroidtoothPlugin implements DuplexPlugin {
return UUID.fromString(uuid);
}
private void tryToClose(BluetoothServerSocket ss) {
private void tryToClose(@Nullable BluetoothServerSocket ss) {
try {
if (ss != null) ss.close();
} catch (IOException e) {
@@ -236,7 +248,7 @@ class DroidtoothPlugin implements DuplexPlugin {
}
if (LOG.isLoggable(INFO)) {
String address = s.getRemoteDevice().getAddress();
LOG.info("Connection from " + address);
LOG.info("Connection from " + scrubMacAddress(address));
}
backoff.reset();
callback.incomingConnectionCreated(wrapSocket(s));
@@ -261,7 +273,7 @@ class DroidtoothPlugin implements DuplexPlugin {
@Override
public boolean isRunning() {
return running && adapter.isEnabled();
return running && adapter != null && adapter.isEnabled();
}
@Override
@@ -302,10 +314,12 @@ class DroidtoothPlugin implements DuplexPlugin {
}
}
@Nullable
private BluetoothSocket connect(String address, String uuid) {
// Validate the address
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
if (LOG.isLoggable(WARNING))
// not scrubbing here to be able to figure out the problem
LOG.warning("Invalid address " + address);
return null;
}
@@ -321,22 +335,26 @@ class DroidtoothPlugin implements DuplexPlugin {
BluetoothDevice d = adapter.getRemoteDevice(address);
BluetoothSocket s = null;
try {
s = InsecureBluetooth.createSocket(d, u);
if (LOG.isLoggable(INFO)) LOG.info("Connecting to " + address);
s = d.createInsecureRfcommSocketToServiceRecord(u);
if (LOG.isLoggable(INFO))
LOG.info("Connecting to " + scrubMacAddress(address));
s.connect();
if (LOG.isLoggable(INFO)) LOG.info("Connected to " + address);
if (LOG.isLoggable(INFO))
LOG.info("Connected to " + scrubMacAddress(address));
return s;
} catch (IOException e) {
if (LOG.isLoggable(INFO))
LOG.info("Failed to connect to " + address);
if (LOG.isLoggable(INFO)) {
LOG.info("Failed to connect to " + scrubMacAddress(address)
+ ": " + e);
}
tryToClose(s);
return null;
}
}
private void tryToClose(BluetoothSocket s) {
private void tryToClose(@Nullable Closeable c) {
try {
if (s != null) s.close();
if (c != null) c.close();
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
@@ -372,7 +390,8 @@ class DroidtoothPlugin implements DuplexPlugin {
// Bind a server socket for receiving invitation connections
BluetoothServerSocket ss;
try {
ss = InsecureBluetooth.listen(adapter, "RFCOMM", uuid);
ss = adapter.listenUsingInsecureRfcommWithServiceRecord(
"RFCOMM", uuid);
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
return null;
@@ -413,7 +432,7 @@ class DroidtoothPlugin implements DuplexPlugin {
}
private void closeSockets(final List<Future<BluetoothSocket>> futures,
final BluetoothSocket chosen) {
@Nullable final BluetoothSocket chosen) {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
@@ -446,34 +465,39 @@ class DroidtoothPlugin implements DuplexPlugin {
@Override
public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
if (!isRunning()) return null;
// There's no point listening if we can't discover our own address
String address = AndroidUtils.getBluetoothAddress(appContext, adapter);
if (address.isEmpty()) return null;
// No truncation necessary because COMMIT_LENGTH = 16
UUID uuid = UUID.nameUUIDFromBytes(commitment);
if (LOG.isLoggable(INFO)) LOG.info("Key agreement UUID " + uuid);
// Bind a server socket for receiving invitation connections
BluetoothServerSocket ss;
try {
ss = InsecureBluetooth.listen(adapter, "RFCOMM", uuid);
ss = adapter.listenUsingInsecureRfcommWithServiceRecord(
"RFCOMM", uuid);
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
return null;
}
TransportProperties p = new TransportProperties();
String address = AndroidUtils.getBluetoothAddress(appContext, adapter);
if (!StringUtils.isNullOrEmpty(address))
p.put(PROP_ADDRESS, address);
TransportDescriptor d = new TransportDescriptor(ID, p);
return new BluetoothKeyAgreementListener(d, ss);
BdfList descriptor = new BdfList();
descriptor.add(TRANSPORT_ID_BLUETOOTH);
descriptor.add(StringUtils.macToBytes(address));
return new BluetoothKeyAgreementListener(descriptor, ss);
}
@Override
public DuplexTransportConnection createKeyAgreementConnection(
byte[] commitment, TransportDescriptor d, long timeout) {
byte[] commitment, BdfList descriptor, long timeout) {
if (!isRunning()) return null;
if (!ID.equals(d.getIdentifier())) return null;
TransportProperties p = d.getProperties();
if (p == null) return null;
String address = p.get(PROP_ADDRESS);
if (StringUtils.isNullOrEmpty(address)) return null;
String address;
try {
address = parseAddress(descriptor);
} catch (FormatException e) {
LOG.info("Invalid address in key agreement descriptor");
return null;
}
// No truncation necessary because COMMIT_LENGTH = 16
UUID uuid = UUID.nameUUIDFromBytes(commitment);
if (LOG.isLoggable(INFO))
@@ -483,6 +507,12 @@ class DroidtoothPlugin implements DuplexPlugin {
return new DroidtoothTransportConnection(this, s);
}
private String parseAddress(BdfList descriptor) throws FormatException {
byte[] mac = descriptor.getRaw(1);
if (mac.length != 6) throw new FormatException();
return StringUtils.macToString(mac);
}
private class BluetoothStateReceiver extends BroadcastReceiver {
@Override
@@ -551,7 +581,7 @@ class DroidtoothPlugin implements DuplexPlugin {
private static class DiscoveryReceiver extends BroadcastReceiver {
private final CountDownLatch finished = new CountDownLatch(1);
private final List<String> addresses = new ArrayList<>();
private final List<String> addresses = new CopyOnWriteArrayList<>();
@Override
public void onReceive(Context ctx, Intent intent) {
@@ -562,16 +592,19 @@ class DroidtoothPlugin implements DuplexPlugin {
finished.countDown();
} else if (action.equals(FOUND)) {
BluetoothDevice d = intent.getParcelableExtra(EXTRA_DEVICE);
if (LOG.isLoggable(INFO))
LOG.info("Discovered device: " + d.getAddress());
if (LOG.isLoggable(INFO)) {
LOG.info("Discovered device: " +
scrubMacAddress(d.getAddress()));
}
addresses.add(d.getAddress());
}
}
private List<String> waitForAddresses() throws InterruptedException {
finished.await();
Collections.shuffle(addresses);
return Collections.unmodifiableList(addresses);
List<String> shuffled = new ArrayList<>(addresses);
Collections.shuffle(shuffled);
return shuffled;
}
}
@@ -616,7 +649,7 @@ class DroidtoothPlugin implements DuplexPlugin {
private final BluetoothServerSocket ss;
public BluetoothKeyAgreementListener(TransportDescriptor descriptor,
private BluetoothKeyAgreementListener(BdfList descriptor,
BluetoothServerSocket ss) {
super(descriptor);
this.ss = ss;

View File

@@ -1,18 +1,25 @@
package org.briarproject.plugins.droidtooth;
package org.briarproject.bramble.plugin.droidtooth;
import android.content.Context;
import org.briarproject.android.api.AndroidExecutor;
import org.briarproject.api.TransportId;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.BackoffFactory;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.TransportId;
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 java.security.SecureRandom;
import java.util.concurrent.Executor;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID;
@Immutable
@NotNullByDefault
public class DroidtoothPluginFactory implements DuplexPluginFactory {
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
@@ -38,7 +45,7 @@ public class DroidtoothPluginFactory implements DuplexPluginFactory {
@Override
public TransportId getId() {
return DroidtoothPlugin.ID;
return ID;
}
@Override

View File

@@ -1,14 +1,16 @@
package org.briarproject.plugins.droidtooth;
package org.briarproject.bramble.plugin.droidtooth;
import android.bluetooth.BluetoothSocket;
import org.briarproject.api.plugins.Plugin;
import org.briarproject.api.plugins.duplex.AbstractDuplexTransportConnection;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Plugin;
import org.briarproject.bramble.api.plugin.duplex.AbstractDuplexTransportConnection;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@NotNullByDefault
class DroidtoothTransportConnection extends AbstractDuplexTransportConnection {
private final BluetoothSocket socket;

View File

@@ -1,4 +1,4 @@
package org.briarproject.plugins.tcp;
package org.briarproject.bramble.plugin.tcp;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -7,16 +7,20 @@ import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import static android.content.Context.CONNECTIVITY_SERVICE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI;
@NotNullByDefault
class AndroidLanTcpPlugin extends LanTcpPlugin {
private static final Logger LOG =
@@ -24,6 +28,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
private final Context appContext;
@Nullable
private volatile BroadcastReceiver networkStateReceiver = null;
AndroidLanTcpPlugin(Executor ioExecutor, Backoff backoff,
@@ -34,14 +39,13 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
}
@Override
public boolean start() {
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(CONNECTIVITY_ACTION);
appContext.registerReceiver(networkStateReceiver, filter);
return true;
}
@Override

View File

@@ -1,16 +1,23 @@
package org.briarproject.plugins.tcp;
package org.briarproject.bramble.plugin.tcp;
import android.content.Context;
import org.briarproject.api.TransportId;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.BackoffFactory;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.TransportId;
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 java.util.concurrent.Executor;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
@Immutable
@NotNullByDefault
public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
@@ -32,7 +39,7 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
@Override
public TransportId getId() {
return LanTcpPlugin.ID;
return ID;
}
@Override

View File

@@ -1,18 +1,18 @@
package org.briarproject.plugins.tor;
package org.briarproject.bramble.plugin.tor;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class TorNetworkMetadata {
class TorNetworkMetadata {
// See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
// and https://trac.torproject.org/projects/tor/wiki/doc/OONI/censorshipwiki
// TODO: get a more complete list
private static final Set<String> BLOCKED_IN_COUNTRIES =
new HashSet<String>(Arrays.asList("CN", "IR", "SY", "ZZ"));
new HashSet<>(Arrays.asList("CN", "IR", "SY", "ZZ"));
public static boolean isTorProbablyBlocked(String countryCode) {
static boolean isTorProbablyBlocked(String countryCode) {
return BLOCKED_IN_COUNTRIES.contains(countryCode);
}
}

View File

@@ -1,9 +1,13 @@
package org.briarproject.plugins.tor;
package org.briarproject.bramble.plugin.tor;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.FileObserver;
@@ -11,28 +15,32 @@ import android.os.PowerManager;
import net.freehaven.tor.control.EventHandler;
import net.freehaven.tor.control.TorControlConnection;
import net.sourceforge.jsocks.socks.Socks5Proxy;
import net.sourceforge.jsocks.socks.SocksSocket;
import org.briarproject.android.util.AndroidUtils;
import org.briarproject.api.TransportId;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.crypto.PseudoRandom;
import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventListener;
import org.briarproject.api.event.SettingsUpdatedEvent;
import org.briarproject.api.keyagreement.KeyAgreementListener;
import org.briarproject.api.keyagreement.TransportDescriptor;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
import org.briarproject.api.properties.TransportProperties;
import org.briarproject.api.reporting.DevReporter;
import org.briarproject.api.settings.Settings;
import org.briarproject.api.system.LocationUtils;
import org.briarproject.util.StringUtils;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.crypto.PseudoRandom;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
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.PluginException;
import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.reporting.DevReporter;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.util.AndroidUtils;
import org.briarproject.bramble.util.IoUtils;
import org.briarproject.bramble.util.StringUtils;
import java.io.Closeable;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
@@ -56,6 +64,9 @@ import java.util.logging.Logger;
import java.util.regex.Pattern;
import java.util.zip.ZipInputStream;
import javax.annotation.Nullable;
import javax.net.SocketFactory;
import static android.content.Context.CONNECTIVITY_SERVICE;
import static android.content.Context.MODE_PRIVATE;
import static android.content.Context.POWER_SERVICE;
@@ -67,17 +78,24 @@ import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS;
import static net.freehaven.tor.control.TorControlCommands.HS_PRIVKEY;
import static org.briarproject.bramble.api.plugin.TorConstants.CONTROL_PORT;
import static org.briarproject.bramble.api.plugin.TorConstants.ID;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_ALWAYS;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_NEVER;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WIFI;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT;
import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
static final TransportId ID = new TransportId("tor");
private static final String PROP_ONION = "onion";
private static final String[] EVENTS = {
"CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR"
};
private static final String OWNER = "__OwningControllerProcess";
private static final int SOCKS_PORT = 59050, CONTROL_PORT = 59051;
private static final int COOKIE_TIMEOUT = 3000; // Milliseconds
private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}");
private static final Logger LOG =
@@ -87,6 +105,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final Context appContext;
private final LocationUtils locationUtils;
private final DevReporter reporter;
private final SocketFactory torSocketFactory;
private final Backoff backoff;
private final DuplexPluginCallback callback;
private final String architecture;
@@ -104,13 +123,15 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private volatile BroadcastReceiver networkStateReceiver = null;
TorPlugin(Executor ioExecutor, Context appContext,
LocationUtils locationUtils, DevReporter reporter, Backoff backoff,
LocationUtils locationUtils, DevReporter reporter,
SocketFactory torSocketFactory, Backoff backoff,
DuplexPluginCallback callback, String architecture, int maxLatency,
int maxIdleTime) {
this.ioExecutor = ioExecutor;
this.appContext = appContext;
this.locationUtils = locationUtils;
this.reporter = reporter;
this.torSocketFactory = torSocketFactory;
this.backoff = backoff;
this.callback = callback;
this.architecture = architecture;
@@ -134,7 +155,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override
public TransportId getId() {
return ID;
return TorConstants.ID;
}
@Override
@@ -148,92 +169,90 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
@Override
public boolean start() throws IOException {
public void start() throws PluginException {
if (used.getAndSet(true)) throw new IllegalStateException();
// Try to connect to an existing Tor process if there is one
boolean startProcess = false;
// Install or update the assets if necessary
if (!assetsAreUpToDate()) installAssets();
LOG.info("Starting Tor");
// Watch for the auth cookie file being updated
try {
controlSocket = new Socket("127.0.0.1", CONTROL_PORT);
LOG.info("Tor is already running");
} catch (IOException e) {
LOG.info("Tor is not running");
startProcess = true;
// Install the binary, possibly overwriting an older version
if (!installBinary()) {
LOG.warning("Could not install Tor binary");
return false;
}
// Install the GeoIP database and config file if necessary
if (!isConfigInstalled() && !installConfig()) {
LOG.warning("Could not install Tor config");
return false;
}
LOG.info("Starting Tor");
// Watch for the auth cookie file being created/updated
cookieFile.getParentFile().mkdirs();
cookieFile.createNewFile();
CountDownLatch latch = new CountDownLatch(1);
FileObserver obs = new WriteObserver(cookieFile, latch);
obs.startWatching();
// Start a new Tor process
String torPath = torFile.getAbsolutePath();
String configPath = configFile.getAbsolutePath();
String pid = String.valueOf(android.os.Process.myPid());
String[] cmd = {torPath, "-f", configPath, OWNER, pid};
String[] env = {"HOME=" + torDirectory.getAbsolutePath()};
Process torProcess;
try {
torProcess = Runtime.getRuntime().exec(cmd, env, torDirectory);
} catch (SecurityException e1) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e1.toString(), e1);
return false;
}
// Log the process's standard output until it detaches
if (LOG.isLoggable(INFO)) {
Scanner stdout = new Scanner(torProcess.getInputStream());
while (stdout.hasNextLine()) LOG.info(stdout.nextLine());
stdout.close();
}
try {
// Wait for the process to detach or exit
int exit = torProcess.waitFor();
if (exit != 0) {
if (LOG.isLoggable(WARNING))
LOG.warning("Tor exited with value " + exit);
return false;
}
// Wait for the auth cookie file to be created/updated
if (!latch.await(COOKIE_TIMEOUT, MILLISECONDS)) {
LOG.warning("Auth cookie not created");
if (LOG.isLoggable(INFO)) listFiles(torDirectory);
return false;
}
} catch (InterruptedException e1) {
LOG.warning("Interrupted while starting Tor");
Thread.currentThread().interrupt();
return false;
}
// Now we should be able to connect to the new process
controlSocket = new Socket("127.0.0.1", CONTROL_PORT);
} catch (IOException e) {
throw new PluginException(e);
}
// Open a control connection and authenticate using the cookie file
controlConnection = new TorControlConnection(controlSocket);
controlConnection.authenticate(read(cookieFile));
// Tell Tor to exit when the control connection is closed
controlConnection.takeOwnership();
controlConnection.resetConf(Collections.singletonList(OWNER));
running = true;
// Register to receive events from the Tor process
controlConnection.setEventHandler(this);
controlConnection.setEvents(Arrays.asList(EVENTS));
// If Tor was already running, find out whether it's bootstrapped
if (!startProcess) {
CountDownLatch latch = new CountDownLatch(1);
FileObserver obs = new WriteObserver(cookieFile, latch);
obs.startWatching();
// Start a new Tor process
String torPath = torFile.getAbsolutePath();
String configPath = configFile.getAbsolutePath();
String pid = String.valueOf(android.os.Process.myPid());
Process torProcess;
ProcessBuilder pb =
new ProcessBuilder(torPath, "-f", configPath, OWNER, pid);
Map<String, String> env = pb.environment();
env.put("HOME", torDirectory.getAbsolutePath());
pb.directory(torDirectory);
try {
torProcess = pb.start();
} catch (SecurityException | IOException e) {
throw new PluginException(e);
}
// Log the process's standard output until it detaches
if (LOG.isLoggable(INFO)) {
Scanner stdout = new Scanner(torProcess.getInputStream());
Scanner stderr = new Scanner(torProcess.getErrorStream());
while (stdout.hasNextLine() || stderr.hasNextLine()){
if(stdout.hasNextLine()) {
LOG.info(stdout.nextLine());
}
if(stderr.hasNextLine()){
LOG.info(stderr.nextLine());
}
}
stdout.close();
stderr.close();
}
try {
// Wait for the process to detach or exit
int exit = torProcess.waitFor();
if (exit != 0) {
if (LOG.isLoggable(WARNING))
LOG.warning("Tor exited with value " + exit);
throw new PluginException();
}
// Wait for the auth cookie file to be created/updated
if (!latch.await(COOKIE_TIMEOUT, MILLISECONDS)) {
LOG.warning("Auth cookie not created");
if (LOG.isLoggable(INFO)) listFiles(torDirectory);
throw new PluginException();
}
} catch (InterruptedException e) {
LOG.warning("Interrupted while starting Tor");
Thread.currentThread().interrupt();
throw new PluginException();
}
try {
// Open a control connection and authenticate using the cookie file
controlSocket = new Socket("127.0.0.1", CONTROL_PORT);
controlConnection = new TorControlConnection(controlSocket);
controlConnection.authenticate(read(cookieFile));
// Tell Tor to exit when the control connection is closed
controlConnection.takeOwnership();
controlConnection.resetConf(Collections.singletonList(OWNER));
running = true;
// Register to receive events from the Tor process
controlConnection.setEventHandler(this);
controlConnection.setEvents(Arrays.asList(EVENTS));
// Check whether Tor has already bootstrapped
String phase = controlConnection.getInfo("status/bootstrap-phase");
if (phase != null && phase.contains("PROGRESS=100")) {
LOG.info("Tor has already bootstrapped");
connectionStatus.setBootstrapped();
}
} catch (IOException e) {
throw new PluginException(e);
}
// Register to receive network status events
networkStateReceiver = new NetworkStateReceiver();
@@ -241,110 +260,96 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
appContext.registerReceiver(networkStateReceiver, filter);
// Bind a server socket to receive incoming hidden service connections
bind();
return true;
}
private boolean installBinary() {
InputStream in = null;
OutputStream out = null;
private boolean assetsAreUpToDate() {
try {
// Unzip the Tor binary to the filesystem
in = getTorInputStream();
out = new FileOutputStream(torFile);
copy(in, out);
// Make the Tor binary executable
if (!torFile.setExecutable(true, true)) {
LOG.warning("Could not make Tor binary executable");
return false;
}
return true;
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
tryToClose(in);
tryToClose(out);
return false;
PackageManager pm = appContext.getPackageManager();
PackageInfo pi = pm.getPackageInfo(appContext.getPackageName(), 0);
return doneFile.lastModified() > pi.lastUpdateTime;
} catch (NameNotFoundException e) {
throw new RuntimeException(e);
}
}
private boolean isConfigInstalled() {
return geoIpFile.exists() && configFile.exists() && doneFile.exists();
}
private boolean installConfig() {
private void installAssets() throws PluginException {
InputStream in = null;
OutputStream out = null;
try {
doneFile.delete();
// Unzip the Tor binary to the filesystem
in = getTorInputStream();
out = new FileOutputStream(torFile);
IoUtils.copyAndClose(in, out);
// Make the Tor binary executable
if (!torFile.setExecutable(true, true)) throw new IOException();
// Unzip the GeoIP database to the filesystem
in = getGeoIpInputStream();
out = new FileOutputStream(geoIpFile);
copy(in, out);
IoUtils.copyAndClose(in, out);
// Copy the config file to the filesystem
in = getConfigInputStream();
out = new FileOutputStream(configFile);
copy(in, out);
// Create a file to indicate that installation succeeded
IoUtils.copyAndClose(in, out);
doneFile.createNewFile();
return true;
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
tryToClose(in);
tryToClose(out);
return false;
throw new PluginException(e);
}
}
private InputStream getTorInputStream() throws IOException {
if (LOG.isLoggable(INFO))
LOG.info("Installing Tor binary for " + architecture);
String filename = "tor-" + architecture + ".zip";
InputStream in = appContext.getResources().getAssets().open(filename);
int resId = getResourceId("tor_" + architecture);
InputStream in = appContext.getResources().openRawResource(resId);
ZipInputStream zin = new ZipInputStream(in);
if (zin.getNextEntry() == null) throw new IOException();
return zin;
}
private InputStream getGeoIpInputStream() throws IOException {
String filename = "geoip.zip";
InputStream in = appContext.getResources().getAssets().open(filename);
int resId = getResourceId("geoip");
InputStream in = appContext.getResources().openRawResource(resId);
ZipInputStream zin = new ZipInputStream(in);
if (zin.getNextEntry() == null) throw new IOException();
return zin;
}
private InputStream getConfigInputStream() throws IOException {
return appContext.getResources().getAssets().open("torrc");
int resId = getResourceId("torrc");
return appContext.getResources().openRawResource(resId);
}
private void copy(InputStream in, OutputStream out) throws IOException {
byte[] buf = new byte[4096];
while (true) {
int read = in.read(buf);
if (read == -1) break;
out.write(buf, 0, read);
}
in.close();
out.close();
private int getResourceId(String filename) {
Resources res = appContext.getResources();
return res.getIdentifier(filename, "raw", appContext.getPackageName());
}
private void tryToClose(InputStream in) {
private void tryToClose(@Nullable Closeable c) {
try {
if (in != null) in.close();
if (c != null) c.close();
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
}
private void tryToClose(OutputStream out) {
private void tryToClose(@Nullable Socket s) {
try {
if (out != null) out.close();
if (s != null) s.close();
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
}
private void listFiles(File f) {
if (f.isDirectory()) for (File child : f.listFiles()) listFiles(child);
else LOG.info(f.getAbsolutePath());
if (f.isDirectory()) {
File[] children = f.listFiles();
if (children != null) for (File child : children) listFiles(child);
} else {
LOG.info(f.getAbsolutePath());
}
}
private byte[] read(File f) throws IOException {
@@ -359,7 +364,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
return b;
} finally {
in.close();
tryToClose(in);
}
}
@@ -367,8 +372,9 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
// TODO: Trigger this with a TransportEnabledEvent
File reportDir = AndroidUtils.getReportDir(appContext);
reporter.sendReports(reportDir, SOCKS_PORT);
reporter.sendReports(reportDir);
}
});
}
@@ -378,7 +384,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override
public void run() {
// If there's already a port number stored in config, reuse it
String portString = callback.getSettings().get("port");
String portString = callback.getSettings().get(PREF_TOR_PORT);
int port;
if (StringUtils.isNullOrEmpty(portString)) port = 0;
else port = Integer.parseInt(portString);
@@ -401,7 +407,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
// Store the port number
final String localPort = String.valueOf(ss.getLocalPort());
Settings s = new Settings();
s.put("port", localPort);
s.put(PREF_TOR_PORT, localPort);
callback.mergeSettings(s);
// Create a hidden service if necessary
ioExecutor.execute(new Runnable() {
@@ -417,7 +423,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
});
}
private void tryToClose(ServerSocket ss) {
private void tryToClose(@Nullable ServerSocket ss) {
try {
if (ss != null) ss.close();
} catch (IOException e) {
@@ -453,7 +459,8 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
// Publish the hidden service's onion hostname in transport properties
String hostname = response.get(HS_ADDRESS);
if (LOG.isLoggable(INFO)) LOG.info("Hidden service " + hostname);
if (LOG.isLoggable(INFO))
LOG.info("Hidden service " + scrubOnion(hostname));
TransportProperties p = new TransportProperties();
p.put(PROP_ONION, hostname);
callback.mergeLocalProperties(p);
@@ -495,24 +502,20 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
@Override
public void stop() throws IOException {
public void stop() throws PluginException {
running = false;
tryToClose(socket);
if (networkStateReceiver != null)
appContext.unregisterReceiver(networkStateReceiver);
try {
LOG.info("Stopping Tor");
if (controlSocket == null)
controlSocket = new Socket("127.0.0.1", CONTROL_PORT);
if (controlConnection == null) {
controlConnection = new TorControlConnection(controlSocket);
controlConnection.authenticate(read(cookieFile));
if (controlSocket != null && controlConnection != null) {
try {
LOG.info("Stopping Tor");
controlConnection.setConf("DisableNetwork", "1");
controlConnection.shutdownTor("TERM");
controlSocket.close();
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
controlConnection.setConf("DisableNetwork", "1");
controlConnection.shutdownTor("TERM");
controlSocket.close();
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
wakeLock.release();
}
@@ -562,21 +565,26 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
String onion = p.get(PROP_ONION);
if (StringUtils.isNullOrEmpty(onion)) return null;
if (!ONION.matcher(onion).matches()) {
// not scrubbing this address, so we are able to find the problem
if (LOG.isLoggable(INFO)) LOG.info("Invalid hostname: " + onion);
return null;
}
Socket s = null;
try {
if (LOG.isLoggable(INFO)) LOG.info("Connecting to " + onion);
if (LOG.isLoggable(INFO))
LOG.info("Connecting to " + scrubOnion(onion));
controlConnection.forgetHiddenService(onion);
Socks5Proxy proxy = new Socks5Proxy("127.0.0.1", SOCKS_PORT);
proxy.resolveAddrLocally(false);
Socket s = new SocksSocket(proxy, onion + ".onion", 80);
s = torSocketFactory.createSocket(onion + ".onion", 80);
s.setSoTimeout(socketTimeout);
if (LOG.isLoggable(INFO)) LOG.info("Connected to " + onion);
if (LOG.isLoggable(INFO))
LOG.info("Connected to " + scrubOnion(onion));
return new TorTransportConnection(this, s);
} catch (IOException e) {
if (LOG.isLoggable(INFO))
LOG.info("Could not connect to " + onion + ": " + e.toString());
if (LOG.isLoggable(INFO)) {
LOG.info("Could not connect to " + scrubOnion(onion) + ": " +
e.toString());
}
tryToClose(s);
return null;
}
}
@@ -604,7 +612,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override
public DuplexTransportConnection createKeyAgreementConnection(
byte[] commitment, TransportDescriptor d, long timeout) {
byte[] commitment, BdfList descriptor, long timeout) {
throw new UnsupportedOperationException();
}
@@ -676,7 +684,8 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override
public void eventOccurred(Event e) {
if (e instanceof SettingsUpdatedEvent) {
if (((SettingsUpdatedEvent) e).getNamespace().equals("tor")) {
SettingsUpdatedEvent s = (SettingsUpdatedEvent) e;
if (s.getNamespace().equals(ID.getString())) {
LOG.info("Tor settings updated");
updateConnectionStatus();
}
@@ -698,7 +707,8 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
boolean blocked = TorNetworkMetadata.isTorProbablyBlocked(
country);
Settings s = callback.getSettings();
boolean useMobileData = s.getBoolean("torOverMobile", true);
int network = s.getInt(PREF_TOR_NETWORK,
PREF_TOR_NETWORK_ALWAYS);
if (LOG.isLoggable(INFO)) {
LOG.info("Online: " + online + ", wifi: " + wifi);
@@ -713,7 +723,8 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} else if (blocked) {
LOG.info("Disabling network, country is blocked");
enableNetwork(false);
} else if (!wifi && !useMobileData) {
} else if (network == PREF_TOR_NETWORK_NEVER
|| (network == PREF_TOR_NETWORK_WIFI && !wifi)) {
LOG.info("Disabling network due to data setting");
enableNetwork(false);
} else {

View File

@@ -1,22 +1,29 @@
package org.briarproject.plugins.tor;
package org.briarproject.bramble.plugin.tor;
import android.content.Context;
import android.os.Build;
import org.briarproject.android.util.AndroidUtils;
import org.briarproject.api.TransportId;
import org.briarproject.api.event.EventBus;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.BackoffFactory;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
import org.briarproject.api.reporting.DevReporter;
import org.briarproject.api.system.LocationUtils;
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;
import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TransportId;
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.reporting.DevReporter;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.util.AndroidUtils;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.annotation.concurrent.Immutable;
import javax.net.SocketFactory;
@Immutable
@NotNullByDefault
public class TorPluginFactory implements DuplexPluginFactory {
private static final Logger LOG =
@@ -33,22 +40,25 @@ public class TorPluginFactory implements DuplexPluginFactory {
private final LocationUtils locationUtils;
private final DevReporter reporter;
private final EventBus eventBus;
private final SocketFactory torSocketFactory;
private final BackoffFactory backoffFactory;
public TorPluginFactory(Executor ioExecutor, Context appContext,
LocationUtils locationUtils, DevReporter reporter,
EventBus eventBus, BackoffFactory backoffFactory) {
EventBus eventBus, SocketFactory torSocketFactory,
BackoffFactory backoffFactory) {
this.ioExecutor = ioExecutor;
this.appContext = appContext;
this.locationUtils = locationUtils;
this.reporter = reporter;
this.eventBus = eventBus;
this.torSocketFactory = torSocketFactory;
this.backoffFactory = backoffFactory;
}
@Override
public TransportId getId() {
return TorPlugin.ID;
return TorConstants.ID;
}
@Override
@@ -75,13 +85,13 @@ public class TorPluginFactory implements DuplexPluginFactory {
return null;
}
// Use position-independent executable for SDK >= 16
if (Build.VERSION.SDK_INT >= 16) architecture += "-pie";
if (Build.VERSION.SDK_INT >= 16) architecture += "_pie";
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorPlugin plugin = new TorPlugin(ioExecutor, appContext, locationUtils,
reporter, backoff, callback, architecture, MAX_LATENCY,
MAX_IDLE_TIME);
reporter, torSocketFactory, backoff, callback, architecture,
MAX_LATENCY, MAX_IDLE_TIME);
eventBus.addListener(plugin);
return plugin;
}

View File

@@ -1,13 +1,15 @@
package org.briarproject.plugins.tor;
package org.briarproject.bramble.plugin.tor;
import org.briarproject.api.plugins.Plugin;
import org.briarproject.api.plugins.duplex.AbstractDuplexTransportConnection;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Plugin;
import org.briarproject.bramble.api.plugin.duplex.AbstractDuplexTransportConnection;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
@NotNullByDefault
class TorTransportConnection extends AbstractDuplexTransportConnection {
private final Socket socket;

View File

@@ -1,9 +1,10 @@
package org.briarproject.system;
package org.briarproject.bramble.system;
import android.app.Application;
import android.os.Handler;
import android.os.Looper;
import org.briarproject.android.api.AndroidExecutor;
import org.briarproject.bramble.api.system.AndroidExecutor;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
@@ -16,18 +17,21 @@ import javax.inject.Inject;
class AndroidExecutorImpl implements AndroidExecutor {
private final Handler uiHandler;
private final Runnable loop;
private final AtomicBoolean started = new AtomicBoolean(false);
private final CountDownLatch startLatch = new CountDownLatch(1);
private volatile Handler handler = null;
private volatile Handler backgroundHandler = null;
@Inject
AndroidExecutorImpl() {
AndroidExecutorImpl(Application app) {
uiHandler = new Handler(app.getApplicationContext().getMainLooper());
loop = new Runnable() {
@Override
public void run() {
Looper.prepare();
handler = new Handler();
backgroundHandler = new Handler();
startLatch.countDown();
Looper.loop();
}
@@ -35,10 +39,11 @@ class AndroidExecutorImpl implements AndroidExecutor {
}
private void startIfNecessary() {
if (started.getAndSet(true)) return;
Thread t = new Thread(loop, "AndroidExecutor");
t.setDaemon(true);
t.start();
if (!started.getAndSet(true)) {
Thread t = new Thread(loop, "AndroidExecutor");
t.setDaemon(true);
t.start();
}
try {
startLatch.await();
} catch (InterruptedException e) {
@@ -46,14 +51,28 @@ class AndroidExecutorImpl implements AndroidExecutor {
}
}
public <V> Future<V> submit(Callable<V> c) {
@Override
public <V> Future<V> runOnBackgroundThread(Callable<V> c) {
FutureTask<V> f = new FutureTask<>(c);
execute(f);
runOnBackgroundThread(f);
return f;
}
public void execute(Runnable r) {
@Override
public void runOnBackgroundThread(Runnable r) {
startIfNecessary();
handler.post(r);
backgroundHandler.post(r);
}
@Override
public <V> Future<V> runOnUiThread(Callable<V> c) {
FutureTask<V> f = new FutureTask<>(c);
runOnUiThread(f);
return f;
}
@Override
public void runOnUiThread(Runnable r) {
uiHandler.post(r);
}
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.system;
package org.briarproject.bramble.system;
import android.annotation.SuppressLint;
import android.app.Application;
@@ -6,7 +6,8 @@ import android.content.Context;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import org.briarproject.api.system.LocationUtils;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.LocationUtils;
import java.util.Locale;
import java.util.logging.Logger;
@@ -15,6 +16,7 @@ import javax.inject.Inject;
import static android.content.Context.TELEPHONY_SERVICE;
@NotNullByDefault
class AndroidLocationUtils implements LocationUtils {
private static final Logger LOG =
@@ -23,7 +25,7 @@ class AndroidLocationUtils implements LocationUtils {
private final Context appContext;
@Inject
public AndroidLocationUtils(Application app) {
AndroidLocationUtils(Application app) {
appContext = app.getApplicationContext();
}
@@ -44,6 +46,7 @@ class AndroidLocationUtils implements LocationUtils {
* some reason - both that class and {@code Context.COUNTRY_CODE} are
* annotated {@code @hide}.
*/
@Override
@SuppressLint("DefaultLocale")
public String getCurrentCountry() {
String countryCode = getCountryFromPhoneNetwork();

View File

@@ -0,0 +1,93 @@
package org.briarproject.bramble.system;
import android.app.Application;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.ContentResolver;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Parcel;
import android.provider.Settings;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static android.content.Context.WIFI_SERVICE;
import static android.provider.Settings.Secure.ANDROID_ID;
@Immutable
@NotNullByDefault
class AndroidSecureRandomProvider extends LinuxSecureRandomProvider {
private static final int SEED_LENGTH = 32;
private final Context appContext;
@Inject
AndroidSecureRandomProvider(Application app) {
appContext = app.getApplicationContext();
}
@Override
protected void writeToEntropyPool(DataOutputStream out) throws IOException {
super.writeToEntropyPool(out);
out.writeInt(android.os.Process.myPid());
out.writeInt(android.os.Process.myTid());
out.writeInt(android.os.Process.myUid());
if (Build.FINGERPRINT != null) out.writeUTF(Build.FINGERPRINT);
if (Build.SERIAL != null) out.writeUTF(Build.SERIAL);
ContentResolver contentResolver = appContext.getContentResolver();
String id = Settings.Secure.getString(contentResolver, ANDROID_ID);
if (id != null) out.writeUTF(id);
Parcel parcel = Parcel.obtain();
WifiManager wm =
(WifiManager) appContext.getSystemService(WIFI_SERVICE);
List<WifiConfiguration> configs = wm.getConfiguredNetworks();
if (configs != null) {
for (WifiConfiguration config : configs)
parcel.writeParcelable(config, 0);
}
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
if (bt != null) {
for (BluetoothDevice device : bt.getBondedDevices())
parcel.writeParcelable(device, 0);
}
out.write(parcel.marshall());
parcel.recycle();
}
@Override
protected void writeSeed() {
super.writeSeed();
if (Build.VERSION.SDK_INT >= 16 && Build.VERSION.SDK_INT <= 18)
applyOpenSslFix();
}
// Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html
private void applyOpenSslFix() {
byte[] seed = new LinuxSecureRandomSpi().engineGenerateSeed(
SEED_LENGTH);
try {
// Seed the OpenSSL PRNG
Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto")
.getMethod("RAND_seed", byte[].class)
.invoke(null, seed);
// Mix the output of the Linux PRNG into the OpenSSL PRNG
int bytesRead = (Integer) Class.forName(
"org.apache.harmony.xnet.provider.jsse.NativeCrypto")
.getMethod("RAND_load_file", String.class, long.class)
.invoke(null, "/dev/urandom", 1024);
if (bytesRead != 1024) throw new IOException();
} catch (Exception e) {
throw new SecurityException(e);
}
}
}

View File

@@ -0,0 +1,33 @@
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.SecureRandomProvider;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class AndroidSystemModule {
@Provides
@Singleton
SecureRandomProvider provideSecureRandomProvider(Application app) {
return new AndroidSecureRandomProvider(app);
}
@Provides
LocationUtils provideLocationUtils(Application app) {
return new AndroidLocationUtils(app);
}
@Provides
@Singleton
AndroidExecutor provideAndroidExecutor(Application app) {
return new AndroidExecutorImpl(app);
}
}

View File

@@ -1,20 +1,14 @@
package org.briarproject.android.util;
package org.briarproject.bramble.util;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.os.Build;
import android.provider.Settings;
import android.support.design.widget.TextInputLayout;
import org.briarproject.util.FileUtils;
import org.briarproject.util.StringUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static android.content.Context.MODE_PRIVATE;
@@ -26,26 +20,16 @@ public class AndroidUtils {
private static final String STORED_REPORTS = "dev-reports";
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public static Collection<String> getSupportedArchitectures() {
List<String> abis = new ArrayList<String>();
List<String> abis = new ArrayList<>();
if (Build.VERSION.SDK_INT >= 21) {
abis.addAll(Arrays.asList(Build.SUPPORTED_ABIS));
} else {
abis.add(Build.CPU_ABI);
if (Build.CPU_ABI2 != null) abis.add(Build.CPU_ABI2);
}
return Collections.unmodifiableList(abis);
}
public static void setError(TextInputLayout til, String error,
boolean condition) {
if (condition) {
if (til.getError() == null)
til.setError(error);
} else
til.setError(null);
return abis;
}
public static String getBluetoothAddress(Context ctx,
@@ -73,9 +57,11 @@ public class AndroidUtils {
if (children != null) {
for (File child : children) {
if (!child.getName().equals("lib"))
FileUtils.deleteFileOrDir(child);
IoUtils.deleteFileOrDir(child);
}
}
// Recreate the cache dir as some OpenGL drivers expect it to exist
new File(dataDir, "cache").mkdir();
}
public static File getReportDir(Context ctx) {

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">Bramble</string>
</resources>

41
bramble-api/build.gradle Normal file
View File

@@ -0,0 +1,41 @@
apply plugin: 'java'
sourceCompatibility = 1.6
targetCompatibility = 1.6
apply plugin: 'witness'
dependencies {
compile "com.google.dagger:dagger:2.0.2"
compile 'com.google.dagger:dagger-compiler:2.0.2'
compile 'com.google.code.findbugs:jsr305:3.0.2'
testCompile 'junit:junit:4.12'
testCompile "org.jmock:jmock:2.8.2"
testCompile "org.jmock:jmock-junit4:2.8.2"
testCompile "org.jmock:jmock-legacy:2.8.2"
testCompile "org.hamcrest:hamcrest-library:1.3"
testCompile "org.hamcrest:hamcrest-core:1.3"
}
dependencyVerification {
verify = [
'com.google.dagger:dagger:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.dagger:dagger-compiler:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.code.findbugs:jsr305:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'com.google.dagger:dagger-producers:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.guava:guava:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
]
}
// needed to make test output available to bramble-core and briar-core
configurations {
testOutput.extendsFrom(testCompile)
}
task jarTest(type: Jar, dependsOn: testClasses) {
from sourceSets.test.output
classifier = 'test'
}
artifacts {
testOutput jarTest
}

View File

@@ -1,11 +1,18 @@
package org.briarproject.api;
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.StringUtils;
import java.util.Arrays;
import java.util.Comparator;
import javax.annotation.concurrent.ThreadSafe;
/**
* A wrapper around a byte array, to allow it to be stored in maps etc.
*/
@ThreadSafe
@NotNullByDefault
public class Bytes implements Comparable<Bytes> {
public static final BytesComparator COMPARATOR = new BytesComparator();
@@ -47,6 +54,12 @@ public class Bytes implements Comparable<Bytes> {
return aBytes.length - bBytes.length;
}
@Override
public String toString() {
return getClass().getSimpleName() +
"(" + StringUtils.toHexString(getBytes()) + ")";
}
public static class BytesComparator implements Comparator<Bytes> {
@Override

View File

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

View File

@@ -1,12 +1,10 @@
package org.briarproject.api;
package org.briarproject.bramble.api;
import java.util.Hashtable;
import java.util.Map;
public abstract class StringMap extends Hashtable<String, String> {
private static final long serialVersionUID = 2497176435908100448L;
protected StringMap(Map<String, String> m) {
super(m);
}

View File

@@ -0,0 +1,20 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.ThreadSafe;
@ThreadSafe
@NotNullByDefault
public abstract class UniqueId extends Bytes {
/**
* The length of a unique identifier in bytes.
*/
public static final int LENGTH = 32;
protected UniqueId(byte[] id) {
super(id);
if (id.length != LENGTH) throw new IllegalArgumentException();
}
}

View File

@@ -0,0 +1,36 @@
package org.briarproject.bramble.api.client;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.MessageId;
import java.util.Collection;
import java.util.Collections;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class BdfMessageContext {
private final BdfDictionary dictionary;
private final Collection<MessageId> dependencies;
public BdfMessageContext(BdfDictionary dictionary,
Collection<MessageId> dependencies) {
this.dictionary = dictionary;
this.dependencies = dependencies;
}
public BdfMessageContext(BdfDictionary dictionary) {
this(dictionary, Collections.<MessageId>emptyList());
}
public BdfDictionary getDictionary() {
return dictionary;
}
public Collection<MessageId> getDependencies() {
return dependencies;
}
}

View File

@@ -0,0 +1,66 @@
package org.briarproject.bramble.api.client;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
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.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
@NotNullByDefault
public abstract class BdfMessageValidator implements MessageValidator {
protected static final Logger LOG =
Logger.getLogger(BdfMessageValidator.class.getName());
protected final ClientHelper clientHelper;
protected final MetadataEncoder metadataEncoder;
protected final Clock clock;
protected BdfMessageValidator(ClientHelper clientHelper,
MetadataEncoder metadataEncoder, Clock clock) {
this.clientHelper = clientHelper;
this.metadataEncoder = metadataEncoder;
this.clock = clock;
}
protected abstract BdfMessageContext validateMessage(Message m, Group g,
BdfList body) throws InvalidMessageException, FormatException;
@Override
public MessageContext validateMessage(Message m, Group g)
throws InvalidMessageException {
// Reject the message if it's too far in the future
long now = clock.currentTimeMillis();
if (m.getTimestamp() - now > MAX_CLOCK_DIFFERENCE) {
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);
Metadata meta = metadataEncoder.encode(result.getDictionary());
return new MessageContext(meta, result.getDependencies());
} catch (FormatException e) {
throw new InvalidMessageException(e);
}
}
}

View File

@@ -1,34 +1,44 @@
package org.briarproject.api.clients;
package org.briarproject.bramble.api.client;
import org.briarproject.api.FormatException;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Transaction;
import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId;
import java.security.GeneralSecurityException;
import java.util.Map;
import javax.annotation.Nullable;
@NotNullByDefault
public interface ClientHelper {
void addLocalMessage(Message m, ClientId c, BdfDictionary metadata,
void addLocalMessage(Message m, BdfDictionary metadata, boolean shared)
throws DbException, FormatException;
void addLocalMessage(Transaction txn, Message m, BdfDictionary metadata,
boolean shared) throws DbException, FormatException;
void addLocalMessage(Transaction txn, Message m, ClientId c,
BdfDictionary metadata, boolean shared) throws DbException,
FormatException;
Message createMessage(GroupId g, long timestamp, BdfDictionary body)
throws FormatException;
Message createMessage(GroupId g, long timestamp, BdfList body)
throws FormatException;
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;
@@ -38,7 +48,8 @@ public interface ClientHelper {
BdfDictionary getGroupMetadataAsDictionary(Transaction txn, GroupId g)
throws DbException, FormatException;
BdfDictionary getMessageMetadataAsDictionary(MessageId m) throws DbException,
BdfDictionary getMessageMetadataAsDictionary(MessageId m)
throws DbException,
FormatException;
BdfDictionary getMessageMetadataAsDictionary(Transaction txn, MessageId m)
@@ -77,4 +88,15 @@ public interface ClientHelper {
throws FormatException;
BdfList toList(byte[] b, int off, int len) throws FormatException;
BdfList toList(byte[] b) throws FormatException;
BdfList toList(Message m) throws FormatException;
byte[] sign(String label, BdfList toSign, byte[] privateKey)
throws FormatException, GeneralSecurityException;
void verifySignature(String label, byte[] sig, byte[] publicKey,
BdfList signed) throws FormatException, GeneralSecurityException;
}

View File

@@ -0,0 +1,29 @@
package org.briarproject.bramble.api.client;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.Group;
@NotNullByDefault
public interface ContactGroupFactory {
/**
* Creates a group that is not shared with any contacts.
*/
Group createLocalGroup(ClientId clientId);
/**
* Creates a group for the given client to share with the given contact.
*/
Group createContactGroup(ClientId clientId, Contact contact);
/**
* Creates a group for the given client to share between the given authors
* identified by their AuthorIds.
*/
Group createContactGroup(ClientId clientId, AuthorId authorId1,
AuthorId authorId2);
}

View File

@@ -1,20 +1,26 @@
package org.briarproject.api.contact;
package org.briarproject.bramble.api.contact;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class Contact {
private final ContactId id;
private final Author author;
private final AuthorId localAuthorId;
private final boolean active;
private final boolean verified, active;
public Contact(ContactId id, Author author, AuthorId localAuthorId,
boolean active) {
boolean verified, boolean active) {
this.id = id;
this.author = author;
this.localAuthorId = localAuthorId;
this.verified = verified;
this.active = active;
}
@@ -30,6 +36,10 @@ public class Contact {
return localAuthorId;
}
public boolean isVerified() {
return verified;
}
public boolean isActive() {
return active;
}

View File

@@ -0,0 +1,20 @@
package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface ContactExchangeListener {
void contactExchangeSucceeded(Author remoteAuthor);
/**
* The exchange failed because the contact already exists.
*/
void duplicateContact(Author remoteAuthor);
/**
* A general failure.
*/
void contactExchangeFailed();
}

View File

@@ -0,0 +1,22 @@
package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
/**
* A task for conducting a contact information exchange with a remote peer.
*/
@NotNullByDefault
public interface ContactExchangeTask {
/**
* Exchanges contact information with a remote peer.
*/
void startExchange(ContactExchangeListener listener,
LocalAuthor localAuthor, SecretKey masterSecret,
DuplexTransportConnection conn, TransportId transportId,
boolean alice);
}

View File

@@ -1,9 +1,15 @@
package org.briarproject.api.contact;
package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* Type-safe wrapper for an integer that uniquely identifies a contact within
* the scope of a single node.
*/
@Immutable
@NotNullByDefault
public class ContactId {
private final int id;

View File

@@ -0,0 +1,104 @@
package org.briarproject.bramble.api.contact;
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.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Collection;
@NotNullByDefault
public interface ContactManager {
/**
* Registers a hook to be called whenever a contact is added.
*/
void registerAddContactHook(AddContactHook hook);
/**
* Registers a hook to be called whenever a contact is removed.
*/
void registerRemoveContactHook(RemoveContactHook hook);
/**
* Stores a contact within the given transaction associated with the given
* local and remote pseudonyms, and returns an ID for the contact.
*/
ContactId addContact(Transaction txn, Author remote, AuthorId local,
SecretKey master, long timestamp, boolean alice, boolean verified,
boolean active) throws DbException;
/**
* Stores a contact associated with the given local and remote pseudonyms,
* and returns an ID for the contact.
*/
ContactId addContact(Author remote, AuthorId local,
SecretKey master, long timestamp, boolean alice, boolean verified,
boolean active) throws DbException;
/**
* Returns the contact with the given ID.
*/
Contact getContact(ContactId c) throws DbException;
/**
* Returns the contact with the given remoteAuthorId
* that was added by the LocalAuthor with the given localAuthorId
*
* @throws org.briarproject.bramble.api.db.NoSuchContactException
*/
Contact getContact(AuthorId remoteAuthorId, AuthorId localAuthorId)
throws DbException;
/**
* Returns the contact with the given remoteAuthorId
* that was added by the LocalAuthor with the given localAuthorId
*
* @throws org.briarproject.bramble.api.db.NoSuchContactException
*/
Contact getContact(Transaction txn, AuthorId remoteAuthorId,
AuthorId localAuthorId) throws DbException;
/**
* Returns all active contacts.
*/
Collection<Contact> getActiveContacts() throws DbException;
/**
* Removes a contact and all associated state.
*/
void removeContact(ContactId c) throws DbException;
/**
* Removes a contact and all associated state.
*/
void removeContact(Transaction txn, ContactId c) throws DbException;
/**
* Marks a contact as active or inactive.
*/
void setContactActive(Transaction txn, ContactId c, boolean active)
throws DbException;
/**
* Return true if a contact with this name and public key already exists
*/
boolean contactExists(Transaction txn, AuthorId remoteAuthorId,
AuthorId localAuthorId) throws DbException;
/**
* Return true if a contact with this name and public key already exists
*/
boolean contactExists(AuthorId remoteAuthorId, AuthorId localAuthorId)
throws DbException;
interface AddContactHook {
void addingContact(Transaction txn, Contact c) throws DbException;
}
interface RemoveContactHook {
void removingContact(Transaction txn, Contact c) throws DbException;
}
}

View File

@@ -0,0 +1,31 @@
package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a contact is added.
*/
@Immutable
@NotNullByDefault
public class ContactAddedEvent extends Event {
private final ContactId contactId;
private final boolean active;
public ContactAddedEvent(ContactId contactId, boolean active) {
this.contactId = contactId;
this.active = active;
}
public ContactId getContactId() {
return contactId;
}
public boolean isActive() {
return active;
}
}

View File

@@ -0,0 +1,25 @@
package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a contact is removed.
*/
@Immutable
@NotNullByDefault
public class ContactRemovedEvent extends Event {
private final ContactId contactId;
public ContactRemovedEvent(ContactId contactId) {
this.contactId = contactId;
}
public ContactId getContactId() {
return contactId;
}
}

View File

@@ -0,0 +1,31 @@
package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a contact is marked active or inactive.
*/
@Immutable
@NotNullByDefault
public class ContactStatusChangedEvent extends Event {
private final ContactId contactId;
private final boolean active;
public ContactStatusChangedEvent(ContactId contactId, boolean active) {
this.contactId = contactId;
this.active = active;
}
public ContactId getContactId() {
return contactId;
}
public boolean isActive() {
return active;
}
}

View File

@@ -0,0 +1,26 @@
package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a contact is verified.
*/
@Immutable
@NotNullByDefault
public class ContactVerifiedEvent extends Event {
private final ContactId contactId;
public ContactVerifiedEvent(ContactId contactId) {
this.contactId = contactId;
}
public ContactId getContactId() {
return contactId;
}
}

View File

@@ -1,9 +1,8 @@
package org.briarproject.api.crypto;
package org.briarproject.bramble.api.crypto;
import org.briarproject.api.TransportId;
import org.briarproject.api.transport.TransportKeys;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.transport.TransportKeys;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
@@ -11,14 +10,10 @@ public interface CryptoComponent {
SecretKey generateSecretKey();
MessageDigest getMessageDigest();
PseudoRandom getPseudoRandom(int seed1, int seed2);
SecureRandom getSecureRandom();
Signature getSignature();
KeyPair generateAgreementKeyPair();
KeyParser getAgreementKeyParser();
@@ -44,6 +39,12 @@ public interface CryptoComponent {
*/
SecretKey deriveHeaderKey(SecretKey master, boolean alice);
/**
* Derives a message authentication code key from the given master secret.
* @param alice whether the key is for use by Alice or Bob.
*/
SecretKey deriveMacKey(SecretKey master, boolean alice);
/**
* Derives a nonce from the given master secret for one of the parties to
* sign.
@@ -136,13 +137,50 @@ public interface CryptoComponent {
TransportKeys rotateTransportKeys(TransportKeys k, long rotationPeriod);
/** Encodes the pseudo-random tag that is used to recognise a stream. */
void encodeTag(byte[] tag, SecretKey tagKey, long streamNumber);
void encodeTag(byte[] tag, SecretKey tagKey, int protocolVersion,
long streamNumber);
/**
* Signs the given byte[] with the given PrivateKey.
*
* @param label A label specific to this signature
* to ensure that the signature cannot be repurposed
*/
byte[] sign(String label, byte[] toSign, byte[] privateKey)
throws GeneralSecurityException;
/**
* Verifies that the given signature is valid for the signedData
* and the given publicKey.
*
* @param label A label that was specific to this signature
* to ensure that the signature cannot be repurposed
* @return true if the signature was valid, false otherwise.
*/
boolean verify(String label, byte[] signedData, byte[] publicKey,
byte[] signature) throws GeneralSecurityException;
/**
* Returns the hash of the given inputs. The inputs are unambiguously
* combined by prefixing each input with its length.
*
* @param label A label specific to this hash to ensure that hashes
* calculated for distinct purposes don't collide.
*/
byte[] hash(byte[]... inputs);
byte[] hash(String label, byte[]... inputs);
/**
* Returns the length of hashes produced by
* the {@link CryptoComponent#hash(String, byte[]...)} method.
*/
int getHashLength();
/**
* Returns a message authentication code with the given key over the
* given inputs. The inputs are unambiguously combined by prefixing each
* input with its length.
*/
byte[] mac(SecretKey macKey, byte[]... inputs);
/**
* Encrypts and authenticates the given plaintext so it can be written to
@@ -163,5 +201,11 @@ public interface CryptoComponent {
/**
* Encrypts the given plaintext to the given public key.
*/
String encryptToKey(PublicKey publicKey, byte[] plaintext);
byte[] encryptToKey(PublicKey publicKey, byte[] plaintext);
/**
* Encodes the given data as a hex string divided into lines of the given
* length. The line terminator is CRLF.
*/
String asciiArmour(byte[] b, int lineLength);
}

View File

@@ -0,0 +1,25 @@
package org.briarproject.bramble.api.crypto;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Annotation for injecting the executor for long-running crypto tasks. Also
* used for annotating methods that should run on the crypto executor.
* <p>
* The contract of this executor is that tasks may be run concurrently, and
* submitting a task will never block. Tasks must not run indefinitely. Tasks
* submitted during shutdown are discarded.
*/
@Qualifier
@Target({FIELD, METHOD, PARAMETER})
@Retention(RUNTIME)
public @interface CryptoExecutor {
}

View File

@@ -1,6 +1,14 @@
package org.briarproject.api.crypto;
package org.briarproject.bramble.api.crypto;
/** A key pair consisting of a {@link PublicKey} and a {@link PrivateKey). */
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* A key pair consisting of a {@link PublicKey} and a {@link PrivateKey).
*/
@Immutable
@NotNullByDefault
public class KeyPair {
private final PublicKey publicKey;

View File

@@ -1,7 +1,10 @@
package org.briarproject.api.crypto;
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.security.GeneralSecurityException;
@NotNullByDefault
public interface KeyParser {
PublicKey parsePublicKey(byte[] encodedKey) throws GeneralSecurityException;

View File

@@ -1,11 +1,14 @@
package org.briarproject.api.crypto;
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface PasswordStrengthEstimator {
float NONE = 0;
float WEAK = 0.4f;
float QUITE_WEAK = 0.6f;
float QUITE_STRONG = 0.8f;
float WEAK = 0.25f;
float QUITE_WEAK = 0.5f;
float QUITE_STRONG = 0.75f;
float STRONG = 1;
/**

View File

@@ -0,0 +1,15 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* The private half of a public/private {@link KeyPair}.
*/
@NotNullByDefault
public interface PrivateKey {
/**
* Returns the encoded representation of this key.
*/
byte[] getEncoded();
}

View File

@@ -0,0 +1,12 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* A deterministic pseudo-random number generator.
*/
@NotNullByDefault
public interface PseudoRandom {
byte[] nextBytes(int bytes);
}

View File

@@ -0,0 +1,15 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* The public half of a public/private {@link KeyPair}.
*/
@NotNullByDefault
public interface PublicKey {
/**
* Returns the encoded representation of this key.
*/
byte[] getEncoded();
}

View File

@@ -1,9 +1,14 @@
package org.briarproject.api.crypto;
package org.briarproject.bramble.api.crypto;
/** A secret key used for encryption and/or authentication. */
/**
* A secret key used for encryption and/or authentication.
*/
public class SecretKey {
public static final int LENGTH = 32; // Bytes
/**
* The length of a secret key in bytes.
*/
public static final int LENGTH = 32;
private final byte[] key;

View File

@@ -1,13 +1,17 @@
package org.briarproject.api.crypto;
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.IOException;
@NotNullByDefault
public interface StreamDecrypter {
/**
* Reads a frame, decrypts its payload into the given buffer and returns
* the payload length, or -1 if no more frames can be read from the stream.
* @throws java.io.IOException if an error occurs while reading the frame,
*
* @throws IOException if an error occurs while reading the frame,
* or if authenticated decryption fails.
*/
int readFrame(byte[] payload) throws IOException;

View File

@@ -1,12 +1,16 @@
package org.briarproject.api.crypto;
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.transport.StreamContext;
import java.io.InputStream;
import org.briarproject.api.transport.StreamContext;
@NotNullByDefault
public interface StreamDecrypterFactory {
/** Creates a {@link StreamDecrypter} for decrypting a transport stream. */
/**
* Creates a {@link StreamDecrypter} for decrypting a transport stream.
*/
StreamDecrypter createStreamDecrypter(InputStream in, StreamContext ctx);
/**

View File

@@ -0,0 +1,20 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.IOException;
@NotNullByDefault
public interface StreamEncrypter {
/**
* Encrypts the given frame and writes it to the stream.
*/
void writeFrame(byte[] payload, int payloadLength, int paddingLength,
boolean finalFrame) throws IOException;
/**
* Flushes the stream.
*/
void flush() throws IOException;
}

View File

@@ -1,12 +1,16 @@
package org.briarproject.api.crypto;
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.transport.StreamContext;
import java.io.OutputStream;
import org.briarproject.api.transport.StreamContext;
@NotNullByDefault
public interface StreamEncrypterFactory {
/** Creates a {@link StreamEncrypter} for encrypting a transport stream. */
/**
* Creates a {@link StreamEncrypter} for encrypting a transport stream.
*/
StreamEncrypter createStreamEncrypter(OutputStream out, StreamContext ctx);
/**

View File

@@ -1,13 +1,14 @@
package org.briarproject.api.data;
package org.briarproject.bramble.api.data;
import org.briarproject.api.Bytes;
import org.briarproject.api.FormatException;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.FormatException;
import java.util.Hashtable;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentSkipListMap;
public class BdfDictionary extends Hashtable<String, Object> {
import javax.annotation.Nullable;
public class BdfDictionary extends ConcurrentSkipListMap<String, Object> {
public static final Object NULL_VALUE = new Object();
@@ -40,6 +41,7 @@ public class BdfDictionary extends Hashtable<String, Object> {
throw new FormatException();
}
@Nullable
public Boolean getOptionalBoolean(String key) throws FormatException {
Object o = get(key);
if (o == null || o == NULL_VALUE) return null;
@@ -62,6 +64,7 @@ public class BdfDictionary extends Hashtable<String, Object> {
throw new FormatException();
}
@Nullable
public Long getOptionalLong(String key) throws FormatException {
Object o = get(key);
if (o == null || o == NULL_VALUE) return null;
@@ -88,6 +91,7 @@ public class BdfDictionary extends Hashtable<String, Object> {
throw new FormatException();
}
@Nullable
public Double getOptionalDouble(String key) throws FormatException {
Object o = get(key);
if (o == null || o == NULL_VALUE) return null;
@@ -109,6 +113,7 @@ public class BdfDictionary extends Hashtable<String, Object> {
throw new FormatException();
}
@Nullable
public String getOptionalString(String key) throws FormatException {
Object o = get(key);
if (o == null || o == NULL_VALUE) return null;
@@ -129,6 +134,7 @@ public class BdfDictionary extends Hashtable<String, Object> {
throw new FormatException();
}
@Nullable
public byte[] getOptionalRaw(String key) throws FormatException {
Object o = get(key);
if (o == null || o == NULL_VALUE) return null;
@@ -150,6 +156,7 @@ public class BdfDictionary extends Hashtable<String, Object> {
throw new FormatException();
}
@Nullable
public BdfList getOptionalList(String key) throws FormatException {
Object o = get(key);
if (o == null || o == NULL_VALUE) return null;
@@ -169,6 +176,7 @@ public class BdfDictionary extends Hashtable<String, Object> {
throw new FormatException();
}
@Nullable
public BdfDictionary getOptionalDictionary(String key)
throws FormatException {
Object o = get(key);

View File

@@ -0,0 +1,41 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Map.Entry;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class BdfEntry implements Entry<String, Object>, Comparable<BdfEntry> {
private final String key;
private final Object value;
public BdfEntry(String key, Object value) {
this.key = key;
this.value = value;
}
@Override
public String getKey() {
return key;
}
@Override
public Object getValue() {
return value;
}
@Override
public Object setValue(Object value) {
throw new UnsupportedOperationException();
}
@Override
public int compareTo(BdfEntry e) {
if (e == this) return 0;
return key.compareTo(e.key);
}
}

View File

@@ -1,13 +1,15 @@
package org.briarproject.api.data;
package org.briarproject.bramble.api.data;
import org.briarproject.api.Bytes;
import org.briarproject.api.FormatException;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.FormatException;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import static org.briarproject.api.data.BdfDictionary.NULL_VALUE;
import javax.annotation.Nullable;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
public class BdfList extends Vector<Object> {
@@ -29,13 +31,20 @@ public class BdfList extends Vector<Object> {
super(items);
}
private boolean isInRange(int index) {
return index >= 0 && index < size();
}
public Boolean getBoolean(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof Boolean) return (Boolean) o;
throw new FormatException();
}
@Nullable
public Boolean getOptionalBoolean(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o == null || o == NULL_VALUE) return null;
if (o instanceof Boolean) return (Boolean) o;
@@ -43,12 +52,14 @@ public class BdfList extends Vector<Object> {
}
public Boolean getBoolean(int index, Boolean defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof Boolean) return (Boolean) o;
return defaultValue;
}
public Long getLong(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof Long) return (Long) o;
if (o instanceof Integer) return ((Integer) o).longValue();
@@ -57,7 +68,9 @@ public class BdfList extends Vector<Object> {
throw new FormatException();
}
@Nullable
public Long getOptionalLong(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o == null || o == NULL_VALUE) return null;
if (o instanceof Long) return (Long) o;
@@ -68,6 +81,7 @@ public class BdfList extends Vector<Object> {
}
public Long getLong(int index, Long defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof Long) return (Long) o;
if (o instanceof Integer) return ((Integer) o).longValue();
@@ -77,13 +91,16 @@ public class BdfList extends Vector<Object> {
}
public Double getDouble(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof Double) return (Double) o;
if (o instanceof Float) return ((Float) o).doubleValue();
throw new FormatException();
}
@Nullable
public Double getOptionalDouble(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o == null || o == NULL_VALUE) return null;
if (o instanceof Double) return (Double) o;
@@ -92,6 +109,7 @@ public class BdfList extends Vector<Object> {
}
public Double getDouble(int index, Double defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof Double) return (Double) o;
if (o instanceof Float) return ((Float) o).doubleValue();
@@ -99,12 +117,15 @@ public class BdfList extends Vector<Object> {
}
public String getString(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof String) return (String) o;
throw new FormatException();
}
@Nullable
public String getOptionalString(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o == null || o == NULL_VALUE) return null;
if (o instanceof String) return (String) o;
@@ -112,19 +133,23 @@ public class BdfList extends Vector<Object> {
}
public String getString(int index, String defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof String) return (String) o;
return defaultValue;
}
public byte[] getRaw(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof byte[]) return (byte[]) o;
if (o instanceof Bytes) return ((Bytes) o).getBytes();
throw new FormatException();
}
@Nullable
public byte[] getOptionalRaw(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o == null || o == NULL_VALUE) return null;
if (o instanceof byte[]) return (byte[]) o;
@@ -133,6 +158,7 @@ public class BdfList extends Vector<Object> {
}
public byte[] getRaw(int index, byte[] defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof byte[]) return (byte[]) o;
if (o instanceof Bytes) return ((Bytes) o).getBytes();
@@ -140,12 +166,15 @@ public class BdfList extends Vector<Object> {
}
public BdfList getList(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof BdfList) return (BdfList) o;
throw new FormatException();
}
@Nullable
public BdfList getOptionalList(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o == null || o == NULL_VALUE) return null;
if (o instanceof BdfList) return (BdfList) o;
@@ -153,19 +182,23 @@ public class BdfList extends Vector<Object> {
}
public BdfList getList(int index, BdfList defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof BdfList) return (BdfList) o;
return defaultValue;
}
public BdfDictionary getDictionary(int index) throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof BdfDictionary) return (BdfDictionary) o;
throw new FormatException();
}
@Nullable
public BdfDictionary getOptionalDictionary(int index)
throws FormatException {
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o == null || o == NULL_VALUE) return null;
if (o instanceof BdfDictionary) return (BdfDictionary) o;
@@ -173,6 +206,7 @@ public class BdfList extends Vector<Object> {
}
public BdfDictionary getDictionary(int index, BdfDictionary defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof BdfDictionary) return (BdfDictionary) o;
return defaultValue;

View File

@@ -1,47 +1,75 @@
package org.briarproject.api.data;
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.IOException;
@NotNullByDefault
public interface BdfReader {
int DEFAULT_NESTED_LIMIT = 5;
boolean eof() throws IOException;
void close() throws IOException;
boolean hasNull() throws IOException;
void readNull() throws IOException;
void skipNull() throws IOException;
boolean hasBoolean() throws IOException;
boolean readBoolean() throws IOException;
void skipBoolean() throws IOException;
boolean hasLong() throws IOException;
long readLong() throws IOException;
void skipLong() throws IOException;
boolean hasDouble() throws IOException;
double readDouble() throws IOException;
void skipDouble() throws IOException;
boolean hasString() throws IOException;
String readString(int maxLength) throws IOException;
void skipString() throws IOException;
boolean hasRaw() throws IOException;
byte[] readRaw(int maxLength) throws IOException;
void skipRaw() throws IOException;
boolean hasList() throws IOException;
BdfList readList() throws IOException;
void readListStart() throws IOException;
boolean hasListEnd() throws IOException;
void readListEnd() throws IOException;
void skipList() throws IOException;
boolean hasDictionary() throws IOException;
BdfDictionary readDictionary() throws IOException;
void readDictionaryStart() throws IOException;
boolean hasDictionaryEnd() throws IOException;
void readDictionaryEnd() throws IOException;
void skipDictionary() throws IOException;
}

View File

@@ -0,0 +1,13 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.InputStream;
@NotNullByDefault
public interface BdfReaderFactory {
BdfReader createReader(InputStream in);
BdfReader createReader(InputStream in, int nestedLimit);
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.api.data;
package org.briarproject.bramble.api.data;
import java.io.IOException;
import java.util.Collection;
@@ -7,20 +7,30 @@ import java.util.Map;
public interface BdfWriter {
void flush() throws IOException;
void close() throws IOException;
void writeNull() throws IOException;
void writeBoolean(boolean b) throws IOException;
void writeLong(long l) throws IOException;
void writeDouble(double d) throws IOException;
void writeString(String s) throws IOException;
void writeRaw(byte[] b) throws IOException;
void writeList(Collection<?> c) throws IOException;
void writeListStart() throws IOException;
void writeListEnd() throws IOException;
void writeDictionary(Map<?, ?> m) throws IOException;
void writeDictionaryStart() throws IOException;
void writeDictionaryEnd() throws IOException;
}

View File

@@ -0,0 +1,11 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.OutputStream;
@NotNullByDefault
public interface BdfWriterFactory {
BdfWriter createWriter(OutputStream out);
}

View File

@@ -0,0 +1,11 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface MetadataEncoder {
Metadata encode(BdfDictionary d) throws FormatException;
}

View File

@@ -0,0 +1,11 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface MetadataParser {
BdfDictionary parse(Metadata m) throws FormatException;
}

View File

@@ -0,0 +1,11 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.IOException;
@NotNullByDefault
public interface ObjectReader<T> {
T readObject(BdfReader r) throws IOException;
}

View File

@@ -1,10 +1,8 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
/**
* Thrown when a duplicate contact is added to the database. This exception may
* occur due to concurrent updates and does not indicate a database error.
*/
public class ContactExistsException extends DbException {
private static final long serialVersionUID = -6658762011691502411L;
}

View File

@@ -1,31 +1,38 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
import org.briarproject.api.DeviceId;
import org.briarproject.api.TransportId;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.settings.Settings;
import org.briarproject.api.sync.Ack;
import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId;
import org.briarproject.api.sync.MessageStatus;
import org.briarproject.api.sync.Offer;
import org.briarproject.api.sync.Request;
import org.briarproject.api.transport.TransportKeys;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.sync.Ack;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Group.Visibility;
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.Offer;
import org.briarproject.bramble.api.sync.Request;
import org.briarproject.bramble.api.sync.ValidationManager;
import org.briarproject.bramble.api.transport.TransportKeys;
import java.util.Collection;
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.
*/
@NotNullByDefault
public interface DatabaseComponent {
/**
@@ -49,18 +56,24 @@ public interface DatabaseComponent {
Transaction startTransaction(boolean readOnly) throws DbException;
/**
* Ends a transaction. If the transaction is marked as complete, the
* transaction is committed and any events attached to the transaction are
* broadcast; otherwise the transaction is aborted.
* Commits a transaction to the database.
*/
void endTransaction(Transaction txn) throws DbException;
void commitTransaction(Transaction txn) throws DbException;
/**
* Ends a transaction. If the transaction has not been committed,
* it will be aborted. If the transaction has been committed,
* any events attached to the transaction are broadcast.
* The database lock will be released in either case.
*/
void endTransaction(Transaction txn);
/**
* Stores a contact associated with the given local and remote pseudonyms,
* and returns an ID for the contact.
*/
ContactId addContact(Transaction txn, Author remote, AuthorId local,
boolean active) throws DbException;
boolean verified, boolean active) throws DbException;
/**
* Stores a group.
@@ -75,7 +88,7 @@ public interface DatabaseComponent {
/**
* Stores a local message.
*/
void addLocalMessage(Transaction txn, Message m, ClientId c, Metadata meta,
void addLocalMessage(Transaction txn, Message m, Metadata meta,
boolean shared) throws DbException;
/**
@@ -123,6 +136,7 @@ public interface DatabaseComponent {
* Returns an acknowledgement for the given contact, or null if there are
* no messages to acknowledge.
*/
@Nullable
Ack generateAck(Transaction txn, ContactId c, int maxMessages)
throws DbException;
@@ -132,6 +146,7 @@ public interface DatabaseComponent {
* 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,
int maxLength, int maxLatency) throws DbException;
@@ -140,6 +155,7 @@ public interface DatabaseComponent {
* transport with the given maximum latency, or null if there are no
* messages to offer.
*/
@Nullable
Offer generateOffer(Transaction txn, ContactId c, int maxMessages,
int maxLatency) throws DbException;
@@ -147,6 +163,7 @@ public interface DatabaseComponent {
* Returns a request for the given contact, or null if there are no
* messages to request.
*/
@Nullable
Request generateRequest(Transaction txn, ContactId c, int maxMessages)
throws DbException;
@@ -157,6 +174,7 @@ public interface DatabaseComponent {
* 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,
int maxLength, int maxLatency) throws DbException;
@@ -174,6 +192,14 @@ public interface DatabaseComponent {
*/
Collection<Contact> getContacts(Transaction txn) throws DbException;
/**
* Returns a possibly empty collection of contacts with the given author ID.
* <p/>
* Read-only.
*/
Collection<Contact> getContactsByAuthorId(Transaction txn, AuthorId remote)
throws DbException;
/**
* Returns all contacts associated with the given local pseudonym.
* <p/>
@@ -182,13 +208,6 @@ public interface DatabaseComponent {
Collection<ContactId> getContacts(Transaction txn, AuthorId a)
throws DbException;
/**
* Returns the unique ID for this device.
* <p/>
* Read-only.
*/
DeviceId getDeviceId(Transaction txn) throws DbException;
/**
* Returns the group with the given ID.
* <p/>
@@ -210,6 +229,15 @@ public interface DatabaseComponent {
*/
Collection<Group> getGroups(Transaction txn, ClientId c) throws DbException;
/**
* Returns the given group's visibility to the given contact, or
* {@link Visibility INVISIBLE} if the group is not in the database.
* <p/>
* Read-only.
*/
Visibility getGroupVisibility(Transaction txn, ContactId c, GroupId g)
throws DbException;
/**
* Returns the local pseudonym with the given ID.
* <p/>
@@ -233,16 +261,35 @@ public interface DatabaseComponent {
Collection<MessageId> getMessagesToValidate(Transaction txn, ClientId c)
throws DbException;
/**
* Returns the IDs of any messages that are valid but pending delivery due
* to dependencies on other messages for the given client.
* <p/>
* Read-only.
*/
Collection<MessageId> getPendingMessages(Transaction txn, ClientId c)
throws DbException;
/**
* Returns the IDs of any messages from the given client
* that have a shared dependent, but are still not shared themselves.
* <p/>
* Read-only.
*/
Collection<MessageId> getMessagesToShare(Transaction txn,
ClientId 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(Transaction txn, MessageId m) throws DbException;
/**
* Returns the metadata for all messages in the given group.
* Returns the metadata for all delivered messages in the given group.
* <p/>
* Read-only.
*/
@@ -260,13 +307,22 @@ public interface DatabaseComponent {
Metadata query) throws DbException;
/**
* Returns the metadata for the given message.
* Returns the metadata for the given delivered message.
* <p/>
* Read-only.
*/
Metadata getMessageMetadata(Transaction txn, MessageId m)
throws DbException;
/**
* Returns the metadata for the given delivered and pending message.
* This is meant to be only used by the ValidationManager
* <p/>
* Read-only.
*/
Metadata getMessageMetadataForValidator(Transaction txn, MessageId m)
throws DbException;
/**
* Returns the status of all messages in the given group with respect to
* the given contact.
@@ -276,6 +332,37 @@ public interface DatabaseComponent {
Collection<MessageStatus> getMessageStatus(Transaction txn, ContactId c,
GroupId g) throws DbException;
/**
* Returns the IDs and states of all dependencies of the given message.
* Missing dependencies have the state
* {@link ValidationManager.State UNKNOWN}.
* Dependencies in other groups have the state
* {@link ValidationManager.State INVALID}.
* Note that these states are not set on the dependencies themselves; the
* returned states should only be taken in the context of the given message.
* <p/>
* Read-only.
*/
Map<MessageId, State> getMessageDependencies(Transaction txn, MessageId m)
throws DbException;
/**
* Returns all IDs of messages that depend on the given message.
* Messages in other groups that declare a dependency on the given message
* will be returned even though such dependencies are invalid.
* <p/>
* Read-only.
*/
Map<MessageId, State> 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;
/**
* Returns the status of the given message with respect to the given
* contact.
@@ -307,14 +394,6 @@ public interface DatabaseComponent {
void incrementStreamCounter(Transaction txn, ContactId c, TransportId t,
long rotationPeriod) throws DbException;
/**
* Returns true if the given group is visible to the given contact.
* <p/>
* Read-only.
*/
boolean isVisibleToContact(Transaction txn, ContactId c, GroupId g)
throws DbException;
/**
* Merges the given metadata with the existing metadata for the given
* group.
@@ -378,6 +457,11 @@ public interface DatabaseComponent {
*/
void removeTransport(Transaction txn, TransportId t) throws DbException;
/**
* Marks the given contact as verified.
*/
void setContactVerified(Transaction txn, ContactId c) throws DbException;
/**
* Marks the given contact as active or inactive.
*/
@@ -385,16 +469,27 @@ public interface DatabaseComponent {
throws DbException;
/**
* Marks the given message as shared or unshared.
* Sets the given group's visibility to the given contact.
*/
void setMessageShared(Transaction txn, Message m, boolean shared)
void setGroupVisibility(Transaction txn, ContactId c, GroupId g,
Visibility v) throws DbException;
/**
* Marks the given message as shared.
*/
void setMessageShared(Transaction txn, MessageId m) throws DbException;
/**
* Sets the validation and delivery state of the given message.
*/
void setMessageState(Transaction txn, MessageId m, State state)
throws DbException;
/**
* Marks the given message as valid or invalid.
* Adds dependencies for a message
*/
void setMessageValid(Transaction txn, Message m, ClientId c, boolean valid)
throws DbException;
void addMessageDependencies(Transaction txn, Message dependent,
Collection<MessageId> dependencies) throws DbException;
/**
* Sets the reordering window for the given contact and transport in the
@@ -403,12 +498,6 @@ public interface DatabaseComponent {
void setReorderingWindow(Transaction txn, ContactId c, TransportId t,
long rotationPeriod, long base, byte[] bitmap) throws DbException;
/**
* Makes a group visible or invisible to a contact.
*/
void setVisibleToContact(Transaction txn, ContactId c, GroupId g,
boolean visible) throws DbException;
/**
* Stores the given transport keys, deleting any keys they have replaced.
*/

View File

@@ -0,0 +1,28 @@
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();
void setEncryptionKey(SecretKey key);
@Nullable
SecretKey getEncryptionKey();
void setLocalAuthorName(String nickname);
@Nullable
String getLocalAuthorName();
long getMaxSize();
}

View File

@@ -0,0 +1,26 @@
package org.briarproject.bramble.api.db;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Annotation for injecting the executor for database tasks. Also used for
* annotating methods that should run on the database executor.
* <p>
* The contract of this executor is that tasks are run in the order they're
* submitted, tasks are not run concurrently, and submitting a task will never
* block. Tasks must not run indefinitely. Tasks submitted during shutdown are
* discarded.
*/
@Qualifier
@Target({FIELD, METHOD, PARAMETER})
@Retention(RUNTIME)
public @interface DatabaseExecutor {
}

View File

@@ -0,0 +1,7 @@
package org.briarproject.bramble.api.db;
/**
* Thrown when a database operation is attempted and the database is closed.
*/
public class DbClosedException extends DbException {
}

View File

@@ -0,0 +1,11 @@
package org.briarproject.bramble.api.db;
public class DbException extends Exception {
public DbException() {
}
public DbException(Throwable t) {
super(t);
}
}

View File

@@ -1,7 +1,10 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
import java.util.Hashtable;
import javax.annotation.concurrent.ThreadSafe;
@ThreadSafe
public class Metadata extends Hashtable<String, byte[]> {
/**

View File

@@ -1,4 +1,4 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
/**
* Thrown when a database operation is attempted for a contact that is not in
@@ -6,6 +6,4 @@ package org.briarproject.api.db;
* not indicate a database error.
*/
public class NoSuchContactException extends DbException {
private static final long serialVersionUID = -7048538231308207386L;
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
/**
* Thrown when a database operation is attempted for a group that is not in the
@@ -6,6 +6,4 @@ package org.briarproject.api.db;
* indicate a database error.
*/
public class NoSuchGroupException extends DbException {
private static final long serialVersionUID = -5494178507342571697L;
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
/**
* Thrown when a database operation is attempted for a pseudonym that is not in
@@ -6,6 +6,4 @@ package org.briarproject.api.db;
* not indicate a database error.
*/
public class NoSuchLocalAuthorException extends DbException {
private static final long serialVersionUID = 494398665376703860L;
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
/**
* Thrown when a database operation is attempted for a message that is not in
@@ -6,6 +6,4 @@ package org.briarproject.api.db;
* not indicate a database error.
*/
public class NoSuchMessageException extends DbException {
private static final long serialVersionUID = 9191508339698803848L;
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
/**
* Thrown when a database operation is attempted for a transport that is not in
@@ -6,6 +6,4 @@ package org.briarproject.api.db;
* not indicate a database error.
*/
public class NoSuchTransportException extends DbException {
private static final long serialVersionUID = -6274982612759573100L;
}

View File

@@ -1,21 +1,24 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
import org.briarproject.api.event.Event;
import org.briarproject.bramble.api.event.Event;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.concurrent.NotThreadSafe;
/**
* A wrapper around a database transaction. Transactions are not thread-safe.
*/
@NotThreadSafe
public class Transaction {
private final Object txn;
private final boolean readOnly;
private List<Event> events = null;
private boolean complete = false;
private boolean committed = false;
public Transaction(Object txn, boolean readOnly) {
this.txn = txn;
@@ -55,18 +58,18 @@ public class Transaction {
}
/**
* Returns true if the transaction is ready to be committed.
* Returns true if the transaction has been committed.
*/
public boolean isComplete() {
return complete;
public boolean isCommitted() {
return committed;
}
/**
* Marks the transaction as ready to be committed. This method must not be
* called more than once.
* Marks the transaction as committed. This method should only be called
* by the DatabaseComponent. It must not be called more than once.
*/
public void setComplete() {
if (complete) throw new IllegalStateException();
complete = true;
public void setCommitted() {
if (committed) throw new IllegalStateException();
committed = true;
}
}

View File

@@ -0,0 +1,7 @@
package org.briarproject.bramble.api.event;
/**
* An abstract superclass for events.
*/
public abstract class Event {
}

View File

@@ -0,0 +1,22 @@
package org.briarproject.bramble.api.event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface EventBus {
/**
* Adds a listener to be notified when events occur.
*/
void addListener(EventListener l);
/**
* Removes a listener.
*/
void removeListener(EventListener l);
/**
* Notifies all listeners of an event.
*/
void broadcast(Event e);
}

View File

@@ -0,0 +1,16 @@
package org.briarproject.bramble.api.event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* An interface for receiving notifications when events occur.
*/
@NotNullByDefault
public interface EventListener {
/**
* Called when an event is broadcast. Implementations of this method must
* not block.
*/
void eventOccurred(Event e);
}

View File

@@ -1,11 +1,21 @@
package org.briarproject.api.identity;
package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.UnsupportedEncodingException;
/** A pseudonym for a user. */
import javax.annotation.concurrent.Immutable;
/**
* A pseudonym for a user.
*/
@Immutable
@NotNullByDefault
public class Author {
public enum Status { ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED }
public enum Status {
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES
}
private final AuthorId id;
private final String name;
@@ -25,17 +35,23 @@ public class Author {
this.publicKey = publicKey;
}
/** Returns the author's unique identifier. */
/**
* Returns the author's unique identifier.
*/
public AuthorId getId() {
return id;
}
/** Returns the author's name. */
/**
* Returns the author's name.
*/
public String getName() {
return name;
}
/** Returns the public key used to verify the pseudonym's signatures. */
/**
* Returns the public key used to verify the pseudonym's signatures.
*/
public byte[] getPublicKey() {
return publicKey;
}

View File

@@ -1,8 +1,10 @@
package org.briarproject.api.identity;
package org.briarproject.bramble.api.identity;
public interface AuthorConstants {
/** The maximum length of an author's name in UTF-8 bytes. */
/**
* The maximum length of an author's name in UTF-8 bytes.
*/
int MAX_AUTHOR_NAME_LENGTH = 50;
/**

View File

@@ -1,5 +1,8 @@
package org.briarproject.api.identity;
package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface AuthorFactory {
Author createAuthor(String name, byte[] publicKey);

View File

@@ -1,20 +1,22 @@
package org.briarproject.api.identity;
package org.briarproject.bramble.api.identity;
import org.briarproject.api.UniqueId;
import org.briarproject.bramble.api.UniqueId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.nio.charset.Charset;
import javax.annotation.concurrent.ThreadSafe;
/**
* Type-safe wrapper for a byte array that uniquely identifies an
* {@link org.briarproject.api.identity.Author Author}.
* {@link Author}.
*/
@ThreadSafe
@NotNullByDefault
public class AuthorId extends UniqueId {
/**
* Label for hashing authors to calculate their identities.
*/
public static final byte[] LABEL =
"AUTHOR_ID".getBytes(Charset.forName("US-ASCII"));
public static final String LABEL = "org.briarproject.bramble.AUTHOR_ID";
public AuthorId(byte[] id) {
super(id);

View File

@@ -0,0 +1,38 @@
package org.briarproject.bramble.api.identity;
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.
*/
void registerLocalAuthor(LocalAuthor a) throws DbException;
/**
* Returns the cached main local identity, non-blocking, or loads it from
* the db, blocking
*/
LocalAuthor getLocalAuthor() throws DbException;
/**
* Returns the cached main local identity, non-blocking, or loads it from
* the db, blocking, within the given Transaction.
*/
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

@@ -1,6 +1,14 @@
package org.briarproject.api.identity;
package org.briarproject.bramble.api.identity;
/** A pseudonym for the local user. */
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* A pseudonym for the local user.
*/
@Immutable
@NotNullByDefault
public class LocalAuthor extends Author {
private final byte[] privateKey;
@@ -13,7 +21,9 @@ public class LocalAuthor extends Author {
this.created = created;
}
/** Returns the private key used to generate the pseudonym's signatures. */
/**
* Returns the private key used to generate the pseudonym's signatures.
*/
public byte[] getPrivateKey() {
return privateKey;
}

View File

@@ -0,0 +1,25 @@
package org.briarproject.bramble.api.identity.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a local pseudonym is added.
*/
@Immutable
@NotNullByDefault
public class LocalAuthorAddedEvent extends Event {
private final AuthorId authorId;
public LocalAuthorAddedEvent(AuthorId authorId) {
this.authorId = authorId;
}
public AuthorId getAuthorId() {
return authorId;
}
}

View File

@@ -0,0 +1,25 @@
package org.briarproject.bramble.api.identity.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a local pseudonym is removed.
*/
@Immutable
@NotNullByDefault
public class LocalAuthorRemovedEvent extends Event {
private final AuthorId authorId;
public LocalAuthorRemovedEvent(AuthorId authorId) {
this.authorId = authorId;
}
public AuthorId getAuthorId() {
return authorId;
}
}

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