1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-05 23:53:33 +00:00

Compare commits

...

167 Commits

Author SHA1 Message Date
Kyle Spearrin
405c4d1706 New Crowdin updates (#1155)
* New translations AppResources.resx (Romanian)

* New translations AppResources.resx (Portuguese, Brazilian)

* New translations copy.resx (Serbian (Cyrillic))

* New translations copy.resx (Serbian (Cyrillic))

* New translations AppResources.resx (Swedish)

* New translations AppResources.resx (Turkish)

* New translations AppResources.resx (Ukrainian)

* New translations AppResources.resx (Chinese Simplified)

* New translations AppResources.resx (Chinese Traditional)

* New translations AppResources.resx (Vietnamese)

* New translations AppResources.resx (Indonesian)

* New translations copy.resx (Slovak)

* New translations AppResources.resx (Persian)

* New translations AppResources.resx (Thai)

* New translations AppResources.resx (Croatian)

* New translations AppResources.resx (Estonian)

* New translations AppResources.resx (Latvian)

* New translations AppResources.resx (Hindi)

* New translations AppResources.resx (English, United Kingdom)

* New translations AppResources.resx (Malayalam)

* New translations AppResources.resx (Sinhala)

* New translations AppResources.resx (Norwegian Bokmal)

* New translations AppResources.resx (Serbian (Cyrillic))

* New translations copy.resx (Slovak)

* New translations AppResources.resx (French)

* New translations AppResources.resx (Finnish)

* New translations copy.resx (French)

* New translations AppResources.resx (Spanish)

* New translations AppResources.resx (Afrikaans)

* New translations AppResources.resx (Belarusian)

* New translations AppResources.resx (Bulgarian)

* New translations AppResources.resx (Catalan)

* New translations AppResources.resx (Czech)

* New translations AppResources.resx (Danish)

* New translations AppResources.resx (German)

* New translations AppResources.resx (Greek)

* New translations AppResources.resx (Hebrew)

* New translations AppResources.resx (Slovak)

* New translations AppResources.resx (Hungarian)

* New translations AppResources.resx (Italian)

* New translations AppResources.resx (Japanese)

* New translations AppResources.resx (Korean)

* New translations AppResources.resx (Dutch)

* New translations AppResources.resx (Polish)

* New translations AppResources.resx (Portuguese)

* New translations AppResources.resx (Russian)

* New translations AppResources.resx (English, India)

* New translations copy.resx (French)

* New translations copy.resx (French)
2020-11-19 09:05:37 -05:00
Matt Portune
f7e081ba5d bump version to 2.7.0 (#1153) 2020-11-17 15:23:41 -05:00
Matt Portune
c71deb5051 Enhanced autofill settings (#1150)
* enhanced autofill settings

* cleanup
2020-11-17 09:37:57 -05:00
Vincent Salucci
edab722a76 Updated privacy policy links for theming (#1149) 2020-11-13 14:00:01 -06:00
Kyle Spearrin
2d280bd995 New Crowdin updates (#1148)
* New translations AppResources.resx (Romanian)

* New translations copy.resx (Ukrainian)

* New translations copy.resx (Portuguese, Brazilian)

* New translations copy.resx (Portuguese, Brazilian)

* New translations AppResources.resx (Portuguese, Brazilian)

* New translations copy.resx (Vietnamese)

* New translations copy.resx (Vietnamese)

* New translations copy.resx (Chinese Traditional)

* New translations copy.resx (Chinese Traditional)

* New translations copy.resx (Chinese Simplified)

* New translations copy.resx (Chinese Simplified)

* New translations AppResources.resx (Chinese Simplified)

* New translations copy.resx (Ukrainian)

* New translations copy.resx (Indonesian)

* New translations AppResources.resx (Ukrainian)

* New translations copy.resx (Turkish)

* New translations copy.resx (Turkish)

* New translations copy.resx (Swedish)

* New translations copy.resx (Swedish)

* New translations copy.resx (Serbian (Cyrillic))

* New translations copy.resx (Serbian (Cyrillic))

* New translations AppResources.resx (Serbian (Cyrillic))

* New translations copy.resx (Slovak)

* New translations copy.resx (Slovak)

* New translations AppResources.resx (Indonesian)

* New translations copy.resx (Indonesian)

* New translations copy.resx (Russian)

* New translations copy.resx (English, United Kingdom)

* New translations copy.resx (English, India)

* New translations copy.resx (Norwegian Bokmal)

* New translations copy.resx (Norwegian Bokmal)

* New translations copy.resx (Sinhala)

* New translations copy.resx (Sinhala)

* New translations copy.resx (Malayalam)

* New translations copy.resx (Malayalam)

* New translations AppResources.resx (Malayalam)

* New translations copy.resx (English, United Kingdom)

* New translations AppResources.resx (English, United Kingdom)

* New translations copy.resx (Persian)

* New translations copy.resx (Hindi)

* New translations copy.resx (Hindi)

* New translations copy.resx (Latvian)

* New translations copy.resx (Latvian)

* New translations copy.resx (Estonian)

* New translations copy.resx (Estonian)

* New translations copy.resx (Croatian)

* New translations copy.resx (Croatian)

* New translations copy.resx (Thai)

* New translations copy.resx (Thai)

* New translations copy.resx (Persian)

* New translations AppResources.resx (Slovak)

* New translations copy.resx (Russian)

* New translations copy.resx (Romanian)

* New translations copy.resx (Bulgarian)

* New translations copy.resx (German)

* New translations AppResources.resx (German)

* New translations copy.resx (Danish)

* New translations copy.resx (Danish)

* New translations AppResources.resx (Danish)

* New translations copy.resx (Czech)

* New translations copy.resx (Czech)

* New translations copy.resx (Catalan)

* New translations copy.resx (Catalan)

* New translations AppResources.resx (Catalan)

* New translations copy.resx (Bulgarian)

* New translations AppResources.resx (Greek)

* New translations copy.resx (Belarusian)

* New translations copy.resx (Belarusian)

* New translations copy.resx (Afrikaans)

* New translations copy.resx (Afrikaans)

* New translations copy.resx (Spanish)

* New translations copy.resx (Spanish)

* New translations AppResources.resx (Spanish)

* New translations copy.resx (French)

* New translations copy.resx (French)

* New translations AppResources.resx (French)

* New translations copy.resx (Romanian)

* New translations copy.resx (German)

* New translations copy.resx (Greek)

* New translations AppResources.resx (Russian)

* New translations copy.resx (Korean)

* New translations copy.resx (Portuguese)

* New translations copy.resx (Portuguese)

* New translations AppResources.resx (Portuguese)

* New translations copy.resx (Polish)

* New translations copy.resx (Polish)

* New translations AppResources.resx (Polish)

* New translations copy.resx (Dutch)

* New translations copy.resx (Dutch)

* New translations AppResources.resx (Dutch)

* New translations copy.resx (Korean)

* New translations copy.resx (Japanese)

* New translations copy.resx (Greek)

* New translations copy.resx (Japanese)

* New translations copy.resx (Italian)

* New translations copy.resx (Italian)

* New translations copy.resx (Hungarian)

* New translations copy.resx (Hungarian)

* New translations AppResources.resx (Hungarian)

* New translations copy.resx (Hebrew)

* New translations copy.resx (Hebrew)

* New translations copy.resx (Finnish)

* New translations copy.resx (Finnish)

* New translations AppResources.resx (Finnish)

* New translations copy.resx (English, India)
2020-11-12 21:45:25 -05:00
Trey Greer
27e3c6553e updated english copy for the app stores (#1101) 2020-11-12 15:14:46 -05:00
eliykat
6258a9cff9 reposition buttons in Log In and Unlock pages (#1073)
* reposition buttons in Log In and Unlock pages

-   Log In page: move Log In button to primary location below password
    entry, move Get Your Master Password Hint to the More Options menu
-   Unlock page (Verify Master Password): swap position of Unlock
    and Log Out buttons

* finish changes to improved login ui

- move Log Out button in lock screen to secondary menu
- show Get Hint button on login screen in the iOS autofill login flow

Co-authored-by: Matt Portune <59324545+mportune-bw@users.noreply.github.com>
2020-11-12 11:23:34 -05:00
eliykat
a72f497581 expand contributing guide (#1147) 2020-11-12 09:39:24 -05:00
Matt Portune
311d3dd635 Android 11 inline autofill (#1145)
* Inline autofill support for Android 11 - initial commit

* null check intent before getting bool extra

* Updated xamarin androidx autofill

* fixed broken overlay fallback

* fixed filename

* auto-compat-check cleanup

* simplification
2020-11-10 17:24:24 -05:00
Kyle Spearrin
e80b3e4542 New Crowdin updates (#1146)
* New translations AppResources.resx (Romanian)

* New translations AppResources.resx (Persian)

* New translations AppResources.resx (Serbian (Cyrillic))

* New translations copy.resx (Serbian (Cyrillic))

* New translations copy.resx (Serbian (Cyrillic))

* New translations AppResources.resx (Swedish)

* New translations AppResources.resx (Turkish)

* New translations AppResources.resx (Ukrainian)

* New translations AppResources.resx (Chinese Simplified)

* New translations AppResources.resx (Chinese Traditional)

* New translations AppResources.resx (Vietnamese)

* New translations AppResources.resx (Portuguese, Brazilian)

* New translations AppResources.resx (Indonesian)

* New translations AppResources.resx (Thai)

* New translations AppResources.resx (Russian)

* New translations AppResources.resx (Croatian)

* New translations AppResources.resx (Estonian)

* New translations AppResources.resx (Latvian)

* New translations AppResources.resx (Hindi)

* New translations AppResources.resx (English, United Kingdom)

* New translations AppResources.resx (Malayalam)

* New translations AppResources.resx (Sinhala)

* New translations AppResources.resx (Norwegian Bokmal)

* New translations AppResources.resx (English, India)

* New translations AppResources.resx (Slovak)

* New translations AppResources.resx (Portuguese)

* New translations copy.resx (Romanian)

* New translations AppResources.resx (Danish)

* New translations AppResources.resx (French)

* New translations AppResources.resx (Spanish)

* New translations AppResources.resx (Afrikaans)

* New translations AppResources.resx (Belarusian)

* New translations copy.resx (Belarusian)

* New translations copy.resx (Belarusian)

* New translations AppResources.resx (Bulgarian)

* New translations AppResources.resx (Catalan)

* New translations AppResources.resx (Czech)

* New translations AppResources.resx (German)

* New translations AppResources.resx (Polish)

* New translations AppResources.resx (Greek)

* New translations AppResources.resx (Finnish)

* New translations AppResources.resx (Hebrew)

* New translations AppResources.resx (Hungarian)

* New translations AppResources.resx (Italian)

* New translations AppResources.resx (Japanese)

* New translations AppResources.resx (Korean)

* New translations AppResources.resx (Dutch)

* New translations copy.resx (English, India)

* New translations copy.resx (English, India)
2020-11-10 17:20:44 -05:00
Vincent Salucci
82c96555dc [GDPR] Adjusted TOS/Privacy acceptance (#1138)
* GDPR acceptance flows

* Added specialized margin by platform

* Changed property name
2020-11-05 10:50:18 -06:00
Matt Portune
75b6e69d34 testing removal of setup-nuget (#1137) 2020-11-03 13:46:13 -05:00
Matt Portune
532b5f7c33 change msbuild reference to v1 (#1136) 2020-11-03 13:23:31 -05:00
Matt Portune
a841419c30 Use plain shield icon for accessibility overlay for quick identification (#1135) 2020-11-03 12:30:34 -05:00
Matt Portune
730a56380a Replacement of bitmap icons with vector versions (Android) (#1133) 2020-11-02 11:44:39 -05:00
stevenlele
97aa974443 Update support for several browsers and HTML viewer (#1121)
* Update accessibility support for Via browser

* Add Via browser (CN) & HTML viewer to AutofillHelpers

* Add Via browser (CN) & HTML viewer to autofillservice

* Add browsers to AccessibilityHelpers

* Add browsers to AutofillHelpers

* Add browsers to autofillservice
2020-10-21 09:10:31 -04:00
Matt Portune
b2eee8bde7 remove deprecated info.plist key (#1127) 2020-10-20 16:15:13 -04:00
Matt Portune
3cbe932248 Additional support for system theme setting (#1124)
* first pass with iOS 13+ support

* tweaks for ios pre-13

* Added Android support for dark/light splash & detection with default theme

* update cipher cell text color on system theme change (android)
2020-10-20 15:26:25 -04:00
Vincent Salucci
26d5504a2f Added New policy types (only org & require sso) (#1122) 2020-10-19 11:48:42 -05:00
Matt Portune
b163a0fe77 fix for stuck extension sheets when dismissed by swipe (#1117)
* fix for stuck extension sheets when dismissed by swipe

* simplify dismiss action assignments
2020-10-15 14:34:31 -04:00
Contribucious
523e713d7a [KnownUsernameField] Entries update (Top 20 JP enhancement) (#1051)
This adds support for alternative access for NTT DOCOMO (KnownUsernameField > Top 20 Japan).
2020-10-15 13:10:08 -04:00
Contribucious
c7cf634a94 Update support for Ungoogled Chromium browser (#1119) 2020-10-15 12:34:32 -04:00
Contribucious
c8c14396f1 Firefox (+ some forks): switch resource-id priority order (#1116) 2020-10-15 12:24:40 -04:00
Vincent Salucci
e72ccaf440 Initial commit for new user provision flow (#1091) 2020-10-13 15:01:14 -05:00
Matt Portune
0b7e07ebab clear cipher cache when replacing ios autofill identities (#1112)
* clear cipher cache when replacing ios autofill identities

* changed to be service-centric

* support for multiple cache keys

* async suffix

* added cache keys for android
2020-10-13 15:39:36 -04:00
Matt Portune
37e19d9a60 Support for storing multiple biometric integrity states for iOS (#1110)
* support for storing multiple biometric integrity states for iOS

* remove unused var & save new extension bio state upon password validation
2020-10-07 12:18:36 -04:00
yaakovfeldman
8f533bc576 Add support for Iceraven browser (#1106)
* Add support for Iceraven browser

* Remove legacy Firefox support from Iceraven
2020-10-05 09:15:01 -04:00
Matt Portune
096a9561ed workaround for xamarin.android issue with Android 11 emulator debugging (#1102) 2020-10-01 14:36:52 -04:00
Matt Portune
c6ac9376fc re-select support for android tabbed page buttons (#1100)
* re-select support for android tabbed page buttons

* applied Sane Person Technology (tm) to index check

* remove extra line
2020-10-01 14:16:37 -04:00
TheDuffman85
fd55cf6996 Update AddEditPage.xaml (#1097)
Removed Keyboard="Numeric" property from CardNumberEntry. European debit card numbers are alphanumeric. See also https://en.wikipedia.org/wiki/International_Bank_Account_Number.
2020-09-30 10:45:07 -04:00
Matt Portune
0359705361 fix issue with bio unlock button visibility (#1098) 2020-09-30 10:23:55 -04:00
Chad Scharf
e31a7e5236 Remap pt to pt-BR instead of pt-PT and handle valid mapping of pt to pt-BR initially (#1096)
* Rename pt-BR to pt, mapping for crowdin

* Map localized pt to pt-BR

* Revert "Rename pt-BR to pt, mapping for crowdin"

This reverts commit 42a09e14b7.
2020-09-29 10:58:50 -04:00
Kyle Spearrin
bb477908ef map en-IN 2020-09-28 14:22:09 -04:00
Matt Portune
26175fbe1b fix issue with search bar color on iOS (#1095) 2020-09-28 10:14:31 -04:00
Matt Portune
67bc59f6b6 bump version to 2.6.2 (#1094) 2020-09-26 07:41:02 -04:00
Matt Portune
7b358b1bbb biometric integrity check in iOS extensions (#1093) 2020-09-25 21:14:10 -04:00
Trey Greer
0387d5bdd1 Android + iOS screenshot updates (#971)
* added Android Screenshots

* added new iOS Screenshots

* fixed resolution for some screenshots

* fixed resolution for iPad pro #5

* modified iPhone 6+ images
2020-09-23 09:06:44 -04:00
Matt Portune
2ddf624f7d fix for sso login when bio unlock already enabled (#1086) 2020-09-23 09:02:20 -04:00
Indranil012
74b34661a5 To add autofill support for Idm browser (#1085)
* Update AutofillHelpers.cs

* Update autofillservice.xml

* Update AccessibilityHelpers.cs

* Update AccessibilityHelpers.cs
2020-09-22 09:17:47 -04:00
Matt Portune
dc9765ef58 version bumps to 2.6.1 (#1083) 2020-09-21 19:56:49 -04:00
Oscar Hinton
a50e66faf4 Handle if GetState is null in biometric integrity check (#1082) 2020-09-21 12:34:22 -04:00
Matt Portune
0388738e02 fix issue with biometric validation (#1081)
* fix issue with biometric validation

* null check key & cipher
2020-09-21 11:59:56 -04:00
Kyle Spearrin
d33e38012a update languages (#1080) 2020-09-21 10:20:45 -04:00
vachan-maker
785d0b21c6 Update MobileI18nService.cs (#1075) 2020-09-21 08:23:51 -04:00
Kyle Spearrin
db12cd92b7 check authed before checking if token has premium (#1074) 2020-09-18 15:07:32 -04:00
Kyle Spearrin
52261f99d7 New Crowdin updates (#1071)
* New translations AppResources.resx (Romanian)

* New translations AppResources.resx (Bulgarian)
2020-09-15 12:54:53 -04:00
Kyle Spearrin
692dc154ef New Crowdin updates (#1070)
* New translations AppResources.resx (Romanian)

* New translations AppResources.resx (French)

* New translations AppResources.resx (Estonian)

* New translations AppResources.resx (Persian)

* New translations AppResources.resx (Portuguese, Brazilian)

* New translations copy.resx (Chinese Simplified)

* New translations AppResources.resx (Chinese Simplified)

* New translations AppResources.resx (Ukrainian)

* New translations AppResources.resx (Turkish)

* New translations AppResources.resx (Swedish)

* New translations AppResources.resx (Slovak)

* New translations AppResources.resx (Russian)

* New translations AppResources.resx (Portuguese)

* New translations AppResources.resx (Polish)

* New translations AppResources.resx (Dutch)

* New translations copy.resx (Korean)

* New translations AppResources.resx (Korean)

* New translations AppResources.resx (Japanese)

* New translations AppResources.resx (Italian)

* New translations AppResources.resx (Hungarian)

* New translations AppResources.resx (Finnish)

* New translations AppResources.resx (German)

* New translations AppResources.resx (Danish)

* New translations AppResources.resx (Catalan)

* New translations AppResources.resx (Spanish)

* New translations AppResources.resx (English, United Kingdom)

* New translations AppResources.resx (Malayalam)
2020-09-14 10:49:42 -04:00
Matt Portune
22101d8f4a fix for passphrase generator persistent settings (#1065) 2020-09-10 12:19:02 -04:00
Matt Portune
f68db90b1f fix state comparison (value vs instance) (#1063) 2020-09-09 11:51:28 -04:00
Kyle Spearrin
5e680531da New Crowdin updates (#1062)
* New translations AppResources.resx (Romanian)

* New translations AppResources.resx (Portuguese)

* New translations AppResources.resx (Polish)

* New translations AppResources.resx (Dutch)

* New translations AppResources.resx (Korean)

* New translations AppResources.resx (Japanese)

* New translations AppResources.resx (Slovak)

* New translations AppResources.resx (Italian)

* New translations AppResources.resx (Vietnamese)

* New translations AppResources.resx (Chinese Traditional)

* New translations AppResources.resx (Chinese Simplified)

* New translations AppResources.resx (Ukrainian)

* New translations AppResources.resx (Turkish)

* New translations AppResources.resx (Swedish)

* New translations AppResources.resx (Russian)

* New translations AppResources.resx (Catalan)

* New translations AppResources.resx (Bulgarian)

* New translations AppResources.resx (Belarusian)

* New translations AppResources.resx (Afrikaans)

* New translations AppResources.resx (Spanish)

* New translations AppResources.resx (French)

* New translations AppResources.resx (Czech)

* New translations AppResources.resx (Hebrew)

* New translations AppResources.resx (Finnish)

* New translations AppResources.resx (Hungarian)

* New translations AppResources.resx (German)

* New translations AppResources.resx (Danish)

* New translations AppResources.resx (Greek)

* New translations copy.resx (Latvian)

* New translations copy.resx (Latvian)

* New translations AppResources.resx (Hindi)

* New translations copy.resx (Hindi)

* New translations AppResources.resx (English, United Kingdom)

* New translations AppResources.resx (Sinhala)

* New translations AppResources.resx (Malayalam)

* New translations copy.resx (Malayalam)

* New translations copy.resx (Malayalam)

* New translations AppResources.resx (Norwegian Bokmal)

* New translations AppResources.resx (Latvian)

* New translations AppResources.resx (Portuguese, Brazilian)

* New translations AppResources.resx (Indonesian)

* New translations AppResources.resx (Persian)

* New translations AppResources.resx (Estonian)

* New translations AppResources.resx (Thai)

* New translations AppResources.resx (Croatian)
2020-09-08 11:30:08 -04:00
Matt Portune
93cd31018e publish to google play internal test track (#1061)
publish directly to internal test track to skip play store approval process for internal testers (artifact can then be manually promoted to alpha > beta > prod like before).  This should bring the testing experience up to speed with TestFlight for iOS (i.e. push code > ci build > immediate availability)
2020-09-06 20:18:44 -04:00
Chad Scharf
277c570723 version bump (#1060) 2020-09-05 21:50:38 -04:00
Matt Portune
f1419a75f6 Added SSO flows and functionality (#1047)
* SSO login flow for pre-existing user and no 2FA

* 2FA progress

* 2FA support

* Added SSO flows and functionality

* Handle webauthenticator cancellation gracefully

* updates & bugfixes

* Added state validation to web auth response handling

* SSO auth, account registration, and environment settings support for iOS extensions

* Added SSO prevalidation to auth process

* prevalidation now hitting identity service base url

* additional error handling

* Requested changes

* fixed case
2020-09-03 12:30:40 -04:00
Contribucious
3af08a4727 [KnownUsernameField] Entries update (Yandex) (#1044)
This adds all missing entries for Yandex (exhaustive list of Yandex domain names obtained by contacting their support).
2020-08-20 09:56:11 -04:00
Contribucious
a535cea85f [KnownUsernameField] Fix for the special case "eBay India" (#1041)
See explanations in the PR.
2020-08-17 15:13:13 -04:00
Kyle Spearrin
29e443ed76 base64 url encode/decode heleprs (#1038) 2020-08-14 10:08:50 -04:00
Oscar Hinton
f95cddd05a Return the correct value for valid biometric (#1037) 2020-08-12 15:55:15 -04:00
Oscar Hinton
ae28de4159 Invalidate biometric on change (#1026)
* Initial working version for Android

* Add a fallback for when upgrading from older app version.

* Ensure biometric validity is re-checked on focus

* Only setup biometric integrity key if biometric is turned on.

* Fix styling according to comments

* Fallback for Android 5.

* Improve comment

* Add boilerplate for iOS

* Change BiometricService to public

* Untested iOS implementation.

* Convert IBiometricService to async. Fix code style for iOS.

* Base64 NSData.

* Review comments for Android BiometricService.

* Rename methods in BiometricService to append Async

* Ensure we wait for async SetupBiometricAsync.

* Update BiometricService.cs

Co-authored-by: Kyle Spearrin <kspearrin@users.noreply.github.com>
2020-08-08 21:33:49 -04:00
Contribucious
39de2c1d25 [KnownUsernameField] Entries update (main ones) (#1034)
* [KUF] Fix Google; Add natl/dskp Amazon/eBay & Atlassian+Bitly ENT.+Tumblr+Yandex

... also, add missing OAuth support for PayPal. And add "My docomo" from NTT DOCOMO, as part of a Top 20 Japan.

* Less spacing

* Even less spacing

* Additional reduction of spacing

* [Perf. optim.] Google: most frequently used entry in first position
2020-08-07 11:02:08 -04:00
Contribucious
22570e08aa [KnownUsernameField] Engine update (make the system more flexible) (#1011)
* [KnownUsernameField] Engine update (make the system more flexible)

* [KnownUsernameField] Engine update (make the system more flexible)

* Use of tuples array instead of multidimensional array (string[,])

* Use of tuples array instead of multidimensional array (string[,])

* [FIX] IndexOf -> Contains
2020-08-06 12:38:25 -04:00
aaxdev
3b4ef4d238 Feature sync on refresh (#937)
* Added new option: Sync on refresh

* Removed unused field

* Fixed refreshing on disappearing & unnecessary codes removed

* Requested changes

* Calling storage service instead of a dedicated service function (mobile-specific)
2020-08-05 13:19:27 -04:00
Chad Scharf
c5a71c4304 Fix Pin cannot be hidden after showing it #1025 (#1027) 2020-07-30 13:46:06 -04:00
K. Sasa
4f37c2cb73 Replace copy value button fa-clipboard(&#xf0ea;) to fa-clone(&#xf24d;) (#1024) 2020-07-27 13:22:27 -04:00
Chad Scharf
c1ec97055c Added android:installLocation=internalOnly (#1019) 2020-07-23 09:19:11 -04:00
Matt Smith
086c71126f Allow only non-deleted creds to be added to autofill (#1015) 2020-07-16 11:53:02 -05:00
Matt Smith
10a78c1c94 Modified listing of website from Hostname to Host (#1012)
* Modified listing of website from Hostname to Host

* Removed last _hostname artifact.
2020-07-14 13:17:08 -05:00
Gal Szkolnik
cf6021d898 Don't break when CipherType data is null (#1008)
as explained in issue https://github.com/bitwarden/mobile/issues/1006
2020-07-11 09:06:48 -04:00
Matt Smith
ff322cd2dd Modified Permissions Flow (#1005)
Permissions flow for Android was causing the white screen on initial permission grant on occasion. Moved permission grant to pre-TOTP page load.
2020-07-08 14:09:08 -05:00
Kyle Spearrin
1a96d3c38e bump version 2020-07-06 14:36:10 -04:00
Kyle Spearrin
cfe84963fa switch to access token, bump version 2020-07-06 13:54:44 -04:00
Kyle Spearrin
d908a599b1 bump version and build fixes 2020-07-06 13:28:19 -04:00
Kyle Spearrin
9b3ddb8da3 bump version via hub release command 2020-07-06 11:56:00 -04:00
Kyle Spearrin
56d994a69d bump version 2020-07-06 11:27:19 -04:00
Kyle Spearrin
67cd17c604 do actions on master push or release event 2020-07-06 11:26:51 -04:00
Kyle Spearrin
f4fb7eb8b7 New Crowdin updates (#1003)
* New translations AppResources.resx (Dutch)

* New translations AppResources.resx (Slovak)
2020-07-06 10:39:38 -04:00
Kyle Spearrin
b9021e4331 bump version 2020-07-06 10:36:23 -04:00
Kyle Spearrin
3583836d3e Upload release assets for ios too 2020-07-06 09:55:16 -04:00
Kyle Spearrin
278815119f update workflow for release tasks 2020-07-06 09:50:26 -04:00
Contribucious
1bb678e455 [KnownUsernameField] Compatibility with more browsers (#1000) 2020-07-01 10:31:12 -04:00
Kyle Spearrin
b9e5fc604b New Crowdin updates (#999)
* New translations AppResources.resx (Spanish)

* New translations AppResources.resx (Bulgarian)

* New translations AppResources.resx (Danish)

* New translations AppResources.resx (German)

* New translations AppResources.resx (Polish)

* New translations copy.resx (Polish)

* New translations copy.resx (Polish)
2020-06-29 11:30:02 -04:00
Kyle Spearrin
b65e8c48ce New Crowdin updates (#996)
* New translations AppResources.resx (Romanian)

* New translations AppResources.resx (Persian)

* New translations AppResources.resx (Ukrainian)

* New translations AppResources.resx (Chinese Traditional)

* New translations AppResources.resx (Vietnamese)

* New translations AppResources.resx (Indonesian)

* New translations AppResources.resx (Thai)

* New translations AppResources.resx (Hindi)

* New translations AppResources.resx (English, United Kingdom)

* New translations AppResources.resx (Sinhala)

* New translations copy.resx (Sinhala)

* New translations copy.resx (Sinhala)

* New translations AppResources.resx (Slovak)

* New translations AppResources.resx (Portuguese)

* New translations copy.resx (Romanian)

* New translations copy.resx (Romanian)

* New translations AppResources.resx (French)

* New translations AppResources.resx (Afrikaans)

* New translations AppResources.resx (Belarusian)

* New translations AppResources.resx (Bulgarian)

* New translations AppResources.resx (German)

* New translations AppResources.resx (Finnish)

* New translations AppResources.resx (Hebrew)

* New translations AppResources.resx (Korean)

* New translations AppResources.resx (Norwegian Bokmal)
2020-06-26 21:28:06 -04:00
Chad Scharf
e59bc1a08e version bump (#994)
* version bump

* version bump + fix manifest XML formatting
2020-06-25 17:30:14 -04:00
Kyle Spearrin
ff994629de Do not process hostname for regex logins (#987) 2020-06-18 11:58:19 -04:00
Matt Portune
a458b9bc88 Workaround for disabling predictive text in visible password fields (#983)
* Workaround for disabling predictive text in visible password fields

* Fix for non-master branch iOS builds (#984)

* Enable extra workflow steps to allow iOS builds to succeed from non-master branch

* re-enable provisioning profile setup
2020-06-16 11:09:26 -04:00
Matt Portune
2834e25151 Fix for non-master branch iOS builds (#984)
* Enable extra workflow steps to allow iOS builds to succeed from non-master branch

* re-enable provisioning profile setup
2020-06-16 09:55:08 -04:00
Oscar Hinton
c2582fe055 Resolve new ciphers defaulting to ViewPassword = false, causing passwords to be non editable. (#982) 2020-06-15 12:33:36 -04:00
Matt Portune
0980219c8d Add autofill/a11y support for ungoogled.chromium browser (#978) 2020-06-12 15:01:23 -04:00
Oscar Hinton
c5f158f1cf Resolve all passwords being hidden after upgrade (#977) 2020-06-12 09:50:36 -04:00
Kyle Spearrin
62afc023c8 print github ref 2020-06-11 16:26:10 -04:00
Oscar Hinton
52ca84946b Add support for hidden passwords (#920)
* Add support for hidden passwords

* Hide TOTP, hide hidden fields.

* Change _cipher to Cipher.
2020-06-11 16:16:43 -04:00
Kyle Spearrin
e64fb39c32 bump version 2020-06-10 13:49:58 -04:00
Kyle Spearrin
1066598150 fix ipa path 2020-06-10 13:30:08 -04:00
Kyle Spearrin
caed8c2cf0 explore paths 2020-06-10 13:13:03 -04:00
Kyle Spearrin
663be2402d list file system 2020-06-10 12:43:52 -04:00
Kyle Spearrin
6fd24c842f get proper ipa for app store 2020-06-10 12:24:52 -04:00
Kyle Spearrin
302631c4fa set CFBundlePackageType 2020-06-10 11:54:21 -04:00
Kyle Spearrin
8a94623b2b type ios 2020-06-10 11:48:02 -04:00
Kyle Spearrin
016dfdb455 dont archive for app store if not master 2020-06-10 11:33:43 -04:00
Kyle Spearrin
097415385e deploy to app store 2020-06-10 11:32:16 -04:00
Kyle Spearrin
8e6c6e04a3 cleanup export, ipa artifact 2020-06-10 10:53:57 -04:00
Kyle Spearrin
81a30e580e export ipa for app store 2020-06-10 10:02:15 -04:00
Kyle Spearrin
676efe7253 ls archive folder 2020-06-10 09:24:27 -04:00
Kyle Spearrin
39e0e77824 archive on build 2020-06-10 09:03:12 -04:00
Kyle Spearrin
363f5be8ff increment version for ios 2020-06-09 21:23:10 -04:00
Kyle Spearrin
df15fa2f0e move stuff to setup keychain script 2020-06-09 20:47:46 -04:00
Kyle Spearrin
e8c1fbb86f allow codesign to access certs and key 2020-06-09 20:36:44 -04:00
Kyle Spearrin
df986b9ecf timeout settings are for build.keychain 2020-06-09 20:32:23 -04:00
Kyle Spearrin
daabf4bab9 build again 2020-06-09 20:16:03 -04:00
Kyle Spearrin
3095948024 set keychain timeout 2020-06-09 20:14:40 -04:00
Kyle Spearrin
fad289305f add codesign to set-key-partition-list 2020-06-09 17:43:40 -04:00
Kyle Spearrin
97d8f07e0d Merge branch 'master' of github.com:bitwarden/mobile 2020-06-09 17:33:03 -04:00
Kyle Spearrin
dc374c7ce9 try unlocking keychain 2020-06-09 17:32:53 -04:00
Matt Portune
1584475bc3 added hi-res icon for google play (#966)
* added hi-res icon for google play

* moved to proper location
2020-06-09 17:24:19 -04:00
Kyle Spearrin
8f1db25c5c move cloc to its own job 2020-06-09 13:18:22 -04:00
Kyle Spearrin
092b536009 remove debug 2020-06-09 13:14:11 -04:00
Kyle Spearrin
f95bbaa0f7 resolve path of ~ 2020-06-09 13:09:00 -04:00
Kyle Spearrin
bc1f6464d3 change home path to ~ 2020-06-09 13:00:43 -04:00
Kyle Spearrin
b828cd5975 write out homePath 2020-06-09 12:56:53 -04:00
Kyle Spearrin
766b4f7971 create profiles dir path if it doesnt exist 2020-06-09 12:35:39 -04:00
Kyle Spearrin
45e2ffd71e properly escape space 2020-06-09 12:31:18 -04:00
Kyle Spearrin
98757c3f11 use proper params for copy-item 2020-06-09 12:27:40 -04:00
Kyle Spearrin
9aed6d350b setup provisioning profiles 2020-06-09 12:25:09 -04:00
Kyle Spearrin
ca6ce6db32 add mobile profiles 2020-06-09 12:15:06 -04:00
Kyle Spearrin
1c9a6a02af change all seps to / so that it works x-platform 2020-06-09 11:52:23 -04:00
Kyle Spearrin
ba9bafcb5f fix sep character 2020-06-09 11:48:11 -04:00
Kyle Spearrin
0628394122 update path sep character 2020-06-09 11:46:16 -04:00
Kyle Spearrin
99b2cd2ad0 fix pathing 2020-06-09 11:41:03 -04:00
Kyle Spearrin
707a6ecbaa setup ios keychain 2020-06-09 11:37:40 -04:00
Kyle Spearrin
aa2bc40f03 decrypt ios secrets 2020-06-09 11:19:02 -04:00
Kyle Spearrin
5e00e76c4b ios secrets 2020-06-09 11:16:13 -04:00
Kyle Spearrin
0dba992dd4 fix build for app store script path 2020-06-09 10:51:35 -04:00
Kyle Spearrin
b6f61cac9b build play store publisher 2020-06-09 10:47:20 -04:00
Kyle Spearrin
0e41945a8a build ios 2020-06-09 10:47:09 -04:00
Kyle Spearrin
a05e037308 deploy to play store 2020-06-09 10:21:46 -04:00
Kyle Spearrin
f40576c39d print lines of code from CLOC 2020-06-09 10:17:26 -04:00
Kyle Spearrin
9fc810182a print dotnet info 2020-06-09 09:58:28 -04:00
Kyle Spearrin
dd7a52ba08 print version code 2020-06-08 16:10:17 -04:00
Kyle Spearrin
fa6d2a3080 break steps out a bit more 2020-06-08 16:04:04 -04:00
Laurent Tréguier
36efc0c877 Tweak icons to better blend with Android and iOS (#962)
* Add shadow to Android icon

* Add gradient to iOS icon
2020-06-08 15:02:20 -04:00
Kyle Spearrin
e9efcf1b92 rework build scripts 2020-06-08 13:19:44 -04:00
Kyle Spearrin
f4ad1ec8e7 fix secretOutputPath 2020-06-08 13:02:38 -04:00
Kyle Spearrin
0027c21630 more pathing fixes 2020-06-08 13:00:52 -04:00
Kyle Spearrin
6173cab99f fix decryptSecretPath 2020-06-08 12:56:58 -04:00
Kyle Spearrin
80c8097a71 fix paths to ps scripts 2020-06-08 12:55:02 -04:00
Kyle Spearrin
ba3d577125 try shell: pwsh 2020-06-08 12:29:57 -04:00
Kyle Spearrin
8ce4ebb16e powershell Invoke-Expression 2020-06-08 12:25:39 -04:00
Kyle Spearrin
4358ff2338 run powershell commands 2020-06-08 12:21:43 -04:00
Kyle Spearrin
53f9eb083d branches ignore and only on master 2020-06-08 12:17:53 -04:00
Kyle Spearrin
0a3a982cb9 github action android build steps 2020-06-08 12:14:22 -04:00
Kyle Spearrin
c30239b3a8 encrypted GPG files for github actions 2020-06-08 12:14:22 -04:00
Matt Portune
183834689d Fix for accessibility overlay on Android 5 & 6 (#965)
* Fix for accessibility overlay on Android 5 & 6

* changed to skip check outright until API 26
2020-06-08 08:25:24 -04:00
Matt Portune
5da2f3279b biometrics cleanup (#964) 2020-06-08 08:25:13 -04:00
Kyle Spearrin
ec7d87e757 bump version 2020-06-07 11:56:16 -04:00
Kyle Spearrin
4155f69e3c formatting fixes 2020-06-07 11:54:14 -04:00
Matt Portune
473e93ea16 Fix for deadlock in iOS autofill & share extensions (#960) 2020-06-07 00:15:51 -04:00
Kyle Spearrin
fd1941cc3e target iPhone 2020-06-05 15:31:30 -04:00
Kyle Spearrin
dbb51b58db update platforms for ios core builds 2020-06-05 15:30:24 -04:00
Kyle Spearrin
e7d00cfe54 set iphone and sim platforms for ios core 2020-06-05 15:23:15 -04:00
Kyle Spearrin
63453fa962 fix syntax 2020-06-05 14:40:44 -04:00
Kyle Spearrin
689eb7f87b CI updates 2020-06-05 14:39:29 -04:00
Kyle Spearrin
67a4646a50 try out github actions 2020-06-05 13:51:57 -04:00
Kyle Spearrin
a4e0535464 null check all the things (#957) 2020-06-05 13:30:53 -04:00
Kyle Spearrin
61495cd428 bumping ios version to match what was released 2020-06-04 09:48:10 -04:00
Carl
9e7b7415a5 Add support for Bromite's vanilla build of Chromium (#951) 2020-06-02 23:18:30 -04:00
Kyle Spearrin
06a462d48c skip litedb from ios linker 2020-06-02 14:06:53 -04:00
Kyle Spearrin
d3e6e415b9 bump version 2020-06-02 13:08:04 -04:00
Kyle Spearrin
7e633d31a0 sign fdroid builds with a different keystore (#949) 2020-06-02 10:36:16 -04:00
522 changed files with 22885 additions and 4316 deletions

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>ad-hoc</string>
<key>provisioningProfiles</key>
<dict>
<key>com.8bit.bitwarden</key>
<string>Ad hoc: Bitwarden 2020</string>
<key>com.8bit.bitwarden.autofill</key>
<string>Ad hoc: Autofill 2020</string>
<key>com.8bit.bitwarden.find-login-action-extension</key>
<string>Ad hoc: Extension 2020</string>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>app-store</string>
<key>provisioningProfiles</key>
<dict>
<key>com.8bit.bitwarden</key>
<string>Dist: Bitwarden 2020</string>
<key>com.8bit.bitwarden.autofill</key>
<string>Dist: Autofill 2020</string>
<key>com.8bit.bitwarden.find-login-action-extension</key>
<string>Dist: Extension 2020</string>
</dict>
</dict>
</plist>

13
.github/scripts/android/build.ps1 vendored Normal file
View File

@@ -0,0 +1,13 @@
param (
[Parameter(Mandatory=$true)]
[string] $configuration
)
$rootPath = $env:GITHUB_WORKSPACE;
$androidPath = $($rootPath + "/src/Android/Android.csproj");
Write-Output "########################################"
Write-Output "##### Build $configuration Configuration"
Write-Output "########################################"
msbuild "$($androidPath)" "/p:Configuration=$configuration"

View File

@@ -0,0 +1,75 @@
$rootPath = $env:GITHUB_WORKSPACE;
$androidPath = $($rootPath + "/src/Android/Android.csproj");
$appPath = $($rootPath + "/src/App/App.csproj");
$androidManifest = $($rootPath + "/src/Android/Properties/AndroidManifest.xml");
Write-Output "########################################"
Write-Output "##### Clean Android and App"
Write-Output "########################################"
msbuild "$($androidPath)" "/t:Clean" "/p:Configuration=FDroid"
msbuild "$($appPath)" "/t:Clean" "/p:Configuration=FDroid"
Write-Output "########################################"
Write-Output "##### Backup project files"
Write-Output "########################################"
Copy-Item $androidManifest $($androidManifest + ".original");
Copy-Item $androidPath $($androidPath + ".original");
Copy-Item $appPath $($appPath + ".original");
Write-Output "########################################"
Write-Output "##### Cleanup Android Manifest"
Write-Output "########################################"
$xml=New-Object XML;
$xml.Load($androidManifest);
$nsAndroid=New-Object System.Xml.XmlNamespaceManager($xml.NameTable);
$nsAndroid.AddNamespace("android", "http://schemas.android.com/apk/res/android");
$firebaseReceiver1=$xml.SelectSingleNode(`
"/manifest/application/receiver[@android:name='com.google.firebase.iid.FirebaseInstanceIdInternalReceiver']", `
$nsAndroid);
$firebaseReceiver1.ParentNode.RemoveChild($firebaseReceiver1);
$firebaseReceiver2=$xml.SelectSingleNode(`
"/manifest/application/receiver[@android:name='com.google.firebase.iid.FirebaseInstanceIdReceiver']", `
$nsAndroid);
$firebaseReceiver2.ParentNode.RemoveChild($firebaseReceiver2);
$xml.Save($androidManifest);
Write-Output "########################################"
Write-Output "##### Uninstall from Android.csproj"
Write-Output "########################################"
$xml=New-Object XML;
$xml.Load($androidPath);
$ns=New-Object System.Xml.XmlNamespaceManager($xml.NameTable);
$ns.AddNamespace("ns", $xml.DocumentElement.NamespaceURI);
$firebaseNode=$xml.SelectSingleNode(`
"/ns:Project/ns:ItemGroup/ns:PackageReference[@Include='Xamarin.Firebase.Messaging']", $ns);
$firebaseNode.ParentNode.RemoveChild($firebaseNode);
$safetyNetNode=$xml.SelectSingleNode(`
"/ns:Project/ns:ItemGroup/ns:PackageReference[@Include='Xamarin.GooglePlayServices.SafetyNet']", $ns);
$safetyNetNode.ParentNode.RemoveChild($safetyNetNode);
$xml.Save($androidPath);
Write-Output "########################################"
Write-Output "##### Uninstall from App.csproj"
Write-Output "########################################"
$xml=New-Object XML;
$xml.Load($appPath);
$appCenterNode=$xml.SelectSingleNode("/Project/ItemGroup/PackageReference[@Include='Microsoft.AppCenter.Crashes']");
$appCenterNode.ParentNode.RemoveChild($appCenterNode);
$xml.Save($appPath);

View File

@@ -0,0 +1,24 @@
#!/usr/bin/env bash
cd $GITHUB_WORKSPACE
mkdir dist
cp CNAME ./dist
cd store
chmod 600 fdroid/config.py fdroid/keystore.jks
mkdir -p temp/fdroid
TEMP_DIR="$GITHUB_WORKSPACE/store/temp/fdroid"
cd fdroid
echo "keypass=\"$FDROID_STORE_KEYSTORE_PASSWORD\"" >>config.py
echo "keystorepass=\"$FDROID_STORE_KEYSTORE_PASSWORD\"" >>config.py
echo "local_copy_dir=\"$TEMP_DIR\"" >>config.py
mkdir -p repo
curl -Lo repo/com.x8bit.bitwarden-fdroid.apk \
https://github.com/bitwarden/mobile/releases/download/$RELEASE_TAG_NAME/com.x8bit.bitwarden-fdroid.apk
fdroid update
fdroid server update
cd ..
rm -rf temp/fdroid/archive
mv -v temp/fdroid ../dist
cd fdroid
cp index.html btn.png qr.png ../../dist/fdroid
cd $GITHUB_WORKSPACE

View File

@@ -0,0 +1,22 @@
$rootPath = $env:GITHUB_WORKSPACE;
$decryptSecretPath = $($rootPath + "/.github/scripts/decrypt-secret.ps1");
$appKeystorePlayFilename = "app_play-keystore.jks";
$appKeystorePlayPath = $($rootPath + "/src/Android/$appKeystorePlayFilename");
$appKeystoreUploadFilename = "app_upload-keystore.jks";
$appKeystoreUploadPath = $($rootPath + "/src/Android/$appKeystoreUploadFilename");
$appKeystoreFdroidFilename = "app_fdroid-keystore.jks";
$appKeystoreFdroidPath = $($rootPath + "/src/Android/$appKeystoreFdroidFilename");
$googleServicesFilename = "google-services.json";
$googleServicesPath = $($rootPath + "/src/Android/$googleServicesFilename");
Invoke-Expression `
"& `"$decryptSecretPath`" -filename $($appKeystorePlayFilename + ".gpg") -output $($appKeystorePlayPath)"
Invoke-Expression `
"& `"$decryptSecretPath`" -filename $($appKeystoreUploadFilename + ".gpg") -output $($appKeystoreUploadPath)"
Invoke-Expression `
"& `"$decryptSecretPath`" -filename $($appKeystoreFdroidFilename + ".gpg") -output $($appKeystoreFdroidPath)"
Invoke-Expression `
"& `"$decryptSecretPath`" -filename $($googleServicesFilename + ".gpg") -output $($googleServicesPath)"
Invoke-Expression "& `"$decryptSecretPath`" -filename play_creds.json.gpg"

View File

@@ -0,0 +1,9 @@
$rootPath = $env:GITHUB_WORKSPACE;
$homePath = Resolve-Path "~" | Select-Object -ExpandProperty Path;
$publisherPath = $($rootPath + "/store/google/Publisher/bin/Release/netcoreapp2.0/Publisher.dll");
$credsPath = $($homePath + "/secrets/play_creds.json");
$aabPath = $($rootPath + "/com.x8bit.bitwarden.aab");
$track = "internal";
dotnet $publisherPath $credsPath $aabPath $track

View File

@@ -0,0 +1,16 @@
$rootPath = $env:GITHUB_WORKSPACE;
$buildNumber = 3000 + [int]$env:GITHUB_RUN_NUMBER;
Write-Output "########################################"
Write-Output "##### Setting Version Code $buildNumber"
Write-Output "########################################"
$androidManifest = $($rootPath + "/src/Android/Properties/AndroidManifest.xml");
$xml=New-Object XML;
$xml.Load($androidManifest);
$node=$xml.SelectNodes("/manifest");
$node.SetAttribute("android:versionCode", [string]$buildNumber);
$xml.Save($androidManifest);

23
.github/scripts/android/sign-fdroid.ps1 vendored Normal file
View File

@@ -0,0 +1,23 @@
$rootPath = $env:GITHUB_WORKSPACE;
$androidPath = $($rootPath + "/src/Android/Android.csproj");
$appKeystoreFdroidFilename = "app_fdroid-keystore.jks";
Write-Output "########################################"
Write-Output "##### Sign FDroid Configuration"
Write-Output "########################################"
msbuild "$($androidPath)" "/t:SignAndroidPackage" "/p:Configuration=FDroid" "/p:AndroidKeyStore=true" `
"/p:AndroidSigningKeyAlias=bitwarden" "/p:AndroidSigningKeyPass=$($env:FDROID_KEYSTORE_PASSWORD)" `
"/p:AndroidSigningKeyStore=$($appKeystoreFdroidFilename)" `
"/p:AndroidSigningStorePass=$($env:FDROID_KEYSTORE_PASSWORD)" "/v:quiet"
Write-Output "########################################"
Write-Output "##### Copy FDroid apk to project root"
Write-Output "########################################"
$signedApkPath = $($rootPath + "/src/Android/bin/FDroid/com.x8bit.bitwarden-Signed.apk");
$signedApkDestPath = $($rootPath + "/com.x8bit.bitwarden-fdroid.apk");
Copy-Item $signedApkPath $signedApkDestPath

42
.github/scripts/android/sign-play.ps1 vendored Normal file
View File

@@ -0,0 +1,42 @@
$rootPath = $env:GITHUB_WORKSPACE;
$androidPath = $($rootPath + "/src/Android/Android.csproj");
$appKeystorePlayFilename = "app_play-keystore.jks";
$appKeystoreUploadFilename = "app_upload-keystore.jks";
Write-Output "########################################"
Write-Output "##### Sign Google Play Bundle Release Configuration"
Write-Output "########################################"
msbuild "$($androidPath)" "/t:SignAndroidPackage" "/p:Configuration=Release" "/p:AndroidKeyStore=true" `
"/p:AndroidSigningKeyAlias=upload" "/p:AndroidSigningKeyPass=$($env:UPLOAD_KEYSTORE_PASSWORD)" `
"/p:AndroidSigningKeyStore=$($appKeystoreUploadFilename)" `
"/p:AndroidSigningStorePass=$($env:UPLOAD_KEYSTORE_PASSWORD)" "/p:AndroidPackageFormat=aab" "/v:quiet"
Write-Output "########################################"
Write-Output "##### Copy Google Play Bundle to project root"
Write-Output "########################################"
$signedAabPath = $($rootPath + "/src/Android/bin/Release/com.x8bit.bitwarden-Signed.aab");
$signedAabDestPath = $($rootPath + "/com.x8bit.bitwarden.aab");
Copy-Item $signedAabPath $signedAabDestPath
Write-Output "########################################"
Write-Output "##### Sign APK Release Configuration"
Write-Output "########################################"
msbuild "$($androidPath)" "/t:SignAndroidPackage" "/p:Configuration=Release" "/p:AndroidKeyStore=true" `
"/p:AndroidSigningKeyAlias=bitwarden" "/p:AndroidSigningKeyPass=$($env:PLAY_KEYSTORE_PASSWORD)" `
"/p:AndroidSigningKeyStore=$($appKeystorePlayFilename)" `
"/p:AndroidSigningStorePass=$($env:PLAY_KEYSTORE_PASSWORD)" "/v:quiet"
Write-Output "########################################"
Write-Output "##### Copy Release APK to project root"
Write-Output "########################################"
$signedApkPath = $($rootPath + "/src/Android/bin/Release/com.x8bit.bitwarden-Signed.apk");
$signedApkDestPath = $($rootPath + "/com.x8bit.bitwarden.apk");
Copy-Item $signedApkPath $signedApkDestPath

29
.github/scripts/decrypt-secret.ps1 vendored Normal file
View File

@@ -0,0 +1,29 @@
param (
[Parameter(Mandatory=$true)]
[string] $filename,
[string] $output
)
$homePath = Resolve-Path "~" | Select-Object -ExpandProperty Path
$rootPath = $env:GITHUB_WORKSPACE
$secretInputPath = $rootPath + "/.github/secrets"
$input = $secretInputPath + "/" + $filename
$passphrase = $env:DECRYPT_FILE_PASSWORD
$secretOutputPath = $homePath + "/secrets"
if ([string]::IsNullOrEmpty($output)) {
if ($filename.EndsWith(".gpg")) {
$output = $secretOutputPath + "/" + $filename.TrimEnd(".gpg")
} else {
$output = $secretOutputPath + "/" + $filename + ".plaintext"
}
}
if (!(Test-Path -Path $secretOutputPath))
{
New-Item -ItemType Directory -Path $secretOutputPath
}
gpg --quiet --batch --yes --decrypt --passphrase="$passphrase" --output $output $input

29
.github/scripts/ios/build.ps1 vendored Normal file
View File

@@ -0,0 +1,29 @@
param (
[Parameter(Mandatory=$true)]
[string] $configuration,
[string] $platform = "iPhone",
[switch] $archive
)
$rootPath = $env:GITHUB_WORKSPACE;
$iosPath = $($rootPath + "/src/iOS/iOS.csproj");
if ($archive)
{
Write-Output "########################################"
Write-Output "##### Archive $configuration Configuration for $platform Platform"
Write-Output "########################################"
msbuild "$($iosPath)" "/p:Platform=$platform" "/p:Configuration=$configuration" `
"/p:ArchiveOnBuild=true" "/t:`"Build`""
Write-Output "########################################"
Write-Output "##### Done"
Write-Output "########################################"
ls ~/Library/Developer/Xcode/Archives
} else
{
Write-Output "########################################"
Write-Output "##### Build $configuration Configuration for $platform Platform"
Write-Output "########################################"
msbuild "$($iosPath)" "/p:Platform=$platform" "/p:Configuration=$configuration" "/t:`"Build`""
}

View File

@@ -0,0 +1,9 @@
$rootPath = $env:GITHUB_WORKSPACE;
$decryptSecretPath = $($rootPath + "/.github/scripts/decrypt-secret.ps1");
Invoke-Expression "& `"$decryptSecretPath`" -filename bitwarden-mobile-key.p12.gpg"
Invoke-Expression "& `"$decryptSecretPath`" -filename iphone-distribution-cert.p12.gpg"
Invoke-Expression "& `"$decryptSecretPath`" -filename dist_autofill.mobileprovision.gpg"
Invoke-Expression "& `"$decryptSecretPath`" -filename dist_bitwarden.mobileprovision.gpg"
Invoke-Expression "& `"$decryptSecretPath`" -filename dist_extension.mobileprovision.gpg"

View File

@@ -0,0 +1,5 @@
$rootPath = $env:GITHUB_WORKSPACE;
$ipaPath = "$rootPath/bitwarden-export/Bitwarden.ipa"
xcrun altool --upload-app --type ios --file "$ipaPath" `
--username "$env:APPLE_ID_USERNAME" --password "$env:APPLE_ID_PASSWORD"

13
.github/scripts/ios/export-ipa.ps1 vendored Normal file
View File

@@ -0,0 +1,13 @@
param (
[Parameter(Mandatory=$true)]
[string] $method
)
$rootPath = $env:GITHUB_WORKSPACE;
$homePath = Resolve-Path "~" | Select-Object -ExpandProperty Path
$exportOptionsPath = "$rootPath/.github/resources/export-options-$method.plist";
$archivePath = "$homePath/Library/Developer/Xcode/Archives/*/*.xcarchive";
$exportPath = "$rootPath/bitwarden-export";
xcodebuild -exportArchive -archivePath $archivePath -exportPath $exportPath -exportOptionsPlist $exportOptionsPath

View File

@@ -0,0 +1,26 @@
$rootPath = $env:GITHUB_WORKSPACE;
$buildNumber = 100 + [int]$env:GITHUB_RUN_NUMBER;
$bitwardenInfo = $($rootPath + "/src/iOS/Info.plist");
$extensionInfo = $($rootPath + "/src/iOS.Extension/Info.plist");
$autofillInfo = $($rootPath + "/src/iOS.Autofill/Info.plist");
Write-Output "########################################"
Write-Output "##### Setting CFBundleVersion $buildNumber"
Write-Output "########################################"
function Update-Version($file) {
$xml=New-Object XML;
$xml.Load($file);
Select-Xml -xml $xml -XPath "//dict/key[. = 'CFBundleVersion']/following-sibling::string[1]" |
%{
$_.Node.InnerXml = $buildNumber
}
$xml.Save($file);
}
Update-Version $bitwardenInfo
Update-Version $extensionInfo
Update-Version $autofillInfo

13
.github/scripts/ios/setup-keychain.ps1 vendored Normal file
View File

@@ -0,0 +1,13 @@
$homePath = Resolve-Path "~" | Select-Object -ExpandProperty Path;
$secretsPath = $homePath + "/secrets"
$mobileKeyPath = $($secretsPath + "/bitwarden-mobile-key.p12");
$distCertPath = $($secretsPath + "/iphone-distribution-cert.p12");
security create-keychain -p $env:KEYCHAIN_PASSWORD build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p $env:KEYCHAIN_PASSWORD build.keychain
security set-keychain-settings -lut 1200 build.keychain
security import $mobileKeyPath -k build.keychain -P $env:MOBILE_KEY_PASSWORD -T /usr/bin/codesign -T /usr/bin/security
security import $distCertPath -k build.keychain -P $env:DIST_CERT_PASSWORD -T /usr/bin/codesign -T /usr/bin/security
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $env:KEYCHAIN_PASSWORD build.keychain

21
.github/scripts/ios/setup-profiles.ps1 vendored Normal file
View File

@@ -0,0 +1,21 @@
$homePath = Resolve-Path "~" | Select-Object -ExpandProperty Path;
$secretsPath = $homePath + "/secrets"
$autofillProfilePath = $($secretsPath + "/dist_autofill.mobileprovision");
$bitwardenProfilePath = $($secretsPath + "/dist_bitwarden.mobileprovision");
$extensionProfilePath = $($secretsPath + "/dist_extension.mobileprovision");
$profilesDirPath = "~/Library/MobileDevice/Provisioning Profiles"
if (!(Test-Path -Path $profilesDirPath))
{
New-Item -ItemType Directory -Path $profilesDirPath
}
$autofill_uuid = grep UUID -A1 -a $autofillProfilePath | grep -io "[-A-F0-9]\{36\}"
Copy-Item $autofillProfilePath -destination "$profilesDirPath/$autofill_uuid.mobileprovision"
$bitwarden_uuid = grep UUID -A1 -a $bitwardenProfilePath | grep -io "[-A-F0-9]\{36\}"
Copy-Item $bitwardenProfilePath -destination "$profilesDirPath/$bitwarden_uuid.mobileprovision"
$extension_uuid = grep UUID -A1 -a $extensionProfilePath | grep -io "[-A-F0-9]\{36\}"
Copy-Item $extensionProfilePath -destination "$profilesDirPath/$extension_uuid.mobileprovision"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,3 @@
<EFBFBD>
 K<>Y#<23>(<28><><EFBFBD><EFBFBD>EI֐߄T?)l<><6C><EFBFBD><18><><10>"=<3D>|<7C>'e<><0E>m<EFBFBD>/~<7E><>' F<><46>><3E><><EFBFBD><EFBFBD>l<EFBFBD>b<EFBFBD>[<5B>+R<><52>iL<69><4C>"<22><><EFBFBD>~V:<3A><>p<EFBFBD>a<17>ڵel%8t<38><74><EFBFBD>y<<3C>n<EFBFBD><6E><EFBFBD>aU<61>w<16>JD<4A><44><1F><>We<57>9<EFBFBD><39><EFBFBD><EFBFBD><x8d<38>O<EFBFBD>j\<14>ד<EFBFBD><D793><EFBFBD>Vq<56><71>֋
Ǻ<EFBFBD>-<2D>#<23><><11><>]$<24>(<28>l,<2C>Br<42><02><>d<><64><EFBFBD>•a-<2D><><EFBFBD>:<3A><>:<3A><04>9b,!Em<02><19><>Qf<>D<EFBFBD>g<EFBFBD><06><0E>x(P<>ȡ~<7E>͹<EFBFBD><CDB9> <09><>[<06><>!:<3A>;f<><66>

Binary file not shown.

BIN
.github/secrets/play_creds.json.gpg vendored Normal file

Binary file not shown.

Binary file not shown.

294
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,294 @@
name: Build
on:
push:
branches-ignore:
- 'l10n_master'
- 'gh-pages'
release:
types:
- published
jobs:
cloc:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v2
- name: Set up cloc
run: |
sudo apt-get update
sudo apt-get -y install cloc
- name: Print lines of code
run: cloc --vcs git --exclude-dir Resources,store,test,Properties --include-lang C#,XAML
android:
runs-on: windows-latest
steps:
- name: Set up MSBuild
uses: microsoft/setup-msbuild@v1
- name: Print environment
run: |
nuget help
msbuild -version
dotnet --info
Write-Output "GitHub ref: $env:GITHUB_REF"
Write-Output "GitHub event: $env:GITHUB_EVENT"
shell: pwsh
env:
GITHUB_REF: ${{ github.ref }}
GITHUB_EVENT: ${{ github.event_name }}
- name: Checkout repo
uses: actions/checkout@v2
- name: Decrypt secrets
if: github.ref == 'refs/heads/master' || github.event_name == 'release'
run: ./.github/scripts/android/decrypt-secrets.ps1
shell: pwsh
env:
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }}
- name: Increment version
if: github.ref == 'refs/heads/master' || github.event_name == 'release'
run: ./.github/scripts/android/increment-version.ps1
shell: pwsh
- name: Restore packages
run: nuget restore
- name: Build Play Store publisher
run: dotnet build ./store/google/Publisher/Publisher.csproj -p:Configuration=Release
- name: Build for Play Store
run: ./.github/scripts/android/build.ps1 -configuration Release
shell: pwsh
- name: Sign for Play Store
if: github.ref == 'refs/heads/master' || github.event_name == 'release'
run: ./.github/scripts/android/sign-play.ps1
shell: pwsh
env:
PLAY_KEYSTORE_PASSWORD: ${{ secrets.PLAY_KEYSTORE_PASSWORD }}
UPLOAD_KEYSTORE_PASSWORD: ${{ secrets.UPLOAD_KEYSTORE_PASSWORD }}
- name: Upload Play Store .aab artifact
if: github.ref == 'refs/heads/master' || github.event_name == 'release'
uses: actions/upload-artifact@v2
with:
name: com.x8bit.bitwarden.aab
path: ./com.x8bit.bitwarden.aab
- name: Upload Play Store .apk artifact
if: github.ref == 'refs/heads/master' || github.event_name == 'release'
uses: actions/upload-artifact@v2
with:
name: com.x8bit.bitwarden.apk
path: ./com.x8bit.bitwarden.apk
- name: Clean for F-Droid
run: ./.github/scripts/android/clean-fdroid.ps1
shell: pwsh
- name: Restore packages
run: nuget restore
- name: Build for F-Droid
run: ./.github/scripts/android/build.ps1 -configuration FDroid
shell: pwsh
- name: Sign for F-Droid
if: github.ref == 'refs/heads/master' || github.event_name == 'release'
run: ./.github/scripts/android/sign-fdroid.ps1
shell: pwsh
env:
FDROID_KEYSTORE_PASSWORD: ${{ secrets.FDROID_KEYSTORE_PASSWORD }}
- name: Upload F-Droid .apk artifact
if: github.ref == 'refs/heads/master' || github.event_name == 'release'
uses: actions/upload-artifact@v2
with:
name: com.x8bit.bitwarden-fdroid.apk
path: ./com.x8bit.bitwarden-fdroid.apk
- name: Deploy to Play Store
if: github.ref == 'refs/heads/master' || github.event_name == 'release'
run: ./.github/scripts/android/deploy-play.ps1
shell: pwsh
- name: Upload release assets
if: github.event_name == 'release'
run: |
hub release edit `
-a ./com.x8bit.bitwarden.aab `
-a ./com.x8bit.bitwarden.apk `
-a ./com.x8bit.bitwarden-fdroid.apk `
-m "Version $($env:RELEASE_TAG_NAME.TrimStart('v'))" `
$env:RELEASE_TAG_NAME
shell: pwsh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG_NAME: ${{ github.event.release.tag_name }}
android-ubuntu:
runs-on: ubuntu-latest
needs: android
steps:
- name: Set up Node
if: github.event_name == 'release'
uses: actions/setup-node@v1
with:
node-version: '10.x'
- name: Set up F-Droid server
if: github.event_name == 'release'
run: |
sudo apt-get -qq update
sudo apt-get -qqy install --no-install-recommends fdroidserver wget
- name: Set up git credentials
if: github.event_name == 'release'
env:
ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
run: |
git config --global credential.helper store
echo "https://${ACCESS_TOKEN}:x-oauth-basic@github.com" >> ~/.git-credentials
git config --global user.email "ci@bitwarden.com"
git config --global user.name "Bitwarden CI"
- name: Print environment
if: github.event_name == 'release'
run: |
node --version
npm --version
git --version
Write-Output "GitHub ref: $env:GITHUB_REF"
Write-Output "GitHub event: $env:GITHUB_EVENT"
shell: pwsh
env:
GITHUB_REF: ${{ github.ref }}
GITHUB_EVENT: ${{ github.event_name }}
- name: Checkout repo
if: github.event_name == 'release'
uses: actions/checkout@v2
- name: Install Node dependencies
if: github.event_name == 'release'
run: npm install
- name: Decrypt secrets
if: github.event_name == 'release'
run: |
./.github/scripts/decrypt-secret.ps1 -filename store_fdroid-keystore.jks.gpg `
-output ./store/fdroid/keystore.jks
shell: pwsh
env:
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }}
- name: Compile for F-Droid Store
if: github.event_name == 'release'
run: |
sudo chmod +x ./.github/scripts/android/compile-fdroid.sh
./.github/scripts/android/compile-fdroid.sh
env:
FDROID_STORE_KEYSTORE_PASSWORD: ${{ secrets.FDROID_STORE_KEYSTORE_PASSWORD }}
RELEASE_TAG_NAME: ${{ github.event.release.tag_name }}
- name: Deploy to gh-pages
if: github.event_name == 'release'
run: npm run deploy
ios:
runs-on: macos-latest
steps:
- name: Print environment
run: |
nuget help
msbuild -version
dotnet --info
Write-Output "GitHub ref: $env:GITHUB_REF"
Write-Output "GitHub event: $env:GITHUB_EVENT"
shell: pwsh
env:
GITHUB_REF: ${{ github.ref }}
GITHUB_EVENT: ${{ github.event_name }}
- name: Checkout repo
uses: actions/checkout@v2
- name: Decrypt secrets
run: ./.github/scripts/ios/decrypt-secrets.ps1
shell: pwsh
env:
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }}
- name: Increment version
if: github.ref == 'refs/heads/master' || github.event_name == 'release'
run: ./.github/scripts/ios/increment-version.ps1
shell: pwsh
- name: Set up keychain
run: ./.github/scripts/ios/setup-keychain.ps1
shell: pwsh
env:
KEYCHAIN_PASSWORD: ${{ secrets.IOS_KEYCHAIN_PASSWORD }}
MOBILE_KEY_PASSWORD: ${{ secrets.IOS_KEY_PASSWORD }}
DIST_CERT_PASSWORD: ${{ secrets.IOS_DIST_CERT_PASSWORD }}
- name: Set up provisioning profiles
run: ./.github/scripts/ios/setup-profiles.ps1
shell: pwsh
- name: Restore packages
run: nuget restore
- name: Archive Build for App Store
if: github.ref == 'refs/heads/master' || github.event_name == 'release'
run: ./.github/scripts/ios/build.ps1 -configuration AppStore -platform iPhone -archive
shell: pwsh
- name: Build for App Store
if: github.ref != 'refs/heads/master'
run: ./.github/scripts/ios/build.ps1 -configuration AppStore -platform iPhone
shell: pwsh
- name: Export .ipa for App Store
if: github.ref == 'refs/heads/master' || github.event_name == 'release'
run: ./.github/scripts/ios/export-ipa.ps1 -method app-store
shell: pwsh
- name: Upload App Store .ipa artifact
if: github.ref == 'refs/heads/master' || github.event_name == 'release'
uses: actions/upload-artifact@v2
with:
name: Bitwarden.ipa
path: ./bitwarden-export/Bitwarden.ipa
- name: Deploy to App Store
if: github.ref == 'refs/heads/master' || github.event_name == 'release'
run: ./.github/scripts/ios/deploy-app-store.ps1
shell: pwsh
env:
APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
- name: Upload release assets
if: github.event_name == 'release'
run: |
hub release edit `
-a ./bitwarden-export/Bitwarden.ipa `
-m "Version $($env:RELEASE_TAG_NAME.TrimStart('v'))" `
$env:RELEASE_TAG_NAME
shell: pwsh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG_NAME: ${{ github.event.release.tag_name }}

View File

@@ -1,4 +1,31 @@
Code contributions are welcome! Please commit any pull requests against the `master` branch.
# How to Contribute
Contributions of all kinds are welcome!
Please visit our [Community Forums](https://community.bitwarden.com/) for general community discussion and the development roadmap.
Here is how you can get involved:
* **Request a new feature:** Go to the [Feature Requests category](https://community.bitwarden.com/c/feature-requests/) of the Community Forums. Please search existing feature requests before making a new one
* **Write code for a new feature:** Make a new post in the [Github Contributions category](https://community.bitwarden.com/c/github-contributions/) of the Community Forums. Include a description of your proposed contribution, screeshots, and links to any relevant feature requests. This helps get feedback from the community and Bitwarden team members before you start writing code
* **Report a bug or submit a bugfix:** Use Github issues and pull requests
* **Write documentation:** Submit a pull request to the [Bitwarden help repository](https://github.com/bitwarden/help)
* **Help other users:** Go to the [User-to-User Support category](https://community.bitwarden.com/c/support/) on the Community Forums
* **Translate:** See the localization (i10n) section below
## Contributor Agreement
Please sign the [Contributor Agreement](https://cla-assistant.io/bitwarden/mobile) if you intend on contributing to any Github repository. Pull requests cannot be accepted and merged unless the author has signed the Contributor Agreement.
## Pull Request Guidelines
* commit any pull requests against the `master` branch
* include a link to your Community Forums post
# Localization (l10n)

View File

@@ -24,6 +24,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.editorconfig = .editorconfig
.gitignore = .gitignore
appveyor.yml = appveyor.yml
.github\workflows\build.yml = .github\workflows\build.yml
CONTRIBUTING.md = CONTRIBUTING.md
crowdin.yml = crowdin.yml
README.md = README.md
@@ -238,22 +239,22 @@ Global
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|Any CPU.Build.0 = Ad-Hoc|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|Any CPU.ActiveCfg = AppStore|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|Any CPU.Build.0 = AppStore|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhone.ActiveCfg = AppStore|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhone.Build.0 = AppStore|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhoneSimulator.Build.0 = AppStore|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhone.Build.0 = AppStore|iPhone
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|iPhone.Build.0 = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|iPhone.ActiveCfg = Debug|iPhone
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|iPhone.Build.0 = Debug|iPhone
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{E71F3053-056C-4381-9638-048ED73BDFF6}.FDroid|Any CPU.ActiveCfg = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.FDroid|Any CPU.Build.0 = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.FDroid|iPhone.ActiveCfg = FDroid|Any CPU

View File

@@ -9,6 +9,7 @@ files:
pt-PT: pt-PT
pt-BR: pt-BR
en-GB: en-GB
en-IN: en-IN
- source: /store/apple/en/copy.resx
translation: /store/apple/%two_letters_code%/copy.resx
update_option: update_as_unapproved
@@ -19,6 +20,7 @@ files:
pt-PT: pt-PT
pt-BR: pt-BR
en-GB: en-GB
en-IN: en-IN
- source: /store/google/en/copy.resx
translation: /store/google/%two_letters_code%/copy.resx
update_option: update_as_unapproved
@@ -29,3 +31,4 @@ files:
pt-BR: pt-BR
pt-PT: pt-PT
en-GB: en-GB
en-IN: en-IN

View File

@@ -50,13 +50,15 @@ namespace Bit.Droid.Accessibility
new Browser("com.google.android.apps.chrome_dev", "url_bar"),
new Browser("com.kiwibrowser.browser", "url_bar"),
new Browser("com.microsoft.emmx", "url_bar"),
new Browser("com.mmbox.browser", "search_box"),
new Browser("com.mmbox.xbrowser", "search_box"),
new Browser("com.naver.whale", "url_bar"),
new Browser("com.opera.browser", "url_field"),
new Browser("com.opera.browser.beta", "url_field"),
new Browser("com.opera.mini.native", "url_field"),
new Browser("com.opera.mini.native.beta", "url_field"),
new Browser("com.opera.touch", "addressbarEdit"),
new Browser("com.qwant.liberty", "url_bar_title,mozac_browser_toolbar_url_view"), // 2nd = Anticipation
new Browser("com.qwant.liberty", "mozac_browser_toolbar_url_view,url_bar_title"), // 2nd = Legacy (before v4)
new Browser("com.sec.android.app.sbrowser", "location_bar_edit_text"),
new Browser("com.sec.android.app.sbrowser.beta", "location_bar_edit_text"),
new Browser("com.stoutner.privacybrowser.free", "url_edittext"),
@@ -66,25 +68,35 @@ namespace Bit.Droid.Accessibility
new Browser("com.vivaldi.browser.sopranos", "url_bar"),
new Browser("com.yandex.browser", "bro_omnibar_address_title_text,bro_omnibox_collapsed_title",
(s) => s.Split(new char[]{' ', ' '}).FirstOrDefault()), // 0 = Regular Space, 1 = No-break space (00A0)
new Browser("mark.via.gp", "aw"),
new Browser("com.z28j.feel", "g2"), // "g2" for version 0.9.8.4 (984)
new Browser("idm.internet.download.manager", "search"),
new Browser("idm.internet.download.manager.adm.lite", "search"),
new Browser("idm.internet.download.manager.plus", "search"),
new Browser("io.github.forkmaintainers.iceraven", "mozac_browser_toolbar_url_view"),
new Browser("mark.via", "o"), // "o" for version 4.0.7 (20200929)
new Browser("mark.via.gp", "o"), // "o" for version 4.0.7 (20200929)
new Browser("org.adblockplus.browser", "url_bar,url_bar_title"), // 2nd = Legacy (before v2)
new Browser("org.adblockplus.browser.beta", "url_bar,url_bar_title"), // 2nd = Legacy (before v2)
new Browser("org.bromite.bromite", "url_bar"),
new Browser("org.bromite.chromium", "url_bar"),
new Browser("org.chromium.chrome", "url_bar"),
new Browser("org.codeaurora.swe.browser", "url_bar"),
new Browser("org.gnu.icecat", "url_bar_title,mozac_browser_toolbar_url_view"), // 2nd = Anticipation
new Browser("org.mozilla.fenix", "mozac_browser_toolbar_url_view"),
new Browser("org.mozilla.fenix.nightly", "mozac_browser_toolbar_url_view"),
new Browser("org.mozilla.fennec_aurora", "mozac_browser_toolbar_url_view,url_bar_title"), // 2nd = Legacy
new Browser("org.mozilla.fennec_fdroid", "url_bar_title,mozac_browser_toolbar_url_view"), // 2nd = Anticipation
new Browser("org.mozilla.firefox", "url_bar_title,mozac_browser_toolbar_url_view"), // 2nd = Anticipation
new Browser("org.mozilla.fenix.nightly", "mozac_browser_toolbar_url_view"), // [DEPRECATED]
new Browser("org.mozilla.fennec_aurora", "mozac_browser_toolbar_url_view,url_bar_title"), // [DEPRECATED]
new Browser("org.mozilla.fennec_fdroid", "mozac_browser_toolbar_url_view,url_bar_title"), // 2nd = Legacy
new Browser("org.mozilla.firefox", "mozac_browser_toolbar_url_view,url_bar_title"), // 2nd = Legacy
new Browser("org.mozilla.firefox_beta", "mozac_browser_toolbar_url_view,url_bar_title"), // 2nd = Legacy
new Browser("org.mozilla.focus", "display_url"),
new Browser("org.mozilla.klar", "display_url"),
new Browser("org.mozilla.reference.browser", "mozac_browser_toolbar_url_view"),
new Browser("org.mozilla.rocket", "display_url"),
new Browser("org.torproject.torbrowser", "url_bar_title,mozac_browser_toolbar_url_view"), // 2nd = Anticipation
new Browser("org.torproject.torbrowser_alpha", "url_bar_title,mozac_browser_toolbar_url_view"), // 2nd = Anticipation
new Browser("org.torproject.torbrowser_alpha", "mozac_browser_toolbar_url_view,url_bar_title"), // 2nd = Legacy (before v10.0a8)
new Browser("org.ungoogled.chromium", "url_bar"), // [DEPRECATED]
new Browser("org.ungoogled.chromium.extensions.stable", "url_bar"),
new Browser("org.ungoogled.chromium.stable", "url_bar"),
// [Section B] Entries only present here
//
@@ -127,16 +139,197 @@ namespace Bit.Droid.Accessibility
"com.ss.squarehome2",
"com.treydev.pns"
};
// Be sure to keep these entries sorted alphabetically
// Be sure to keep these sections sorted alphabetically
public static Dictionary<string, KnownUsernameField> KnownUsernameFields => new List<KnownUsernameField>
{
new KnownUsernameField("accounts.google.com", "ServiceLogin", "Email"),
new KnownUsernameField("amazon.com", "signin", "ap_email_login"),
new KnownUsernameField("github.com", "", "user[login]-footer"),
new KnownUsernameField("paypal.com", "signin", "email"),
new KnownUsernameField("signin.aws.amazon.com", "signin", "resolving_input"),
new KnownUsernameField("signin.ebay.com", "eBayISAPI.dll", "userid"),
/**************************************************************************************
* SECTION A ——— World-renowned web sites/applications
*************************************************************************************/
// REM.: For this type of web sites/applications, the Top 100 (SimilarWeb, 2019)
// and the Top 50 (Alexa Internet, 2020) are covered. National variants
// have been added when available. Mobile and desktop versions supported.
//
// A few other popular web sites/applications have also been added.
//
// Could not be added, however:
// web sites/applications that don't use an "id" attribute for their login field.
// NOTE: The case of OAuth compatible web sites/applications that also provide
// a "user ID only" login page in this situation
// was taken into account in the tests as well.
/*
* A
*/
// Amazon ——— ap_email_login = mobile / ap_email = desktop (amazon.co.jp currently uses ap_email in both cases, as of July 2020).
new KnownUsernameField("amazon.ae", new (string, string)[] { ("contains:/ap/signin", "ap_email_login,ap_email") }),
new KnownUsernameField("amazon.ca", new (string, string)[] { ("contains:/ap/signin", "ap_email_login,ap_email") }),
new KnownUsernameField("amazon.cn", new (string, string)[] { ("contains:/ap/signin", "ap_email_login,ap_email") }),
new KnownUsernameField("amazon.co.jp", new (string, string)[] { ("contains:/ap/signin", "ap_email_login,ap_email") }),
new KnownUsernameField("amazon.co.uk", new (string, string)[] { ("contains:/ap/signin", "ap_email_login,ap_email") }),
new KnownUsernameField("amazon.com", new (string, string)[] { ("contains:/ap/signin", "ap_email_login,ap_email") }),
new KnownUsernameField("amazon.com.au", new (string, string)[] { ("contains:/ap/signin", "ap_email_login,ap_email") }),
new KnownUsernameField("amazon.com.br", new (string, string)[] { ("contains:/ap/signin", "ap_email_login,ap_email") }),
new KnownUsernameField("amazon.com.mx", new (string, string)[] { ("contains:/ap/signin", "ap_email_login,ap_email") }),
new KnownUsernameField("amazon.com.tr", new (string, string)[] { ("contains:/ap/signin", "ap_email_login,ap_email") }),
new KnownUsernameField("amazon.de", new (string, string)[] { ("contains:/ap/signin", "ap_email_login,ap_email") }),
new KnownUsernameField("amazon.es", new (string, string)[] { ("contains:/ap/signin", "ap_email_login,ap_email") }),
new KnownUsernameField("amazon.fr", new (string, string)[] { ("contains:/ap/signin", "ap_email_login,ap_email") }),
new KnownUsernameField("amazon.in", new (string, string)[] { ("contains:/ap/signin", "ap_email_login,ap_email") }),
new KnownUsernameField("amazon.it", new (string, string)[] { ("contains:/ap/signin", "ap_email_login,ap_email") }),
new KnownUsernameField("amazon.nl", new (string, string)[] { ("contains:/ap/signin", "ap_email_login,ap_email") }),
new KnownUsernameField("amazon.sa", new (string, string)[] { ("contains:/ap/signin", "ap_email_login,ap_email") }),
new KnownUsernameField("amazon.sg", new (string, string)[] { ("contains:/ap/signin", "ap_email_login,ap_email") }),
// Amazon Web Services
new KnownUsernameField("signin.aws.amazon.com", new (string, string)[] { ("signin", "resolving_input") }),
// Atlassian
new KnownUsernameField("id.atlassian.com", new (string, string)[] { ("login", "username") }),
/*
* B
*/
// Bitly ——— enterprise users.
new KnownUsernameField("bitly.com", new (string, string)[] { ("/sso/url_slug", "url_slug") }),
/*
* E
*/
// eBay ——— 1st = traditional access / 2nd = direct access (i.e. https://signin.ebay.tld/).
new KnownUsernameField("signin.befr.ebay.be", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.benl.ebay.be", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.cafr.ebay.ca", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.at", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.be", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.ca", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.ch", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.co.uk", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.com", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.com.au", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.com.hk", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.com.my", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.com.sg", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.de", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.es", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.fr", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.ie", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.in", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.it", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.nl", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.ph", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
new KnownUsernameField("signin.ebay.pl", new (string, string)[] { ("iendswith:eBayISAPI.dll", "userid"), ("icontains:/signin/", "userid") }),
/*
* G
*/
// Google ——— 1st = used in most cases (v2) / 2nd = used in some cases (v1).
new KnownUsernameField("accounts.google.com", new (string, string)[] { ("identifier", "identifierId"), ("ServiceLogin", "Email") }),
/*
* P
*/
// PayPal ——— 1st = traditional access / 2nd = access using OAuth.
new KnownUsernameField("paypal.com", new (string, string)[] { ("signin", "email"), ("contains:/connect/", "email") }),
/*
* T
*/
// Tumblr ——— despite "signup" in its ID, it's the login field (the website offers registration if the account doesn't exist).
new KnownUsernameField("tumblr.com", new (string, string)[] { ("login", "signup_determine_email") }),
/*
* Y
*/
// Yandex
new KnownUsernameField("passport.yandex.az", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.by", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.co.il", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.com", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.com.am", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.com.ge", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.com.tr", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.ee", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.fi", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.fr", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.kg", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.kz", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.lt", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.lv", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.md", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.pl", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.ru", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.tj", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.tm", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.ua", new (string, string)[] { ("auth", "passp-field-login") }),
new KnownUsernameField("passport.yandex.uz", new (string, string)[] { ("auth", "passp-field-login") }),
/**************************************************************************************
* SECTION B ——— Top 100 worldwide
*************************************************************************************/
// As of July 2020, all entries that needed to be added from
// Top 100 (SimilarWeb, 2019) and Top 50 (Alexa Internet, 2020)
// matched section A.
//
// Therefore, no entry currently.
/**************************************************************************************
* SECTION C ——— Top 20 for selected countries
*************************************************************************************/
// REM.: For these selected countries, the Top 20 (SimilarWeb, 2020)
// and the Top 20 (Alexa Internet, 2020) are covered.
// Mobile and desktop versions supported.
//
// Could not be added, however:
// web sites/applications that don't use an "id" attribute for their login field.
/*
* Japan
*/
// NTT DOCOMO ——— mainly used for "My docomo".
new KnownUsernameField("cfg.smt.docomo.ne.jp", new (string, string)[] { ("contains:/auth/", "Di_Uid") }),
new KnownUsernameField("id.smt.docomo.ne.jp", new (string, string)[] { ("contains:/cgi7/", "Di_Uid") }),
/**************************************************************************************
* SECTION D ——— Miscellaneous
*************************************************************************************/
/*
* Various entries ——— Following user requests, etc.
*/
// No entry, currently.
/**************************************************************************************
* SECTION Z ——— Special forms
*
* Despite "user ID + password" fields both visible, detection rules required.
*************************************************************************************/
/*
* Main
*/
// No entry, currently.
/*
* Test/example purposes only
*/
// GitHub ——— VERY special case (signup form, just to test the proper functioning of special forms).
new KnownUsernameField("github.com", new (string, string)[] { ("", "user[login]-footer") }),
}.ToDictionary(n => n.UriAuthority);
public static void PrintTestData(AccessibilityNodeInfo root, AccessibilityEvent e)
@@ -306,11 +499,13 @@ namespace Bit.Droid.Accessibility
public static AccessibilityNodeInfo GetUsernameEditText(string uriString,
IEnumerable<AccessibilityNodeInfo> allEditTexts)
{
string uriAuthority = null;
string uriKey = null;
string uriLocalPath = null;
if (Uri.TryCreate(uriString, UriKind.Absolute, out var uri))
{
uriKey = uri.Authority;
uriAuthority = uri.Authority;
uriKey = uriAuthority.StartsWith("www.", StringComparison.Ordinal) ? uriAuthority.Substring(4) : uriAuthority;
uriLocalPath = uri.LocalPath;
}
@@ -326,15 +521,64 @@ namespace Bit.Droid.Accessibility
if (KnownUsernameFields.ContainsKey(uriKey))
{
var usernameField = KnownUsernameFields[uriKey];
if (uriLocalPath.EndsWith(usernameField.UriPathEnd))
(string UriPathWanted, string UsernameViewId)[] accessOptions = usernameField.AccessOptions;
for (int i = 0; i < accessOptions.Length; i++)
{
foreach (var editText in allEditTexts)
string curUriPathWanted = accessOptions[i].UriPathWanted;
string curUsernameViewId = accessOptions[i].UsernameViewId;
bool uriLocalPathMatches = false;
// Case-sensitive comparison
if (curUriPathWanted.StartsWith("startswith:", StringComparison.Ordinal))
{
foreach (var usernameViewId in usernameField.UsernameViewId.Split(","))
curUriPathWanted = curUriPathWanted.Substring(11);
uriLocalPathMatches = uriLocalPath.StartsWith(curUriPathWanted, StringComparison.Ordinal);
}
else if (curUriPathWanted.StartsWith("contains:", StringComparison.Ordinal))
{
curUriPathWanted = curUriPathWanted.Substring(9);
uriLocalPathMatches = uriLocalPath.Contains(curUriPathWanted, StringComparison.Ordinal);
}
else if (curUriPathWanted.StartsWith("endswith:", StringComparison.Ordinal))
{
curUriPathWanted = curUriPathWanted.Substring(9);
uriLocalPathMatches = uriLocalPath.EndsWith(curUriPathWanted, StringComparison.Ordinal);
}
// Case-insensitive comparison
else if (curUriPathWanted.StartsWith("istartswith:", StringComparison.Ordinal))
{
curUriPathWanted = curUriPathWanted.Substring(12);
uriLocalPathMatches = uriLocalPath.StartsWith(curUriPathWanted, StringComparison.OrdinalIgnoreCase);
}
else if (curUriPathWanted.StartsWith("icontains:", StringComparison.Ordinal))
{
curUriPathWanted = curUriPathWanted.Substring(10);
uriLocalPathMatches = uriLocalPath.Contains(curUriPathWanted, StringComparison.OrdinalIgnoreCase);
}
else if (curUriPathWanted.StartsWith("iendswith:", StringComparison.Ordinal))
{
curUriPathWanted = curUriPathWanted.Substring(10);
uriLocalPathMatches = uriLocalPath.EndsWith(curUriPathWanted, StringComparison.OrdinalIgnoreCase);
}
// Default type of comparison
else
{
uriLocalPathMatches = uriLocalPath.EndsWith(curUriPathWanted, StringComparison.Ordinal);
}
if (uriLocalPathMatches)
{
foreach (var editText in allEditTexts)
{
if (usernameViewId == editText.ViewIdResourceName)
foreach (var usernameViewId in curUsernameViewId.Split(","))
{
return editText;
if (usernameViewId == editText.ViewIdResourceName)
{
return editText;
}
}
}
}
@@ -435,7 +679,7 @@ namespace Bit.Droid.Accessibility
var icon = (ImageView)view.FindViewById(Resource.Id.icon);
text1.Text = AppResources.AutofillWithBitwarden;
text2.Text = AppResources.GoToMyVault;
icon.SetImageResource(Resource.Drawable.icon);
icon.SetImageResource(Resource.Drawable.shield);
return view;
}
@@ -600,7 +844,12 @@ namespace Bit.Droid.Accessibility
public static bool IsAutofillServicePromptVisible(IEnumerable<AccessibilityWindowInfo> windows)
{
return windows?.Any(w => w.Title?.ToLower().Contains("autofill") ?? false) ?? false;
// Autofill framework not available until API 26
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
return windows?.Any(w => w.Title?.ToLower().Contains("autofill") ?? false) ?? false;
}
return false;
}
public static int GetNodeHeight(AccessibilityNodeInfo node)

View File

@@ -255,13 +255,13 @@ namespace Bit.Droid.Accessibility
if (!AccessibilityHelpers.OverlayPermitted())
{
if (!AccessibilityHelpers.IsAutofillTileAdded)
if (Build.VERSION.SdkInt <= BuildVersionCodes.M)
{
// The user has the option of only using the autofill tile and leaving the overlay permission
// disabled, so only show this toast if they're using accessibility without overlay permission and
// have _not_ added the autofill tile
// disabled, so only show this toast if they're using accessibility without overlay permission on
// a version of Android without quick-action tile support
System.Diagnostics.Debug.WriteLine(">>> Overlay Permission not granted");
Toast.MakeText(this, AppResources.AccessibilityOverlayPermissionAlert, ToastLength.Long).Show();
Toast.MakeText(this, AppResources.AccessibilityDrawOverPermissionAlert, ToastLength.Long).Show();
}
return;
}

View File

@@ -2,15 +2,13 @@
{
public class KnownUsernameField
{
public KnownUsernameField(string uriAuthority, string uriPathEnd, string usernameViewId)
public KnownUsernameField(string uriAuthority, (string UriPathWanted, string UsernameViewId)[] accessOptions)
{
UriAuthority = uriAuthority;
UriPathEnd = uriPathEnd;
UsernameViewId = usernameViewId;
AccessOptions = accessOptions;
}
public string UriAuthority { get; set; }
public string UriPathEnd { get; set; }
public string UsernameViewId { get; set; }
public (string UriPathWanted, string UsernameViewId)[] AccessOptions { get; set; }
}
}

View File

@@ -15,7 +15,7 @@
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
<TargetFrameworkVersion>v10.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v11.0</TargetFrameworkVersion>
<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
@@ -31,6 +31,8 @@
<AndroidLinkMode>None</AndroidLinkMode>
<AndroidSupportedAbis />
<JavaMaximumHeapSize>1G</JavaMaximumHeapSize>
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugSymbols>false</DebugSymbols>
@@ -77,8 +79,9 @@
<PackageReference Include="Portable.BouncyCastle">
<Version>1.8.6.7</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.AutoFill" Version="1.1.0.3-beta01" />
<PackageReference Include="Xamarin.Essentials">
<Version>1.5.3.1</Version>
<Version>1.5.3.2</Version>
</PackageReference>
<PackageReference Include="Xamarin.Firebase.Messaging">
<Version>71.1740.0</Version>
@@ -120,6 +123,7 @@
<Compile Include="Receivers\LockAlarmReceiver.cs" />
<Compile Include="Receivers\PackageReplacedReceiver.cs" />
<Compile Include="Renderers\CipherViewCellRenderer.cs" />
<Compile Include="Renderers\CustomTabbedRenderer.cs" />
<Compile Include="Renderers\ExtendedSliderRenderer.cs" />
<Compile Include="Renderers\CustomEditorRenderer.cs" />
<Compile Include="Renderers\CustomPickerRenderer.cs" />
@@ -133,6 +137,7 @@
<Compile Include="MainActivity.cs" />
<Compile Include="Resources\Resource.designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Services\BiometricService.cs" />
<Compile Include="Services\CryptoPrimitiveService.cs" />
<Compile Include="Services\DeviceActionService.cs" />
<Compile Include="Services\LocalizeService.cs" />
@@ -141,6 +146,7 @@
<Compile Include="Tiles\MyVaultTileService.cs" />
<Compile Include="Utilities\AndroidHelpers.cs" />
<Compile Include="Utilities\AppCenterHelper.cs" />
<Compile Include="WebAuthCallbackActivity.cs" />
</ItemGroup>
<ItemGroup>
<AndroidAsset Include="Assets\FontAwesome.ttf" />
@@ -150,36 +156,33 @@
<None Include="ci-build-apks.ps1" />
<GoogleServicesJson Include="google-services.json" />
<GoogleServicesJson Include="google-services.json.enc" />
<None Include="fdroid-keystore.jks.enc" />
<None Include="Properties\AndroidManifest.xml" />
<None Include="upload-keystore.jks.enc" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\accessibility_overlay.png" />
<AndroidResource Include="Resources\drawable-hdpi\accessibility_permission.png" />
<AndroidResource Include="Resources\drawable-hdpi\accessibility_step1.png" />
<AndroidResource Include="Resources\drawable-hdpi\accessibility_step2.png" />
<AndroidResource Include="Resources\drawable-hdpi\autofill_enable.png" />
<AndroidResource Include="Resources\drawable-hdpi\autofill_use.png" />
<AndroidResource Include="Resources\drawable-xhdpi\accessibility_overlay.png" />
<AndroidResource Include="Resources\drawable-xhdpi\accessibility_permission.png" />
<AndroidResource Include="Resources\drawable-xhdpi\accessibility_step1.png" />
<AndroidResource Include="Resources\drawable-xhdpi\accessibility_step2.png" />
<AndroidResource Include="Resources\drawable-xhdpi\autofill_enable.png" />
<AndroidResource Include="Resources\drawable-xhdpi\autofill_use.png" />
<AndroidResource Include="Resources\drawable-xxhdpi\accessibility_overlay.png" />
<AndroidResource Include="Resources\drawable-xxhdpi\accessibility_permission.png" />
<AndroidResource Include="Resources\drawable-xxhdpi\accessibility_step1.png" />
<AndroidResource Include="Resources\drawable-xxhdpi\accessibility_step2.png" />
<AndroidResource Include="Resources\drawable-xxhdpi\autofill_enable.png" />
<AndroidResource Include="Resources\drawable-xxhdpi\autofill_use.png" />
<AndroidResource Include="Resources\drawable\accessibility_overlay.png" />
<AndroidResource Include="Resources\drawable\accessibility_permission.png" />
<AndroidResource Include="Resources\drawable\accessibility_step1.png" />
<AndroidResource Include="Resources\drawable\accessibility_step2.png" />
<AndroidResource Include="Resources\drawable\autofill_enable.png" />
<AndroidResource Include="Resources\drawable\autofill_use.png" />
<AndroidResource Include="Resources\drawable-hdpi\logo_legacy.png" />
<AndroidResource Include="Resources\drawable-hdpi\logo_white_legacy.png" />
<AndroidResource Include="Resources\drawable-xhdpi\logo_legacy.png" />
<AndroidResource Include="Resources\drawable-xhdpi\logo_white_legacy.png" />
<AndroidResource Include="Resources\drawable-xxhdpi\logo_legacy.png" />
<AndroidResource Include="Resources\drawable-xxhdpi\logo_white_legacy.png" />
<AndroidResource Include="Resources\drawable\card.xml" />
<AndroidResource Include="Resources\drawable\cog.xml" />
<AndroidResource Include="Resources\drawable\icon.xml" />
<AndroidResource Include="Resources\drawable\ic_launcher_foreground.xml" />
<AndroidResource Include="Resources\drawable\id.xml" />
<AndroidResource Include="Resources\drawable\lock.xml" />
<AndroidResource Include="Resources\drawable\login.xml" />
<AndroidResource Include="Resources\drawable\logo.xml" />
<AndroidResource Include="Resources\drawable\logo_white.xml" />
<AndroidResource Include="Resources\drawable\pencil.xml" />
<AndroidResource Include="Resources\drawable\plus.xml" />
<AndroidResource Include="Resources\drawable\refresh.xml" />
<AndroidResource Include="Resources\drawable\search.xml" />
<AndroidResource Include="Resources\drawable\shield.xml" />
<AndroidResource Include="Resources\drawable-v23\splash_screen.xml" />
<AndroidResource Include="Resources\drawable-v23\splash_screen_dark.xml" />
<AndroidResource Include="Resources\layout\Tabbar.axml" />
<AndroidResource Include="Resources\layout\Toolbar.axml" />
<AndroidResource Include="Resources\mipmap-anydpi-v26\ic_launcher.xml" />
@@ -194,6 +197,7 @@
<AndroidResource Include="Resources\mipmap-xxhdpi\ic_launcher_round.png" />
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher.png" />
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher_round.png" />
<AndroidResource Include="Resources\values-night\styles.xml" />
<AndroidResource Include="Resources\values\styles.xml" />
<AndroidResource Include="Resources\values\colors.xml" />
</ItemGroup>
@@ -231,138 +235,15 @@
<ItemGroup>
<AndroidResource Include="Resources\layout\autofill_listitem.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\login.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\login.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\login.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\login.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxxhdpi\login.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\logo.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\values-v21\styles.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\refresh.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\lock.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\logo.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\yubikey.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\yubikey.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\shield.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\yubikey.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\logo.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\yubikey.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\lock.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\refresh.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\refresh.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\lock.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\lock.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\refresh.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxxhdpi\lock.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxxhdpi\refresh.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\id.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\card.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\id.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\card.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\id.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\card.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\id.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\card.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxxhdpi\card.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxxhdpi\id.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\pencil.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\plus.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\pencil.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\plus.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\pencil.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\plus.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\pencil.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\plus.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxxhdpi\plus.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxxhdpi\pencil.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\slider_thumb.xml" />
</ItemGroup>
@@ -372,78 +253,12 @@
<SubType>Designer</SubType>
</AndroidResource>
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\logo_white.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\logo_white.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\logo_white.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\search.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\search.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\search.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\search.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxxhdpi\search.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\cog.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\cog.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\cog.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\cog.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxxhdpi\cog.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\values\dimens.xml">
<Generator>MSBuild:UpdateGeneratedFiles</Generator>
<SubType>Designer</SubType>
</AndroidResource>
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\shield.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\shield.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\shield.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxxhdpi\shield.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\refresh_sm.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\refresh_sm.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\refresh_sm.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi\refresh_sm.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxxhdpi\refresh_sm.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\layout\CipherViewCell.axml">
<Generator>MSBuild:UpdateGeneratedFiles</Generator>

View File

@@ -1,14 +1,24 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using Android.Content;
using Android.Service.Autofill;
using Android.Widget;
using System.Linq;
using Android.App;
using System.Threading.Tasks;
using Android.App.Slices;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.OS;
using Android.Runtime;
using Android.Widget.Inline;
using Bit.App.Resources;
using Bit.Core.Enums;
using Android.Views.Autofill;
using AndroidX.AutoFill.Inline;
using AndroidX.AutoFill.Inline.V1;
using Bit.Core.Abstractions;
using SaveFlags = Android.Service.Autofill.SaveFlags;
namespace Bit.Droid.Autofill
{
@@ -41,6 +51,7 @@ namespace Bit.Droid.Autofill
"com.amazon.cloud9",
"com.android.browser",
"com.android.chrome",
"com.android.htmlviewer",
"com.avast.android.secure.browser",
"com.avg.android.secure.browser",
"com.brave.browser",
@@ -56,6 +67,8 @@ namespace Bit.Droid.Autofill
"com.google.android.apps.chrome_dev",
"com.kiwibrowser.browser",
"com.microsoft.emmx",
"com.mmbox.browser",
"com.mmbox.xbrowser",
"com.naver.whale",
"com.opera.browser",
"com.opera.browser.beta",
@@ -71,10 +84,17 @@ namespace Bit.Droid.Autofill
"com.vivaldi.browser.snapshot",
"com.vivaldi.browser.sopranos",
"com.yandex.browser",
"com.z28j.feel",
"idm.internet.download.manager",
"idm.internet.download.manager.adm.lite",
"idm.internet.download.manager.plus",
"io.github.forkmaintainers.iceraven",
"mark.via",
"mark.via.gp",
"org.adblockplus.browser",
"org.adblockplus.browser.beta",
"org.bromite.bromite",
"org.bromite.chromium",
"org.chromium.chrome",
"org.codeaurora.swe.browser",
"org.gnu.icecat",
@@ -88,6 +108,9 @@ namespace Bit.Droid.Autofill
"org.mozilla.rocket",
"org.torproject.torbrowser",
"org.torproject.torbrowser_alpha",
"org.ungoogled.chromium",
"org.ungoogled.chromium.extensions.stable",
"org.ungoogled.chromium.stable",
};
// The URLs are blacklisted from autofilling
@@ -119,14 +142,49 @@ namespace Bit.Droid.Autofill
return new List<FilledItem>();
}
public static FillResponse BuildFillResponse(Parser parser, List<FilledItem> items, bool locked)
public static FillResponse BuildFillResponse(Parser parser, List<FilledItem> items, bool locked,
bool inlineAutofillEnabled, FillRequest fillRequest = null)
{
// Acquire inline presentation specs on Android 11+
IList<InlinePresentationSpec> inlinePresentationSpecs = null;
var inlinePresentationSpecsCount = 0;
var inlineMaxSuggestedCount = 0;
if (inlineAutofillEnabled && fillRequest != null && (int)Build.VERSION.SdkInt >= 30)
{
var inlineSuggestionsRequest = fillRequest.InlineSuggestionsRequest;
inlineMaxSuggestedCount = inlineSuggestionsRequest?.MaxSuggestionCount ?? 0;
inlinePresentationSpecs = inlineSuggestionsRequest?.InlinePresentationSpecs;
inlinePresentationSpecsCount = inlinePresentationSpecs?.Count ?? 0;
}
// Build response
var responseBuilder = new FillResponse.Builder();
if (items != null && items.Count > 0)
{
foreach (var item in items)
var maxItems = items.Count;
if (inlineMaxSuggestedCount > 0)
{
var dataset = BuildDataset(parser.ApplicationContext, parser.FieldCollection, item);
// -1 to adjust for 'open vault' option
maxItems = Math.Min(maxItems, inlineMaxSuggestedCount - 1);
}
for (int i = 0; i < maxItems; i++)
{
InlinePresentationSpec inlinePresentationSpec = null;
if (inlinePresentationSpecs != null)
{
if (i < inlinePresentationSpecsCount)
{
inlinePresentationSpec = inlinePresentationSpecs[i];
}
else
{
// If the max suggestion count is larger than the number of specs in the list, then
// the last spec is used for the remainder of the suggestions
inlinePresentationSpec = inlinePresentationSpecs[inlinePresentationSpecsCount - 1];
}
}
var dataset = BuildDataset(parser.ApplicationContext, parser.FieldCollection, items[i],
inlinePresentationSpec);
if (dataset != null)
{
responseBuilder.AddDataset(dataset);
@@ -134,16 +192,34 @@ namespace Bit.Droid.Autofill
}
}
responseBuilder.AddDataset(BuildVaultDataset(parser.ApplicationContext, parser.FieldCollection,
parser.Uri, locked));
AddSaveInfo(parser, responseBuilder, parser.FieldCollection);
parser.Uri, locked, inlinePresentationSpecs));
AddSaveInfo(parser, fillRequest, responseBuilder, parser.FieldCollection);
responseBuilder.SetIgnoredIds(parser.FieldCollection.IgnoreAutofillIds.ToArray());
return responseBuilder.Build();
}
public static Dataset BuildDataset(Context context, FieldCollection fields, FilledItem filledItem)
public static Dataset BuildDataset(Context context, FieldCollection fields, FilledItem filledItem,
InlinePresentationSpec inlinePresentationSpec = null)
{
var datasetBuilder = new Dataset.Builder(
BuildListView(filledItem.Name, filledItem.Subtitle, filledItem.Icon, context));
var overlayPresentation = BuildOverlayPresentation(
filledItem.Name,
filledItem.Subtitle,
filledItem.Icon,
context);
var inlinePresentation = BuildInlinePresentation(
inlinePresentationSpec,
filledItem.Name,
filledItem.Subtitle,
filledItem.Icon,
null,
context);
var datasetBuilder = new Dataset.Builder(overlayPresentation);
if (inlinePresentation != null)
{
datasetBuilder.SetInlinePresentation(inlinePresentation);
}
if (filledItem.ApplyToFields(fields, datasetBuilder))
{
return datasetBuilder.Build();
@@ -151,7 +227,8 @@ namespace Bit.Droid.Autofill
return null;
}
public static Dataset BuildVaultDataset(Context context, FieldCollection fields, string uri, bool locked)
public static Dataset BuildVaultDataset(Context context, FieldCollection fields, string uri, bool locked,
IList<InlinePresentationSpec> inlinePresentationSpecs = null)
{
var intent = new Intent(context, typeof(MainActivity));
intent.PutExtra("autofillFramework", true);
@@ -175,14 +252,26 @@ namespace Bit.Droid.Autofill
var pendingIntent = PendingIntent.GetActivity(context, ++_pendingIntentId, intent,
PendingIntentFlags.CancelCurrent);
var view = BuildListView(
var overlayPresentation = BuildOverlayPresentation(
AppResources.AutofillWithBitwarden,
locked ? AppResources.VaultIsLocked : AppResources.GoToMyVault,
Resource.Drawable.icon,
context);
var datasetBuilder = new Dataset.Builder(view);
datasetBuilder.SetAuthentication(pendingIntent.IntentSender);
var inlinePresentation = BuildInlinePresentation(
inlinePresentationSpecs?.Last(),
AppResources.Bitwarden,
locked ? AppResources.VaultIsLocked : AppResources.MyVault,
Resource.Drawable.icon,
pendingIntent,
context);
var datasetBuilder = new Dataset.Builder(overlayPresentation);
if (inlinePresentation != null)
{
datasetBuilder.SetInlinePresentation(inlinePresentation);
}
datasetBuilder.SetAuthentication(pendingIntent?.IntentSender);
// Dataset must have a value set. We will reset this in the main activity when the real item is chosen.
foreach (var autofillId in fields.AutofillIds)
@@ -192,7 +281,7 @@ namespace Bit.Droid.Autofill
return datasetBuilder.Build();
}
public static RemoteViews BuildListView(string text, string subtext, int iconId, Context context)
public static RemoteViews BuildOverlayPresentation(string text, string subtext, int iconId, Context context)
{
var packageName = context.PackageName;
var view = new RemoteViews(packageName, Resource.Layout.autofill_listitem);
@@ -202,11 +291,87 @@ namespace Bit.Droid.Autofill
return view;
}
public static void AddSaveInfo(Parser parser, FillResponse.Builder responseBuilder, FieldCollection fields)
public static InlinePresentation BuildInlinePresentation(InlinePresentationSpec inlinePresentationSpec,
string text, string subtext, int iconId, PendingIntent pendingIntent, Context context)
{
if ((int)Build.VERSION.SdkInt < 30 || inlinePresentationSpec == null)
{
return null;
}
if (pendingIntent == null)
{
// InlinePresentation requires nonNull pending intent (even though we only utilize one for the
// "my vault" presentation) so we're including an empty one here
pendingIntent = PendingIntent.GetService(context, 0, new Intent(),
PendingIntentFlags.OneShot | PendingIntentFlags.UpdateCurrent);
}
var slice = CreateInlinePresentationSlice(
inlinePresentationSpec,
text,
subtext,
iconId,
"Autofill option",
pendingIntent,
context);
if (slice != null)
{
return new InlinePresentation(slice, inlinePresentationSpec, false);
}
return null;
}
private static Slice CreateInlinePresentationSlice(
InlinePresentationSpec inlinePresentationSpec,
string text,
string subtext,
int iconId,
string contentDescription,
PendingIntent pendingIntent,
Context context)
{
var imeStyle = inlinePresentationSpec.Style;
if (!UiVersions.GetVersions(imeStyle).Contains(UiVersions.InlineUiVersion1))
{
return null;
}
var contentBuilder = InlineSuggestionUi.NewContentBuilder(pendingIntent)
.SetContentDescription(contentDescription);
if (!string.IsNullOrWhiteSpace(text))
{
contentBuilder.SetTitle(text);
}
if (!string.IsNullOrWhiteSpace(subtext))
{
contentBuilder.SetSubtitle(subtext);
}
if (iconId > 0)
{
var icon = Icon.CreateWithResource(context, iconId);
if (icon != null)
{
if (iconId == Resource.Drawable.icon)
{
// Don't tint our logo
icon.SetTintBlendMode(BlendMode.Dst);
}
contentBuilder.SetStartIcon(icon);
}
}
return contentBuilder.Build().JavaCast<InlineSuggestionUi.Content>()?.Slice;
}
public static void AddSaveInfo(Parser parser, FillRequest fillRequest, FillResponse.Builder responseBuilder,
FieldCollection fields)
{
// Docs state that password fields cannot be reliably saved in Compat mode since they will show as
// masked values.
var compatBrowser = CompatBrowsers.Contains(parser.PackageName);
bool? compatRequest = null;
if (Build.VERSION.SdkInt >= BuildVersionCodes.Q && fillRequest != null)
{
// Attempt to automatically establish compat request mode on Android 10+
compatRequest = (fillRequest.Flags | FillRequest.FlagCompatibilityModeRequest) == fillRequest.Flags;
}
var compatBrowser = compatRequest ?? CompatBrowsers.Contains(parser.PackageName);
if (compatBrowser && fields.SaveType == SaveDataType.Password)
{
return;

View File

@@ -46,6 +46,8 @@ namespace Bit.Droid.Autofill
{
return;
}
var inlineAutofillEnabled = await _storageService.GetAsync<bool?>(Constants.InlineAutofillEnabledKey) ?? true;
if (_vaultTimeoutService == null)
{
@@ -64,7 +66,7 @@ namespace Bit.Droid.Autofill
}
// build response
var response = AutofillHelpers.BuildFillResponse(parser, items, locked);
var response = AutofillHelpers.BuildFillResponse(parser, items, locked, inlineAutofillEnabled, request);
callback.OnSuccess(response);
}

View File

@@ -221,4 +221,4 @@ namespace Bit.Droid.Autofill
return null;
}
}
}
}

View File

@@ -18,13 +18,14 @@ using Android.Nfc;
using Bit.App.Utilities;
using System.Threading.Tasks;
using AndroidX.Core.Content;
using ZXing.Net.Mobile.Android;
namespace Bit.Droid
{
[Activity(
Label = "Bitwarden",
Icon = "@mipmap/ic_launcher",
Theme = "@style/LightTheme.Splash",
Theme = "@style/LaunchTheme",
MainLauncher = true,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
[Register("com.x8bit.bitwarden.MainActivity")]
@@ -143,6 +144,7 @@ namespace Bit.Droid
protected override void OnResume()
{
base.OnResume();
Xamarin.Essentials.Platform.OnResume();
if (_deviceActionService.SupportsNfc())
{
try
@@ -193,8 +195,7 @@ namespace Bit.Droid
else
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
ZXing.Net.Mobile.Forms.Android.PermissionsHandler.OnRequestPermissionsResult(
requestCode, permissions, grantResults);
PermissionsHandler.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
@@ -333,7 +334,11 @@ namespace Bit.Droid
private void UpdateTheme(string theme)
{
if (theme == "dark")
if (theme == "light")
{
SetTheme(Resource.Style.LightTheme);
}
else if (theme == "dark")
{
SetTheme(Resource.Style.DarkTheme);
}
@@ -347,7 +352,14 @@ namespace Bit.Droid
}
else
{
SetTheme(Resource.Style.LightTheme);
if (_deviceActionService.UsingDarkTheme())
{
SetTheme(Resource.Style.DarkTheme);
}
else
{
SetTheme(Resource.Style.LightTheme);
}
}
}

View File

@@ -41,7 +41,8 @@ namespace Bit.Droid
{
RegisterLocalServices();
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
ServiceContainer.Init(deviceActionService.DeviceUserAgent);
ServiceContainer.Init(deviceActionService.DeviceUserAgent, Constants.ClearCiphersCacheKey,
Constants.AndroidAllClearCipherCacheKeys);
}
#if !FDROID
if (Build.VERSION.SdkInt <= BuildVersionCodes.Kitkat)
@@ -98,6 +99,7 @@ namespace Bit.Droid
broadcasterService, () => ServiceContainer.Resolve<IEventService>("eventService"));
var platformUtilsService = new MobilePlatformUtilsService(deviceActionService, messagingService,
broadcasterService);
var biometricService = new BiometricService();
ServiceContainer.Register<IBroadcasterService>("broadcasterService", broadcasterService);
ServiceContainer.Register<IMessagingService>("messagingService", messagingService);
@@ -108,6 +110,7 @@ namespace Bit.Droid
ServiceContainer.Register<IStorageService>("secureStorageService", secureStorageService);
ServiceContainer.Register<IDeviceActionService>("deviceActionService", deviceActionService);
ServiceContainer.Register<IPlatformUtilsService>("platformUtilsService", platformUtilsService);
ServiceContainer.Register<IBiometricService>("biometricService", biometricService);
// Push
#if FDROID

View File

@@ -3,10 +3,11 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:versionCode="1"
android:versionName="2.4.1"
android:versionName="2.7.0"
android:installLocation="internalOnly"
package="com.x8bit.bitwarden">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="29" />
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.NFC" />
@@ -23,7 +24,7 @@
<application
android:label="Bitwarden"
android:theme="@style/LightTheme.Splash"
android:theme="@style/LaunchTheme"
android:allowBackup="false"
tools:replace="android:allowBackup"
android:icon="@mipmap/ic_launcher"

View File

@@ -27,12 +27,15 @@ namespace Bit.Droid.Renderers
private static Android.Graphics.Color _textColor;
private static Android.Graphics.Color _mutedColor;
private static Android.Graphics.Color _disabledIconColor;
private static bool _usingLightTheme;
private AndroidCipherCell _cell;
protected override Android.Views.View GetCellCore(Cell item, Android.Views.View convertView,
ViewGroup parent, Context context)
{
// TODO expand beyond light/dark detection once we support custom theme switching without app restart
var themeChanged = _usingLightTheme != ThemeManager.UsingLightTheme;
if (_faTypeface == null)
{
_faTypeface = Typeface.CreateFromAsset(context.Assets, "FontAwesome.ttf");
@@ -41,18 +44,19 @@ namespace Bit.Droid.Renderers
{
_miTypeface = Typeface.CreateFromAsset(context.Assets, "MaterialIcons_Regular.ttf");
}
if (_textColor == default(Android.Graphics.Color))
if (_textColor == default(Android.Graphics.Color) || themeChanged)
{
_textColor = ThemeManager.GetResourceColor("TextColor").ToAndroid();
}
if (_mutedColor == default(Android.Graphics.Color))
if (_mutedColor == default(Android.Graphics.Color) || themeChanged)
{
_mutedColor = ThemeManager.GetResourceColor("MutedColor").ToAndroid();
}
if (_disabledIconColor == default(Android.Graphics.Color))
if (_disabledIconColor == default(Android.Graphics.Color) || themeChanged)
{
_disabledIconColor = ThemeManager.GetResourceColor("DisabledIconColor").ToAndroid();
}
_usingLightTheme = ThemeManager.UsingLightTheme;
var cipherCell = item as CipherViewCell;
_cell = convertView as AndroidCipherCell;

View File

@@ -1,5 +1,9 @@
using Android.Content;
using System.ComponentModel;
using Android.Content;
using Android.Graphics;
using Android.Text;
using Android.Views.InputMethods;
using Android.Widget;
using Bit.Droid.Renderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
@@ -24,5 +28,46 @@ namespace Bit.Droid.Renderers
(ImeAction)ImeFlags.NoExtractUi;
}
}
// Workaround for failure to disable text prediction on non-password fields
// see https://github.com/xamarin/Xamarin.Forms/issues/10857
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
// Check if changed property is "IsPassword", otherwise ignore
if (e.PropertyName == Entry.IsPasswordProperty.PropertyName)
{
// Check if field type is text, otherwise ignore (numeric passwords, etc.)
EditText.InputType = Element.Keyboard.ToInputType();
bool isText = (EditText.InputType & InputTypes.ClassText) == InputTypes.ClassText,
isNumber = (EditText.InputType & InputTypes.ClassNumber) == InputTypes.ClassNumber;
if (isText || isNumber)
{
if (Element.IsPassword)
{
// Element is a password field, set inputType to TextVariationPassword which disables
// predictive text by default
EditText.InputType = EditText.InputType |
(isText ? InputTypes.TextVariationPassword : InputTypes.NumberVariationPassword);
}
else
{
// Element is not a password field, set inputType to TextVariationVisiblePassword to
// disable predictive text while still displaying the content.
EditText.InputType = EditText.InputType |
(isText ? InputTypes.TextVariationVisiblePassword : InputTypes.NumberVariationNormal);
}
// The workaround above forces a reset of the style properties, so we need to re-apply the font.
// see https://xamarin.github.io/bugzilla-archives/33/33666/bug.html
var typeface = Typeface.CreateFromAsset(Context.Assets, "RobotoMono_Regular.ttf");
if (Control is TextView label)
{
label.Typeface = typeface;
}
}
}
}
}
}

View File

@@ -0,0 +1,60 @@
using Android.Content;
using Android.Views;
using Bit.Droid.Renderers;
using Google.Android.Material.BottomNavigation;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Xamarin.Forms.Platform.Android.AppCompat;
[assembly: ExportRenderer(typeof(TabbedPage), typeof(CustomTabbedRenderer))]
namespace Bit.Droid.Renderers
{
public class CustomTabbedRenderer : TabbedPageRenderer, BottomNavigationView.IOnNavigationItemReselectedListener
{
private TabbedPage _page;
public CustomTabbedRenderer(Context context) : base(context) { }
protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
_page = e.NewElement;
GetBottomNavigationView()?.SetOnNavigationItemReselectedListener(this);
}
else
{
_page = e.OldElement;
}
}
private BottomNavigationView GetBottomNavigationView()
{
for (var i = 0; i < ViewGroup.ChildCount; i++)
{
var childView = ViewGroup.GetChildAt(i);
if (childView is ViewGroup viewGroup)
{
for (var j = 0; j < viewGroup.ChildCount; j++)
{
var childRelativeLayoutView = viewGroup.GetChildAt(j);
if (childRelativeLayoutView is BottomNavigationView bottomNavigationView)
{
return bottomNavigationView;
}
}
}
}
return null;
}
async void BottomNavigationView.IOnNavigationItemReselectedListener.OnNavigationItemReselected(IMenuItem item)
{
if (_page?.CurrentPage?.Navigation != null && _page.CurrentPage.Navigation.NavigationStack.Count > 0)
{
await _page.CurrentPage.Navigation.PopToRootAsync();
}
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 775 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 487 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 904 B

View File

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 495 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 943 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 825 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 440 B

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
TODO: When API 23 becomes our new minimum, replace 'splash_screen.xml' in 'drawable' with this version, and delete
all versions of 'logo_legacy.png' and 'logo_white_legacy.png'. The bitmaps only exist due to a bug in API <23 where
vector drawables used in layer-lists (our splash screen) stretch to fill the full height of the parent.
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<color android:color="@color/lightgray"/>
</item>
<item
android:drawable="@drawable/logo"
android:tileMode="disabled"
android:gravity="center"/>
</layer-list>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
TODO: When API 23 becomes our new minimum, replace 'splash_screen_dark.xml' in 'drawable' with this version, and delete
all versions of 'logo_legacy.png' and 'logo_white_legacy.png'. The bitmaps only exist due to a bug in API <23 where
vector drawables used in layer-lists (our splash screen) stretch to fill the full height of the parent.
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<color android:color="@color/darkgray"/>
</item>
<item
android:drawable="@drawable/logo_white"
android:tileMode="disabled"
android:gravity="center"/>
</layer-list>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 359 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 817 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 607 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 868 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 835 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 571 B

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