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

Compare commits

...

308 Commits

Author SHA1 Message Date
Federico Maccaroni
f312e8c4d2 PM-7052 WIP fix theme change on iOS Autofill extension (with ClipLogger activated) 2024-03-26 10:58:09 -03:00
Federico Maccaroni
1b3d5e5eb2 Merge branch 'main' into feature/maui-migration-passkeys 2024-03-25 15:37:46 -03:00
Federico Maccaroni
81fbb91c76 PM-6475 Fix dark theme on iOS Autofill extension (#3114) 2024-03-25 12:18:00 -03:00
Federico Maccaroni
45641aadfe [PM-6798] Fix account switch on autofill (#3106)
* PM-6798 Force state update when opening the Autofill extension

* PM-6798 Fix InitAppIfNeededAsync to be awaited and also ignored Fido2AuthenticatorException from logging them to AppCenter since they don't add much information and we're logging in other places what we need
2024-03-25 12:17:40 -03:00
Federico Maccaroni
27380abd89 PM-6844 Fix passkey creation cipher list empty label on small devices (#3104) 2024-03-25 12:17:27 -03:00
Bitwarden DevOps
9db32ca019 Bumped version to 2024.3.3 (#3113) 2024-03-25 14:20:35 +00:00
Federico Maccaroni
1fd7dd462e Merge branch 'main' into feature/maui-migration-passkeys 2024-03-22 15:42:51 -03:00
Dinis Vieira
f04ff7777a Added specific try catch in Android launchApp to avoid the app crashing when trying to launch app package name that are not installed on the device. (#3092) 2024-03-22 16:31:15 +00:00
github-actions[bot]
64775694e0 Autosync the updated translations (#3105)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-03-22 16:07:23 +00:00
Dinis Vieira
3c0007a21a [PM-7009] Improved exception messages for the Broadcast Service message callback function (#3091)
* Improved exception messages for the Broadcast Service message callback function

* Update src/Core/App.xaml.cs

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>

* Update src/Core/App.xaml.cs

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>

* Update src/Core/App.xaml.cs

Additional Null Check

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>

* Update src/Core/App.xaml.cs

Additional Null Check

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>

* Update src/Core/App.xaml.cs

Additional Null Check

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>

* Update src/Core/App.xaml.cs

Additional Null Check

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>

* Update src/Core/App.xaml.cs

Additional Null Check

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>

---------

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
2024-03-22 12:29:12 -03:00
Federico Maccaroni
ff49d041be [PM-6655] Add username empty fallback on passkey (#3101)
* PM-6655 Added fallback "Unknown account" to passkey username and moved it so it can be shared with Android

* PM-6655 Improved code lines formatting
2024-03-21 13:56:37 -03:00
Federico Maccaroni
b931263662 PM-6793 Updated autofill settings copy (#3102) 2024-03-21 13:28:54 -03:00
Federico Maccaroni
3a10e09469 PM-6706 Fixed UV attempts to be maximum 5 attempts and not 6 (#3103) 2024-03-21 13:28:38 -03:00
Federico Maccaroni
ebc068d820 [PM-6848] Improved User verification on passkeys creation (#3099)
* PM-6848 Updated cancellation flow on passkey user verification and improved UV enforcement on creation

* PM-6848 Added null checks to help diagnosing if NRE is presented
2024-03-21 13:28:14 -03:00
Federico Maccaroni
6bec0ede05 Merge branch 'main' into feature/maui-migration-passkeys 2024-03-20 09:02:57 -03:00
Bitwarden DevOps
35ff235010 Bumped version to 2024.3.2 (#3096) 2024-03-19 15:15:29 +00:00
Bitwarden DevOps
01bd5a7b8d Bumped version to 2024.3.1 (#3095) 2024-03-19 14:43:30 +00:00
Vince Grassia
3fce8c76bc Add Cleanup RC Branch workflow (#3093) 2024-03-18 11:36:21 -06:00
github-actions[bot]
3b64d7b979 Autosync the updated translations (#3083)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-03-15 23:31:54 +00:00
Federico Maccaroni
f343a2cdbb [PM-6852 ] Fix F-Droid build constant (#3085)
* Fix FDROID trackers removal by changing publish to build to see if doing this it adds the corresponding CustomConstants

* Changed parameters in new line delimiter to the one used in bash to see if that fixes passing the corresponding parameters to the build

* Revert "Changed parameters in new line delimiter to the one used in bash to see if that fixes passing the corresponding parameters to the build"

This reverts commit 608b23d115.

* Enable FDROID constant by replacing the content of Directory.Build.props in the clean stage of F-Droid
2024-03-15 17:01:15 -03:00
Federico Maccaroni
39da2a82c6 PM-6706 Add maximum attempts to UV with MP and with PIN (#3079) 2024-03-14 18:22:38 -03:00
Federico Maccaroni
970d3c2621 PM-6468 Implemented copy TOTP if needed after using a Fido2 credential. Also added the Fido2MediatorService to have one point to interact with the authentication and also to add any new logic we need. (#3082) 2024-03-14 18:12:50 -03:00
Federico Maccaroni
faa515b415 Merge branch 'main' into feature/maui-migration-passkeys 2024-03-14 18:08:42 -03:00
Federico Maccaroni
74085689d3 PM-6685 Fix race condition issue where the biometrics check is being done before the iOS extension is being shown. So when we need the UI, we wait until ViewDidAppear happens. (#3078) 2024-03-14 18:07:52 -03:00
Vince Grassia
9a9fb85ad8 Add version codes to GitHub step summary (#3081) 2024-03-14 10:06:51 -06:00
Bitwarden DevOps
e7f9d64edb Bumped version to 2024.3.0 (#3080) 2024-03-14 11:10:21 -04:00
Federico Maccaroni
144fc7c727 [PM-5154] Implement combined view for passwords and passkeys on iOS Autofill extension (#3075)
* PM-5154 Implemented combined view of passwords and passkeys and improved search and items UI

* PM-5154 Code improvement from PR feedback

* PM-5154 Code improvement to log unknown exceptions
2024-03-13 12:06:08 -03:00
Federico Maccaroni
53aedea93a Merge branch 'main' into feature/maui-migration-passkeys 2024-03-12 18:13:08 -03:00
Vince Grassia
459d20c019 DEVOPS-1840 - Update for automatic version bump calculation (#3043) 2024-03-12 14:10:11 -06:00
Federico Maccaroni
dd997aaa47 Merge branch 'main' into feature/maui-migration-passkeys 2024-03-12 12:38:52 -03:00
github-actions[bot]
a8529fa4b7 Autosync the updated translations (#3064)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-03-12 08:41:52 +00:00
Dinis Vieira
d1e82c9f1d [PM-6751]Added missing query intent for CustomTabs that might be responsible for the Exception in WebAuthenticator (#3071)
* Added missing query intent for CustomTabs that might be responsible for the crashes in WebAuthenticator

* minor formatting issue on AndroidManifest.xml

* Fix formatting in AndroidManifest
2024-03-11 19:36:07 -03:00
Federico Maccaroni
46c1d72b3c Merge branch 'main' into feature/maui-migration-passkeys 2024-03-11 18:12:27 -03:00
Dinis Vieira
9bc2901255 [PM-6726] Fix for Android 14 devices crashing when using the Tiles (#3069)
* Fix for Android 14 devices crashing when using the TileService.
Also added fix for an "hidden" crash in accessibility autofill

* Shared StartActivityAndCollapseFromTileService in AndroidHelpers

* Update src/App/Platforms/Android/Utilities/AndroidHelpers.cs

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>

* Updated name of StartActivityAndCollapseWithIntent method name used by TileService

---------

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
2024-03-11 18:06:37 -03:00
Federico Maccaroni
01fe329f3b Merge branch 'main' into feature/maui-migration-passkeys 2024-03-08 14:03:05 -03:00
Federico Maccaroni
67f7b3156e [PM-6496] Improved iOS extensions cipher cell UI (#3058)
* PM-6496 Improved iOS extensions cipher list to have an updated UI for each cell

* PM-6496 Improved UI on iOS extensions list cells
2024-03-08 13:59:15 -03:00
Vince Grassia
e3441845cd DEVOPS-1866 - Fix F-Droid Signing (#3063) 2024-03-07 23:45:15 +00:00
Vince Grassia
3f463647a0 Add login step to be able to download secrets (#3061) 2024-03-07 07:18:32 -08:00
Bitwarden DevOps
4f169a6fe3 Bumped version to 2024.2.2 (#3060) 2024-03-07 15:07:46 +00:00
Vince Grassia
82c2e91446 Update release workflow with proper paths (#3059) 2024-03-07 15:53:27 +01:00
Federico Maccaroni
39187732c0 [PM-6474] Remove header on Save passkey as new login (#3054)
* PM-6474 Removed header on empty list view on iOS Autofill create passkey flow

* PM-6474 Fix TableView being hidden on Logins scene
2024-03-07 11:04:00 -03:00
renovate[bot]
7482808857 [deps]: Update chrnorm/deployment-status action to v2.0.3 (#3050)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-06 13:52:31 -05:00
Federico Maccaroni
4292542155 [PM-6466] Implement passkeys User Verification (#3044)
* PM-6441 Implement passkeys User Verification

* PM-6441 Reorganized UserVerificationMediatorService so everything is not in the same file

* PM-6441 Fix Unit tests

* PM-6441 Refactor UserVerification on Fido2Authenticator and Client services to be of an enum type so we can see which specific preference the RP sent and to be passed into the user verification mediator service to perform the correct flow depending on that. Also updated Unit tests.

* PM-6441 Changed user verification logic a bit so if preference is Preferred and the app has the ability to verify the user then enforce required UV and fix issue on on Discouraged to take into account MP reprompt
2024-03-06 12:32:39 -03:00
Federico Maccaroni
e41abf5003 Merge branch 'main' into feature/maui-migration-passkeys 2024-03-06 11:19:18 -03:00
Opeyemi
fd233fa27f Update Failure Job (#3055) 2024-03-06 13:58:41 +01:00
Andreas Coroiu
4c2932f4d0 Fix FIDO2 client bugs (#3056)
* fix: blockedUris null issue

* fix: trailing slash in origin breaking check
2024-03-06 10:58:48 +00:00
Federico Maccaroni
a10481603d Merge branch 'main' into feature/maui-migration-passkeys
# Conflicts:
#	src/iOS.Core/Controllers/LoginAddViewController.cs
2024-03-05 18:23:23 -03:00
Federico Maccaroni
19f238d9bb [PM-6539] Fix Autofill Extension TDE without MP flow (#3049)
* PM-6539 Fix Autofill Extension TDE without MP updating PromptSSO to work in MAUI and also Generator view. WebAuthenticator copied with UIWindow gotten as it was in Xamarin forms to work. Also fix one NRE on state migration.

* PM-6539 Remove unnecessary using
2024-03-05 18:09:20 -03:00
Vince Grassia
6f6487ccc9 Fix GoogleServices file location (#3053) 2024-03-04 08:11:54 -07:00
Federico Maccaroni
b8ff0e0244 Merge branch 'main' into feature/maui-migration-passkeys 2024-03-04 11:03:30 -03:00
Dinis Vieira
dd3dc82595 PM-6552 Added missing using (#3052) 2024-03-04 13:29:22 +00:00
Dinis Vieira
40c80f082d [PM-6552] Fix for Android Window issues when opening Autofill/Accessibility (#3051)
* PM-6552 Removed several of the Window Workarounds for Android. Now always relying on the AndroidNavigationRedirectPage.
AndroidNavigationRedirectPage now more resilient to failure and navigates to HomePage as fallback.

* Update src/Core/Pages/AndroidNavigationRedirectPage.xaml.cs

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>

---------

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
2024-03-04 13:03:09 +00:00
Federico Maccaroni
85755902e1 Merge branch 'main' into feature/maui-migration-passkeys 2024-03-01 17:15:22 -03:00
André Bispo
bca5b95446 [PM-4760] Admin Recovery Permissions prompted to set MP. (#2912)
* [PM-4760] Add force password reset check on sync complete.

* [PM-4760] Log error on exception
2024-03-01 19:43:18 +00:00
Dinis Vieira
602627b5fa PM-6552 Fix for App only showing Home (Login) Page after closed after opening Accessibility Settings (#3047) 2024-03-01 19:17:45 +00:00
github-actions[bot]
6f32afb919 Autosync the updated translations (#3045)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-03-01 12:26:42 +01:00
Daniel James Smith
2ca47a4da4 Update ownership of translations (#3046)
Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
2024-03-01 11:10:15 +00:00
Federico Maccaroni
38d3a7ed41 [PM-6513] Omit creating CredentialIdentity if it throws an exception (#3040)
* PM-6513 Omit creating CredentialIdentity if that throws, so it doesn't affect other ciphers. E.g. if a Passkey doesn't have a UserName it will throw here and it shouldn't break replacing all the other identities.

* PM-6513 Added fallback values to passkey username not being set
2024-02-29 11:08:13 -03:00
Dinis Vieira
4ff56ba11e PM-5916 Fix for incorrect fonts in fingerprint phrases (#3042) 2024-02-29 09:57:25 +00:00
Vince Grassia
22d0cc681c Change version to proper value (#3041) 2024-02-28 11:49:30 -07:00
André Bispo
4e0a18cce5 [PM-6506] Fix double execution of command on returnType Go (#3039)
* [PM-6506] Fix double execution of command on returnType Go

* [PM-6506] Hide keyboard on environment page close

* [PM-6506] Task guard

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>

---------

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
2024-02-28 17:49:46 +00:00
Vince Grassia
c9fdfa7a15 DEVOPS-1746 - Update iOS distribution certificate and profiles (#3018) 2024-02-28 09:48:16 -03:00
Vince Grassia
850a7e754a DEVOPS-1834 - Apply fix for signing issue (#3038) 2024-02-27 20:18:24 +00:00
Federico Maccaroni
18fae7ddd8 Merge branch 'main' into feature/maui-migration-passkeys
# Conflicts:
#	Directory.Build.props
2024-02-27 12:46:30 -03:00
Dinis Vieira
67c5f79625 [PM-5917] Fix for send arrow now being touch sensitive to expand collapse (#3036)
* PM-5917 fix for send arrow not being tappable

* Added min width to send icon button so that it has correct spacing like in Android and old Xamarin Forms app.

* Updated min width from previous commit to 25 instead of 20 for more equivalent look to xamarin forms app on iOS
2024-02-26 23:45:59 +00:00
Federico Maccaroni
04e7cfe06d [PM-6428] Implement Legacy Secure Storage (#3027) 2024-02-26 19:25:08 -03:00
Álison Fernandes
d6c2ebe4c2 [PM-6480] Update MAUI to 8.0.7 (#3035)
* Update MAUI to 8.0.7

Updates MAUI to the future SR2 release version.

* Using the released version instead of nightly
2024-02-26 22:24:44 +00:00
Dinis Vieira
2a28294f91 PM-5912 Added default min height and corner radius for iOS buttons. Also removed incorrect style class from one button. (#3031) 2024-02-26 19:23:06 -03:00
Federico Maccaroni
b83473ce3a Merge branch 'main' into feature/maui-migration-passkeys 2024-02-26 15:42:12 -03:00
Dinis Vieira
8584bbaecc PM-6301 Removed IsRefreshing=true in RefreshAsync as it can trigger the RefreshView to trigger the RefreshView command again (#3026) 2024-02-26 17:28:18 +00:00
Dinis Vieira
2f3cded9c5 PM-6309 Fix to ensure the Icon and Icon placeholder visibility states is updated correctly based on website icons visibility choice (#3033) 2024-02-26 17:16:54 +00:00
github-actions[bot]
eff0ea7ce7 Autosync the updated translations (#3025)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-02-26 15:29:26 +00:00
renovate[bot]
6c3a53dd76 [deps]: Update dawidd6/action-download-artifact action to v3.1.2 (#3028)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-26 09:37:03 -05:00
Federico Maccaroni
e34a58e875 [PM-5154] Implement iOS Passkey -> Add login item (#3019)
* PM-5154 Implement iOS passkey add login

* PM-5154 Added Username to Create new login for passkey, for this the param was changed to the Fido2ConfirmNewCredentialParams object so we have access to the proper values. Also added back RpId to the params to have access to it when creating the vault item. Finally added loading to saving the passkey as new login
2024-02-26 09:33:39 -03:00
Federico Maccaroni
9f92fdeb29 Merge branch 'main' into feature/maui-migration-passkeys
# Conflicts:
#	src/Core/Resources/Localization/AppResources.resx
2024-02-23 20:11:27 -03:00
Vince Grassia
cf8d801c55 Add .NET 3.1 to fix Google Publisher project signing (#3024) 2024-02-22 13:45:42 -07:00
Federico Maccaroni
eaa6844742 Update build.yml to go back to net3.1 Publisher (#3023) 2024-02-22 17:01:33 -03:00
Federico Maccaroni
29e2f728e0 Update Publisher.csproj to go back to net 3.1 to see if that fixes the build (#3022) 2024-02-22 16:39:09 -03:00
Andreas Coroiu
c31444dc8b feat: optimize assertion network calls (#3021)
The server only needs to be updated if we have changed the counter. New passkeys that leave their counters at zero can therefore skip this step.
2024-02-22 14:34:10 +01:00
Federico Maccaroni
16e1b60a4d [PM-5154] Implement Passkeys on iOS (#3017)
* [PM-5731] feat: implement get assertion params object

* [PM-5731] feat: add first test

* [PM-5731] feat: add rp mismatch test

* [PM-5731] feat: ask for credentials when found

* [PM-5731] feat: find discoverable credentials

* [PM-5731] feat: add tests for successful UV requests

* [PM-5731] feat: add user does not consent test

* [PM-5731] feat: check for UV when reprompt is active

* [PM-5731] fix: tests a bit, needed some additional "arrange" steps

* [PM-5731] feat: add support for counter

* [PM-5731] feat: implement assertion without signature

* [PM-5732] feat: finish authenticator assertion implementation

note: CryptoFunctionService still needs Sign implemenation

* [PM-5731] chore: minor clean up

* [PM-5731] feat: scaffold make credential

* [PM-5731] feat: start implementing attestation

* [PM-5731] feat: implement credential exclusion

* [PM-5731] feat: add new credential confirmaiton

* [PM-5731] feat: implement credential creation

* [PM-5731] feat: add user verification checks

* [PM-5731] feat: add unknown error handling

* [PM-5731] chore: clean up unusued params

* [PM-5731] feat: partial attestation implementation

* [PM-5731] feat: implement key generation

* [PM-5731] feat: return public key in DER format

* [PM-5731] feat: implement signing

* [PM-5731] feat: remove logging

* [PM-5731] chore: use primary constructor

* [PM-5731] chore: add Async to method names

* [PM-5731] feat: add support for silent discoverability

* [PM-5731] feat: add support for specifying user presence requirement

* [PM-5731] feat: ensure unlocked vault

* [PM-5731] chore: clean up and refactor assertion tests

* [PM-5731] chore: clean up and refactor attestation tests

* [PM-5731] chore: add user presence todo comment

* [PM-5731] feat: scaffold fido2 client

* PM-5731 Fix build updating discoverable flag

* [PM-5731] fix: failing test

* [PM-5731] feat: add sameOriginWithAncestor and user id length checks

* [PM-5731] feat: add incomplete rpId verification

* [PM-5731] chore: document uri helpers

* [PM-5731] feat: implement fido2 client createCredential

* Added iOS passkeys integration, warning this branch has lots of logs to ease "debugging" extensions.

* [PM-5731] feat: implement credential assertion in client

* PM-5154 Fixed select passkey flow and started implementing create passkey on iOS

* fix wrong signature format

* PM-5154 [Passkeys iOS] Fix Credential ID handling on bytes and string formats. Fix Discoverable to be lowercase on set so it doesn't break parsing on clients. Added UserDisplayName on Fido2 entities. Extracted the Guid Standard/Raw format helpers to a extensions class.

* Fix incompatible GUID conversions

* PM-5154 [Passkeys iOS] Added custom UI flow for passkey creation

* PM-5154 [Passkeys iOS] Updated UI for passkey creation

* PM-5154 [Passkeys iOS] Refactored and added cipher selection for passkey creation on autofill search.

* PM-5154 [Passkeys iOS] Fixed empty top space on autofill password list

---------

Co-authored-by: Andreas Coroiu <andreas.coroiu@gmail.com>
Co-authored-by: mpbw2 <59324545+mpbw2@users.noreply.github.com>
2024-02-21 14:51:44 -03:00
Opeyemi
fe160a570f Add stub for DEVOPS-1822 (#3016) 2024-02-21 15:27:43 +00:00
Andreas Coroiu
71de3bedf4 [PM-5731] Create C# WebAuthn authenticator to support maui apps (#2951)
* [PM-5731] feat: implement get assertion params object

* [PM-5731] feat: add first test

* [PM-5731] feat: add rp mismatch test

* [PM-5731] feat: ask for credentials when found

* [PM-5731] feat: find discoverable credentials

* [PM-5731] feat: add tests for successful UV requests

* [PM-5731] feat: add user does not consent test

* [PM-5731] feat: check for UV when reprompt is active

* [PM-5731] fix: tests a bit, needed some additional "arrange" steps

* [PM-5731] feat: add support for counter

* [PM-5731] feat: implement assertion without signature

* [PM-5732] feat: finish authenticator assertion implementation

note: CryptoFunctionService still needs Sign implemenation

* [PM-5731] chore: minor clean up

* [PM-5731] feat: scaffold make credential

* [PM-5731] feat: start implementing attestation

* [PM-5731] feat: implement credential exclusion

* [PM-5731] feat: add new credential confirmaiton

* [PM-5731] feat: implement credential creation

* [PM-5731] feat: add user verification checks

* [PM-5731] feat: add unknown error handling

* [PM-5731] chore: clean up unusued params

* [PM-5731] feat: partial attestation implementation

* [PM-5731] feat: implement key generation

* [PM-5731] feat: return public key in DER format

* [PM-5731] feat: implement signing

* [PM-5731] feat: remove logging

* [PM-5731] chore: use primary constructor

* [PM-5731] chore: add Async to method names

* [PM-5731] feat: add support for silent discoverability

* [PM-5731] feat: add support for specifying user presence requirement

* [PM-5731] feat: ensure unlocked vault

* [PM-5731] chore: clean up and refactor assertion tests

* [PM-5731] chore: clean up and refactor attestation tests

* [PM-5731] chore: add user presence todo comment

* [PM-5731] feat: scaffold fido2 client

* PM-5731 Fix build updating discoverable flag

* [PM-5731] fix: failing test

* [PM-5731] feat: add sameOriginWithAncestor and user id length checks

* [PM-5731] feat: add incomplete rpId verification

* [PM-5731] chore: document uri helpers

* [PM-5731] feat: implement fido2 client createCredential

* [PM-5731] feat: implement credential assertion in client

* fix wrong signature format

(cherry picked from commit a1c9ebf01f)

* [PM-5731] fix: issues after cherry-pick

* Fix incompatible GUID conversions

(cherry picked from commit c801b2fc3a)

* [PM-5731] chore: remove default constructor

* [PM-5731] feat: refactor user interface to increase flexibility

* [PM-5731] feat: implement generic assertion user interface class

* [PM-5731] feat: remove ability to make user presence optional

* [PM-5731] chore: remove logging comments

* [PM-5731] feat: add native reprompt support to the authenticator

* [PM-5731] feat: allow pre and post UV

* [PM-5731] chore: add `Async` to method name. Remove `I` from struct

* [PM-5731] fix: discoverable string repr lowercase

* [PM-5731] chore: don't use C# 12 features

* [PM-5731] fix: replace magic strings and numbers with contants and enums

* [PM-5731] fix: use UTC creation date

* [PM-5731] fix: formatting

* [PM-5731] chore: use properties for public fields

* [PM-5731] chore: remove TODO

* [PM-5731] fix: IsValidRpId

---------

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
Co-authored-by: mpbw2 <59324545+mpbw2@users.noreply.github.com>
2024-02-21 12:12:52 -03:00
Dinis Vieira
a508bea4b0 [PM-6291] Fix Device Login Pending Requests screen not displaying anything (#3012)
* PM-6291 Changed Passwordless Request Login Page Layout structure so that it can display properly

* PM-6291 Additional changes to allow iOS to show the correct with on the collectionview items
2024-02-21 10:55:26 +00:00
Dinis Vieira
a73923c4f7 [PM-5909] Fix Font MAUI Sizes (#3014)
* PM-5909 Set the default FontSize for Entry, Editor, SearchBar and Picker on Android so that the fonts have a similar size to the one in the Xamarin Forms app.

* PM-5909 Set the default FontSize for Entry, Editor, SearchBar and Picker on iOS so that the fonts have a similar size to the one in the Xamarin Forms app.

* PM-5909 Added spacing in specific scenario for Send Groups (between icon and text)
2024-02-20 22:06:47 +00:00
renovate[bot]
11465e8975 [deps]: Update gh minor (#3011)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-20 16:01:34 -05:00
André Bispo
4c88524f0e [PM-4615] [PM-6217] Add new DUO frameless 2fa flow (#2956)
* [PM-4615] Update DUO 2FA screen to support DUO frameless flow.
2024-02-20 18:46:47 +00:00
Opeyemi
f1c20e03bc Remove individual linter file (#3010) 2024-02-15 11:15:13 -05:00
github-actions[bot]
920a2273c5 Autosync Crowdin Translations (#3009)
* Autosync the updated translations

* Add whitespace to build.yml to trigger workflow linter

* Remove whitespace from build.yml

---------

Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
2024-02-15 12:52:13 -03:00
Federico Maccaroni
d339514d9a Merge branch 'main' into feature/maui-migration-passkeys
# Conflicts:
#	.github/workflows/build.yml
#	nuget.config
#	src/App/App.csproj
#	src/App/Platforms/Android/AndroidManifest.xml
#	src/App/Platforms/iOS/AppDelegate.cs
#	src/Core/Core.csproj
#	src/Core/Pages/Settings/AutofillSettingsPageViewModel.android.cs
#	src/Core/Utilities/ThemeManager.cs
#	src/iOS.Autofill/CredentialProviderViewController.cs
#	src/iOS.Autofill/iOS.Autofill.csproj
2024-02-14 14:19:51 -03:00
Federico Maccaroni
75ec96f282 PM-3349 Added exception on gitignore so the nupkg for the AndroidX Credentials is added 2024-02-14 13:58:35 -03:00
mpbw2
96a9978ef8 fix resources path for crowdin (#3008) 2024-02-14 10:26:36 -05:00
Dinis Vieira
1ae388cb03 [PM-5900] Fix for Device Login push notifications cause the app to show HomePage (#2989)
* PM-5900 Fix for Device Login push notifications cause the app to show the HomePage

* PM-5900 Added edge case scenario if intent / packageName / packageManager is null
2024-02-13 22:07:09 +00:00
Vince Grassia
c6aaf5002f Add xmllint install step (#3006) 2024-02-12 12:37:52 -07:00
Bitwarden DevOps
75be6504e1 Bumped version to 2024.2.2 (#3005) 2024-02-12 19:20:44 +00:00
renovate[bot]
cae1825e3f [deps]: Update gh minor (#2992)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-12 14:09:14 -05:00
Vince Grassia
c23100d281 Update CODEOWNERS file for Version Bump automation (#3004) 2024-02-12 14:03:12 -05:00
Vince Grassia
c9c0d0b4d6 Fix while loop (#3003) 2024-02-12 18:20:29 +00:00
mpbw2
fec0743e4d Fix for Android builds (#3001)
* enable unit test flag

* revert UT flag and modify flags in ThemeManager
2024-02-12 12:45:52 -05:00
Vince Grassia
118dcf164c Fix all paths (#2999) 2024-02-12 07:51:51 -08:00
Vince Grassia
bd03b6b5aa Version Bump workflow - Fix location of AndroidManifest.xml file (#2998) 2024-02-12 07:35:19 -08:00
Federico Maccaroni
333917c00d Fix Android build UT Failing because of precompiler directives. (#2991) 2024-02-12 09:34:43 -05:00
Vince Grassia
450101d9e4 Update auto version bump workflow (#2987) 2024-02-12 07:56:08 -05:00
Federico Maccaroni
4e50f1697d PM-6209 Removed MAUI label from environment and about pages (#2990) 2024-02-09 12:08:45 -03:00
Dinis Vieira
3c96ae2220 [PM-5913] Fix for MAUI not reporting the correct Theme when resuming an iOS App (#2988)
* PM-5913 Fix for incorrect iOS Theme when resuming iOS app. Also added minor DeviceInfo change and InvokeOnMainThread is on ThemeManager even though it can be moved elsewhere.

* PM-5913 removed redundant iOS check and changed #elif to #else
2024-02-09 14:28:43 +00:00
Vince Grassia
fdbd16a6fd Add build version to step summary (#2986) 2024-02-09 11:31:25 +01:00
Federico Maccaroni
39a34bd8c4 [PM-3349] [PM-3350] MAUI Migration Initial (#2806)
* PM-3349 PM-3350 MAUI Migration Initial

* PM-3349 PM-3350 MAUI Migration fix nullable exception bindings and AsyncCommand canExecute null exception

* PM-3349 PM-3350 MAUI Migration fix nullable bindings and fallbacks

* PM-3349: Android
Added CustomTabbedPageHandler for Android to handle the tab "reselection" for PopToRoot.
Commented support for Windows in App.csproj
Disabled Interpreter on Android to avoid very slow app in Debug (during Login for example)
Added some null checks that were causing crashes (on GeneratorPageVM and PickerVM)
Minor TabsPage cleanup

* TabBarEffect removed and it's behavior is now taken care of by CustomTabbedPageHandler

* PM-3349 PM-3350 Add null checks on CipherDetailsPageVM to avoid crash opening Secure Notes.

* PM-3349 PM-3350 MAUI Migration Start iOS extensions

* Changes to solution to hopefully fix Config Mappings

* PM-3349 Removed Deploy from iOS.Autofill to allow running Android
Changed MainApplication SpecialFolder.Personal to SpecialFolder.LocalApplicationData

* PM-3350 MAUI Migration Fix iOS Autofill extension

* PM-3349 Changed UseMauiApp init so that Android Handlers still get added

* PM-3349 Implemented HybridWebViewHandler for Android which enables 2nd factor auth flows
Ensured CustomTabbedPageHandler had it's DisconnectHandler called
Some minor code upgrades of older obsolete Xamarin Forms code.

* PM-3349 Implemented HybridWebViewHandler for iOS

* hardcoded AccountViewCell Avatar image to 40x40 to avoid current iOS/Android bugs where they fill much larger space.

* PM-3349 PM-3350
Added (migrated) CustomNavigationHandler (which should partially fix the AvatarIcon in the NavBar in iOS)
Added (migrated) CustomContentPageHandler (which should mostly place the AvatarIcon in the navBar in the correct place for iOS)
Added Task.Delay (workaround) to allow the Avatar to load in iOS on the LoginPage
Added workaround for iOS bug with the toolbar size (more info in comment in AvatarImageSource.cs)
Went through the AccountViewCell MAUI-Migration comments. (and deleted/added more comments as needed)
Migrated some Device calls to DeviceInfo and MainThread
Added (migrated) CustomTabbedHandler (for managing the iOS TabBar)

* PM-3349 Replaced the FabShadowEffect with the new MAUI Shadow to fix the buggy shadows on the Android Fab Button.

* PM-3349 ToolbarHandler created for setting text on Android go back buttons.

* PM-3350 Migrated the CustomViewCellRenderer for iOS

* PM-3350 Removed ButtonHandlerMappings and some other code related with fonts as MAUI is taking care of Accessibility and no custom code should be needed
Migrated SelectableLabelRenderer to Handler
Cleaned LabelHandlerMappings and added logic to migrate the CustomLabelRenderer

* Enabled argon2Id for iOS

* PM-3349
Added Argon libraries for Android
minor change to gitignore so that the Argon x86 lib is not ignored on the Android platform

* PM-3350 Migrated some Device to DeviceInfo and added temporary workaround with some comments to be able to see the Generated Password on iOS

* PM-3350 Added some missing images in iOS

* PM-3349 PRM-3350 Replaced XZing with Camera.MAUI for QRCodes

* Checked some [MAUI-Migration] and deleted when it's working as intended.
SearchBarHandlerMapping: IME options working as intended
SliderHandlerMappings: The MAUI "replacement" for Color.Default seems to be White so the old use case doesn't seem to be needed anymore.

* PM-3350 Checked some [MAUI-Migration] and changed as needed.
TimePickerHandlerMappings: Remove old code for forcing the Wheel. After testing without it wheel picker is still used so this code shouldn't be needed anymore.
AppDelegate.ContinueUserActivity: Uncommented and changed the iOS ContinueUserActivity. It needs to call Platform.ContinueUserActivity according with Xamarin Essentials migration docs.

* PM-3349 Fixed white tint color not appearing on images added as MAU IImage SVG
PM-3349 PM-3350 Fix for Avatar text not adjusting to white/black color correctly

* PM-3350 Removed MAUI Splash Screen. Fixed iOS Privacy Screen logo (hardcoded image to avoid it getting cropped)

* PM-3350 Quick workaround to allow 2nd factor auth to not get stuck in iOS in modals.
Updated some older "Device" code to the newer MAUI code.

* PM-3350 Removed duplicate reference to LaunchScreen.storyboard

* PM-3349 PM-3350 Minor change to HomePage to set fixed Image height otherwise it takes more space than it did in the old Xamarin Forms app.
Added HIdeSoftInputOnTapped on several pages (the ones with Entry controls) to allow hiding the keyboard when tapping "outside" of it. (just like we did in Xamarin Forms app)

* PM-3350 Added Scrollview on HomePage so that the "Create account" button can be accessed in smaller devices like iPhone SE.

* PM-3349 Added Handler that enables the ExtendedDatePicker to get IsFocused events in Android. This is a workaround for fixing the current bug where it's not possible to select the "current day" in the expiration date of a Send.
Fix for TimePicker not displaying default Time Value
Updated some "Device" code to the new MAUI "DeviceInfo"

* PM-3349 PM-3350 Migrated IconLabelButton Frames to Borders to fix issue with TapGestureRecognizer in Android
Also fixed some minor "styles" for normal Button and IconLabelButton (both Android and iOS)

* PM-3349 Fix for TabGestureRecognizer not working inside the StackLayout area of IconLabelButton

* PM-3349 Fix for Android buttons having all letters in Caps

* PM-3349 PM-3350 Started using OnNavigatedTo/From instead of On(Dis)Appearing for LoginPage and LoginSSOPage to avoid the "Modal loading" issues in iOS
Also had to add IsInitialized logic to these pages because OnNavigatedTo can be called twice in some scenario.
Some minor migrations of Device to DeviceInfo was also done

* PM-3350 Fixed iOS extensions (iOS.Extension and iOS.ShareExtension)  to load and commented argon2id from debug configuration until we have the .a compiled again with the new platform/arch

* PM-3350 Added configurations for Release mode (no FDroid yet)

* PM-3349 PM-3350 Migrated remaining AutomationProperties to SemanticProperties.
All 'IsInAccessibleTree="True"' were deleted.
'IsInAccessibleTree="False"' were kept and stayed in code.

* PM-3349 PM-3350 Changed binding set for CipherViewCell so it updates accordingly

* PM-3349 PM-3350 Changed AccountViewCell and its binding to be directly against the ViewModel

* PM-3349 Fix for HTML Label on Android. Color hex doesn't need to be cropped anymore.

* PM-3350 Fix for colored html text on iOS

* PM-3349 PM-3350 Added the partial MAUI Community Toolkit implementation for TouchEffect. This is a temporary solution until they finalize this and add it to their nuget package.
This allows implementing the LongPressCommand in AccountSwitchingOverlay and also have the "Ripple effect" animation when touching an item in Android

* PM-3349 PM-3350 Changed SendViewCell and its binding to be directly against the ViewModel

* PM-3350 Fixed iOS Share extension lazy views loading and an issue with the avatar loading. Also discovered issue with TapGestureRecognizer not working on MAUI Embedding

* PM-3350 Fixed iOS Extensions navigation to several pages and improved avoiding duplicate calls to OnNavigatedTo

* PM-3350 Updated PCL Crypto to latest alpha version to fix "Dll not found NCrypt" issue

* PM-3350 Removed workaround for iOS issue with Avatar icon as it's now fixed in latest .Net8 release.

* PM-3349 PM-3350 Removed AsyncCommand "wrapper" and added AsyncRelayCommand directly in all ViewModels that were using the other one.

* PM-3350 Added watchOS app to main project and fixed some csproj conditions for runtime identifiers on iOS.

* PM-3350 Fixed/Updated all MAUI-Migration TODOs

* PM-3350 Fixed account toolbar item and TitleView on SendAddOnlyPage, also removed comments on AvatarImageSource given the workaround is not needed anymore to draw the image successfully.

* PM-3350 Updated AppCenter package to latest version 5.0.3 and updated some things into MAUI style

* PM-3350 Added workaround for iOS Avatar icon again.

* PM-3349 Added workaround for Android to avoid issues with setting MainPage when app is in background. They are now kept on a Queue to be executed after the app has resumed.
Updated some things on App.xaml.cs to the new MAUI style

* PM-3349 PM-3350 Fixed issue where creating an account with weak/exposed password would get stuck after the Captcha (if a captcha is shown)
Changed App.xaml.cs NavigateImpl to be private

* PM-3349 Started to configure build.yml for MAUI Android

* PM-3349 build.yml update paths for MAUI Android

* PM-3349 build.yml commented verify format and just set qa as variant on MAUI Android for faster checks on CI

* PM-3349 PM-3350 build.cake updated paths

* PM-3349 build.yml updated env helpers variables and set specific csproj to build on Android so not to build iOS extensions

* PM-3349 build.yml add Android "prod" variant

* PM-3350 build.yml updated iOS build and ignore Android build to try the CI faster

* PM-3350 build.yml changed nuget restore for dotnet restore on iOS build to fix issue on restoring due to msbuild

* PM-3350 build.yml Upgraded iOS build to run on macos-13 image which has XCode 15, and set the XCode 15 version as currently the default one is 14.x

* PM-3350 build.yml try to fix ILLINK warnings and changed image to be macos-13-arm64 to see if the build is faster

* PM-3350 build.yml changed image back to be macos-13 to see if the build is faster

* PM-3350 Added Document.Build.props to disable trimming on publish

* PM-3350 build.yml disable trimming on publish so it's faster

* PM-3350 added linkskip for iOS csprojs

* PM-3350 iOS projs disable linking and set Newstandkit as weak framework

* Update build.yml disabling iOS job to avoid long running process of publish until we can fix that

* PM-3349 PM-3350 Workaround to fix issues with text getting cropped/truncated when a Label has both Multiline and LinebreakMode set

* PM-3349 build.yml enabled android build workflow

* PM-3349 build.yml configured FDROID job for MAUI

* PM-3350 iOS extensions TapGestureRecognizer try Window workaround

* PM-3350 iOS applied workaround on the iOS Autofill and Share extension to maui embed the navigation page with its content page in the Window

* PM-3349 PM-3350 Added workaround for More Options to work on Search and Groupings Page
Updated some code to MAUI Style also

* PM-3349 PM-3350 Added the ability for users to press "Continue" button as a fallback when using the Yubikey if the "SubmitCommand" doesn't trigger automatically.

* PM-3349 PM-3350 Fix for text getting cut/truncated in both account switcher and ciphers/search lists
Issue is due to MAUI but can be avoided by using slightly different layout

* PM-3350 iOS updated CFBundlerShortVersionString to latest one 2023.10.1

* PM-3350 fix build.yml Bitwarden.ipa AppStore exported file

* PM-3350 build.yml added step to validate app for submitting into App Store and have better logs of it

* PM-3350 build.yml Added several fixes like not using MtouchUseLLVM on the iOS builds to fix they taking forever to build and some changes on the automation CI to do a debug build for the moment

* PM-3350 Improved MTouch linking and extra args on iOS related csprojs

* PM-3349 PM-3350 Added MAUI label on self-host settings and on about settings to differentiate from XF app

* PM-3349 PM-3350 build.yml uncommented jobs so we have a more complete workflow

* PM-3349 PM-3350 Minor change: removed unneeded HorizontalTextAlignment from Label.

* PM-3349 Replaced CrossCurrentActivity plugin with MAUI internal CurrentActivity

* PM-3350 Fix iOS extensions navigation and Window/RootViewController handling for TapGestureRecognizer to work

* PM-3350 Cleared left ClipLogger from the iOS extensions debug logging.

* PM-3349 PM-3350 Refactored cipher bindings to have a simpler approach reusing a new CipherItemViewModel to avoid unwanted issues in the app

* PM-3349 Added base structure for avoiding Android Autofill crash. This workaround works but it's not complete as it can't handle the entire workflow when showing CipherSelectionPAge (like checking if it should show LockPage)

* PM-3350 Bumped iOS version

* PM-3350 Changed linker to use default mode given that "Full" is presenting some problems as the linker is stripping things it shouldn't and we're trying to solve it. So for now we will use the mode "Link SDK assemblies only" so QA can test.

* PM-3349 Fix for app crashing on Android when Dark mode is enabled
Removed unused button style for android

* Proof of concept for having multiple window in Android for autofill support and navigating with the help of an Extended splash page.

* PM-3350 Fix crash on Release by adding Interpreter on iOS and also adding System.Security.Cryptography to be ignored by the linker

* PM-3350 Apply Cryptography TrimmerRootAssembly only to iOS

* PM-3350 Updated Plugin.Fingerprint so biometrics work

* Update .github/workflows/build.yml setup-xcode commit hash

Co-authored-by: Vince Grassia <593223+vgrassia@users.noreply.github.com>

* PM-3349 PM-3350 Enabled argon2id and fixed one issue with the Uris when getting the icon image

* PM-3349 Upgraded Android targetSdkVersion to 34

* minor change (public to private fields)

* minor improvemments on autofill-redirect

* PM-3349 Commented the Deploy step for Android job given that we're using the hotfix-rc branch for testing iOS on TestFlight

* PM-3349 Uncommented the Deploy step for Android job

* PM-3349 Ensure "_isResumed=true" is set on App.xaml.cs:Bootstrap

* Reusing App.xaml.cs Navigation for the Android RedirectPage
Some other cleanup and changes

* Improved autofill workaround to better handle switching between windows.

* PM-3349 minor fix to add space in HomePage between the region picker labels.

* Added some comments and improvemments.

* PM-3349 Added Window events unsubscription of events. Also changed code to avoid potentially having multiple autofillwindow

* PM-3349 Minor ui fix (space between buttons in delete account page)

* initial commit of android credential provider service (wip)

* Revert "initial commit of android credential provider service (wip)"

This reverts commit 6011b63958.

* PM-3350 Fix for Delete Account buttons on iOS

* PM-3349 PM-3350 Changed search icon used in app to avoid issue with icon size on iOS

* PM-3349 Added custom window so that we can always get the current Active Window. This is used to support the Android Autofil and multi-window scenarios.

* PM-3349 Fix for icon and text spacing in some list items

* PM-3349 Minor aligment improvemment for region selection in HomePage

* PM-3349 Changed the "track color" for the Android switch so that the color is different from the "thumb"

* PM-3350 Updated version to 2024.1.0 on iOS

* PM-3349 Fix Picker selection style by doing a custom PickerHandler for Android which uses SetSingleChoiceItems(...) to provide with the appropriate UI

* PM-3350 Updated MauiVersion to 8.0.4-nightly.* to have the TapGestureRecognizer fix applied. This is done on the Directory.Build.props so we don't have to change it on every csproj. Also removed the workaround of TapGestureHack and fix the Show environment picker to work on the extensions as well.

* PM-3350 Added nuget.config so we add the nuget package source for MAUI Nightly builds

* Bump main iOS version

* PM-3350 Removed "iOS" old folder project that has been moved into the MAUI Single app project.

* PM-3350 Improved code safety adding a lot of try...catch and logging throughout the app. Also made the invoking on main thread safer on several places of the app. Additionally, on the GroupingsPageViewModel changed the code removing the old Xamarin hack and just using Replace directly instead of Clearing first to see if that fixes the crash we're having sometimes on the app.

* PM-3350 PM-3349 Updated Unit Test projects to NET 8.0 and fixed it to work with Core project reference. Also fixed a test that was breaking due to CIpherKey creation being wrong. Added "UT" as a constant to add when building/running Core.Test project so we have something on the context that tells us that is for a UT. With this I had to remove FFImageLoading on UT context because it doesn't support NET 8.0

* PM-3350 PM-3349 Updated Readme with MAUI and main branch

* PM-3350 PM-3349 Enable running Core tests

* PM-3350 Fix build.yml format

* PM-3349 Fix navigation when coming from autofill with Accessibility Services enabled. The user was getting into Home page instead of where they were, with this workaround the app navigates as if the account has been switched, leaving the user as closely as possible to where they were, basically on the first screen for the current state of the user.

* PM-3350 PM-3349 Added property to Directory.Build.props to enable Unit Testing globally so Test runners work

* Improve TOTP scan performance on Android

* Move Android camera/scan changes to xaml

* PM-3350 Testing UseInterpreter false on CI build

* PM-3350 Enabled back UseInterpreter on iOS Release given that it crashes on startup without it.

* PM-3349 PM-3350 Improved code safety with try...catch, better invoke on main thread and better null handling.

* PM-3349 PM-3350 Updated XCode version on build.yml to 15.1

* PM-3350 Removed TapGesture Window MAUI hack from iOS.Extension and iOS.ShareExtension

* PM-3350 Fixed CancellationTokenSource proper disposal

* PM-3350 Fix Avatar toolbar icon on extensions to load properly and to take advantage of using directly SkiaSharp to do the native conversion to UIImage. Also improved the toolbar item so that size is set appropriately.

* PM-3349 PM-3350 Fix external link icon

* PM-3350 Added new style to prevent spell check and text prediction

* Fix merge from main

* PM-3350 Commented event collection upload on the timer and when sending the app to background to see if that prevents the app from crashing on release mode.

* PM-3350 Added check for state migration version before trying to migrate LiteDB values into Prefs when there's no need to and that may be inducing crashes on backgrounded iOS apps.

* PM-3350 Try to disable Interpreter to have better crash knowledge. This time testing if avoiding loading the argon2id lib we're able to not use the interpreter.

* PM-5928 Fix circle animation to be shown on verification codes list on each item

* PM-3350 Go back to use Interpreter and added some Directory.Build.props to easily change Codesign properties and also include/exclude iOS extensions / WatchOS from the build.

* PM-3350 Enabled iOS extensions and WatchOS app to be included based on the Directory.Build.props

* PM-3350 Go back to include argon2id and interpreter

* Removing error/loading placeholders of icons on the cells to see if that is causing the background crash on iOS; so we can test this in TestFlight

* [PM-5910] Workaround for for sliding elements in Duo 2FA flow (#2967)

* workaround for sliding elements in duo 2fa flow

* restrict workaround to Android

* restrict workaround to Android

* Revert "restrict workaround to Android"

This reverts commit c2753d5dc4.

* Revert "restrict workaround to Android"

This reverts commit 69688cfb98.

* PM-5902 fix for account switcher not dismissing when tapping outside (#2974)

* PM-3350 Fix iossimulator-x64 argon2id load so we can test on simulators and also made easier to maintain loading the argon2id library on the iOS projects by setting a general Directory.Build.props that is shared.

* PM-5903 Changed App.xaml.cs SetOption to only update the needed properties instead of replacing the existing Options object which would cause the AccountSwitcher button bug (#2973)

* [PM-5896] Fix MAUI iOS Background crash due to lock files on suspension (#2969)

* PM-5896 Fix background crash on iOS due to lock files when app gets suspended. Changed loading and error placeholders of the CachedImage to not be used and use default icon of IconLabel instead changing visibility.

* PM-5896 Changed methods to be protected so that they don't get removed by the linker.

* PM-5896 Added stub class and references to it so to have stronger references to Icon_Success and Icon_Error so the linker doesn't remove them.

* PM-3349 Removed commented code from build.yml regarding FDroid that is not needed anymore.

* PM-6077 Separated Android and iOS HybridWebViewHandler so that it can be used on iOS.Core (#2983)

* [PM-5907] Fix for incorrect TOTP white text color on label when using light theme on iOS (#2982)

* PM-5907 workaround for incorrect textcolor when programmatically changing text on Entry

* Update src/Core/Pages/Vault/CipherAddEditPage.xaml.cs

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>

---------

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>

* [PM-5906] Fix for incorrect Send MaxAccess white text color on label when using light theme on iOS (#2981)

* PM-5906 workaround for incorrect textcolor when programmatically changing text on Entry

* Update src/Core/Pages/Send/SendAddEditPage.xaml.cs

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>

---------

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>

* PM-3349 PM-3350 Fixed Unit tests because of referencing FFImageLoading when it's not possible

---------

Co-authored-by: Dinis Vieira <dinisvieira@outlook.com>
Co-authored-by: Vince Grassia <593223+vgrassia@users.noreply.github.com>
Co-authored-by: mpbw2 <59324545+mpbw2@users.noreply.github.com>
2024-02-08 16:05:26 -03:00
Federico Maccaroni
8f8a5795d3 Merge branch 'feature/maui-migration' into feature/maui-migration-passkeys 2024-02-08 12:33:16 -03:00
Federico Maccaroni
4631a9e62c PM-3349 PM-3350 Fixed Unit tests because of referencing FFImageLoading when it's not possible 2024-02-08 12:31:52 -03:00
Federico Maccaroni
51ee6a84b5 Merged main into maui-migration 2024-02-08 12:17:34 -03:00
Bitwarden DevOps
f30158adf5 Bumped version to 2024.2.1 (#2985) 2024-02-07 21:25:16 +00:00
Dinis Vieira
8d5006c0bd [PM-5906] Fix for incorrect Send MaxAccess white text color on label when using light theme on iOS (#2981)
* PM-5906 workaround for incorrect textcolor when programmatically changing text on Entry

* Update src/Core/Pages/Send/SendAddEditPage.xaml.cs

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>

---------

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
2024-02-07 19:09:18 +00:00
Dinis Vieira
37208571fe [PM-5907] Fix for incorrect TOTP white text color on label when using light theme on iOS (#2982)
* PM-5907 workaround for incorrect textcolor when programmatically changing text on Entry

* Update src/Core/Pages/Vault/CipherAddEditPage.xaml.cs

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>

---------

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
2024-02-07 19:08:51 +00:00
Dinis Vieira
759627b3c7 PM-6077 Separated Android and iOS HybridWebViewHandler so that it can be used on iOS.Core (#2983) 2024-02-07 17:50:07 +00:00
Federico Maccaroni
08fac4752f PM-3349 PM-3350 Fix crash on iOS AppGroup container URL because of sln config on AndroidX Credentials. Changed the project reference of Credentials to be a local NuGet. 2024-02-07 13:59:31 -03:00
Federico Maccaroni
9307e7e0d8 Merge branch 'feature/maui-migration' into feature/maui-migration-passkeys 2024-02-05 14:31:44 -03:00
Federico Maccaroni
b1a0801f9b PM-3349 Removed commented code from build.yml regarding FDroid that is not needed anymore. 2024-02-05 13:14:37 -03:00
Federico Maccaroni
04cc53b934 Merge branch 'main' into feature/maui-migration 2024-02-05 11:50:41 -03:00
Federico Maccaroni
c138658a31 [PM-5896] Fix MAUI iOS Background crash due to lock files on suspension (#2969)
* PM-5896 Fix background crash on iOS due to lock files when app gets suspended. Changed loading and error placeholders of the CachedImage to not be used and use default icon of IconLabel instead changing visibility.

* PM-5896 Changed methods to be protected so that they don't get removed by the linker.

* PM-5896 Added stub class and references to it so to have stronger references to Icon_Success and Icon_Error so the linker doesn't remove them.
2024-02-05 11:46:08 -03:00
renovate[bot]
c6a086fe62 [deps]: Update gh minor (#2977)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-05 09:08:52 -05:00
renovate[bot]
b217451ea9 [deps]: Update crazy-max/ghaction-import-gpg action to v6 (#2978)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-05 09:08:33 -05:00
renovate[bot]
8cb7d5e1a3 [deps]: Update dawidd6/action-download-artifact action to v3 (#2979)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-05 09:03:08 -05:00
Vince Grassia
82b837ef33 Update Version Bump workflow logic (#2975) 2024-02-05 08:49:22 -05:00
Dinis Vieira
f1854f2c04 PM-5903 Changed App.xaml.cs SetOption to only update the needed properties instead of replacing the existing Options object which would cause the AccountSwitcher button bug (#2973) 2024-02-03 15:59:22 +00:00
Federico Maccaroni
e4056d9ee6 Merge branch 'feature/maui-migration' into feature/maui-migration-passkeys 2024-02-02 15:51:50 -03:00
Federico Maccaroni
eb95a54db2 PM-3350 Fix iossimulator-x64 argon2id load so we can test on simulators and also made easier to maintain loading the argon2id library on the iOS projects by setting a general Directory.Build.props that is shared. 2024-02-02 15:48:04 -03:00
Dinis Vieira
7ddea4c70b PM-5902 fix for account switcher not dismissing when tapping outside (#2974) 2024-02-01 21:44:13 +00:00
Federico Maccaroni
3804e86995 Merge branch 'feature/maui-migration' into feature/maui-migration-passkeys 2024-02-01 12:35:50 -03:00
Federico Maccaroni
b23bed182f Merge branch 'main' into feature/maui-migration 2024-01-31 12:14:02 -03:00
Federico Maccaroni
f8e421871b Merge branch 'feature/maui-migration' of https://github.com/bitwarden/mobile into feature/maui-migration 2024-01-31 12:13:31 -03:00
André Bispo
ebb2a288a1 [PM-5856] Add visibility to label. (#2955) 2024-01-30 12:30:23 +00:00
Todd Martin
de7ae27a77 [PM-5638] Update minimum version for vault item encryption to 2024.2.0 (#2966) 2024-01-29 17:54:30 -05:00
mpbw2
d0103496b9 [PM-5910] Workaround for for sliding elements in Duo 2FA flow (#2967)
* workaround for sliding elements in duo 2fa flow

* restrict workaround to Android

* restrict workaround to Android

* Revert "restrict workaround to Android"

This reverts commit c2753d5dc4.

* Revert "restrict workaround to Android"

This reverts commit 69688cfb98.
2024-01-29 17:26:14 -05:00
Federico Maccaroni
cd8952221e Merge branch 'main' into feature/maui-migration 2024-01-29 17:17:07 -03:00
Federico Maccaroni
155c7539bd Removing error/loading placeholders of icons on the cells to see if that is causing the background crash on iOS; so we can test this in TestFlight 2024-01-29 17:16:01 -03:00
Vince Grassia
d3dd2e9342 Add files for Version Bump automation (#2965) 2024-01-29 14:15:06 -05:00
Federico Maccaroni
5f43681fb1 PM-3350 Go back to include argon2id and interpreter 2024-01-29 14:30:42 -03:00
Federico Maccaroni
d2965e6e10 PM-3350 Enabled iOS extensions and WatchOS app to be included based on the Directory.Build.props 2024-01-29 14:01:18 -03:00
Federico Maccaroni
ec1ade7761 Merge branch 'main' into feature/maui-migration
# Conflicts:
#	src/App/Platforms/Android/AndroidManifest.xml
2024-01-29 13:58:30 -03:00
Federico Maccaroni
f35bef0d7b PM-3350 Go back to use Interpreter and added some Directory.Build.props to easily change Codesign properties and also include/exclude iOS extensions / WatchOS from the build. 2024-01-29 13:56:31 -03:00
Bitwarden DevOps
a5878d3341 Bumped version to 2024.2.0 (#2964) 2024-01-29 13:30:13 -03:00
renovate[bot]
1dc55f78e7 [deps]: Update gh minor (#2960)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-29 10:38:18 -05:00
renovate[bot]
37b62b317f [deps]: Update actions/stale action to v9 (#2961)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-29 10:36:54 -05:00
renovate[bot]
528e412458 [deps]: Update actions/upload-artifact action to v4 (#2962)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-29 10:34:12 -05:00
github-actions[bot]
0f22f2750e Autosync the updated translations (#2963)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-01-29 11:18:32 +00:00
Todd Martin
7bbb711175 [PM-5638] Bump minimum server version for vault item encryption (#2959)
Co-authored-by: Carlos Gonçalves <cgoncalves@bitwarden.com>
2024-01-26 17:03:39 -05:00
Federico Maccaroni
138d37cf5e PM-5928 Fix circle animation to be shown on verification codes list on each item 2024-01-26 12:27:57 -03:00
Federico Maccaroni
fc2fed079f PM-3350 Try to disable Interpreter to have better crash knowledge. This time testing if avoiding loading the argon2id lib we're able to not use the interpreter. 2024-01-26 10:34:28 -03:00
Federico Maccaroni
9c441a98f4 Merge branch 'main' into feature/maui-migration 2024-01-26 10:17:21 -03:00
github-actions[bot]
fd80a9ce7c Autosync the updated translations (#2957)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-01-26 10:52:01 +00:00
Federico Maccaroni
1491872b62 PM-3350 Added check for state migration version before trying to migrate LiteDB values into Prefs when there's no need to and that may be inducing crashes on backgrounded iOS apps. 2024-01-25 17:56:28 -03:00
Federico Maccaroni
c74636ffa5 PM-3350 Commented event collection upload on the timer and when sending the app to background to see if that prevents the app from crashing on release mode. 2024-01-25 13:22:42 -03:00
Federico Maccaroni
05677f93c5 Fix merge from main 2024-01-25 13:20:13 -03:00
Federico Maccaroni
0aef241df6 Merge branch 'main' into feature/maui-migration
# Conflicts:
#	src/Core/Pages/Settings/AboutSettingsPageViewModel.cs
2024-01-25 13:16:42 -03:00
mpbw2
3f10a6be24 Add privacy policy link to about screen (#2954) 2024-01-24 15:07:39 -05:00
renovate[bot]
f3537b1a74 [deps]: Update gh minor (#2544)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-24 10:07:10 -05:00
Vince Grassia
849a0c24b0 Update Renovate config (#2953) 2024-01-24 10:05:30 -05:00
Federico Maccaroni
e0b58461b5 Merge branch 'main' into feature/maui-migration 2024-01-24 11:22:28 -03:00
Federico Maccaroni
cd33c7f608 PM-3350 Added new style to prevent spell check and text prediction 2024-01-24 11:22:02 -03:00
Carlos Gonçalves
f6a58e469f [PM-4739] Implement checksum uri validation (#2893)
* PM-4739 Implement checksum uri validation

* PM-4739 Add missing field

* PM-4739 Fix PR comments

* PM-4739 Remove unnecessary comment

* PM-4739 Add try catch and log exception

* PM-4739 Added missing files from last commit

* PM-4739 Change arg name

* [PM-5461] Fix item saving with blank URI (#2948)

* PM-5461 Fix item saving with blank URI

* PM-5461 Fix PR comment
2024-01-24 13:15:24 +00:00
Federico Maccaroni
9d29af36e5 Merge branch 'feature/maui-migration' into feature/maui-migration-passkeys 2024-01-23 18:00:53 -03:00
Federico Maccaroni
4472d7f9a8 PM-3349 PM-3350 Fix external link icon 2024-01-23 17:59:32 -03:00
Federico Maccaroni
999579915c Merge branch 'main' into feature/maui-migration 2024-01-23 17:34:55 -03:00
Federico Maccaroni
63904fd303 PM-3350 Fix Avatar toolbar icon on extensions to load properly and to take advantage of using directly SkiaSharp to do the native conversion to UIImage. Also improved the toolbar item so that size is set appropriately. 2024-01-23 17:34:27 -03:00
renovate[bot]
983937c9eb [deps]: Update actions/setup-node action to v4 (#2868)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-23 15:02:04 -05:00
Federico Maccaroni
2cb6872e4e Merge branch 'feature/maui-migration' into feature/maui-migration-passkeys 2024-01-22 16:57:59 -03:00
Federico Maccaroni
f539bf051d Merge branch 'main' into feature/maui-migration 2024-01-22 16:57:45 -03:00
Federico Maccaroni
14f845d623 Merge branch 'feature/maui-migration' into feature/maui-migration-passkeys
# Conflicts:
#	src/App/Platforms/iOS/AppDelegate.cs
2024-01-22 16:57:07 -03:00
renovate[bot]
b2f93d3d4b [deps]: Update actions/setup-dotnet action to v4 (#2947)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-22 10:31:17 -05:00
Federico Maccaroni
133a80acef PM-3350 Fixed CancellationTokenSource proper disposal 2024-01-22 12:30:29 -03:00
Federico Maccaroni
b43790de9a Merge branch 'main' into feature/maui-migration 2024-01-22 10:00:30 -03:00
Matt Bishop
64c694e593 Fix code ownership (#2946) 2024-01-19 17:31:32 -05:00
renovate[bot]
56b9e3f615 Pin dependency gh-pages to 3.2.3 (#2542)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-19 17:05:36 -05:00
Matt Bishop
7558f60a44 Fix Renovate config (#2945) 2024-01-19 17:04:54 -05:00
Federico Maccaroni
0bdd63df06 Merge branch 'main' into feature/maui-migration 2024-01-19 15:14:50 -03:00
Federico Maccaroni
c6544b49e9 PM-3350 Removed TapGesture Window MAUI hack from iOS.Extension and iOS.ShareExtension 2024-01-19 15:14:22 -03:00
Federico Maccaroni
8e1a8b5f0e PM-3349 PM-3350 Updated XCode version on build.yml to 15.1 2024-01-19 15:02:53 -03:00
Federico Maccaroni
4717f5e230 PM-3349 PM-3350 Improved code safety with try...catch, better invoke on main thread and better null handling. 2024-01-19 15:01:31 -03:00
github-actions[bot]
e66ac9dd44 Autosync the updated translations (#2944)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-01-19 09:45:12 +00:00
Federico Maccaroni
01ee1ff845 PM-3350 Enabled back UseInterpreter on iOS Release given that it crashes on startup without it. 2024-01-18 18:54:34 -03:00
Federico Maccaroni
75b4655f38 PM-3350 Testing UseInterpreter false on CI build 2024-01-18 16:32:00 -03:00
mpbw2
9b2f596d15 Move Android camera/scan changes to xaml 2024-01-18 11:31:16 -05:00
mpbw2
55fb71744d Improve TOTP scan performance on Android 2024-01-17 13:03:11 -05:00
Federico Maccaroni
ee252be634 Merge branch 'feature/maui-migration' into feature/maui-migration-passkeys 2024-01-17 13:22:47 -03:00
Federico Maccaroni
66f0471f2e Merge branch 'main' into feature/maui-migration 2024-01-17 13:22:26 -03:00
Federico Maccaroni
6b9eeba88d PM-3350 PM-3349 Added property to Directory.Build.props to enable Unit Testing globally so Test runners work 2024-01-17 13:22:00 -03:00
Federico Maccaroni
0a1fbfafb5 PM-3349 Fix navigation when coming from autofill with Accessibility Services enabled. The user was getting into Home page instead of where they were, with this workaround the app navigates as if the account has been switched, leaving the user as closely as possible to where they were, basically on the first screen for the current state of the user. 2024-01-17 09:34:31 -03:00
Daniel James Smith
d6c139cb8a Import-link routes to import page after login (#2939)
Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
2024-01-16 12:02:06 -03:00
Federico Maccaroni
0a5d772886 PM-3350 Fix build.yml format 2024-01-16 11:32:27 -03:00
Daniel James Smith
6b7c6eac71 Import-link routes to import page after login (#2937)
Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
2024-01-16 11:49:40 +00:00
Federico Maccaroni
70c8a264d2 PM-3350 PM-3349 Enable running Core tests 2024-01-15 17:35:37 -03:00
Federico Maccaroni
b5fbb2cade Merge branch 'feature/maui-migration' into feature/maui-migration-passkeys
# Conflicts:
#	bitwarden-mobile.sln
2024-01-15 17:24:33 -03:00
Federico Maccaroni
9027755b71 PM-3350 PM-3349 Updated Readme with MAUI and main branch 2024-01-15 17:20:46 -03:00
Federico Maccaroni
6d625f285b PM-3350 PM-3349 Updated Unit Test projects to NET 8.0 and fixed it to work with Core project reference. Also fixed a test that was breaking due to CIpherKey creation being wrong. Added "UT" as a constant to add when building/running Core.Test project so we have something on the context that tells us that is for a UT. With this I had to remove FFImageLoading on UT context because it doesn't support NET 8.0 2024-01-15 17:18:51 -03:00
Federico Maccaroni
822ad7564e Merge branch 'feature/maui-migration' into feature/maui-migration-passkeys
# Conflicts:
#	src/iOS.Autofill/iOS.Autofill.csproj
2024-01-12 13:59:59 -03:00
Federico Maccaroni
1949a450fd PM-3350 Improved code safety adding a lot of try...catch and logging throughout the app. Also made the invoking on main thread safer on several places of the app. Additionally, on the GroupingsPageViewModel changed the code removing the old Xamarin hack and just using Replace directly instead of Clearing first to see if that fixes the crash we're having sometimes on the app. 2024-01-12 13:54:34 -03:00
Federico Maccaroni
27fa79e0bd Merge branch 'main' into feature/maui-migration 2024-01-12 09:16:10 -03:00
github-actions[bot]
9e1d6c7b03 Autosync the updated translations (#2936)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-01-12 06:46:31 +01:00
Federico Maccaroni
1e29eacc61 PM-3350 Removed "iOS" old folder project that has been moved into the MAUI Single app project. 2024-01-11 17:51:34 -03:00
Federico Maccaroni
b81d26d589 Bump main iOS version 2024-01-11 14:18:34 -03:00
Federico Maccaroni
cd107b6161 Merge branch 'main' into feature/maui-migration
# Conflicts:
#	src/App/Platforms/Android/AndroidManifest.xml
#	src/iOS.Core/Renderers/CollectionView/ExtendedGroupableItemsViewController.cs
2024-01-11 14:17:34 -03:00
Federico Maccaroni
7ac3646fb0 PM-3350 Added nuget.config so we add the nuget package source for MAUI Nightly builds 2024-01-11 10:31:36 -03:00
Federico Maccaroni
d1e4e8645a PM-3350 Updated MauiVersion to 8.0.4-nightly.* to have the TapGestureRecognizer fix applied. This is done on the Directory.Build.props so we don't have to change it on every csproj. Also removed the workaround of TapGestureHack and fix the Show environment picker to work on the extensions as well. 2024-01-10 19:53:53 -03:00
Bitwarden DevOps
e107b893ea Bumped version to 2024.1.1 (#2934) 2024-01-10 17:30:04 +00:00
André Bispo
5de02c863f [PM-5633] Ignore ArgumentOutOfRangeException to collect more data about the crash (#2933) 2024-01-10 17:02:54 +00:00
André Bispo
0e95d4d4ca [PM-5542] Update sso endpoint (#2930) 2024-01-09 21:32:42 +00:00
Federico Maccaroni
36a648e53e Merge branch 'feature/maui-migration' into feature/maui-migration-passkeys
# Conflicts:
#	src/Core/Core.csproj
2024-01-09 18:10:56 -03:00
Federico Maccaroni
6c04ac67b1 PM-3349 Fix Picker selection style by doing a custom PickerHandler for Android which uses SetSingleChoiceItems(...) to provide with the appropriate UI 2024-01-09 15:08:45 -03:00
github-actions[bot]
a42b88b666 Autosync the updated translations (#2929)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-01-05 11:37:30 +01:00
Federico Maccaroni
dfb7a0621f PM-5154 Added Fido2AuthenticationService to provide us a wrapper for the actual implementation 2024-01-03 19:02:49 -03:00
mpbw2
1eb9e5f8ea add cred manager project to build config 2024-01-03 16:36:56 -05:00
mpbw2
b149e7549c initial commit of android credential provider service (wip) 2024-01-03 16:30:44 -05:00
Federico Maccaroni
e3877cc589 PM-5154 Continue Passkeys Autofill in iOS 2024-01-03 18:22:03 -03:00
Federico Maccaroni
275ae76761 PM-5154 Start implementing Passkeys Autofill in iOS 2024-01-03 18:21:02 -03:00
Federico Maccaroni
a1e4f0aaa2 PM-3350 Updated version to 2024.1.0 on iOS 2024-01-02 13:21:32 -03:00
Federico Maccaroni
adaef0d15b Merge branch 'main' into feature/maui-migration
# Conflicts:
#	src/App/Platforms/Android/AndroidManifest.xml
2024-01-02 13:20:15 -03:00
Bitwarden DevOps
af6866cee1 Bumped version to 2024.1.0 (#2928) 2024-01-02 14:40:03 +00:00
André Bispo
0cec49f121 [PM-4584] Add device identifier to request headers. (#2909) 2024-01-02 13:10:37 +00:00
github-actions[bot]
d091922017 Autosync the updated translations (#2927)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-01-02 11:49:43 +01:00
github-actions[bot]
f14be2a3a2 Autosync the updated translations (#2919)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2023-12-29 00:59:08 +00:00
github-actions[bot]
8ee744b746 Autosync the updated translations (#2918)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2023-12-28 13:07:30 +00:00
Dinis Vieira
fa4a2247e3 PM-3349 Changed the "track color" for the Android switch so that the color is different from the "thumb" 2023-12-23 23:09:11 +00:00
Dinis Vieira
5d2fc4530f PM-3349 Minor aligment improvemment for region selection in HomePage 2023-12-23 15:25:41 +00:00
Dinis Vieira
9b64af3423 PM-3349 Fix for icon and text spacing in some list items 2023-12-23 14:30:24 +00:00
Dinis Vieira
b6ff6e34f6 PM-3349 Added custom window so that we can always get the current Active Window. This is used to support the Android Autofil and multi-window scenarios. 2023-12-23 12:30:21 +00:00
Dinis Vieira
6d4c706026 Merge branch 'feature/maui-migration-android-autofill' into feature/maui-migration-android-autofill-redirect-page 2023-12-22 22:16:17 +00:00
Dinis Vieira
14fd026ea0 Merge branch 'feature/maui-migration' into feature/maui-migration-android-autofill 2023-12-22 22:15:58 +00:00
Dinis Vieira
a4392a8730 PM-3349 PM-3350 Changed search icon used in app to avoid issue with icon size on iOS 2023-12-22 22:15:01 +00:00
Dinis Vieira
1b885ea438 PM-3350 Fix for Delete Account buttons on iOS 2023-12-22 17:07:43 +00:00
github-actions[bot]
15a03ba573 Autosync the updated translations (#2913)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2023-12-22 10:20:55 +00:00
mpbw2
fa022a1a4f Revert "initial commit of android credential provider service (wip)"
This reverts commit 6011b63958.
2023-12-20 18:23:08 -05:00
mpbw2
6011b63958 initial commit of android credential provider service (wip) 2023-12-20 18:04:21 -05:00
Dinis Vieira
7d79b98bf2 PM-3349 Minor ui fix (space between buttons in delete account page) 2023-12-20 19:04:26 +00:00
Dinis Vieira
d4e75e9de8 PM-3349 Added Window events unsubscription of events. Also changed code to avoid potentially having multiple autofillwindow 2023-12-18 22:56:21 +00:00
Vince Grassia
82711a0235 Merge _cut_rc.yml into version-bump.yml (#2908) 2023-12-18 10:59:41 -07:00
Dinis Vieira
c3370b58ec Added some comments and improvemments. 2023-12-18 00:24:38 +00:00
Dinis Vieira
3de13325c9 Merge branch 'feature/maui-migration-android-autofill' into feature/maui-migration-android-autofill-redirect-page 2023-12-17 22:26:46 +00:00
Dinis Vieira
c253c110c1 Merge branch 'feature/maui-migration' into feature/maui-migration-android-autofill 2023-12-17 22:26:33 +00:00
Dinis Vieira
bf35d1f2dc PM-3349 minor fix to add space in HomePage between the region picker labels. 2023-12-17 22:26:15 +00:00
Dinis Vieira
05b6aa90b6 Improved autofill workaround to better handle switching between windows. 2023-12-17 22:05:37 +00:00
Dinis Vieira
e39898bba6 Reusing App.xaml.cs Navigation for the Android RedirectPage
Some other cleanup and changes
2023-12-16 15:18:07 +00:00
Dinis Vieira
da0866cc85 Merge branch 'feature/maui-migration-android-autofill' into feature/maui-migration-android-autofill-redirect-page 2023-12-15 23:51:08 +00:00
Dinis Vieira
b3140381ab Merge branch 'feature/maui-migration' into feature/maui-migration-android-autofill
# Conflicts:
#	src/Core/App.xaml.cs
2023-12-15 23:50:48 +00:00
Dinis Vieira
c01a8f8d93 PM-3349 Ensure "_isResumed=true" is set on App.xaml.cs:Bootstrap 2023-12-15 23:48:11 +00:00
Federico Maccaroni
8484b4af30 PM-3349 Uncommented the Deploy step for Android job 2023-12-15 16:38:40 -03:00
Federico Maccaroni
6b9faed45f PM-3349 Commented the Deploy step for Android job given that we're using the hotfix-rc branch for testing iOS on TestFlight 2023-12-15 12:08:01 -03:00
Federico Maccaroni
770a1c5dfe Merge branch 'main' into feature/maui-migration 2023-12-15 11:53:57 -03:00
github-actions[bot]
e6635564aa Autosync the updated translations (#2906)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2023-12-15 15:20:45 +01:00
Dinis Vieira
3c87d4db1c minor improvemments on autofill-redirect 2023-12-15 13:48:34 +00:00
Vince Grassia
6c078fe343 Update version bump workflow (#2905) 2023-12-15 13:30:15 +01:00
Dinis Vieira
8b3c6ab35f minor change (public to private fields) 2023-12-14 22:43:50 +00:00
Dinis Vieira
90912977c4 Merge branch 'feature/maui-migration-android-autofill' into feature/maui-migration-android-autofill-redirect-page 2023-12-14 22:02:39 +00:00
Dinis Vieira
740b368b8c Merge branch 'feature/maui-migration' into feature/maui-migration-android-autofill 2023-12-14 22:00:06 +00:00
Federico Maccaroni
3a40a4cda8 PM-3349 Upgraded Android targetSdkVersion to 34 2023-12-14 17:52:11 -03:00
Federico Maccaroni
9bcd2e51f7 Merge branch 'feature/maui-migration' of https://github.com/bitwarden/mobile into feature/maui-migration 2023-12-14 17:32:48 -03:00
Federico Maccaroni
741214a1cc PM-3349 PM-3350 Enabled argon2id and fixed one issue with the Uris when getting the icon image 2023-12-14 17:32:43 -03:00
Federico Maccaroni
aad87dfdce Update .github/workflows/build.yml setup-xcode commit hash
Co-authored-by: Vince Grassia <593223+vgrassia@users.noreply.github.com>
2023-12-14 17:28:10 -03:00
Federico Maccaroni
8fc1e9a3b9 PM-3350 Updated Plugin.Fingerprint so biometrics work 2023-12-14 16:32:04 -03:00
Federico Maccaroni
2a8e15146e PM-3350 Apply Cryptography TrimmerRootAssembly only to iOS 2023-12-14 14:28:20 -03:00
Federico Maccaroni
8559d5908e Merge branch 'feature/maui-migration' of https://github.com/bitwarden/mobile into feature/maui-migration 2023-12-14 13:16:41 -03:00
Federico Maccaroni
f60c4d94fe PM-3350 Fix crash on Release by adding Interpreter on iOS and also adding System.Security.Cryptography to be ignored by the linker 2023-12-14 13:16:32 -03:00
Dinis Vieira
05858bea48 Proof of concept for having multiple window in Android for autofill support and navigating with the help of an Extended splash page. 2023-12-13 23:42:58 +00:00
Dinis Vieira
5cbef47fd4 Merge branch 'feature/maui-migration' into feature/maui-migration-android-autofill 2023-12-13 22:05:52 +00:00
Dinis Vieira
4bf695d18c PM-3349 Fix for app crashing on Android when Dark mode is enabled
Removed unused button style for android
2023-12-13 19:20:43 +00:00
Dinis Vieira
c24e0dfa28 Merge branch 'feature/maui-migration' into feature/maui-migration-android-autofill 2023-12-13 17:30:27 +00:00
Federico Maccaroni
9ccd0834ff Merge branch 'main' into feature/maui-migration 2023-12-13 10:24:29 -03:00
Joseph Flinn
743e71ff92 Fix branch (#2903) 2023-12-13 05:56:34 -05:00
Federico Maccaroni
a806f17d3b PM-3350 Changed linker to use default mode given that "Full" is presenting some problems as the linker is stripping things it shouldn't and we're trying to solve it. So for now we will use the mode "Link SDK assemblies only" so QA can test. 2023-12-12 21:10:51 -03:00
Federico Maccaroni
436a162df2 Merge branch 'main' into feature/maui-migration 2023-12-12 20:19:42 -03:00
github-actions[bot]
7b579b7aa5 Autosync the updated translations (#2902)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2023-12-12 20:09:30 +00:00
Joseph Flinn
fe10fd7766 Point workflows to main (#2896) 2023-12-12 11:12:27 -08:00
Vince Grassia
3c0de8aacc Add token to checkout step (#2901) 2023-12-12 09:38:12 -08:00
Vince Grassia
18d9a77f25 Fix version bump workflow on call (#2900) 2023-12-12 08:55:24 -08:00
Vince Grassia
9eca82a62b Update version bump workflow (#2898) 2023-12-12 10:22:22 -05:00
Dinis Vieira
f2c298607e Merge branch 'feature/maui-migration' into feature/maui-migration-android-autofill 2023-12-11 22:19:49 +00:00
mpbw2
b90e030b8f [PM-4837] Hide TOTP seed copy button when Can view, except password permission set (#2869)
* Hide TOTP seed copy button when Can view, except password permission set

* additional check

* removal of null check
2023-12-11 16:40:09 -05:00
Federico Maccaroni
b5dbb9ae5e PM-3350 Bumped iOS version 2023-12-11 13:21:31 -03:00
Federico Maccaroni
7a5f7c0274 Merge branch 'master' into feature/maui-migration 2023-12-11 11:42:46 -03:00
Dinis Vieira
17acb57732 PM-3349 Added base structure for avoiding Android Autofill crash. This workaround works but it's not complete as it can't handle the entire workflow when showing CipherSelectionPAge (like checking if it should show LockPage) 2023-12-10 15:05:08 +00:00
github-actions[bot]
9a28419a4e Autosync the updated translations (#2894)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2023-12-08 10:56:26 +00:00
Federico Maccaroni
5803635f44 PM-3349 PM-3350 Refactored cipher bindings to have a simpler approach reusing a new CipherItemViewModel to avoid unwanted issues in the app 2023-12-07 23:59:06 -03:00
Federico Maccaroni
19c393842f PM-3350 Cleared left ClipLogger from the iOS extensions debug logging. 2023-12-07 18:14:02 -03:00
Federico Maccaroni
15a306490d Merge branch 'feature/maui-migration' into feature/maui-migration-ios-ext-tap-workaround 2023-12-07 17:41:53 -03:00
Federico Maccaroni
a4a3d31c19 PM-3350 Fix iOS extensions navigation and Window/RootViewController handling for TapGestureRecognizer to work 2023-12-07 17:40:20 -03:00
github-actions[bot]
f4c468e6a1 Bumped version to 2023.12.1 (#2892)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2023-12-06 13:35:08 -05:00
Dinis Vieira
922dc683af PM-3349 Replaced CrossCurrentActivity plugin with MAUI internal CurrentActivity 2023-12-06 17:27:17 +00:00
github-actions[bot]
2c346eb710 Bumped version to 2023.12.0 (#2891)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2023-12-06 10:47:08 -05:00
Daniel James Smith
9c0908f7b7 Remove tools ownership for store/google/Publisher (#2890) 2023-12-06 08:15:24 -05:00
Bahasnyldz
827fbbc9ce Add Cromite browser (#2640) 2023-12-04 18:37:34 -03:00
Dinis Vieira
bae1b3e891 PM-3349 PM-3350 Minor change: removed unneeded HorizontalTextAlignment from Label. 2023-12-04 16:54:55 +00:00
Federico Maccaroni
a5888827c9 Merge branch 'feature/maui-migration' into feature/maui-migration-ios-ext-tap-workaround 2023-12-04 12:18:01 -03:00
Federico Maccaroni
0348940a12 Merge branch 'master' into feature/maui-migration 2023-12-04 12:17:48 -03:00
Federico Maccaroni
5b249bed67 PM-5064 Fix lock interaction between biometrics and vault timeout never (#2885) 2023-12-04 12:13:13 -03:00
Federico Maccaroni
4c2998337d Merge branch 'feature/maui-migration' into feature/maui-migration-ios-ext-tap-workaround 2023-12-04 11:44:03 -03:00
Federico Maccaroni
7ea86380f4 PM-3349 PM-3350 build.yml uncommented jobs so we have a more complete workflow 2023-12-04 11:41:55 -03:00
Federico Maccaroni
406f4425c8 PM-3349 PM-3350 Added MAUI label on self-host settings and on about settings to differentiate from XF app 2023-12-04 11:35:35 -03:00
Federico Maccaroni
95ca911444 PM-3350 Improved MTouch linking and extra args on iOS related csprojs 2023-12-04 11:30:54 -03:00
Federico Maccaroni
fa62510e09 PM-3350 build.yml Added several fixes like not using MtouchUseLLVM on the iOS builds to fix they taking forever to build and some changes on the automation CI to do a debug build for the moment 2023-12-04 10:41:41 -03:00
Federico Maccaroni
65dc73495d PM-3350 build.yml added step to validate app for submitting into App Store and have better logs of it 2023-12-04 10:11:29 -03:00
Federico Maccaroni
02a2e41118 PM-3350 fix build.yml Bitwarden.ipa AppStore exported file 2023-12-04 10:10:18 -03:00
Federico Maccaroni
bd6f8295e7 PM-3350 iOS updated CFBundlerShortVersionString to latest one 2023.10.1 2023-12-04 10:01:56 -03:00
Federico Maccaroni
0a0cb7093b Merge branch 'master' into feature/maui-migration
# Conflicts:
#	.github/workflows/build.yml
2023-12-04 09:59:52 -03:00
Dinis Vieira
465e5eff76 PM-3349 PM-3350 Fix for text getting cut/truncated in both account switcher and ciphers/search lists
Issue is due to MAUI but can be avoided by using slightly different layout
2023-12-03 22:17:16 +00:00
Dinis Vieira
5b756aaf7a PM-3349 PM-3350 Added the ability for users to press "Continue" button as a fallback when using the Yubikey if the "SubmitCommand" doesn't trigger automatically. 2023-12-01 16:49:14 +00:00
Federico Maccaroni
afbcb212f6 [PM-4896] Fix null reference exception on the region when setting env urls (#2876)
* PM-4896 Fix null reference exception on the region

* PM-4896 Updated dotnet version to set up in build workflow

* PM-4896 Add NET 3.1.x and NET 7.0.x to Android build

* PM-4896 Reversed to NET 3.1.x  Android build

* PM-4896 Removed changes on build.yml for net version name
2023-12-01 12:30:27 -03:00
Dinis Vieira
d168a7b750 PM-3349 PM-3350 Added workaround for More Options to work on Search and Groupings Page
Updated some code to MAUI Style also
2023-12-01 15:02:12 +00:00
github-actions[bot]
a71c28536d Autosync the updated translations (#2884)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2023-12-01 12:06:17 +01:00
Vince Grassia
ba5fa8a518 Fix Build workflow - Install OpenJDK 11 (#2883) 2023-11-27 17:18:28 -05:00
github-actions[bot]
65ea5574de Autosync the updated translations (#2880)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2023-11-27 11:36:59 +00:00
506 changed files with 16001 additions and 7093 deletions

28
.github/CODEOWNERS vendored
View File

@@ -1,12 +1,21 @@
# Please sort lines alphabetically, this will ensure we don't accidentally add duplicates. # Please sort into logical groups with comment headers. Sort groups in order of specificity.
# For example, default owners should always be the first group.
# Sort lines alphabetically within these groups to avoid accidentally adding duplicates.
# #
# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
# The following owners will be the default owners for everything in the repo. # Default file owners
# Unless a later match takes precedence * @bitwarden/dept-development-mobile
# @bitwarden/tech-leads
@bitwarden/dept-development-mobile # DevOps for Actions and other workflow changes
.github/workflows @bitwarden/dept-devops
# DevOps for Version Bumping
src/App/Platforms/Android/AndroidManifest.xml
src/iOS.Autofill/Info.plist
src/iOS.Extension/Info.plist
src/iOS.ShareExtension/Info.plist
src/App/Platforms/iOS/Info.plist
## Auth team files ## ## Auth team files ##
@@ -21,14 +30,17 @@ src/watchOS @bitwarden/team-vault-dev
src/Core/Services/EmailForwarders @bitwarden/team-tools-dev src/Core/Services/EmailForwarders @bitwarden/team-tools-dev
## Crowdin Sync files ## ## Crowdin Sync files ##
src/App/Resources @bitwarden/team-tools-dev src/Core/Resources/Localization @bitwarden/team-tools-dev
src/watchOS/bitwarden/bitwarden\ WatchKit\ Extension/Localization @bitwarden/team-tools-dev src/watchOS/bitwarden/bitwarden\ WatchKit\ Extension/Localization @bitwarden/team-tools-dev
store/apple @bitwarden/team-tools-dev store/apple @bitwarden/team-tools-dev
store/google @bitwarden/team-tools-dev store/google @bitwarden/team-tools-dev
## Locales ## ## Locales ##
src/App/Resources/AppResources.Designer.cs src/Core/Resources/Localization/AppResources.Designer.cs
src/App/Resources/AppResources.resx src/Core/Resources/Localization/AppResources.resx
src/watchOS/bitwarden/bitwarden\ WatchKit\ Extension/Localization/en.lproj src/watchOS/bitwarden/bitwarden\ WatchKit\ Extension/Localization/en.lproj
store/apple/en store/apple/en
store/google/en store/google/en
## Utils ##
store/google/Publisher

17
.github/renovate.json vendored
View File

@@ -2,22 +2,21 @@
"$schema": "https://docs.renovatebot.com/renovate-schema.json", "$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [ "extends": [
"config:base", "config:base",
"github>bitwarden/renovate-config:pin-actions",
":combinePatchMinorReleases", ":combinePatchMinorReleases",
":dependencyDashboard", ":dependencyDashboard",
":maintainLockFilesWeekly", ":maintainLockFilesWeekly",
":pinAllExceptPeerDependencies", ":pinAllExceptPeerDependencies",
":prConcurrentLimit10", ":prConcurrentLimit10",
":rebaseStalePrs", ":rebaseStalePrs",
"schedule:weekends", ":separateMajorReleases",
":separateMajorReleases" "group:monorepos",
"schedule:weekends"
], ],
"enabledManagers": ["cargo", "github-actions", "npm", "nuget"], "enabledManagers": ["github-actions", "npm", "nuget"],
"commitMessagePrefix": "[deps]:",
"commitMessageTopic": "{{depName}}",
"packageRules": [ "packageRules": [
{
"groupName": "cargo minor",
"matchManagers": ["cargo"],
"matchUpdateTypes": ["minor", "patch"]
},
{ {
"groupName": "gh minor", "groupName": "gh minor",
"matchManagers": ["github-actions"], "matchManagers": ["github-actions"],
@@ -32,6 +31,6 @@
"groupName": "nuget minor", "groupName": "nuget minor",
"matchManagers": ["nuget"], "matchManagers": ["nuget"],
"matchUpdateTypes": ["minor", "patch"] "matchUpdateTypes": ["minor", "patch"]
}, }
] ]
} }

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

@@ -1,3 +0,0 @@
<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.

Binary file not shown.

Binary file not shown.

5
.github/workflows/build-beta.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
---
name: Build Beta
on:
workflow_dispatch:

File diff suppressed because it is too large Load Diff

53
.github/workflows/cleanup-rc-branch.yml vendored Normal file
View File

@@ -0,0 +1,53 @@
---
name: Cleanup RC Branch
on:
push:
tags:
- v**
jobs:
delete-rc:
name: Delete RC Branch
runs-on: ubuntu-22.04
steps:
- name: Login to Azure - CI Subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve bot secrets
id: retrieve-bot-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: bitwarden-ci
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
- name: Checkout main
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: main
token: ${{ steps.retrieve-bot-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
- name: Check if a RC branch exists
id: branch-check
run: |
hotfix_rc_branch_check=$(git ls-remote --heads origin hotfix-rc | wc -l)
rc_branch_check=$(git ls-remote --heads origin rc | wc -l)
if [[ "${hotfix_rc_branch_check}" -gt 0 ]]; then
echo "hotfix-rc branch exists." | tee -a $GITHUB_STEP_SUMMARY
echo "name=hotfix-rc" >> $GITHUB_OUTPUT
elif [[ "${rc_branch_check}" -gt 0 ]]; then
echo "rc branch exists." | tee -a $GITHUB_STEP_SUMMARY
echo "name=rc" >> $GITHUB_OUTPUT
fi
- name: Delete RC branch
env:
BRANCH_NAME: ${{ steps.branch-check.outputs.name }}
run: |
if ! [[ -z "$BRANCH_NAME" ]]; then
git push --quiet origin --delete $BRANCH_NAME
echo "Deleted $BRANCH_NAME branch." | tee -a $GITHUB_STEP_SUMMARY
fi

View File

@@ -15,10 +15,10 @@ jobs:
_CROWDIN_PROJECT_ID: "269690" _CROWDIN_PROJECT_ID: "269690"
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- name: Login to Azure - CI Subscription - name: Login to Azure - CI Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.6 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
@@ -30,13 +30,13 @@ jobs:
secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase" secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase"
- name: Download translations - name: Download translations
uses: crowdin/github-action@965d501f160af7b1f88aed4c29154b0caf1e94b9 # v1.9.0 uses: crowdin/github-action@c953b17499daa6be3e5afbf7a63616fb02d8b18d # v1.19.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
with: with:
config: crowdin.yml config: crowdin.yml
crowdin_branch_name: master crowdin_branch_name: main
upload_sources: false upload_sources: false
upload_translations: false upload_translations: false
download_translations: true download_translations: true

View File

@@ -28,7 +28,7 @@ jobs:
branch-name: ${{ steps.branch.outputs.branch-name }} branch-name: ${{ steps.branch.outputs.branch-name }}
steps: steps:
- name: Branch check - name: Branch check
if: github.event.inputs.release_type != 'Dry Run' if: inputs.release_type != 'Dry Run'
run: | run: |
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then
echo "===================================" echo "==================================="
@@ -38,15 +38,15 @@ jobs:
fi fi
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- name: Check Release Version - name: Check Release Version
id: version id: version
uses: bitwarden/gh-actions/release-version-check@main uses: bitwarden/gh-actions/release-version-check@main
with: with:
release-type: ${{ github.event.inputs.release_type }} release-type: ${{ inputs.release_type }}
project-type: xamarin project-type: xamarin
file: src/Android/Properties/AndroidManifest.xml file: src/App/Platforms/Android/AndroidManifest.xml
- name: Get branch name - name: Get branch name
id: branch id: branch
@@ -55,8 +55,8 @@ jobs:
echo "branch-name=$BRANCH_NAME" >> $GITHUB_OUTPUT echo "branch-name=$BRANCH_NAME" >> $GITHUB_OUTPUT
- name: Create GitHub deployment - name: Create GitHub deployment
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ inputs.release_type != 'Dry Run' }}
uses: chrnorm/deployment-action@d42cde7132fcec920de534fffc3be83794335c00 # v2.0.5 uses: chrnorm/deployment-action@55729fcebec3d284f60f5bcabbd8376437d696b1 # v2.0.7
id: deployment id: deployment
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
@@ -67,27 +67,27 @@ jobs:
- name: Download all artifacts - name: Download all artifacts
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ inputs.release_type != 'Dry Run' }}
uses: dawidd6/action-download-artifact@246dbf436b23d7c49e21a7ab8204ca9ecd1fe615 # v2.27.0 uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
branch: ${{ steps.branch.outputs.branch-name }} branch: ${{ steps.branch.outputs.branch-name }}
- name: Dry Run - Download all artifacts - name: Dry Run - Download all artifacts
if: ${{ github.event.inputs.release_type == 'Dry Run' }} if: ${{ inputs.release_type == 'Dry Run' }}
uses: dawidd6/action-download-artifact@246dbf436b23d7c49e21a7ab8204ca9ecd1fe615 # v2.27.0 uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
branch: master branch: main
- name: Prep Bitwarden iOS release asset - name: Prep Bitwarden iOS release asset
run: zip -r Bitwarden\ iOS.zip Bitwarden\ iOS run: zip -r Bitwarden\ iOS.zip Bitwarden\ iOS
- name: Create release - name: Create release
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ inputs.release_type != 'Dry Run' }}
uses: ncipollo/release-action@6c75be85e571768fa31b40abf38de58ba0397db5 # v1.13.0 uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0
with: with:
artifacts: "./com.x8bit.bitwarden.aab/com.x8bit.bitwarden.aab, artifacts: "./com.x8bit.bitwarden.aab/com.x8bit.bitwarden.aab,
./com.x8bit.bitwarden.apk/com.x8bit.bitwarden.apk, ./com.x8bit.bitwarden.apk/com.x8bit.bitwarden.apk,
@@ -103,16 +103,16 @@ jobs:
draft: true draft: true
- name: Update deployment status to Success - name: Update deployment status to Success
if: ${{ github.event.inputs.release_type != 'Dry Run' && success() }} if: ${{ inputs.release_type != 'Dry Run' && success() }}
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1 uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
state: 'success' state: 'success'
deployment-id: ${{ steps.deployment.outputs.deployment_id }} deployment-id: ${{ steps.deployment.outputs.deployment_id }}
- name: Update deployment status to Failure - name: Update deployment status to Failure
if: ${{ github.event.inputs.release_type != 'Dry Run' && failure() }} if: ${{ inputs.release_type != 'Dry Run' && failure() }}
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1 uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
state: 'failure' state: 'failure'
@@ -126,11 +126,11 @@ jobs:
if: inputs.fdroid_publish if: inputs.fdroid_publish
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- name: Download F-Droid .apk artifact - name: Download F-Droid .apk artifact
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ inputs.release_type != 'Dry Run' }}
uses: dawidd6/action-download-artifact@246dbf436b23d7c49e21a7ab8204ca9ecd1fe615 # v2.27.0 uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
@@ -138,16 +138,16 @@ jobs:
name: com.x8bit.bitwarden-fdroid.apk name: com.x8bit.bitwarden-fdroid.apk
- name: Dry Run - Download F-Droid .apk artifact - name: Dry Run - Download F-Droid .apk artifact
if: ${{ github.event.inputs.release_type == 'Dry Run' }} if: ${{ inputs.release_type == 'Dry Run' }}
uses: dawidd6/action-download-artifact@246dbf436b23d7c49e21a7ab8204ca9ecd1fe615 # v2.27.0 uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
branch: master branch: main
name: com.x8bit.bitwarden-fdroid.apk name: com.x8bit.bitwarden-fdroid.apk
- name: Set up Node - name: Set up Node
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with: with:
node-version: '16.x' node-version: '16.x'
@@ -176,13 +176,19 @@ jobs:
- name: Install Node dependencies - name: Install Node dependencies
run: npm install run: npm install
- name: Decrypt secrets - name: Login to Azure - CI Subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Download secrets
env: env:
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} ACCOUNT_NAME: bitwardenci
CONTAINER_NAME: mobile
run: | run: |
mkdir -p ~/secrets mkdir -p $HOME/secrets
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
--output ./store/fdroid/keystore.jks ./.github/secrets/store_fdroid-keystore.jks.gpg --name store_fdroid-keystore.jks --file ./store/fdroid/keystore.jks --output none
- name: Compile for F-Droid Store - name: Compile for F-Droid Store
env: env:
@@ -211,5 +217,5 @@ jobs:
cd $GITHUB_WORKSPACE cd $GITHUB_WORKSPACE
- name: Deploy to gh-pages - name: Deploy to gh-pages
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ inputs.release_type != 'Dry Run' }}
run: npm run deploy run: npm run deploy

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- name: 'Run stale action' - name: 'Run stale action'
uses: actions/stale@f7176fd3007623b69d27091f9b9d4ab7995f0a06 # v5.2.1 uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0
with: with:
stale-issue-label: 'needs-reply' stale-issue-label: 'needs-reply'
stale-pr-label: 'needs-changes' stale-pr-label: 'needs-changes'
@@ -27,4 +27,4 @@ jobs:
If youre still working on this, please respond here after youve made the changes weve requested and our team will re-open it for further review. If youre still working on this, please respond here after youve made the changes weve requested and our team will re-open it for further review.
Please make sure to resolve any conflicts with the master branch before requesting another review. Please make sure to resolve any conflicts with the main branch before requesting another review.

View File

@@ -1,5 +1,5 @@
--- ---
name: Version Auto Bump name: Auto Bump Mobile Version
on: on:
push: push:
@@ -7,33 +7,25 @@ on:
- v** - v**
jobs: jobs:
setup: bump-version:
name: "Setup" name: Bump Mobile Version
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
outputs:
version_number: ${{ steps.version.outputs.new-version }}
steps: steps:
- name: Checkout Branch - name: Login to Azure - CI Subscription
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Calculate bumped version - name: Retrieve bot secrets
id: version id: retrieve-bot-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: bitwarden-ci
secrets: "github-pat-bitwarden-devops-bot-repo-scope"
- name: Trigger Version Bump workflow
env: env:
RELEASE_TAG: ${{ github.ref }} GH_TOKEN: ${{ steps.retrieve-bot-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
run: | run: |
CURR_MAJOR=$(echo $RELEASE_TAG | sed -r 's/refs\/tags\/v([0-9]{4}\.[0-9]{1,2})\.([0-9]{1,2})/\1/') echo '{"cut_rc_branch": "false"}' | \
CURR_PATCH=$(echo $RELEASE_TAG | sed -r 's/refs\/tags\/v([0-9]{4}\.[0-9]{1,2})\.([0-9]{1,2})/\2/') gh workflow run version-bump.yml --json --repo bitwarden/mobile
echo "Current Major: $CURR_MAJOR"
echo "Current Patch: $CURR_PATCH"
NEW_PATCH=$((CURR_PATCH+1))
NEW_VER=$CURR_MAJOR.$NEW_PATCH
echo "New Version: $NEW_VER"
echo "new-version=$NEW_VER" >> $GITHUB_OUTPUT
trigger_version_bump:
name: Bump version to ${{ needs.setup.outputs.version_number }}
needs: setup
uses: ./.github/workflows/version-bump.yml
with:
version_number: ${{ needs.setup.outputs.version_number }}

View File

@@ -4,81 +4,200 @@ name: Version Bump
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
version_number: version_number_override:
description: "New Version" description: "New version override (leave blank for automatic calculation, example: '2024.1.0')"
required: true required: false
workflow_call:
inputs:
version_number:
required: true
type: string type: string
cut_rc_branch:
description: "Cut RC branch?"
default: true
type: boolean
jobs: jobs:
bump_version: bump_version:
name: "Create version_bump_${{ github.event.inputs.version_number }} branch" name: Bump Version
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
outputs:
version: ${{ steps.set-final-version-output.outputs.version }}
steps: steps:
- name: Validate version input
if: ${{ inputs.version_number_override != '' }}
uses: bitwarden/gh-actions/version-check@main
with:
version: ${{ inputs.version_number_override }}
- name: Checkout Branch - name: Checkout Branch
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: main
- name: Check if RC branch exists
if: ${{ inputs.cut_rc_branch == true }}
run: |
remote_rc_branch_check=$(git ls-remote --heads origin rc | wc -l)
if [[ "${remote_rc_branch_check}" -gt 0 ]]; then
echo "Remote RC branch exists."
echo "Please delete current RC branch before running again."
exit 1
fi
- name: Login to Azure - CI Subscription - name: Login to Azure - CI Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets - name: Retrieve secrets
id: retrieve-secrets id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main uses: bitwarden/gh-actions/get-keyvault-secrets@main
with: with:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "github-gpg-private-key, github-gpg-private-key-passphrase" secrets: "github-gpg-private-key,
github-gpg-private-key-passphrase,
github-pat-bitwarden-devops-bot-repo-scope"
- name: Import GPG key - name: Import GPG key
uses: crazy-max/ghaction-import-gpg@d6f3f49f3345e29369fe57596a3ca8f94c4d2ca7 # v5.4.0 uses: crazy-max/ghaction-import-gpg@01dd5d3ca463c7f10f7f4f7b4f177225ac661ee4 # v6.1.0
with: with:
gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }} gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }}
passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }} passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }}
git_user_signingkey: true git_user_signingkey: true
git_commit_gpgsign: true git_commit_gpgsign: true
- name: Create Version Branch
run: git switch -c version_bump_${{ github.event.inputs.version_number }}
- name: Bump Version - Android XML
uses: bitwarden/gh-actions/version-bump@main
with:
version: ${{ github.event.inputs.version_number }}
file_path: "./src/Android/Properties/AndroidManifest.xml"
- name: Bump Version - iOS.Autofill
uses: bitwarden/gh-actions/version-bump@main
with:
version: ${{ github.event.inputs.version_number }}
file_path: "./src/iOS.Autofill/Info.plist"
- name: Bump Version - iOS.Extension
uses: bitwarden/gh-actions/version-bump@main
with:
version: ${{ github.event.inputs.version_number }}
file_path: "./src/iOS.Extension/Info.plist"
- name: Bump Version - iOS.ShareExtension
uses: bitwarden/gh-actions/version-bump@main
with:
version: ${{ github.event.inputs.version_number }}
file_path: "./src/iOS.ShareExtension/Info.plist"
- name: Bump Version - iOS
uses: bitwarden/gh-actions/version-bump@main
with:
version: ${{ github.event.inputs.version_number }}
file_path: "./src/iOS/Info.plist"
- name: Setup git - name: Setup git
run: | run: |
git config --local user.email "106330231+bitwarden-devops-bot@users.noreply.github.com" git config --local user.email "106330231+bitwarden-devops-bot@users.noreply.github.com"
git config --local user.name "bitwarden-devops-bot" git config --local user.name "bitwarden-devops-bot"
- name: Create Version Branch
id: create-branch
run: |
NAME=version_bump_${{ github.ref_name }}_$(date +"%Y-%m-%d")
git switch -c $NAME
echo "name=$NAME" >> $GITHUB_OUTPUT
- name: Install xmllint
run: |
sudo apt-get update
sudo apt-get install -y libxml2-utils
- name: Get current version
id: current-version
run: |
CURRENT_VERSION=$(xmllint --xpath '
string(/manifest/@*[local-name()="versionName"
and namespace-uri()="http://schemas.android.com/apk/res/android"])
' src/App/Platforms/Android/AndroidManifest.xml)
echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
- name: Verify input version
if: ${{ inputs.version_number_override != '' }}
env:
CURRENT_VERSION: ${{ steps.current-version.outputs.version }}
NEW_VERSION: ${{ inputs.version_number_override }}
run: |
# Error if version has not changed.
if [[ "$NEW_VERSION" == "$CURRENT_VERSION" ]]; then
echo "Version has not changed."
exit 1
fi
# Check if version is newer.
printf '%s\n' "${CURRENT_VERSION}" "${NEW_VERSION}" | sort -C -V
if [ $? -eq 0 ]; then
echo "Version check successful."
else
echo "Version check failed."
exit 1
fi
- name: Calculate next release version
if: ${{ inputs.version_number_override == '' }}
id: calculate-next-version
uses: bitwarden/gh-actions/version-next@main
with:
version: ${{ steps.current-version.outputs.version }}
- name: Bump Version - Android XML - Version Override
if: ${{ inputs.version_number_override != '' }}
id: bump-version-override
uses: bitwarden/gh-actions/version-bump@main
with:
file_path: "src/App/Platforms/Android/AndroidManifest.xml"
version: ${{ inputs.version_number_override }}
- name: Bump Version - Android XML - Automatic Calculation
if: ${{ inputs.version_number_override == '' }}
id: bump-version-automatic
uses: bitwarden/gh-actions/version-bump@main
with:
file_path: "src/App/Platforms/Android/AndroidManifest.xml"
version: ${{ steps.calculate-next-version.outputs.version }}
- name: Bump Version - iOS.Autofill - Version Override
if: ${{ inputs.version_number_override != '' }}
uses: bitwarden/gh-actions/version-bump@main
with:
file_path: "src/iOS.Autofill/Info.plist"
version: ${{ inputs.version_number_override }}
- name: Bump Version - iOS.Autofill - Automatic Calculation
if: ${{ inputs.version_number_override == '' }}
uses: bitwarden/gh-actions/version-bump@main
with:
file_path: "src/iOS.Autofill/Info.plist"
version: ${{ steps.calculate-next-version.outputs.version }}
- name: Bump Version - iOS.Extension - Version Override
if: ${{ inputs.version_number_override != '' }}
uses: bitwarden/gh-actions/version-bump@main
with:
file_path: "src/iOS.Extension/Info.plist"
version: ${{ inputs.version_number_override }}
- name: Bump Version - iOS.Extension - Automatic Calculation
if: ${{ inputs.version_number_override == '' }}
uses: bitwarden/gh-actions/version-bump@main
with:
file_path: "src/iOS.Extension/Info.plist"
version: ${{ steps.calculate-next-version.outputs.version }}
- name: Bump Version - iOS.ShareExtension - Version Override
if: ${{ inputs.version_number_override != '' }}
uses: bitwarden/gh-actions/version-bump@main
with:
file_path: "src/iOS.ShareExtension/Info.plist"
version: ${{ inputs.version_number_override }}
- name: Bump Version - iOS.ShareExtension - Automatic Calculation
if: ${{ inputs.version_number_override == '' }}
uses: bitwarden/gh-actions/version-bump@main
with:
file_path: "src/iOS.ShareExtension/Info.plist"
version: ${{ steps.calculate-next-version.outputs.version }}
- name: Bump Version - iOS - Version Override
if: ${{ inputs.version_number_override != '' }}
uses: bitwarden/gh-actions/version-bump@main
with:
file_path: "src/App/Platforms/iOS/Info.plist"
version: ${{ inputs.version_number_override }}
- name: Bump Version - iOS - Automatic Calculation
if: ${{ inputs.version_number_override == '' }}
uses: bitwarden/gh-actions/version-bump@main
with:
file_path: "src/App/Platforms/iOS/Info.plist"
version: ${{ steps.calculate-next-version.outputs.version }}
- name: Set Job output
id: set-final-version-output
run: |
if [[ "${{ steps.bump-version-override.outcome }}" == "success" ]]; then
echo "version=${{ inputs.version_number_override }}" >> $GITHUB_OUTPUT
elif [[ "${{ steps.bump-version-automatic.outcome }}" == "success" ]]; then
echo "version=${{ steps.calculate-next-version.outputs.version }}" >> $GITHUB_OUTPUT
fi
- name: Check if version changed - name: Check if version changed
id: version-changed id: version-changed
run: | run: |
@@ -91,22 +210,24 @@ jobs:
- name: Commit files - name: Commit files
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
run: git commit -m "Bumped version to ${{ github.event.inputs.version_number }}" -a run: git commit -m "Bumped version to ${{ steps.set-final-version-output.outputs.version }}" -a
- name: Push changes - name: Push changes
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
run: git push -u origin version_bump_${{ github.event.inputs.version_number }} env:
PR_BRANCH: ${{ steps.create-branch.outputs.name }}
run: git push -u origin $PR_BRANCH
- name: Create Version PR - name: Create Version PR
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
id: create-pr
env: env:
PR_BRANCH: "version_bump_${{ github.event.inputs.version_number }}" GH_TOKEN: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" PR_BRANCH: ${{ steps.create-branch.outputs.name }}
BASE_BRANCH: master TITLE: "Bump version to ${{ steps.set-final-version-output.outputs.version }}"
TITLE: "Bump version to ${{ github.event.inputs.version_number }}"
run: | run: |
gh pr create --title "$TITLE" \ PR_URL=$(gh pr create --title "$TITLE" \
--base "$BASE" \ --base "main" \
--head "$PR_BRANCH" \ --head "$PR_BRANCH" \
--label "version update" \ --label "version update" \
--label "automated pr" \ --label "automated pr" \
@@ -119,4 +240,58 @@ jobs:
- [X] Other - [X] Other
## Objective ## Objective
Automated version bump to ${{ github.event.inputs.version_number }}" Automated version bump to ${{ steps.set-final-version-output.outputs.version }}")
echo "pr_number=${PR_URL##*/}" >> $GITHUB_OUTPUT
- name: Approve PR
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }}
run: gh pr review $PR_NUMBER --approve
- name: Merge PR
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
env:
GH_TOKEN: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }}
PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }}
run: gh pr merge $PR_NUMBER --squash --auto --delete-branch
cut_rc:
name: Cut RC branch
if: ${{ inputs.cut_rc_branch == true }}
needs: bump_version
runs-on: ubuntu-22.04
steps:
- name: Checkout Branch
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: main
- name: Install xmllint
run: |
sudo apt-get update
sudo apt-get install -y libxml2-utils
- name: Verify version has been updated
env:
NEW_VERSION: ${{ needs.bump_version.outputs.version }}
run: |
# Wait for version to change.
while : ; do
echo "Waiting for version to be updated..."
git pull --force
CURRENT_VERSION=$(xmllint --xpath '
string(/manifest/@*[local-name()="versionName"
and namespace-uri()="http://schemas.android.com/apk/res/android"])
' src/App/Platforms/Android/AndroidManifest.xml)
# If the versions don't match we continue the loop, otherwise we break out of the loop.
[[ "$NEW_VERSION" != "$CURRENT_VERSION" ]] || break
sleep 10
done
- name: Cut RC branch
run: |
git switch --quiet --create rc
git push --quiet --set-upstream origin rc

View File

@@ -1,11 +0,0 @@
---
name: Workflow Linter
on:
pull_request:
paths:
- .github/workflows/**
jobs:
call-workflow:
uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@main

1
.gitignore vendored
View File

@@ -148,6 +148,7 @@ publish/
# NuGet Packages # NuGet Packages
*.nupkg *.nupkg
!**/Xamarin.AndroidX.Credentials.1.0.0.nupkg
# The packages folder can be ignored because of Package Restore # The packages folder can be ignored because of Package Restore
**/packages/* **/packages/*
# except build/, which is used as an MSBuild target. # except build/, which is used as an MSBuild target.

16
Directory.Build.props Normal file
View File

@@ -0,0 +1,16 @@
<Project>
<PropertyGroup>
<MauiVersion>8.0.7</MauiVersion>
<ReleaseCodesignProvision>Automatic:AppStore</ReleaseCodesignProvision>
<ReleaseCodesignKey>iPhone Distribution</ReleaseCodesignKey>
<IncludeBitwardeniOSExtensions>True</IncludeBitwardeniOSExtensions>
<IncludeBitwardenWatchOSApp>True</IncludeBitwardenWatchOSApp>
<Argon2IdLoadMtouchExtraArgs>-gcc_flags "-L$(ProjectDir)../../lib/ios -largon2 -force_load $(ProjectDir)../../lib/ios/libargon2.a"</Argon2IdLoadMtouchExtraArgs>
<!-- Uncomment this when Unit Testing-->
<!-- <CustomConstants>UT</CustomConstants> -->
<!-- Uncomment this when building FDROID-->
<!-- <CustomConstants>FDROID</CustomConstants> -->
</PropertyGroup>
</Project>

View File

@@ -1,4 +1,4 @@
[![Github Workflow build on master](https://github.com/bitwarden/mobile/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/bitwarden/mobile/actions/workflows/build.yml?query=branch:master) [![Github Workflow build on main](https://github.com/bitwarden/mobile/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/bitwarden/mobile/actions/workflows/build.yml?query=branch:main)
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/bitwarden-mobile/localized.svg)](https://crowdin.com/project/bitwarden-mobile) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/bitwarden-mobile/localized.svg)](https://crowdin.com/project/bitwarden-mobile)
[![Join the chat at https://gitter.im/bitwarden/Lobby](https://badges.gitter.im/bitwarden/Lobby.svg)](https://gitter.im/bitwarden/Lobby) [![Join the chat at https://gitter.im/bitwarden/Lobby](https://badges.gitter.im/bitwarden/Lobby.svg)](https://gitter.im/bitwarden/Lobby)
@@ -6,7 +6,7 @@
<a href="https://play.google.com/store/apps/details?id=com.x8bit.bitwarden" target="_blank"><img alt="Get it on Google Play" src="https://imgur.com/YQzmZi9.png" width="153" height="46"></a> <a href="https://mobileapp.bitwarden.com/fdroid/" target="_blank"><img alt="Get it on F-Droid" src="https://i.imgur.com/HDicnzz.png" width="154" height="46"></a> <a href="https://itunes.apple.com/us/app/bitwarden-free-password-manager/id1137397744?mt=8" target="_blank"><img src="https://imgur.com/GdGqPMY.png" width="135" height="40"></a> <a href="https://play.google.com/store/apps/details?id=com.x8bit.bitwarden" target="_blank"><img alt="Get it on Google Play" src="https://imgur.com/YQzmZi9.png" width="153" height="46"></a> <a href="https://mobileapp.bitwarden.com/fdroid/" target="_blank"><img alt="Get it on F-Droid" src="https://i.imgur.com/HDicnzz.png" width="154" height="46"></a> <a href="https://itunes.apple.com/us/app/bitwarden-free-password-manager/id1137397744?mt=8" target="_blank"><img src="https://imgur.com/GdGqPMY.png" width="135" height="40"></a>
The Bitwarden mobile application is written in C# with Xamarin Android, Xamarin iOS, and Xamarin Forms. The Bitwarden mobile application is written in C# using .NET MAUI.
<img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/mobile-android-myvault.png" alt="" width="325" height="650" /> <img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/mobile-ios-myvault.png" alt="" width="300" height="650" /> <img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/mobile-android-myvault.png" alt="" width="325" height="650" /> <img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/mobile-ios-myvault.png" alt="" width="300" height="650" />
@@ -20,6 +20,6 @@ Interested in contributing in a big way? Consider joining our team! We're hiring
# Contribute # Contribute
Code contributions are welcome! Please commit any pull requests against the `master` branch. Learn more about how to contribute by reading the [Contributing Guidelines](https://contributing.bitwarden.com/contributing/). Check out the [Contributing Documentation](https://contributing.bitwarden.com/) for how to get started with your first contribution. Code contributions are welcome! Please commit any pull requests against the `main` branch. Learn more about how to contribute by reading the [Contributing Guidelines](https://contributing.bitwarden.com/contributing/). Check out the [Contributing Documentation](https://contributing.bitwarden.com/) for how to get started with your first contribution.
Security audits and feedback are welcome. Please open an issue or email us privately if the report is sensitive in nature. You can read our security policy in the [`SECURITY.md`](SECURITY.md) file. Security audits and feedback are welcome. Please open an issue or email us privately if the report is sensitive in nature. You can read our security policy in the [`SECURITY.md`](SECURITY.md) file.

View File

@@ -5,7 +5,7 @@ VisualStudioVersion = 17.8.34112.27
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "App", "src\App\App.csproj", "{971FDF07-E288-4239-B47A-E9E7E912193B}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "App", "src\App\App.csproj", "{971FDF07-E288-4239-B47A-E9E7E912193B}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core", "src\Core\Core.csproj", "{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "src\Core\Core.csproj", "{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "iOS.Core", "src\iOS.Core\iOS.Core.csproj", "{E71F3053-056C-4381-9638-048ED73BDFF6}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "iOS.Core", "src\iOS.Core\iOS.Core.csproj", "{E71F3053-056C-4381-9638-048ED73BDFF6}"
EndProject EndProject
@@ -15,6 +15,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.ShareExtension", "src\i
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.Autofill", "src\iOS.Autofill\iOS.Autofill.csproj", "{83449CC4-1F76-4CFE-92B1-D2E13A62506F}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.Autofill", "src\iOS.Autofill\iOS.Autofill.csproj", "{83449CC4-1F76-4CFE-92B1-D2E13A62506F}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{BB702EBD-3B79-4ECA-A2A6-1237B07F0AF0}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B972BBFA-917F-4A10-B07E-B89CFEC6BBDC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.Test", "test\Core.Test\Core.Test.csproj", "{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "test\Common\Common.csproj", "{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -27,6 +35,7 @@ Global
AppStore|iPhone = AppStore|iPhone AppStore|iPhone = AppStore|iPhone
Ad-Hoc|iPhoneSimulator = Ad-Hoc|iPhoneSimulator Ad-Hoc|iPhoneSimulator = Ad-Hoc|iPhoneSimulator
Ad-Hoc|iPhone = Ad-Hoc|iPhone Ad-Hoc|iPhone = Ad-Hoc|iPhone
FDroid|Any CPU = FDroid|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{971FDF07-E288-4239-B47A-E9E7E912193B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {971FDF07-E288-4239-B47A-E9E7E912193B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -51,6 +60,8 @@ Global
{971FDF07-E288-4239-B47A-E9E7E912193B}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU {971FDF07-E288-4239-B47A-E9E7E912193B}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU {971FDF07-E288-4239-B47A-E9E7E912193B}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU {971FDF07-E288-4239-B47A-E9E7E912193B}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.FDroid|Any CPU.ActiveCfg = Debug|Any CPU
{971FDF07-E288-4239-B47A-E9E7E912193B}.FDroid|Any CPU.Build.0 = Debug|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Debug|Any CPU.Build.0 = Debug|Any CPU {11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Release|Any CPU.ActiveCfg = Release|Any CPU {11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -71,6 +82,8 @@ Global
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU {11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU {11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU {11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.FDroid|Any CPU.ActiveCfg = Debug|Any CPU
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C}.FDroid|Any CPU.Build.0 = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {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|Any CPU.Build.0 = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Release|Any CPU.ActiveCfg = Release|Any CPU {E71F3053-056C-4381-9638-048ED73BDFF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -91,6 +104,8 @@ Global
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU {E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU {E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU {E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.FDroid|Any CPU.ActiveCfg = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.FDroid|Any CPU.Build.0 = Debug|Any CPU
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|Any CPU.Build.0 = Debug|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|Any CPU.Build.0 = Debug|Any CPU
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|Any CPU.ActiveCfg = Release|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -111,6 +126,8 @@ Global
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU {324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.FDroid|Any CPU.ActiveCfg = Debug|Any CPU
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.FDroid|Any CPU.Build.0 = Debug|Any CPU
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|Any CPU.Build.0 = Debug|Any CPU {F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|Any CPU.ActiveCfg = Release|Any CPU {F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -131,6 +148,8 @@ Global
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU {F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU {F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU {F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
{F8C3F648-EA5A-4719-8005-85D1690B1655}.FDroid|Any CPU.ActiveCfg = Debug|Any CPU
{F8C3F648-EA5A-4719-8005-85D1690B1655}.FDroid|Any CPU.Build.0 = Debug|Any CPU
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {83449CC4-1F76-4CFE-92B1-D2E13A62506F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.Debug|Any CPU.Build.0 = Debug|Any CPU {83449CC4-1F76-4CFE-92B1-D2E13A62506F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.Release|Any CPU.ActiveCfg = Release|Any CPU {83449CC4-1F76-4CFE-92B1-D2E13A62506F}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -143,6 +162,52 @@ Global
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.AppStore|iPhone.Build.0 = Release|Any CPU {83449CC4-1F76-4CFE-92B1-D2E13A62506F}.AppStore|iPhone.Build.0 = Release|Any CPU
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU {83449CC4-1F76-4CFE-92B1-D2E13A62506F}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU {83449CC4-1F76-4CFE-92B1-D2E13A62506F}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.FDroid|Any CPU.ActiveCfg = Debug|Any CPU
{83449CC4-1F76-4CFE-92B1-D2E13A62506F}.FDroid|Any CPU.Build.0 = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Release|Any CPU.Build.0 = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Debug|iPhone.Build.0 = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Release|iPhone.ActiveCfg = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Release|iPhone.Build.0 = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.AppStore|iPhone.ActiveCfg = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.AppStore|iPhone.Build.0 = Release|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.FDroid|Any CPU.ActiveCfg = Debug|Any CPU
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6}.FDroid|Any CPU.Build.0 = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Release|Any CPU.Build.0 = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Debug|iPhone.Build.0 = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Release|iPhone.ActiveCfg = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Release|iPhone.Build.0 = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.AppStore|iPhone.ActiveCfg = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.AppStore|iPhone.Build.0 = Release|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.FDroid|Any CPU.ActiveCfg = Debug|Any CPU
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44}.FDroid|Any CPU.Build.0 = Debug|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -155,4 +220,14 @@ Global
$0.DotNetNamingPolicy = $1 $0.DotNetNamingPolicy = $1
$1.DirectoryNamespaceAssociation = PrefixedHierarchical $1.DirectoryNamespaceAssociation = PrefixedHierarchical
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{971FDF07-E288-4239-B47A-E9E7E912193B} = {B972BBFA-917F-4A10-B07E-B89CFEC6BBDC}
{11DBC05E-F8B4-49ED-AAC9-96D92336D21C} = {B972BBFA-917F-4A10-B07E-B89CFEC6BBDC}
{83449CC4-1F76-4CFE-92B1-D2E13A62506F} = {B972BBFA-917F-4A10-B07E-B89CFEC6BBDC}
{E71F3053-056C-4381-9638-048ED73BDFF6} = {B972BBFA-917F-4A10-B07E-B89CFEC6BBDC}
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545} = {B972BBFA-917F-4A10-B07E-B89CFEC6BBDC}
{F8C3F648-EA5A-4719-8005-85D1690B1655} = {B972BBFA-917F-4A10-B07E-B89CFEC6BBDC}
{137959BD-073B-4EC7-8ED5-31D73FA7DBC6} = {BB702EBD-3B79-4ECA-A2A6-1237B07F0AF0}
{1AC5ED7F-301E-4B3C-ACDE-C0EADFA5AE44} = {BB702EBD-3B79-4ECA-A2A6-1237B07F0AF0}
EndGlobalSection
EndGlobal EndGlobal

View File

@@ -2,9 +2,9 @@ project_id_env: _CROWDIN_PROJECT_ID
api_token_env: CROWDIN_API_TOKEN api_token_env: CROWDIN_API_TOKEN
preserve_hierarchy: true preserve_hierarchy: true
files: files:
- source: /src/App/Resources/AppResources.resx - source: /src/Core/Resources/Localization/AppResources.resx
dest: /src/App/Resources/%original_file_name% dest: /src/Core/Resources/Localization/%original_file_name%
translation: /src/App/Resources/AppResources.%two_letters_code%.resx translation: /src/Core/Resources/Localization/AppResources.%two_letters_code%.resx
update_option: update_as_unapproved update_option: update_as_unapproved
languages_mapping: languages_mapping:
two_letters_code: two_letters_code:

View File

@@ -0,0 +1,8 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Xamarin.AndroidX.Credentials</name>
</assembly>
<members>
</members>
</doc>

7
nuget.config Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="MAUI Nightly builds" value="https://pkgs.dev.azure.com/xamarin/public/_packaging/maui-nightly/nuget/v3/index.json" />
<add key="Local AndroidX Credentials" value="lib/android/Xamarin.AndroidX.Credentials" />
</packageSources>
</configuration>

2
package-lock.json generated
View File

@@ -8,7 +8,7 @@
"name": "bitwarden-mobile", "name": "bitwarden-mobile",
"version": "0.0.0", "version": "0.0.0",
"devDependencies": { "devDependencies": {
"gh-pages": "^3.2.3" "gh-pages": "3.2.3"
} }
}, },
"node_modules/array-union": { "node_modules/array-union": {

View File

@@ -6,6 +6,6 @@
"clean:l10n": "git push origin --delete l10n_master" "clean:l10n": "git push origin --delete l10n_master"
}, },
"devDependencies": { "devDependencies": {
"gh-pages": "^3.2.3" "gh-pages": "3.2.3"
} }
} }

View File

@@ -53,24 +53,28 @@
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0-ios|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0-ios|AnyCPU'">
<CreatePackage>false</CreatePackage> <CreatePackage>false</CreatePackage>
<CodesignProvision>Automatic</CodesignProvision> <CodesignProvision>Automatic</CodesignProvision>
<CodesignKey>iPhone Developer</CodesignKey> <CodesignKey>iPhone Developer</CodesignKey>
<CodesignEntitlements>Platforms\iOS\Entitlements.plist</CodesignEntitlements> <CodesignEntitlements>Platforms\iOS\Entitlements.plist</CodesignEntitlements>
<MtouchInterpreter>all</MtouchInterpreter> <UseInterpreter>true</UseInterpreter>
<MtouchLink>None</MtouchLink> </PropertyGroup>
<!--TODO: add argon2id load when library is built with the corresponding architecture for iOS Simulator--> <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(RuntimeIdentifier)'=='Debug|net8.0-ios|iossimulator-x64'">
<MtouchExtraArgs>$(Argon2IdLoadMtouchExtraArgs)</MtouchExtraArgs>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(RuntimeIdentifier)'=='Debug|net8.0-ios|ios-arm64'"> <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(RuntimeIdentifier)'=='Debug|net8.0-ios|ios-arm64'">
<MtouchExtraArgs>-gcc_flags "-L$(ProjectDir)../../lib/ios -largon2 -force_load $(ProjectDir)../../lib/ios/libargon2.a"</MtouchExtraArgs> <MtouchExtraArgs>$(Argon2IdLoadMtouchExtraArgs)</MtouchExtraArgs>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0-ios|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0-ios|AnyCPU'">
<CreatePackage>false</CreatePackage> <CreatePackage>false</CreatePackage>
<CodesignProvision>Automatic:AppStore</CodesignProvision> <CodesignProvision>$(ReleaseCodesignProvision)</CodesignProvision>
<CodesignKey>iPhone Distribution</CodesignKey> <CodesignKey>$(ReleaseCodesignKey)</CodesignKey>
<CodesignEntitlements>Platforms\iOS\Entitlements.plist</CodesignEntitlements> <CodesignEntitlements>Platforms\iOS\Entitlements.plist</CodesignEntitlements>
<MtouchInterpreter>all</MtouchInterpreter> <UseInterpreter>true</UseInterpreter>
<MtouchLink>None</MtouchLink> <MtouchExtraArgs>$(Argon2IdLoadMtouchExtraArgs)</MtouchExtraArgs>
<MtouchExtraArgs>--weak-framework=NewsstandKit.framework/NewsstandKit --linkskip=LiteDB --linkskip=CsvHelper --linkskip=Core --linkskip=iOS.Core --linkskip=iOS.Autofill --linkskip=iOS.Extension --linkskip=iOS.ShareExtension --linkskip=App -gcc_flags "-L$(ProjectDir)../../lib/ios -largon2 -force_load $(ProjectDir)../../lib/ios/libargon2.a"</MtouchExtraArgs>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
<!--This is needed for PCLCrypto to work correctly-->
<TrimmerRootAssembly Include="System.Security.Cryptography" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<AndroidNativeLibrary Include="Platforms\Android\lib\arm64-v8a\libargon2.so" /> <AndroidNativeLibrary Include="Platforms\Android\lib\arm64-v8a\libargon2.so" />
<AndroidNativeLibrary Include="Platforms\Android\lib\armeabi-v7a\libargon2.so" /> <AndroidNativeLibrary Include="Platforms\Android\lib\armeabi-v7a\libargon2.so" />
@@ -92,7 +96,7 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="zxcvbn-core" Version="7.0.92" /> <PackageReference Include="zxcvbn-core" Version="7.0.92" />
<PackageReference Include="CommunityToolkit.Maui" Version="5.2.0" /> <PackageReference Include="CommunityToolkit.Maui" Version="5.2.0" />
<PackageReference Include="Plugin.Fingerprint" Version="2.1.5" /> <PackageReference Include="Plugin.Fingerprint" Version="3.0.0-beta.1" />
<PackageReference Include="SkiaSharp.Views.Maui.Controls" Version="2.88.4-preview.84" /> <PackageReference Include="SkiaSharp.Views.Maui.Controls" Version="2.88.4-preview.84" />
<PackageReference Include="SkiaSharp.Views.Maui.Controls.Compatibility" Version="2.88.4-preview.84" /> <PackageReference Include="SkiaSharp.Views.Maui.Controls.Compatibility" Version="2.88.4-preview.84" />
<PackageReference Include="FFImageLoadingCompat.Maui" Version="0.1.1" /> <PackageReference Include="FFImageLoadingCompat.Maui" Version="0.1.1" />
@@ -115,9 +119,9 @@
<Folder Include="Platforms\Android\Utilities\" /> <Folder Include="Platforms\Android\Utilities\" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'"> <ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
<PackageReference Include="Plugin.CurrentActivity" Version="2.1.0.4" />
<PackageReference Include="Xamarin.AndroidX.AutoFill" Version="1.1.0.18" /> <PackageReference Include="Xamarin.AndroidX.AutoFill" Version="1.1.0.18" />
<PackageReference Include="Xamarin.AndroidX.Activity.Ktx" Version="1.7.2.1" /> <PackageReference Include="Xamarin.AndroidX.Activity.Ktx" Version="1.7.2.1" />
<PackageReference Include="Xamarin.AndroidX.Credentials" Version="1.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android' AND !$(DefineConstants.Contains(FDROID))"> <ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android' AND !$(DefineConstants.Contains(FDROID))">
<PackageReference Include="Xamarin.GooglePlayServices.SafetyNet" Version="118.0.1.5" /> <PackageReference Include="Xamarin.GooglePlayServices.SafetyNet" Version="118.0.1.5" />
@@ -154,6 +158,15 @@
<BundleResource Include="Platforms\Android\Resources\drawable-hdpi\logo_white_legacy.png" /> <BundleResource Include="Platforms\Android\Resources\drawable-hdpi\logo_white_legacy.png" />
<BundleResource Include="Platforms\Android\Resources\mipmap-xhdpi\ic_launcher.png" /> <BundleResource Include="Platforms\Android\Resources\mipmap-xhdpi\ic_launcher.png" />
<BundleResource Include="Platforms\Android\Resources\mipmap-xhdpi\ic_launcher_round.png" /> <BundleResource Include="Platforms\Android\Resources\mipmap-xhdpi\ic_launcher_round.png" />
<BundleResource Include="Platforms\iOS\Resources\logo.png" />
<BundleResource Include="Platforms\iOS\Resources\logo_white%402x.png" />
<BundleResource Include="Platforms\iOS\Resources\more_vert%402x.png" />
<BundleResource Include="Platforms\iOS\Resources\logo_white%403x.png" />
<BundleResource Include="Platforms\iOS\Resources\logo%403x.png" />
<BundleResource Include="Platforms\iOS\Resources\more_vert%403x.png" />
<BundleResource Include="Platforms\iOS\Resources\more_vert.png" />
<BundleResource Include="Platforms\iOS\Resources\logo_white.png" />
<BundleResource Include="Platforms\iOS\Resources\logo%402x.png" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\iOS.Core\iOS.Core.csproj" Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'" /> <ProjectReference Include="..\iOS.Core\iOS.Core.csproj" Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'" />
@@ -193,15 +206,12 @@
<MauiImage Include="Resources\plus.svg" TintColor="#FFFFFFFF"> <MauiImage Include="Resources\plus.svg" TintColor="#FFFFFFFF">
<BaseSize>24,24</BaseSize> <BaseSize>24,24</BaseSize>
</MauiImage> </MauiImage>
<MauiImage Include="Resources\search.svg" TintColor="#FFFFFFFF">
<BaseSize>24,24</BaseSize>
</MauiImage>
<MauiImage Include="Resources\send.svg"> <MauiImage Include="Resources\send.svg">
<BaseSize>24,24</BaseSize> <BaseSize>24,24</BaseSize>
</MauiImage> </MauiImage>
<MauiImage Include="Resources\yubikey.png" /> <MauiImage Include="Resources\yubikey.png" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'"> <ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios' AND '$(IncludeBitwardeniOSExtensions)' == 'True'">
<ProjectReference Include="..\iOS.Autofill\iOS.Autofill.csproj"> <ProjectReference Include="..\iOS.Autofill\iOS.Autofill.csproj">
<IsAppExtension>true</IsAppExtension> <IsAppExtension>true</IsAppExtension>
<IsWatchApp>false</IsWatchApp> <IsWatchApp>false</IsWatchApp>
@@ -215,15 +225,15 @@
<IsWatchApp>false</IsWatchApp> <IsWatchApp>false</IsWatchApp>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<PropertyGroup Condition="'$(TargetFramework)'=='net8.0-ios'"> <PropertyGroup Condition="'$(TargetFramework)'=='net8.0-ios' AND '$(IncludeBitwardenWatchOSApp)' == 'True'">
<WatchAppBuildPath Condition=" '$(Configuration)' == 'Debug' ">$(Home)/Library/Developer/Xcode/DerivedData/bitwarden-acgkbpwvmebfiofokotvoerzkqcl/Build/Products</WatchAppBuildPath> <WatchAppBuildPath Condition=" '$(Configuration)' == 'Debug' ">$(Home)/Library/Developer/Xcode/DerivedData/bitwarden-acgkbpwvmebfiofokotvoerzkqcl/Build/Products</WatchAppBuildPath>
<WatchAppBuildPath Condition=" '$(Configuration)' != 'Debug' ">$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\..'))/watchOS/bitwarden.xcarchive/Products/Applications/bitwarden.app/Watch</WatchAppBuildPath> <WatchAppBuildPath Condition=" '$(Configuration)' != 'Debug' ">$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\..'))/watchOS/bitwarden.xcarchive/Products/Applications/bitwarden.app/Watch</WatchAppBuildPath>
<WatchAppBundle>Bitwarden.app</WatchAppBundle> <WatchAppBundle>Bitwarden.app</WatchAppBundle>
<WatchAppConfiguration Condition="'$(RuntimeIdentifier)'!='ios-arm64'"> >watchsimulator</WatchAppConfiguration> <WatchAppConfiguration Condition="'$(RuntimeIdentifier)'!='ios-arm64'">watchsimulator</WatchAppConfiguration>
<WatchAppConfiguration Condition="'$(RuntimeIdentifier)'=='ios-arm64'"> >watchos</WatchAppConfiguration> <WatchAppConfiguration Condition="'$(RuntimeIdentifier)'=='ios-arm64'">watchos</WatchAppConfiguration>
<WatchAppBundleFullPath Condition=" '$(Configuration)' == 'Debug' ">$(WatchAppBuildPath)/$(Configuration)-$(WatchAppConfiguration)/$(WatchAppBundle)</WatchAppBundleFullPath> <WatchAppBundleFullPath Condition=" '$(Configuration)' == 'Debug' ">$(WatchAppBuildPath)/$(Configuration)-$(WatchAppConfiguration)/$(WatchAppBundle)</WatchAppBundleFullPath>
<WatchAppBundleFullPath Condition=" '$(Configuration)' != 'Debug' ">$(WatchAppBuildPath)/$(WatchAppBundle)</WatchAppBundleFullPath> <WatchAppBundleFullPath Condition=" '$(Configuration)' != 'Debug' ">$(WatchAppBuildPath)/$(WatchAppBundle)</WatchAppBundleFullPath>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net8.0-ios' AND Exists('$(WatchAppBundleFullPath)') "> <ItemGroup Condition="'$(TargetFramework)'=='net8.0-ios' AND Exists('$(WatchAppBundleFullPath)') ">
<_ResolvedWatchAppReferences Include="$(WatchAppBundleFullPath)" /> <_ResolvedWatchAppReferences Include="$(WatchAppBundleFullPath)" />
</ItemGroup> </ItemGroup>
@@ -237,4 +247,15 @@
<GoogleServicesJson Include="Platforms\Android\google-services.json" /> <GoogleServicesJson Include="Platforms\Android\google-services.json" />
<GoogleServicesJson Include="Platforms\Android\google-services.json.enc" /> <GoogleServicesJson Include="Platforms\Android\google-services.json.enc" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Remove="Platforms\iOS\Resources\logo.png" />
<None Remove="Platforms\iOS\Resources\logo_white%402x.png" />
<None Remove="Platforms\iOS\Resources\more_vert%402x.png" />
<None Remove="Platforms\iOS\Resources\logo_white%403x.png" />
<None Remove="Platforms\iOS\Resources\logo%403x.png" />
<None Remove="Platforms\iOS\Resources\more_vert%403x.png" />
<None Remove="Platforms\iOS\Resources\more_vert.png" />
<None Remove="Platforms\iOS\Resources\logo_white.png" />
<None Remove="Platforms\iOS\Resources\logo%402x.png" />
</ItemGroup>
</Project> </Project>

View File

@@ -1,25 +0,0 @@
#if IOS || MACCATALYST
using PlatformView = WebKit.WKWebView;
#elif ANDROID
using PlatformView = Android.Webkit.WebView;
#elif (NETSTANDARD || !PLATFORM) || (NET6_0_OR_GREATER && !IOS && !ANDROID)
using PlatformView = System.Object;
#endif
using Bit.App.Controls;
using Microsoft.Maui.Handlers;
namespace Bit.App.Handlers
{
public partial class HybridWebViewHandler
{
public static PropertyMapper<HybridWebView, HybridWebViewHandler> PropertyMapper = new PropertyMapper<HybridWebView, HybridWebViewHandler>(ViewHandler.ViewMapper)
{
[nameof(HybridWebView.Uri)] = MapUri
};
public HybridWebViewHandler() : base(PropertyMapper)
{
}
}
}

View File

@@ -13,7 +13,6 @@
}, },
handlers => handlers =>
{ {
handlers.AddHandler(typeof(Bit.App.Controls.HybridWebView), typeof(Bit.App.Handlers.HybridWebViewHandler));
#if ANDROID #if ANDROID
Bit.App.Handlers.EntryHandlerMappings.Setup(); Bit.App.Handlers.EntryHandlerMappings.Setup();
Bit.App.Handlers.EditorHandlerMappings.Setup(); Bit.App.Handlers.EditorHandlerMappings.Setup();
@@ -28,6 +27,7 @@
Bit.App.Handlers.ButtonHandlerMappings.Setup(); Bit.App.Handlers.ButtonHandlerMappings.Setup();
Bit.App.Handlers.ToolbarHandlerMappings.Setup(); Bit.App.Handlers.ToolbarHandlerMappings.Setup();
handlers.AddHandler(typeof(Bit.App.Controls.HybridWebView), typeof(Bit.App.Handlers.HybridWebViewHandler));
handlers.AddHandler(typeof(Bit.App.Pages.TabsPage), typeof(Bit.App.Handlers.CustomTabbedPageHandler)); handlers.AddHandler(typeof(Bit.App.Pages.TabsPage), typeof(Bit.App.Handlers.CustomTabbedPageHandler));
handlers.AddHandler(typeof(Bit.App.Controls.ExtendedDatePicker), typeof(Bit.App.Handlers.ExtendedDatePickerHandler)); handlers.AddHandler(typeof(Bit.App.Controls.ExtendedDatePicker), typeof(Bit.App.Handlers.ExtendedDatePickerHandler));
#else #else

View File

@@ -112,6 +112,7 @@ namespace Bit.Droid.Accessibility
new Browser("org.bromite.chromium", "url_bar"), new Browser("org.bromite.chromium", "url_bar"),
new Browser("org.chromium.chrome", "url_bar"), new Browser("org.chromium.chrome", "url_bar"),
new Browser("org.codeaurora.swe.browser", "url_bar"), new Browser("org.codeaurora.swe.browser", "url_bar"),
new Browser("org.cromite.cromite", "url_bar"),
new Browser("org.gnu.icecat", "url_bar_title,mozac_browser_toolbar_url_view"), // 2nd = Anticipation 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", "mozac_browser_toolbar_url_view"),
new Browser("org.mozilla.fenix.nightly", "mozac_browser_toolbar_url_view"), // [DEPRECATED ENTRY] new Browser("org.mozilla.fenix.nightly", "mozac_browser_toolbar_url_view"), // [DEPRECATED ENTRY]

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2023.10.1" android:installLocation="internalOnly" package="com.x8bit.bitwarden"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2024.3.3" android:installLocation="internalOnly" package="com.x8bit.bitwarden">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" /> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.NFC" /> <uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -43,6 +43,9 @@
<!-- Support for Xamarin.Essentials.Browser.OpenAsync (for Android > 11) --> <!-- Support for Xamarin.Essentials.Browser.OpenAsync (for Android > 11) -->
<!-- Related docs: https://learn.microsoft.com/en-us/xamarin/essentials/open-browser?tabs=android --> <!-- Related docs: https://learn.microsoft.com/en-us/xamarin/essentials/open-browser?tabs=android -->
<queries> <queries>
<intent>
<action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>
<intent> <intent>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<data android:scheme="http" /> <data android:scheme="http" />

View File

@@ -130,6 +130,7 @@ namespace Bit.Droid.Autofill
"org.bromite.chromium", "org.bromite.chromium",
"org.chromium.chrome", "org.chromium.chrome",
"org.codeaurora.swe.browser", "org.codeaurora.swe.browser",
"org.cromite.cromite",
"org.gnu.icecat", "org.gnu.icecat",
"org.mozilla.fenix", "org.mozilla.fenix",
"org.mozilla.fenix.nightly", "org.mozilla.fenix.nightly",
@@ -346,7 +347,7 @@ namespace Bit.Droid.Autofill
// InlinePresentation requires nonNull pending intent (even though we only utilize one for the // InlinePresentation requires nonNull pending intent (even though we only utilize one for the
// "my vault" presentation) so we're including an empty one here // "my vault" presentation) so we're including an empty one here
pendingIntent = PendingIntent.GetService(context, 0, new Intent(), pendingIntent = PendingIntent.GetService(context, 0, new Intent(),
AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.OneShot | PendingIntentFlags.UpdateCurrent, true)); AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.OneShot | PendingIntentFlags.UpdateCurrent, false));
} }
var slice = CreateInlinePresentationSlice( var slice = CreateInlinePresentationSlice(
inlinePresentationSpec, inlinePresentationSpec,

View File

@@ -0,0 +1,9 @@
namespace Bit.Droid.Autofill
{
public class CredentialProviderConstants
{
public const string CredentialProviderCipherId = "credentialProviderCipherId";
public const string CredentialDataIntentExtra = "CREDENTIAL_DATA";
public const string CredentialIdIntentExtra = "credId";
}
}

View File

@@ -0,0 +1,65 @@
using System.Threading.Tasks;
using Android.App;
using Android.Content.PM;
using Android.OS;
using AndroidX.Credentials.Provider;
using AndroidX.Credentials.WebAuthn;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
using Bit.App.Droid.Utilities;
namespace Bit.Droid.Autofill
{
[Activity(
NoHistory = true,
LaunchMode = LaunchMode.SingleTop)]
public class CredentialProviderSelectionActivity : MauiAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
Intent?.Validate();
base.OnCreate(bundle);
var cipherId = Intent?.GetStringExtra(CredentialProviderConstants.CredentialProviderCipherId);
if (string.IsNullOrEmpty(cipherId))
{
SetResult(Result.Canceled);
Finish();
return;
}
GetCipherAndPerformPasskeyAuthAsync(cipherId).FireAndForget();
}
private async Task GetCipherAndPerformPasskeyAuthAsync(string cipherId)
{
// TODO this is a work in progress
// https://developer.android.com/training/sign-in/credential-provider#passkeys-implement
var getRequest = PendingIntentHandler.RetrieveProviderGetCredentialRequest(Intent);
// var publicKeyRequest = getRequest?.CredentialOptions as PublicKeyCredentialRequestOptions;
var requestInfo = Intent.GetBundleExtra(CredentialProviderConstants.CredentialDataIntentExtra);
var credIdEnc = requestInfo?.GetString(CredentialProviderConstants.CredentialIdIntentExtra);
var cipherService = ServiceContainer.Resolve<ICipherService>();
var cipher = await cipherService.GetAsync(cipherId);
var decCipher = await cipher.DecryptAsync();
var passkey = decCipher.Login.Fido2Credentials.Find(f => f.CredentialId == credIdEnc);
var credId = Convert.FromBase64String(credIdEnc);
// var privateKey = Convert.FromBase64String(passkey.PrivateKey);
// var uid = Convert.FromBase64String(passkey.uid);
var origin = getRequest?.CallingAppInfo.Origin;
var packageName = getRequest?.CallingAppInfo.PackageName;
// --- continue WIP here (save TOTP copy as last step) ---
// Copy TOTP if needed
var autofillHandler = ServiceContainer.Resolve<IAutofillHandler>();
autofillHandler.Autofill(decCipher);
}
}
}

View File

@@ -0,0 +1,147 @@
using Android;
using Android.App;
using Android.Content;
using Android.Graphics.Drawables;
using Android.OS;
using Android.Runtime;
using AndroidX.Credentials.Provider;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
using AndroidX.Credentials.Exceptions;
using AndroidX.Credentials.WebAuthn;
using Bit.Core.Models.View;
using Resource = Microsoft.Maui.Resource;
namespace Bit.Droid.Autofill
{
[Service(Permission = Manifest.Permission.BindCredentialProviderService, Label = "Bitwarden", Exported = true)]
[IntentFilter(new string[] { "android.service.credentials.CredentialProviderService" })]
[MetaData("android.credentials.provider", Resource = "@xml/provider")]
[Register("com.x8bit.bitwarden.Autofill.CredentialProviderService")]
public class CredentialProviderService : AndroidX.Credentials.Provider.CredentialProviderService
{
private const string GetPasskeyIntentAction = "PACKAGE_NAME.GET_PASSKEY";
private const int UniqueRequestCode = 94556023;
private ICipherService _cipherService;
private IUserVerificationService _userVerificationService;
private IVaultTimeoutService _vaultTimeoutService;
private LazyResolve<ILogger> _logger = new LazyResolve<ILogger>("logger");
public override async void OnBeginCreateCredentialRequest(BeginCreateCredentialRequest request,
CancellationSignal cancellationSignal, IOutcomeReceiver callback) => throw new NotImplementedException();
public override async void OnBeginGetCredentialRequest(BeginGetCredentialRequest request,
CancellationSignal cancellationSignal, IOutcomeReceiver callback)
{
try
{
_vaultTimeoutService ??= ServiceContainer.Resolve<IVaultTimeoutService>();
await _vaultTimeoutService.CheckVaultTimeoutAsync();
var locked = await _vaultTimeoutService.IsLockedAsync();
if (!locked)
{
var response = await ProcessGetCredentialsRequestAsync(request);
callback.OnResult(response);
}
// TODO handle auth/unlock account flow
}
catch (GetCredentialException e)
{
_logger.Value.Exception(e);
callback.OnError(e.ErrorMessage ?? "Error getting credentials");
}
catch (Exception e)
{
_logger.Value.Exception(e);
throw;
}
}
private async Task<BeginGetCredentialResponse> ProcessGetCredentialsRequestAsync(
BeginGetCredentialRequest request)
{
IList<CredentialEntry> credentialEntries = null;
foreach (var option in request.BeginGetCredentialOptions)
{
var credentialOption = option as BeginGetPublicKeyCredentialOption;
if (credentialOption != null)
{
credentialEntries ??= new List<CredentialEntry>();
((List<CredentialEntry>)credentialEntries).AddRange(
await PopulatePasskeyDataAsync(request.CallingAppInfo, credentialOption));
}
}
if (credentialEntries == null)
{
return new BeginGetCredentialResponse();
}
return new BeginGetCredentialResponse.Builder()
.SetCredentialEntries(credentialEntries)
.Build();
}
private async Task<List<CredentialEntry>> PopulatePasskeyDataAsync(CallingAppInfo callingAppInfo,
BeginGetPublicKeyCredentialOption option)
{
var packageName = callingAppInfo.PackageName;
var origin = callingAppInfo.Origin;
var signingInfo = callingAppInfo.SigningInfo;
var request = new PublicKeyCredentialRequestOptions(option.RequestJson);
var passkeyEntries = new List<CredentialEntry>();
_cipherService ??= ServiceContainer.Resolve<ICipherService>();
var ciphers = await _cipherService.GetAllDecryptedForUrlAsync(origin);
if (ciphers == null)
{
return passkeyEntries;
}
var passkeyCiphers = ciphers.Where(cipher => cipher.HasFido2Credential).ToList();
if (!passkeyCiphers.Any())
{
return passkeyEntries;
}
foreach (var cipher in passkeyCiphers)
{
var passkeyEntry = GetPasskey(cipher, option);
passkeyEntries.Add(passkeyEntry);
}
return passkeyEntries;
}
private PublicKeyCredentialEntry GetPasskey(CipherView cipher, BeginGetPublicKeyCredentialOption option)
{
var credDataBundle = new Bundle();
credDataBundle.PutString(CredentialProviderConstants.CredentialIdIntentExtra,
cipher.Login.MainFido2Credential.CredentialId);
var intent = new Intent(ApplicationContext, typeof(CredentialProviderSelectionActivity))
.SetAction(GetPasskeyIntentAction).SetPackage(Constants.PACKAGE_NAME);
intent.PutExtra(CredentialProviderConstants.CredentialDataIntentExtra, credDataBundle);
intent.PutExtra(CredentialProviderConstants.CredentialProviderCipherId, cipher.Id);
var pendingIntent = PendingIntent.GetActivity(ApplicationContext, UniqueRequestCode, intent,
PendingIntentFlags.Mutable | PendingIntentFlags.UpdateCurrent);
return new PublicKeyCredentialEntry.Builder(
ApplicationContext,
cipher.Login.Username ?? "No username",
pendingIntent,
option)
.SetDisplayName(cipher.Name)
.SetIcon(Icon.CreateWithResource(ApplicationContext, Resource.Drawable.icon))
.Build();
}
public override void OnClearCredentialStateRequest(ProviderClearCredentialStateRequest request,
CancellationSignal cancellationSignal, IOutcomeReceiver callback) => throw new NotImplementedException();
}
}

View File

@@ -1,5 +1,6 @@
using AndroidX.AppCompat.View.Menu; using AndroidX.AppCompat.View.Menu;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Services;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Google.Android.Material.BottomNavigation; using Google.Android.Material.BottomNavigation;
using Microsoft.Maui.Handlers; using Microsoft.Maui.Handlers;
@@ -90,7 +91,17 @@ namespace Bit.App.Handlers
if(e.Item is MenuItemImpl item) if(e.Item is MenuItemImpl item)
{ {
System.Diagnostics.Debug.WriteLine($"Tab '{item.Title}' was reselected so we'll PopToRoot."); System.Diagnostics.Debug.WriteLine($"Tab '{item.Title}' was reselected so we'll PopToRoot.");
MainThread.BeginInvokeOnMainThread(async () => await _tabbedPage.CurrentPage.Navigation.PopToRootAsync()); MainThread.BeginInvokeOnMainThread(async () =>
{
try
{
await _tabbedPage.CurrentPage.Navigation.PopToRootAsync();
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
});
} }
} }

View File

@@ -6,10 +6,19 @@ using AWebkit = Android.Webkit;
namespace Bit.App.Handlers namespace Bit.App.Handlers
{ {
public partial class HybridWebViewHandler : ViewHandler<HybridWebView, AWebkit.WebView> public class HybridWebViewHandler : ViewHandler<HybridWebView, AWebkit.WebView>
{ {
private const string JSFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}"; private const string JSFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}";
public static PropertyMapper<HybridWebView, HybridWebViewHandler> PropertyMapper = new PropertyMapper<HybridWebView, HybridWebViewHandler>(ViewHandler.ViewMapper)
{
[nameof(HybridWebView.Uri)] = MapUri
};
public HybridWebViewHandler() : base(PropertyMapper)
{
}
public HybridWebViewHandler([NotNull] IPropertyMapper mapper, CommandMapper commandMapper = null) : base(mapper, commandMapper) public HybridWebViewHandler([NotNull] IPropertyMapper mapper, CommandMapper commandMapper = null) : base(mapper, commandMapper)
{ {
} }

View File

@@ -2,7 +2,10 @@
using Android.Graphics.Drawables; using Android.Graphics.Drawables;
using Android.OS; using Android.OS;
using AndroidX.Core.Content.Resources; using AndroidX.Core.Content.Resources;
using AndroidX.Core.Graphics;
using Bit.App.Droid.Utilities; using Bit.App.Droid.Utilities;
using Bit.App.Utilities;
using Microsoft.Maui.Platform;
namespace Bit.App.Handlers namespace Bit.App.Handlers
{ {
@@ -37,6 +40,31 @@ namespace Bit.App.Handlers
}; };
handler.PlatformView.ThumbTintList = new ColorStateList(thumbStates, thumbColors); handler.PlatformView.ThumbTintList = new ColorStateList(thumbStates, thumbColors);
}); });
Microsoft.Maui.Handlers.SwitchHandler.Mapper.AppendToMapping(nameof(ISwitch.TrackColor), (handler, mauiSwitch) =>
{
var trackStates = new[]
{
new[] { Android.Resource.Attribute.StateChecked }, // checked
new[] { -Android.Resource.Attribute.StateChecked }, // unchecked
};
var selectedColor = ColorUtils.BlendARGB(ThemeHelpers.SwitchOnColor.ToArgb(), Colors.Black.ToPlatform().ToArgb(), 0.5f);
var unselectedColor = ColorUtils.BlendARGB(ThemeHelpers.SwitchThumbColor.ToArgb(), Colors.Black.ToPlatform().ToArgb(), 0.7f);
if (ThemeManager.UsingLightTheme)
{
selectedColor = ColorUtils.BlendARGB(ThemeHelpers.SwitchOnColor.ToArgb(), Colors.White.ToPlatform().ToArgb(), 0.7f);
unselectedColor = ColorUtils.BlendARGB(ThemeHelpers.SwitchThumbColor.ToArgb(), Colors.Black.ToPlatform().ToArgb(), 0.3f);
}
var trackColors = new int[]
{
selectedColor,
unselectedColor
};
handler.PlatformView.TrackTintList = new ColorStateList(trackStates, trackColors);
});
} }
} }
} }

View File

@@ -74,6 +74,11 @@ namespace Bit.Droid
// this needs to be called here before base.OnCreate(...) // this needs to be called here before base.OnCreate(...)
Intent?.Validate(); Intent?.Validate();
//We need to get and set the Options before calling OnCreate as that will "trigger" CreateWindow on App.xaml.cs
_appOptions = GetOptions();
//This does not replace existing Options in App.xaml.cs if it exists already. It only updates properties in Options related with Autofill/CreateSend/etc..
((Bit.App.App)Microsoft.Maui.Controls.Application.Current).SetAndroidOptions(_appOptions);
base.OnCreate(savedInstanceState); base.OnCreate(savedInstanceState);
_deviceActionService.SetScreenCaptureAllowedAsync().FireAndForget(_ => _deviceActionService.SetScreenCaptureAllowedAsync().FireAndForget(_ =>
@@ -89,7 +94,6 @@ namespace Bit.Droid
toplayout.FilterTouchesWhenObscured = true; toplayout.FilterTouchesWhenObscured = true;
} }
_appOptions = GetOptions();
CreateNotificationChannel(); CreateNotificationChannel();
DisableAndroidFontScale(); DisableAndroidFontScale();

View File

@@ -12,7 +12,6 @@ using Bit.Core.Abstractions;
using Bit.Core.Services; using Bit.Core.Services;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Bit.Droid.Services; using Bit.Droid.Services;
using Plugin.CurrentActivity;
using Plugin.Fingerprint; using Plugin.Fingerprint;
using Xamarin.Android.Net; using Xamarin.Android.Net;
using System.Net.Http; using System.Net.Http;
@@ -86,6 +85,12 @@ namespace Bit.Droid
ServiceContainer.Resolve<IWatchDeviceService>(), ServiceContainer.Resolve<IWatchDeviceService>(),
ServiceContainer.Resolve<IConditionedAwaiterManager>()); ServiceContainer.Resolve<IConditionedAwaiterManager>());
ServiceContainer.Register<IAccountsManager>("accountsManager", accountsManager); ServiceContainer.Register<IAccountsManager>("accountsManager", accountsManager);
var userPinService = new UserPinService(
ServiceContainer.Resolve<IStateService>(),
ServiceContainer.Resolve<ICryptoService>(),
ServiceContainer.Resolve<IVaultTimeoutService>());
ServiceContainer.Register<IUserPinService>(userPinService);
} }
#if !FDROID #if !FDROID
if (Build.VERSION.SdkInt <= BuildVersionCodes.Kitkat) if (Build.VERSION.SdkInt <= BuildVersionCodes.Kitkat)
@@ -101,7 +106,6 @@ namespace Bit.Droid
{ {
base.OnCreate(); base.OnCreate();
Bootstrap(); Bootstrap();
CrossCurrentActivity.Current.Init(this);
} }
public void OnProviderInstallFailed(int errorCode, Intent recoveryIntent) public void OnProviderInstallFailed(int errorCode, Intent recoveryIntent)
@@ -136,7 +140,7 @@ namespace Bit.Droid
// }); // });
// ZXing.Net.Mobile.Forms.Android.Platform.Init(); // ZXing.Net.Mobile.Forms.Android.Platform.Init();
//}); //});
CrossFingerprint.SetCurrentActivityResolver(() => CrossCurrentActivity.Current.Activity); CrossFingerprint.SetCurrentActivityResolver(() => Microsoft.Maui.ApplicationModel.Platform.CurrentActivity);
var preferencesStorage = new PreferencesStorageService(null); var preferencesStorage = new PreferencesStorageService(null);
var localAppDataFolderPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData); var localAppDataFolderPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData);
@@ -160,9 +164,8 @@ namespace Bit.Droid
var autofillHandler = new AutofillHandler(stateService, messagingService, clipboardService, var autofillHandler = new AutofillHandler(stateService, messagingService, clipboardService,
platformUtilsService, new LazyResolve<IEventService>()); platformUtilsService, new LazyResolve<IEventService>());
var cryptoFunctionService = new PclCryptoFunctionService(cryptoPrimitiveService); var cryptoFunctionService = new PclCryptoFunctionService(cryptoPrimitiveService);
var cryptoService = new CryptoService(stateService, cryptoFunctionService); var cryptoService = new CryptoService(stateService, cryptoFunctionService, logger);
var biometricService = new BiometricService(stateService, cryptoService); var biometricService = new BiometricService(stateService, cryptoService);
var userPinService = new UserPinService(stateService, cryptoService);
var passwordRepromptService = new MobilePasswordRepromptService(platformUtilsService, cryptoService, stateService); var passwordRepromptService = new MobilePasswordRepromptService(platformUtilsService, cryptoService, stateService);
ServiceContainer.Register<ISynchronousStorageService>(preferencesStorage); ServiceContainer.Register<ISynchronousStorageService>(preferencesStorage);
@@ -186,7 +189,6 @@ namespace Bit.Droid
ServiceContainer.Register<ICryptoService>("cryptoService", cryptoService); ServiceContainer.Register<ICryptoService>("cryptoService", cryptoService);
ServiceContainer.Register<IPasswordRepromptService>("passwordRepromptService", passwordRepromptService); ServiceContainer.Register<IPasswordRepromptService>("passwordRepromptService", passwordRepromptService);
ServiceContainer.Register<IAvatarImageSourcePool>("avatarImageSourcePool", new AvatarImageSourcePool()); ServiceContainer.Register<IAvatarImageSourcePool>("avatarImageSourcePool", new AvatarImageSourcePool());
ServiceContainer.Register<IUserPinService>(userPinService);
// Push // Push
#if FDROID #if FDROID

View File

@@ -7,7 +7,7 @@
<item name="android:windowSplashScreenAnimatedIcon">@drawable/splash_screen_round</item> <item name="android:windowSplashScreenAnimatedIcon">@drawable/splash_screen_round</item>
</style> </style>
<style name="BaseTheme" parent="Theme.AppCompat"> <style name="BaseTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
<item name="windowNoTitle">true</item> <item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item> <item name="windowActionBar">false</item>
<item name="colorPrimaryDark">@color/dark_notificationBar</item> <item name="colorPrimaryDark">@color/dark_notificationBar</item>
@@ -18,10 +18,6 @@
<item name="android:colorActivatedHighlight">@android:color/transparent</item> <item name="android:colorActivatedHighlight">@android:color/transparent</item>
<item name="android:textCursorDrawable">@null</item> <item name="android:textCursorDrawable">@null</item>
<item name="popupTheme">@style/ThemeOverlay.AppCompat</item> <item name="popupTheme">@style/ThemeOverlay.AppCompat</item>
<item name="buttonStyle">@style/ButtonStyle</item>
</style>
<style name="ButtonStyle" parent="Widget.AppCompat.Button">
<item name="android:textAllCaps">false</item> <item name="android:textAllCaps">false</item>
</style> </style>
</resources> </resources>

View File

@@ -20,11 +20,6 @@
<item name="android:colorActivatedHighlight">@android:color/transparent</item> <item name="android:colorActivatedHighlight">@android:color/transparent</item>
<item name="android:textCursorDrawable">@null</item> <item name="android:textCursorDrawable">@null</item>
<item name="popupTheme">@style/ThemeOverlay.AppCompat.Light</item> <item name="popupTheme">@style/ThemeOverlay.AppCompat.Light</item>
<item name="buttonStyle">@style/ButtonStyle</item>
<item name="android:textAllCaps">false</item> <item name="android:textAllCaps">false</item>
</style> </style>
<style name="ButtonStyle" parent="Widget.AppCompat.Button">
<item name="android:textAllCaps">false</item>
</style>
</resources> </resources>

View File

@@ -236,6 +236,9 @@
<compatibility-package <compatibility-package
android:name="org.codeaurora.swe.browser" android:name="org.codeaurora.swe.browser"
android:maxLongVersionCode="10000000000"/> android:maxLongVersionCode="10000000000"/>
<compatibility-package
android:name="org.cromite.cromite"
android:maxLongVersionCode="10000000000"/>
<compatibility-package <compatibility-package
android:name="org.gnu.icecat" android:name="org.gnu.icecat"
android:maxLongVersionCode="10000000000"/> android:maxLongVersionCode="10000000000"/>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<credential-provider xmlns:android="http://schemas.android.com/apk/res/android">
<capabilities>
<capability name="androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL" />
</capabilities>
</credential-provider>

View File

@@ -79,24 +79,29 @@ namespace Bit.Droid.Services
} }
var context = Android.App.Application.Context; var context = Android.App.Application.Context;
var intent = new Intent(context, typeof(MainActivity)); var intent = context.PackageManager?.GetLaunchIntentForPackage(context.PackageName ?? string.Empty);
intent.PutExtra(Bit.Core.Constants.NotificationData, JsonConvert.SerializeObject(data));
var pendingIntentFlags = AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.UpdateCurrent, true);
var pendingIntent = PendingIntent.GetActivity(context, 20220801, intent, pendingIntentFlags);
var deleteIntent = new Intent(context, typeof(NotificationDismissReceiver)); var builder = new NotificationCompat.Builder(context, Bit.Core.Constants.AndroidNotificationChannelId);
deleteIntent.PutExtra(Bit.Core.Constants.NotificationData, JsonConvert.SerializeObject(data)); if(intent != null && context.PackageManager != null && !string.IsNullOrEmpty(context.PackageName))
var deletePendingIntent = PendingIntent.GetBroadcast(context, 20220802, deleteIntent, pendingIntentFlags); {
intent.PutExtra(Bit.Core.Constants.NotificationData, JsonConvert.SerializeObject(data));
var pendingIntentFlags = AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.UpdateCurrent, true);
var pendingIntent = PendingIntent.GetActivity(context, 20220801, intent, pendingIntentFlags);
var builder = new NotificationCompat.Builder(context, Bit.Core.Constants.AndroidNotificationChannelId) var deleteIntent = new Intent(context, typeof(NotificationDismissReceiver));
.SetContentIntent(pendingIntent) deleteIntent.PutExtra(Bit.Core.Constants.NotificationData, JsonConvert.SerializeObject(data));
.SetContentTitle(title) var deletePendingIntent = PendingIntent.GetBroadcast(context, 20220802, deleteIntent, pendingIntentFlags);
builder.SetContentIntent(pendingIntent)
.SetDeleteIntent(deletePendingIntent);
}
builder.SetContentTitle(title)
.SetContentText(message) .SetContentText(message)
.SetSmallIcon(Bit.Core.Resource.Drawable.ic_notification) .SetSmallIcon(Bit.Core.Resource.Drawable.ic_notification)
.SetColor((int)Android.Graphics.Color.White) .SetColor((int)Android.Graphics.Color.White)
.SetDeleteIntent(deletePendingIntent)
.SetAutoCancel(true); .SetAutoCancel(true);
if (data is PasswordlessNotificationData passwordlessNotificationData && passwordlessNotificationData.TimeoutInMinutes > 0) if (data is PasswordlessNotificationData passwordlessNotificationData && passwordlessNotificationData.TimeoutInMinutes > 0)
{ {
builder.SetTimeoutAfter(passwordlessNotificationData.TimeoutInMinutes * 60000); builder.SetTimeoutAfter(passwordlessNotificationData.TimeoutInMinutes * 60000);

View File

@@ -12,7 +12,6 @@ using Bit.Core.Enums;
using Bit.Core.Models.View; using Bit.Core.Models.View;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Bit.Droid.Autofill; using Bit.Droid.Autofill;
using Plugin.CurrentActivity;
using Application = Android.App.Application; using Application = Android.App.Application;
namespace Bit.Droid.Services namespace Bit.Droid.Services
@@ -38,6 +37,23 @@ namespace Bit.Droid.Services
_eventService = eventService; _eventService = eventService;
} }
public bool CredentialProviderServiceEnabled()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.UpsideDownCake)
{
return false;
}
try
{
// TODO - find a way to programmatically check if the credential provider service is enabled
return false;
}
catch
{
return false;
}
}
public bool AutofillServiceEnabled() public bool AutofillServiceEnabled()
{ {
if (Build.VERSION.SdkInt < BuildVersionCodes.O) if (Build.VERSION.SdkInt < BuildVersionCodes.O)
@@ -46,7 +62,7 @@ namespace Bit.Droid.Services
} }
try try
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
var afm = (AutofillManager)activity.GetSystemService( var afm = (AutofillManager)activity.GetSystemService(
Java.Lang.Class.FromType(typeof(AutofillManager))); Java.Lang.Class.FromType(typeof(AutofillManager)));
return afm.IsEnabled && afm.HasEnabledAutofillServices; return afm.IsEnabled && afm.HasEnabledAutofillServices;
@@ -65,7 +81,7 @@ namespace Bit.Droid.Services
} }
try try
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
var type = Java.Lang.Class.FromType(typeof(AutofillManager)); var type = Java.Lang.Class.FromType(typeof(AutofillManager));
var manager = activity.GetSystemService(type) as AutofillManager; var manager = activity.GetSystemService(type) as AutofillManager;
return manager.IsAutofillSupported; return manager.IsAutofillSupported;
@@ -78,7 +94,7 @@ namespace Bit.Droid.Services
public void Autofill(CipherView cipher) public void Autofill(CipherView cipher)
{ {
var activity = CrossCurrentActivity.Current.Activity as MauiAppCompatActivity; var activity = Microsoft.Maui.ApplicationModel.Platform.CurrentActivity as MauiAppCompatActivity;
if (activity == null) if (activity == null)
{ {
return; return;
@@ -164,13 +180,20 @@ namespace Bit.Droid.Services
return Accessibility.AccessibilityHelpers.OverlayPermitted(); return Accessibility.AccessibilityHelpers.OverlayPermitted();
} }
public void DisableCredentialProviderService()
{
try
{
// TODO - find a way to programmatically disable the provider service, or take the user to the settings page where they can do it
}
catch { }
}
public void DisableAutofillService() public void DisableAutofillService()
{ {
try try
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
var type = Java.Lang.Class.FromType(typeof(AutofillManager)); var type = Java.Lang.Class.FromType(typeof(AutofillManager));
var manager = activity.GetSystemService(type) as AutofillManager; var manager = activity.GetSystemService(type) as AutofillManager;
manager.DisableAutofillServices(); manager.DisableAutofillServices();

View File

@@ -41,13 +41,13 @@ namespace Bit.Droid.Services
JavaSystem.LoadLibrary("argon2"); JavaSystem.LoadLibrary("argon2");
int keySize = 32; int keySize = 32;
var key = new byte[keySize]; var key = new byte[keySize];
//argon2id_hash_raw(iterations, memory, parallelism, argon2id_hash_raw(iterations, memory, parallelism,
// password, password.Length, salt, salt.Length, key, key.Length); password, password.Length, salt, salt.Length, key, key.Length);
return key; return key;
} }
//[DllImport("argon2", EntryPoint = "argon2id_hash_raw")] [DllImport("argon2", EntryPoint = "argon2id_hash_raw")]
//private static extern int argon2id_hash_raw(int timeCost, int memoryCost, int parallelism, private static extern int argon2id_hash_raw(int timeCost, int memoryCost, int parallelism,
// byte[] pwd, int pwdlen, byte[] salt, int saltlen, byte[] hash, int hashlen); byte[] pwd, int pwdlen, byte[] salt, int saltlen, byte[] hash, int hashlen);
} }
} }

View File

@@ -11,6 +11,7 @@ using Android.Text.Method;
using Android.Views; using Android.Views;
using Android.Views.InputMethods; using Android.Views.InputMethods;
using Android.Widget; using Android.Widget;
using AndroidX.Credentials;
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.Core.Resources.Localization; using Bit.Core.Resources.Localization;
using Bit.App.Utilities; using Bit.App.Utilities;
@@ -18,7 +19,6 @@ using Bit.App.Utilities.Prompts;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.App.Droid.Utilities; using Bit.App.Droid.Utilities;
using Plugin.CurrentActivity;
using Microsoft.Maui.Controls.Compatibility.Platform.Android; using Microsoft.Maui.Controls.Compatibility.Platform.Android;
using Resource = Bit.Core.Resource; using Resource = Bit.Core.Resource;
using Application = Android.App.Application; using Application = Android.App.Application;
@@ -66,24 +66,35 @@ namespace Bit.Droid.Services
_toast.Dispose(); _toast.Dispose();
_toast = null; _toast = null;
} }
_toast = Android.Widget.Toast.MakeText(CrossCurrentActivity.Current.Activity, text, _toast = Android.Widget.Toast.MakeText(Microsoft.Maui.ApplicationModel.Platform.CurrentActivity, text,
longDuration ? ToastLength.Long : ToastLength.Short); longDuration ? ToastLength.Long : ToastLength.Short);
_toast.Show(); _toast.Show();
} }
public bool LaunchApp(string appName) public bool LaunchApp(string appName)
{ {
if ((int)Build.VERSION.SdkInt < 33) try
{
if ((int)Build.VERSION.SdkInt < 33)
{
// API 33 required to avoid using wildcard app visibility or dangerous permissions
// https://developer.android.com/reference/android/content/pm/PackageManager#getLaunchIntentSenderForPackage(java.lang.String)
return false;
}
var activity = Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
appName = appName.Replace("androidapp://", string.Empty);
var launchIntentSender = activity?.PackageManager?.GetLaunchIntentSenderForPackage(appName);
launchIntentSender?.SendIntent(activity, Result.Ok, null, null, null);
return launchIntentSender != null;
}
catch (IntentSender.SendIntentException)
{
return false;
}
catch (Android.Util.AndroidException)
{ {
// API 33 required to avoid using wildcard app visibility or dangerous permissions
// https://developer.android.com/reference/android/content/pm/PackageManager#getLaunchIntentSenderForPackage(java.lang.String)
return false; return false;
} }
var activity = CrossCurrentActivity.Current.Activity;
appName = appName.Replace("androidapp://", string.Empty);
var launchIntentSender = activity?.PackageManager?.GetLaunchIntentSenderForPackage(appName);
launchIntentSender?.SendIntent(activity, Result.Ok, null, null, null);
return launchIntentSender != null;
} }
public async Task ShowLoadingAsync(string text) public async Task ShowLoadingAsync(string text)
@@ -93,7 +104,7 @@ namespace Bit.Droid.Services
await HideLoadingAsync(); await HideLoadingAsync();
} }
var activity = CrossCurrentActivity.Current.Activity; var activity = Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
var inflater = (LayoutInflater)activity.GetSystemService(Context.LayoutInflaterService); var inflater = (LayoutInflater)activity.GetSystemService(Context.LayoutInflaterService);
var dialogView = inflater.Inflate(Resource.Layout.progress_dialog_layout, null); var dialogView = inflater.Inflate(Resource.Layout.progress_dialog_layout, null);
@@ -159,7 +170,7 @@ namespace Bit.Droid.Services
} }
// Finally if all else fails, let's see if current activity is MainActivity // Finally if all else fails, let's see if current activity is MainActivity
if (CrossCurrentActivity.Current.Activity is MainActivity activity && IsAlive(activity)) if (Microsoft.Maui.ApplicationModel.Platform.CurrentActivity is MainActivity activity && IsAlive(activity))
{ {
activity.RunOnUiThread(actionDismiss); activity.RunOnUiThread(actionDismiss);
return Task.CompletedTask; return Task.CompletedTask;
@@ -193,7 +204,7 @@ namespace Bit.Droid.Services
string text = null, string okButtonText = null, string cancelButtonText = null, string text = null, string okButtonText = null, string cancelButtonText = null,
bool numericKeyboard = false, bool autofocus = true, bool password = false) bool numericKeyboard = false, bool autofocus = true, bool password = false)
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
if (activity == null) if (activity == null)
{ {
return Task.FromResult<string>(null); return Task.FromResult<string>(null);
@@ -250,7 +261,7 @@ namespace Bit.Droid.Services
public Task<ValidatablePromptResponse?> DisplayValidatablePromptAsync(ValidatablePromptConfig config) public Task<ValidatablePromptResponse?> DisplayValidatablePromptAsync(ValidatablePromptConfig config)
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
if (activity == null) if (activity == null)
{ {
return Task.FromResult<ValidatablePromptResponse?>(null); return Task.FromResult<ValidatablePromptResponse?>(null);
@@ -327,7 +338,7 @@ namespace Bit.Droid.Services
public void RateApp() public void RateApp()
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
try try
{ {
var rateIntent = RateIntentForUrl("market://details", activity); var rateIntent = RateIntentForUrl("market://details", activity);
@@ -360,14 +371,14 @@ namespace Bit.Droid.Services
public bool SupportsNfc() public bool SupportsNfc()
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
var manager = activity.GetSystemService(Context.NfcService) as NfcManager; var manager = activity.GetSystemService(Context.NfcService) as NfcManager;
return manager.DefaultAdapter?.IsEnabled ?? false; return manager.DefaultAdapter?.IsEnabled ?? false;
} }
public bool SupportsCamera() public bool SupportsCamera()
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
return activity.PackageManager.HasSystemFeature(PackageManager.FeatureCamera); return activity.PackageManager.HasSystemFeature(PackageManager.FeatureCamera);
} }
@@ -383,7 +394,7 @@ namespace Bit.Droid.Services
public Task<string> DisplayAlertAsync(string title, string message, string cancel, params string[] buttons) public Task<string> DisplayAlertAsync(string title, string message, string cancel, params string[] buttons)
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
if (activity == null) if (activity == null)
{ {
return Task.FromResult<string>(null); return Task.FromResult<string>(null);
@@ -464,7 +475,7 @@ namespace Bit.Droid.Services
public void OpenAccessibilityOverlayPermissionSettings() public void OpenAccessibilityOverlayPermissionSettings()
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
try try
{ {
var intent = new Intent(Settings.ActionManageOverlayPermission); var intent = new Intent(Settings.ActionManageOverlayPermission);
@@ -491,11 +502,32 @@ namespace Bit.Droid.Services
} }
} }
public void OpenCredentialProviderSettings()
{
var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
try
{
var pendingIntent = CredentialManager.Create(activity).CreateSettingsPendingIntent();
pendingIntent.Send();
}
catch (ActivityNotFoundException)
{
var alertBuilder = new AlertDialog.Builder(activity);
alertBuilder.SetMessage(AppResources.BitwardenCredentialProviderGoToSettings);
alertBuilder.SetCancelable(true);
alertBuilder.SetPositiveButton(AppResources.Ok, (sender, args) =>
{
(sender as AlertDialog)?.Cancel();
});
alertBuilder.Create().Show();
}
}
public void OpenAccessibilitySettings() public void OpenAccessibilitySettings()
{ {
try try
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
var intent = new Intent(Settings.ActionAccessibilitySettings); var intent = new Intent(Settings.ActionAccessibilitySettings);
activity.StartActivity(intent); activity.StartActivity(intent);
} }
@@ -504,7 +536,7 @@ namespace Bit.Droid.Services
public void OpenAutofillSettings() public void OpenAutofillSettings()
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
try try
{ {
var intent = new Intent(Settings.ActionRequestSetAutofillService); var intent = new Intent(Settings.ActionRequestSetAutofillService);
@@ -535,7 +567,7 @@ namespace Bit.Droid.Services
public void CloseMainApp() public void CloseMainApp()
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
if (activity == null) if (activity == null)
{ {
return; return;
@@ -549,6 +581,8 @@ namespace Bit.Droid.Services
return true; return true;
} }
public bool SupportsCredentialProviderService() => Build.VERSION.SdkInt >= BuildVersionCodes.UpsideDownCake;
public bool SupportsAutofillServices() => Build.VERSION.SdkInt >= BuildVersionCodes.O; public bool SupportsAutofillServices() => Build.VERSION.SdkInt >= BuildVersionCodes.O;
public bool SupportsInlineAutofill() => Build.VERSION.SdkInt >= BuildVersionCodes.R; public bool SupportsInlineAutofill() => Build.VERSION.SdkInt >= BuildVersionCodes.R;
@@ -574,7 +608,7 @@ namespace Bit.Droid.Services
public float GetSystemFontSizeScale() public float GetSystemFontSizeScale()
{ {
var activity = CrossCurrentActivity.Current?.Activity as MainActivity; var activity = Microsoft.Maui.ApplicationModel.Platform.CurrentActivity as MainActivity;
return activity?.Resources?.Configuration?.FontScale ?? 1; return activity?.Resources?.Configuration?.FontScale ?? 1;
} }
@@ -585,7 +619,7 @@ namespace Bit.Droid.Services
public async Task SetScreenCaptureAllowedAsync() public async Task SetScreenCaptureAllowedAsync()
{ {
var activity = CrossCurrentActivity.Current?.Activity; var activity = Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
if (await _stateService.GetScreenCaptureAllowedAsync()) if (await _stateService.GetScreenCaptureAllowedAsync())
{ {
activity.RunOnUiThread(() => activity.Window.ClearFlags(WindowManagerFlags.Secure)); activity.RunOnUiThread(() => activity.Window.ClearFlags(WindowManagerFlags.Secure));

View File

@@ -13,7 +13,6 @@ using AndroidX.Core.Content;
using Bit.Core.Resources.Localization; using Bit.Core.Resources.Localization;
using Bit.Core; using Bit.Core;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Plugin.CurrentActivity;
using FileProvider = AndroidX.Core.Content.FileProvider; using FileProvider = AndroidX.Core.Content.FileProvider;
namespace Bit.Droid.Services namespace Bit.Droid.Services
@@ -43,7 +42,7 @@ namespace Bit.Droid.Services
{ {
try try
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
var intent = BuildOpenFileIntent(fileData, fileName); var intent = BuildOpenFileIntent(fileData, fileName);
if (intent == null) if (intent == null)
{ {
@@ -60,7 +59,7 @@ namespace Bit.Droid.Services
{ {
try try
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
var intent = BuildOpenFileIntent(new byte[0], string.Concat("opentest_", fileName)); var intent = BuildOpenFileIntent(new byte[0], string.Concat("opentest_", fileName));
if (intent == null) if (intent == null)
{ {
@@ -87,7 +86,7 @@ namespace Bit.Droid.Services
return null; return null;
} }
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
var cachePath = activity.CacheDir; var cachePath = activity.CacheDir;
var filePath = Path.Combine(cachePath.Path, fileName); var filePath = Path.Combine(cachePath.Path, fileName);
File.WriteAllBytes(filePath, fileData); File.WriteAllBytes(filePath, fileData);
@@ -114,7 +113,7 @@ namespace Bit.Droid.Services
{ {
try try
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
if (contentUri != null) if (contentUri != null)
{ {
@@ -162,7 +161,7 @@ namespace Bit.Droid.Services
{ {
try try
{ {
DeleteDir(CrossCurrentActivity.Current.Activity.CacheDir); DeleteDir(Microsoft.Maui.ApplicationModel.Platform.CurrentActivity?.CacheDir);
await _stateService.SetLastFileCacheClearAsync(DateTime.UtcNow); await _stateService.SetLastFileCacheClearAsync(DateTime.UtcNow);
} }
catch (Exception) { } catch (Exception) { }
@@ -170,7 +169,7 @@ namespace Bit.Droid.Services
public Task SelectFileAsync() public Task SelectFileAsync()
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = (MainActivity)Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
var hasStorageWritePermission = !_cameraPermissionsDenied && var hasStorageWritePermission = !_cameraPermissionsDenied &&
HasPermission(Manifest.Permission.WriteExternalStorage); HasPermission(Manifest.Permission.WriteExternalStorage);
var additionalIntents = new List<IParcelable>(); var additionalIntents = new List<IParcelable>();
@@ -249,20 +248,30 @@ namespace Bit.Droid.Services
private bool HasPermission(string permission) private bool HasPermission(string permission)
{ {
return ContextCompat.CheckSelfPermission( var activity = Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
CrossCurrentActivity.Current.Activity, permission) == Permission.Granted; if (activity != null)
{
return ContextCompat.CheckSelfPermission(activity, permission) == Permission.Granted;
}
else
{
return false;
}
} }
private void AskPermission(string permission) private void AskPermission(string permission)
{ {
ActivityCompat.RequestPermissions(CrossCurrentActivity.Current.Activity, new string[] { permission }, var activity = Microsoft.Maui.ApplicationModel.Platform.CurrentActivity;
Core.Constants.SelectFilePermissionRequestCode); if (activity != null)
{
ActivityCompat.RequestPermissions(activity, new string[] { permission }, Core.Constants.SelectFilePermissionRequestCode);
}
} }
private List<IParcelable> GetCameraIntents(Android.Net.Uri outputUri) private List<IParcelable> GetCameraIntents(Android.Net.Uri outputUri)
{ {
var intents = new List<IParcelable>(); var intents = new List<IParcelable>();
var pm = CrossCurrentActivity.Current.Activity.PackageManager; var pm = Microsoft.Maui.ApplicationModel.Platform.CurrentActivity?.PackageManager;
var captureIntent = new Intent(MediaStore.ActionImageCapture); var captureIntent = new Intent(MediaStore.ActionImageCapture);
var listCam = pm.QueryIntentActivities(captureIntent, 0); var listCam = pm.QueryIntentActivities(captureIntent, 0);
foreach (var res in listCam) foreach (var res in listCam)

View File

@@ -8,6 +8,7 @@ using Bit.Core.Abstractions;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Bit.Droid.Accessibility; using Bit.Droid.Accessibility;
using Java.Lang; using Java.Lang;
using Bit.App.Droid.Utilities;
namespace Bit.Droid.Tile namespace Bit.Droid.Tile
{ {
@@ -76,7 +77,7 @@ namespace Bit.Droid.Tile
var intent = new Intent(this, typeof(AccessibilityActivity)); var intent = new Intent(this, typeof(AccessibilityActivity));
intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop); intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop);
intent.PutExtra("autofillTileClicked", true); intent.PutExtra("autofillTileClicked", true);
StartActivityAndCollapse(intent); this.StartActivityAndCollapseWithIntent(intent, isMutable: true);
} }
private void ShowConfigErrorDialog() private void ShowConfigErrorDialog()

View File

@@ -1,15 +1,8 @@
using System; using Android.App;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content; using Android.Content;
using Android.OS;
using Android.Runtime; using Android.Runtime;
using Android.Service.QuickSettings; using Android.Service.QuickSettings;
using Android.Views; using Bit.App.Droid.Utilities;
using Android.Widget;
using Java.Lang; using Java.Lang;
namespace Bit.Droid.Tile namespace Bit.Droid.Tile
@@ -62,7 +55,7 @@ namespace Bit.Droid.Tile
var intent = new Intent(this, typeof(MainActivity)); var intent = new Intent(this, typeof(MainActivity));
intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop); intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop);
intent.PutExtra("generatorTile", true); intent.PutExtra("generatorTile", true);
StartActivityAndCollapse(intent); this.StartActivityAndCollapseWithIntent(intent, isMutable: false);
} }
} }
} }

View File

@@ -1,15 +1,8 @@
using System; using Android.App;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content; using Android.Content;
using Android.OS;
using Android.Runtime; using Android.Runtime;
using Android.Service.QuickSettings; using Android.Service.QuickSettings;
using Android.Views; using Bit.App.Droid.Utilities;
using Android.Widget;
using Java.Lang; using Java.Lang;
namespace Bit.Droid.Tile namespace Bit.Droid.Tile
@@ -63,7 +56,7 @@ namespace Bit.Droid.Tile
var intent = new Intent(this, typeof(MainActivity)); var intent = new Intent(this, typeof(MainActivity));
intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop); intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop);
intent.PutExtra("myVaultTile", true); intent.PutExtra("myVaultTile", true);
StartActivityAndCollapse(intent); this.StartActivityAndCollapseWithIntent(intent, isMutable: false);
} }
} }
} }

View File

@@ -2,6 +2,7 @@
using Android.Content; using Android.Content;
using Android.OS; using Android.OS;
using Android.Provider; using Android.Provider;
using Android.Service.QuickSettings;
using Bit.App.Utilities; using Bit.App.Utilities;
namespace Bit.App.Droid.Utilities namespace Bit.App.Droid.Utilities
@@ -64,5 +65,26 @@ namespace Bit.App.Droid.Utilities
return pendingIntentFlags; return pendingIntentFlags;
} }
public static void StartActivityAndCollapseWithIntent(this TileService service, Intent intent, bool isMutable)
{
//For Android 14+ We need to use PendingIntent instead of Intent directly. Older versions still need to use Intent.
if (Build.VERSION.SdkInt < BuildVersionCodes.UpsideDownCake)
{
service.StartActivityAndCollapse(intent);
return;
}
var pendingIntent = PendingIntent.GetActivity(
service.ApplicationContext,
0,
intent,
AddPendingIntentMutabilityFlag(PendingIntentFlags.UpdateCurrent, isMutable)
);
if (pendingIntent == null)
{
return;
}
service.StartActivityAndCollapse(pendingIntent);
}
} }
} }

View File

@@ -15,6 +15,7 @@ using CoreNFC;
using Foundation; using Foundation;
using Microsoft.Maui.Platform; using Microsoft.Maui.Platform;
using UIKit; using UIKit;
using UserNotifications;
using WatchConnectivity; using WatchConnectivity;
namespace Bit.iOS namespace Bit.iOS
@@ -41,204 +42,253 @@ namespace Bit.iOS
private IStateService _stateService; private IStateService _stateService;
private IEventService _eventService; private IEventService _eventService;
private LazyResolve<IDeepLinkContext> _deepLinkContext = new LazyResolve<IDeepLinkContext>(); private readonly LazyResolve<IDeepLinkContext> _deepLinkContext = new LazyResolve<IDeepLinkContext>();
public override bool FinishedLaunching(UIApplication app, NSDictionary options) public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{ {
InitApp(); try
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
_storageService = ServiceContainer.Resolve<IStorageService>("storageService");
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
_eventService = ServiceContainer.Resolve<IEventService>("eventService");
//LoadApplication(new App.App(null));
//iOSCoreHelpers.AppearanceAdjustments();
//ZXing.Net.Mobile.Forms.iOS.Platform.Init();
ConnectToWatchIfNeededAsync().FireAndForget();
_broadcasterService.Subscribe(nameof(AppDelegate), async (message) =>
{ {
try InitApp();
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
_storageService = ServiceContainer.Resolve<IStorageService>("storageService");
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
_eventService = ServiceContainer.Resolve<IEventService>("eventService");
ConnectToWatchIfNeededAsync().FireAndForget();
_broadcasterService.Subscribe(nameof(AppDelegate), async (message) =>
{ {
if (message.Command == "startEventTimer") try
{ {
StartEventTimer(); if (message.Command == "startEventTimer")
}
else if (message.Command == "stopEventTimer")
{
var task = StopEventTimerAsync();
}
else if (message.Command is ThemeManager.UPDATED_THEME_MESSAGE_KEY)
{
MainThread.BeginInvokeOnMainThread(() =>
{ {
iOSCoreHelpers.AppearanceAdjustments(); StartEventTimer();
});
}
else if (message.Command == "listenYubiKeyOTP")
{
iOSCoreHelpers.ListenYubiKey((bool)message.Data, _deviceActionService, _nfcSession, _nfcDelegate);
}
else if (message.Command == "unlocked")
{
var needsAutofillReplacement = await _storageService.GetAsync<bool?>(
Core.Constants.AutofillNeedsIdentityReplacementKey);
if (needsAutofillReplacement.GetValueOrDefault())
{
await ASHelpers.ReplaceAllIdentities();
} }
} else if (message.Command == "stopEventTimer")
else if (message.Command == "showAppExtension")
{
MainThread.BeginInvokeOnMainThread(() => ShowAppExtension((ExtensionPageViewModel)message.Data));
}
else if (message.Command == "syncCompleted")
{
if (message.Data is Dictionary<string, object> data && data.ContainsKey("successfully"))
{ {
var success = data["successfully"] as bool?; var task = StopEventTimerAsync();
if (success.GetValueOrDefault() && _deviceActionService.SystemMajorVersion() >= 12) }
else if (message.Command is ThemeManager.UPDATED_THEME_MESSAGE_KEY)
{
await MainThread.InvokeOnMainThreadAsync(() =>
{ {
await ASHelpers.ReplaceAllIdentities(); iOSCoreHelpers.AppearanceAdjustments();
});
}
else if (message.Command == "listenYubiKeyOTP" && message.Data is bool listen)
{
iOSCoreHelpers.ListenYubiKey(listen, _deviceActionService, _nfcSession, _nfcDelegate);
}
else if (message.Command == "unlocked")
{
var needsAutofillReplacement = await _storageService.GetAsync<bool?>(
Core.Constants.AutofillNeedsIdentityReplacementKey);
if (needsAutofillReplacement.GetValueOrDefault())
{
await ASHelpers.ReplaceAllIdentitiesAsync();
} }
} }
} else if (message.Command == "showAppExtension")
else if (message.Command == "addedCipher" || message.Command == "editedCipher" ||
message.Command == "restoredCipher")
{
if (_deviceActionService.SystemMajorVersion() >= 12)
{ {
if (await ASHelpers.IdentitiesCanIncremental()) await MainThread.InvokeOnMainThreadAsync(() => ShowAppExtension((ExtensionPageViewModel)message.Data));
}
else if (message.Command == "syncCompleted")
{
if (message.Data is Dictionary<string, object> data && data.TryGetValue("successfully", out var value))
{
var success = value as bool?;
if (success.GetValueOrDefault() && _deviceActionService.SystemMajorVersion() >= 12)
{
await ASHelpers.ReplaceAllIdentitiesAsync();
}
}
}
else if (message.Command == "addedCipher" || message.Command == "editedCipher" ||
message.Command == "restoredCipher")
{
if (!UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
{
return;
}
if (await ASHelpers.IdentitiesSupportIncrementalAsync())
{ {
var cipherId = message.Data as string; var cipherId = message.Data as string;
if (message.Command == "addedCipher" && !string.IsNullOrWhiteSpace(cipherId)) if (message.Command == "addedCipher" && !string.IsNullOrWhiteSpace(cipherId))
{ {
var identity = await ASHelpers.GetCipherIdentityAsync(cipherId); var identity = await ASHelpers.GetCipherPasswordIdentityAsync(cipherId);
if (identity == null) if (identity == null)
{ {
return; return;
} }
await ASCredentialIdentityStore.SharedStore?.SaveCredentialIdentitiesAsync( await ASCredentialIdentityStoreExtensions.SaveCredentialIdentitiesAsync(identity);
new ASPasswordCredentialIdentity[] { identity });
return; return;
} }
} }
await ASHelpers.ReplaceAllIdentities(); await ASHelpers.ReplaceAllIdentitiesAsync();
} }
} else if (message.Command == "deletedCipher" || message.Command == "softDeletedCipher")
else if (message.Command == "deletedCipher" || message.Command == "softDeletedCipher")
{
if (_deviceActionService.SystemMajorVersion() >= 12)
{ {
if (await ASHelpers.IdentitiesCanIncremental()) if (!UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
{ {
var identity = ASHelpers.ToCredentialIdentity( return;
}
if (await ASHelpers.IdentitiesSupportIncrementalAsync())
{
var identity = ASHelpers.ToPasswordCredentialIdentity(
message.Data as Bit.Core.Models.View.CipherView); message.Data as Bit.Core.Models.View.CipherView);
if (identity == null) if (identity == null)
{ {
return; return;
} }
await ASCredentialIdentityStore.SharedStore?.RemoveCredentialIdentitiesAsync( await ASCredentialIdentityStoreExtensions.RemoveCredentialIdentitiesAsync(identity);
new ASPasswordCredentialIdentity[] { identity });
return; return;
} }
await ASHelpers.ReplaceAllIdentities(); await ASHelpers.ReplaceAllIdentitiesAsync();
} }
} else if (message.Command == "logout" && UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
else if (message.Command == "logout")
{
if (_deviceActionService.SystemMajorVersion() >= 12)
{ {
await ASCredentialIdentityStore.SharedStore?.RemoveAllCredentialIdentitiesAsync(); await ASCredentialIdentityStore.SharedStore.RemoveAllCredentialIdentitiesAsync();
} }
} else if ((message.Command == "softDeletedCipher" || message.Command == "restoredCipher")
else if ((message.Command == "softDeletedCipher" || message.Command == "restoredCipher") && UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
&& _deviceActionService.SystemMajorVersion() >= 12)
{
await ASHelpers.ReplaceAllIdentities();
}
else if (message.Command == AppHelpers.VAULT_TIMEOUT_ACTION_CHANGED_MESSAGE_COMMAND)
{
var timeoutAction = await _stateService.GetVaultTimeoutActionAsync();
if (timeoutAction == VaultTimeoutAction.Logout)
{ {
await ASCredentialIdentityStore.SharedStore?.RemoveAllCredentialIdentitiesAsync(); await ASHelpers.ReplaceAllIdentitiesAsync();
} }
else else if (message.Command == AppHelpers.VAULT_TIMEOUT_ACTION_CHANGED_MESSAGE_COMMAND)
{ {
await ASHelpers.ReplaceAllIdentities(); var timeoutAction = await _stateService.GetVaultTimeoutActionAsync();
if (timeoutAction == VaultTimeoutAction.Logout)
{
if (UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
{
await ASCredentialIdentityStore.SharedStore.RemoveAllCredentialIdentitiesAsync();
}
}
else
{
await ASHelpers.ReplaceAllIdentitiesAsync();
}
} }
} }
} catch (Exception ex)
catch (Exception ex) {
{ LoggerHelper.LogEvenIfCantBeResolved(ex);
LoggerHelper.LogEvenIfCantBeResolved(ex); }
} });
});
var finishedLaunching = base.FinishedLaunching(app, options); var finishedLaunching = base.FinishedLaunching(app, options);
ThemeManager.SetTheme(Microsoft.Maui.Controls.Application.Current.Resources); ThemeManager.SetTheme(Microsoft.Maui.Controls.Application.Current.Resources);
iOSCoreHelpers.AppearanceAdjustments(); iOSCoreHelpers.AppearanceAdjustments();
return finishedLaunching; return finishedLaunching;
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
throw;
}
} }
public override void OnResignActivation(UIApplication uiApplication) public override void OnResignActivation(UIApplication uiApplication)
{ {
if (UIApplication.SharedApplication.KeyWindow != null) try
{ {
var view = new UIView(UIApplication.SharedApplication.KeyWindow.Frame) if (UIApplication.SharedApplication.KeyWindow != null)
{ {
Tag = SPLASH_VIEW_TAG var view = new UIView(UIApplication.SharedApplication.KeyWindow.Frame)
}; {
var backgroundView = new UIView(UIApplication.SharedApplication.KeyWindow.Frame) Tag = SPLASH_VIEW_TAG
{ };
BackgroundColor = ThemeManager.GetResourceColor("SplashBackgroundColor").ToPlatform() var backgroundView = new UIView(UIApplication.SharedApplication.KeyWindow.Frame)
}; {
var logo = new UIImage(!ThemeManager.UsingLightTheme ? "logo_white.png" : "logo.png"); BackgroundColor = ThemeManager.GetResourceColor("SplashBackgroundColor").ToPlatform()
var frame = new CGRect(0, 0, 280, 100); //Setting image width to avoid it being larger and getting cropped on smaller devices. This harcoded size should be good even for very small devices. };
var imageView = new UIImageView(frame) var logo = new UIImage(!ThemeManager.UsingLightTheme ? "logo_white.png" : "logo.png");
{ var frame = new CGRect(0, 0, 280, 100); //Setting image width to avoid it being larger and getting cropped on smaller devices. This harcoded size should be good even for very small devices.
Image = logo, var imageView = new UIImageView(frame)
Center = new CGPoint(view.Center.X, view.Center.Y - 30), {
ContentMode = UIViewContentMode.ScaleAspectFit Image = logo,
}; Center = new CGPoint(view.Center.X, view.Center.Y - 30),
view.AddSubview(backgroundView); ContentMode = UIViewContentMode.ScaleAspectFit
view.AddSubview(imageView); };
UIApplication.SharedApplication.KeyWindow.AddSubview(view); view.AddSubview(backgroundView);
UIApplication.SharedApplication.KeyWindow.BringSubviewToFront(view); view.AddSubview(imageView);
UIApplication.SharedApplication.KeyWindow.EndEditing(true); UIApplication.SharedApplication.KeyWindow.AddSubview(view);
UIApplication.SharedApplication.KeyWindow.BringSubviewToFront(view);
UIApplication.SharedApplication.KeyWindow.EndEditing(true);
}
base.OnResignActivation(uiApplication);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
throw;
} }
base.OnResignActivation(uiApplication);
} }
public override void DidEnterBackground(UIApplication uiApplication) public override void DidEnterBackground(UIApplication uiApplication)
{ {
_stateService?.SetLastActiveTimeAsync(_deviceActionService.GetActiveTime()); try
_messagingService?.Send("slept"); {
base.DidEnterBackground(uiApplication); if (_stateService != null && _deviceActionService != null)
{
_stateService.SetLastActiveTimeAsync(_deviceActionService.GetActiveTime());
}
_messagingService?.Send("slept");
base.DidEnterBackground(uiApplication);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
throw;
}
} }
public override void OnActivated(UIApplication uiApplication) public override async void OnActivated(UIApplication uiApplication)
{ {
base.OnActivated(uiApplication); try
UIApplication.SharedApplication.ApplicationIconBadgeNumber = 0; {
UIApplication.SharedApplication.KeyWindow? base.OnActivated(uiApplication);
.ViewWithTag(SPLASH_VIEW_TAG)?
.RemoveFromSuperview();
ThemeManager.UpdateThemeOnPagesAsync(); if (UIDevice.CurrentDevice.CheckSystemVersion(17, 0))
{
await UNUserNotificationCenter.Current.SetBadgeCountAsync(0);
}
else
{
UIApplication.SharedApplication.ApplicationIconBadgeNumber = 0;
}
UIApplication.SharedApplication.KeyWindow?
.ViewWithTag(SPLASH_VIEW_TAG)?
.RemoveFromSuperview();
ThemeManager.UpdateThemeOnPagesAsync();
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
public override void WillEnterForeground(UIApplication uiApplication) public override void WillEnterForeground(UIApplication uiApplication)
{ {
_messagingService?.Send(AppHelpers.RESUMED_MESSAGE_COMMAND); try
base.WillEnterForeground(uiApplication); {
_messagingService?.Send(AppHelpers.RESUMED_MESSAGE_COMMAND);
base.WillEnterForeground(uiApplication);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
[Export("application:openURL:sourceApplication:annotation:")] [Export("application:openURL:sourceApplication:annotation:")]
@@ -249,15 +299,30 @@ namespace Bit.iOS
public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options) public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{ {
return _deepLinkContext.Value.OnNewUri(url) || base.OpenUrl(app, url, options); try
{
return _deepLinkContext.Value.OnNewUri(url) || base.OpenUrl(app, url, options);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
return false;
}
} }
public override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity, public override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity,
UIApplicationRestorationHandler completionHandler) UIApplicationRestorationHandler completionHandler)
{ {
if (Microsoft.Maui.ApplicationModel.Platform.ContinueUserActivity(application, userActivity, completionHandler)) try
{ {
return true; if (Microsoft.Maui.ApplicationModel.Platform.ContinueUserActivity(application, userActivity, completionHandler))
{
return true;
}
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
} }
return base.ContinueUserActivity(application, userActivity, completionHandler); return base.ContinueUserActivity(application, userActivity, completionHandler);
} }
@@ -265,33 +330,68 @@ namespace Bit.iOS
[Export("application:didFailToRegisterForRemoteNotificationsWithError:")] [Export("application:didFailToRegisterForRemoteNotificationsWithError:")]
public void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error) public void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
{ {
_pushHandler?.OnErrorReceived(error); try
{
_pushHandler?.OnErrorReceived(error);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
[Export("application:didRegisterForRemoteNotificationsWithDeviceToken:")] [Export("application:didRegisterForRemoteNotificationsWithDeviceToken:")]
public void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken) public void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{ {
_pushHandler?.OnRegisteredSuccess(deviceToken); try
{
_pushHandler?.OnRegisteredSuccess(deviceToken);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
[Export("application:didRegisterUserNotificationSettings:")] [Export("application:didRegisterUserNotificationSettings:")]
public void DidRegisterUserNotificationSettings(UIApplication application, public void DidRegisterUserNotificationSettings(UIApplication application,
UIUserNotificationSettings notificationSettings) UIUserNotificationSettings notificationSettings)
{ {
application.RegisterForRemoteNotifications(); try
{
application.RegisterForRemoteNotifications();
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
[Export("application:didReceiveRemoteNotification:fetchCompletionHandler:")] [Export("application:didReceiveRemoteNotification:fetchCompletionHandler:")]
public void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, public void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo,
Action<UIBackgroundFetchResult> completionHandler) Action<UIBackgroundFetchResult> completionHandler)
{ {
_pushHandler?.OnMessageReceived(userInfo); try
{
_pushHandler?.OnMessageReceived(userInfo);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
[Export("application:didReceiveRemoteNotification:")] [Export("application:didReceiveRemoteNotification:")]
public void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo) public void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
{ {
_pushHandler?.OnMessageReceived(userInfo); try
{
_pushHandler?.OnMessageReceived(userInfo);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
public void InitApp() public void InitApp()
@@ -304,17 +404,6 @@ namespace Bit.iOS
// Migration services // Migration services
ServiceContainer.Register<INativeLogService>("nativeLogService", new ConsoleLogService()); ServiceContainer.Register<INativeLogService>("nativeLogService", new ConsoleLogService());
// Note: This might cause a race condition. Investigate more.
//Task.Run(() =>
//{
// FFImageLoading.Forms.Platform.CachedImageRenderer.Init();
// FFImageLoading.ImageService.Instance.Initialize(new FFImageLoading.Config.Configuration
// {
// FadeAnimationEnabled = false,
// FadeAnimationForCachedImages = false
// });
//});
iOSCoreHelpers.RegisterLocalServices(); iOSCoreHelpers.RegisterLocalServices();
RegisterPush(); RegisterPush();
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService"); var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
@@ -328,7 +417,7 @@ namespace Bit.iOS
_nfcDelegate = new Core.NFCReaderDelegate((success, message) => _nfcDelegate = new Core.NFCReaderDelegate((success, message) =>
_messagingService.Send("gotYubiKeyOTP", message)); _messagingService.Send("gotYubiKeyOTP", message));
iOSCoreHelpers.Bootstrap(async () => await ApplyManagedSettingsAsync()); iOSCoreHelpers.Bootstrap(ApplyManagedSettingsAsync);
} }
private void RegisterPush() private void RegisterPush()
@@ -373,31 +462,45 @@ namespace Bit.iOS
_eventTimer = null; _eventTimer = null;
MainThread.BeginInvokeOnMainThread(() => MainThread.BeginInvokeOnMainThread(() =>
{ {
_eventTimer = NSTimer.CreateScheduledTimer(60, true, timer => try
{ {
var task = Task.Run(() => _eventService.UploadEventsAsync()); _eventTimer = NSTimer.CreateScheduledTimer(60, true, timer =>
}); {
_eventService?.UploadEventsAsync().FireAndForget();
});
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
}); });
} }
private async Task StopEventTimerAsync() private async Task StopEventTimerAsync()
{ {
_eventTimer?.Invalidate(); try
_eventTimer?.Dispose();
_eventTimer = null;
if (_eventBackgroundTaskId > 0)
{ {
_eventTimer?.Invalidate();
_eventTimer?.Dispose();
_eventTimer = null;
if (_eventBackgroundTaskId > 0)
{
UIApplication.SharedApplication.EndBackgroundTask(_eventBackgroundTaskId);
_eventBackgroundTaskId = 0;
}
_eventBackgroundTaskId = UIApplication.SharedApplication.BeginBackgroundTask(() =>
{
UIApplication.SharedApplication.EndBackgroundTask(_eventBackgroundTaskId);
_eventBackgroundTaskId = 0;
});
await _eventService.UploadEventsAsync();
UIApplication.SharedApplication.EndBackgroundTask(_eventBackgroundTaskId); UIApplication.SharedApplication.EndBackgroundTask(_eventBackgroundTaskId);
_eventBackgroundTaskId = 0; _eventBackgroundTaskId = 0;
} }
_eventBackgroundTaskId = UIApplication.SharedApplication.BeginBackgroundTask(() => catch (Exception ex)
{ {
UIApplication.SharedApplication.EndBackgroundTask(_eventBackgroundTaskId); LoggerHelper.LogEvenIfCantBeResolved(ex);
_eventBackgroundTaskId = 0; }
});
await _eventService.UploadEventsAsync();
UIApplication.SharedApplication.EndBackgroundTask(_eventBackgroundTaskId);
_eventBackgroundTaskId = 0;
} }
private async Task ApplyManagedSettingsAsync() private async Task ApplyManagedSettingsAsync()

View File

@@ -11,7 +11,7 @@
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>com.8bit.bitwarden</string> <string>com.8bit.bitwarden</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2023.9.2</string> <string>2024.3.3</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1</string> <string>1</string>
<key>CFBundleIconName</key> <key>CFBundleIconName</key>

View File

@@ -0,0 +1,27 @@
{
"images": [
{
"appearances": [],
"scale": "1x",
"idiom": "universal",
"filename": "search.png"
},
{
"appearances": [],
"scale": "2x",
"idiom": "universal",
"filename": "search@2x.png"
},
{
"appearances": [],
"scale": "3x",
"idiom": "universal",
"filename": "search@3x.png"
}
],
"properties": {},
"info": {
"version": 1,
"author": ""
}
}

View File

Before

Width:  |  Height:  |  Size: 561 B

After

Width:  |  Height:  |  Size: 561 B

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

Before

Width:  |  Height:  |  Size: 164 B

After

Width:  |  Height:  |  Size: 164 B

View File

Before

Width:  |  Height:  |  Size: 242 B

After

Width:  |  Height:  |  Size: 242 B

View File

Before

Width:  |  Height:  |  Size: 338 B

After

Width:  |  Height:  |  Size: 338 B

View File

@@ -4,6 +4,7 @@ namespace Bit.Core.Abstractions
{ {
public interface IAutofillHandler public interface IAutofillHandler
{ {
bool CredentialProviderServiceEnabled();
bool AutofillServicesEnabled(); bool AutofillServicesEnabled();
bool SupportsAutofillService(); bool SupportsAutofillService();
void Autofill(CipherView cipher); void Autofill(CipherView cipher);
@@ -11,6 +12,7 @@ namespace Bit.Core.Abstractions
bool AutofillAccessibilityServiceRunning(); bool AutofillAccessibilityServiceRunning();
bool AutofillAccessibilityOverlayPermitted(); bool AutofillAccessibilityOverlayPermitted();
bool AutofillServiceEnabled(); bool AutofillServiceEnabled();
void DisableCredentialProviderService();
void DisableAutofillService(); void DisableAutofillService();
} }
} }

View File

@@ -1,7 +1,4 @@
using System; using Bit.Core.Enums;
using System.Collections.Generic;
using System.Threading.Tasks;
using Bit.Core.Enums;
using Bit.Core.Models.Data; using Bit.Core.Models.Data;
using Bit.Core.Models.Domain; using Bit.Core.Models.Domain;
using Bit.Core.Models.View; using Bit.Core.Models.View;
@@ -37,5 +34,7 @@ namespace Bit.Core.Abstractions
Task<byte[]> DownloadAndDecryptAttachmentAsync(string cipherId, AttachmentView attachment, string organizationId); Task<byte[]> DownloadAndDecryptAttachmentAsync(string cipherId, AttachmentView attachment, string organizationId);
Task SoftDeleteWithServerAsync(string id); Task SoftDeleteWithServerAsync(string id);
Task RestoreWithServerAsync(string id); Task RestoreWithServerAsync(string id);
Task<string> CreateNewLoginForPasskeyAsync(Fido2ConfirmNewCredentialParams newPasskeyParams);
Task CopyTotpCodeIfNeededAsync(CipherView cipher);
} }
} }

View File

@@ -1,11 +1,10 @@
using System; namespace Bit.Core.Abstractions
using System.Threading.Tasks;
namespace Bit.Core.Abstractions
{ {
public enum AwaiterPrecondition public enum AwaiterPrecondition
{ {
EnvironmentUrlsInited EnvironmentUrlsInited,
AndroidWindowCreated,
AutofillIOSExtensionViewDidAppear
} }
public interface IConditionedAwaiterManager public interface IConditionedAwaiterManager
@@ -13,5 +12,6 @@ namespace Bit.Core.Abstractions
Task GetAwaiterForPrecondition(AwaiterPrecondition awaiterPrecondition); Task GetAwaiterForPrecondition(AwaiterPrecondition awaiterPrecondition);
void SetAsCompleted(AwaiterPrecondition awaiterPrecondition); void SetAsCompleted(AwaiterPrecondition awaiterPrecondition);
void SetException(AwaiterPrecondition awaiterPrecondition, Exception ex); void SetException(AwaiterPrecondition awaiterPrecondition, Exception ex);
void Recreate(AwaiterPrecondition awaiterPrecondition);
} }
} }

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Models.Domain;
namespace Bit.Core.Abstractions namespace Bit.Core.Abstractions
{ {

View File

@@ -63,5 +63,7 @@ namespace Bit.Core.Abstractions
Task<UserKey> DecryptAndMigrateOldPinKeyAsync(bool masterPasswordOnRestart, string pin, string email, KdfConfig kdfConfig, EncString oldPinKey); Task<UserKey> DecryptAndMigrateOldPinKeyAsync(bool masterPasswordOnRestart, string pin, string email, KdfConfig kdfConfig, EncString oldPinKey);
Task<MasterKey> GetOrDeriveMasterKeyAsync(string password, string userId = null); Task<MasterKey> GetOrDeriveMasterKeyAsync(string password, string userId = null);
Task UpdateMasterKeyAndUserKeyAsync(MasterKey masterKey); Task UpdateMasterKeyAndUserKeyAsync(MasterKey masterKey);
Task<string> HashAsync(string value, CryptoHashAlgorithm hashAlgorithm);
Task<bool> ValidateUriChecksumAsync(EncString remoteUriChecksum, string rawUri, string orgId, SymmetricCryptoKey key);
} }
} }

View File

@@ -28,6 +28,7 @@ namespace Bit.App.Abstractions
bool SupportsNfc(); bool SupportsNfc();
bool SupportsCamera(); bool SupportsCamera();
bool SupportsFido2(); bool SupportsFido2();
bool SupportsCredentialProviderService();
bool SupportsAutofillServices(); bool SupportsAutofillServices();
bool SupportsInlineAutofill(); bool SupportsInlineAutofill();
bool SupportsDrawOver(); bool SupportsDrawOver();
@@ -36,6 +37,7 @@ namespace Bit.App.Abstractions
void RateApp(); void RateApp();
void OpenAccessibilitySettings(); void OpenAccessibilitySettings();
void OpenAccessibilityOverlayPermissionSettings(); void OpenAccessibilityOverlayPermissionSettings();
void OpenCredentialProviderSettings();
void OpenAutofillSettings(); void OpenAutofillSettings();
long GetActiveTime(); long GetActiveTime();
void CloseMainApp(); void CloseMainApp();

View File

@@ -0,0 +1,12 @@
using Bit.Core.Utilities.Fido2;
namespace Bit.Core.Abstractions
{
public interface IFido2AuthenticatorService
{
Task<Fido2AuthenticatorMakeCredentialResult> MakeCredentialAsync(Fido2AuthenticatorMakeCredentialParams makeCredentialParams, IFido2MakeCredentialUserInterface userInterface);
Task<Fido2AuthenticatorGetAssertionResult> GetAssertionAsync(Fido2AuthenticatorGetAssertionParams assertionParams, IFido2GetAssertionUserInterface userInterface);
// TODO: Should this return a List? Or maybe IEnumerable?
Task<Fido2AuthenticatorDiscoverableCredentialMetadata[]> SilentCredentialDiscoveryAsync(string rpId);
}
}

View File

@@ -0,0 +1,35 @@
using Bit.Core.Utilities.Fido2;
namespace Bit.Core.Abstractions
{
/// <summary>
/// This class represents an abstraction of the WebAuthn Client as described by W3C:
/// https://www.w3.org/TR/webauthn-3/#webauthn-client
///
/// The WebAuthn Client is an intermediary entity typically implemented in the user agent
/// (in whole, or in part). Conceptually, it underlies the Web Authentication API and embodies
/// the implementation of the Web Authentication API's operations.
///
/// It is responsible for both marshalling the inputs for the underlying authenticator operations,
/// and for returning the results of the latter operations to the Web Authentication API's callers.
/// </summary>
public interface IFido2ClientService
{
/// <summary>
/// Allows WebAuthn Relying Party scripts to request the creation of a new public key credential source.
/// For more information please see: https://www.w3.org/TR/webauthn-3/#sctn-createCredential
/// </summary>
/// <param name="createCredentialParams">The parameters for the credential creation operation</param>
/// <returns>The new credential</returns>
Task<Fido2ClientCreateCredentialResult> CreateCredentialAsync(Fido2ClientCreateCredentialParams createCredentialParams);
/// <summary>
/// Allows WebAuthn Relying Party scripts to discover and use an existing public key credential, with the users consent.
/// Relying Party script can optionally specify some criteria to indicate what credential sources are acceptable to it.
/// For more information please see: https://www.w3.org/TR/webauthn-3/#sctn-getAssertion
/// </summary>
/// <param name="assertCredentialParams">The parameters for the credential assertion operation</param>
/// <returns>The asserted credential</returns>
Task<Fido2ClientAssertCredentialResult> AssertCredentialAsync(Fido2ClientAssertCredentialParams assertCredentialParams);
}
}

View File

@@ -0,0 +1,20 @@
using Bit.Core.Utilities.Fido2;
namespace Bit.Core.Abstractions
{
public struct Fido2GetAssertionUserInterfaceCredential
{
public string CipherId { get; set; }
public Fido2UserVerificationPreference UserVerificationPreference { get; set; }
}
public interface IFido2GetAssertionUserInterface : IFido2UserInterface
{
/// <summary>
/// Ask the user to pick a credential from a list of existing credentials.
/// </summary>
/// <param name="credentials">The credentials that the user can pick from, and if the user must be verified before completing the operation</param>
/// <returns>The ID of the cipher that contains the credentials the user picked, and if the user was verified before completing the operation</returns>
Task<(string CipherId, bool UserVerified)> PickCredentialAsync(Fido2GetAssertionUserInterfaceCredential[] credentials);
}
}

View File

@@ -0,0 +1,44 @@
using Bit.Core.Utilities.Fido2;
namespace Bit.Core.Abstractions
{
public struct Fido2ConfirmNewCredentialParams
{
///<summary>
/// The name of the credential.
///</summary>
public string CredentialName { get; set; }
///<summary>
/// The name of the user.
///</summary>
public string UserName { get; set; }
/// <summary>
/// The preference to whether or not the user must be verified before completing the operation.
/// </summary>
public Fido2UserVerificationPreference UserVerificationPreference { get; set; }
/// <summary>
/// The relying party identifier
/// </summary>
public string RpId { get; set; }
}
public interface IFido2MakeCredentialUserInterface : IFido2UserInterface
{
/// <summary>
/// Inform the user that the operation was cancelled because their vault contains excluded credentials.
/// </summary>
/// <param name="existingCipherIds">The IDs of the excluded credentials.</param>
/// <returns>When user has confirmed the message</returns>
Task InformExcludedCredentialAsync(string[] existingCipherIds);
/// <summary>
/// Ask the user to confirm the creation of a new credential.
/// </summary>
/// <param name="confirmNewCredentialParams">The parameters to use when asking the user to confirm the creation of a new credential.</param>
/// <returns>The ID of the cipher where the new credential should be saved, and if the user was verified before completing the operation</returns>
Task<(string CipherId, bool UserVerified)> ConfirmNewCredentialAsync(Fido2ConfirmNewCredentialParams confirmNewCredentialParams);
}
}

View File

@@ -0,0 +1,14 @@
using Bit.Core.Utilities.Fido2;
namespace Bit.Core.Abstractions
{
public interface IFido2MediatorService
{
Task<Fido2ClientCreateCredentialResult> CreateCredentialAsync(Fido2ClientCreateCredentialParams createCredentialParams);
Task<Fido2ClientAssertCredentialResult> AssertCredentialAsync(Fido2ClientAssertCredentialParams assertCredentialParams);
Task<Fido2AuthenticatorMakeCredentialResult> MakeCredentialAsync(Fido2AuthenticatorMakeCredentialParams makeCredentialParams, IFido2MakeCredentialUserInterface userInterface);
Task<Fido2AuthenticatorGetAssertionResult> GetAssertionAsync(Fido2AuthenticatorGetAssertionParams assertionParams, IFido2GetAssertionUserInterface userInterface);
Task<Fido2AuthenticatorDiscoverableCredentialMetadata[]> SilentCredentialDiscoveryAsync(string rpId);
}
}

View File

@@ -0,0 +1,17 @@
namespace Bit.Core.Abstractions
{
public interface IFido2UserInterface
{
/// <summary>
/// Whether the vault has been unlocked during this transaction
/// </summary>
bool HasVaultBeenUnlockedInThisTransaction { get; }
/// <summary>
/// Make sure that the vault is unlocked.
/// This should open a window and ask the user to login or unlock the vault if necessary.
/// </summary>
/// <returns>When vault has been unlocked.</returns>
Task EnsureUnlockedVaultAsync();
}
}

View File

@@ -1,5 +1,4 @@
using System.Threading.Tasks; using Bit.Core.Enums;
using Bit.Core.Enums;
namespace Bit.App.Abstractions namespace Bit.App.Abstractions
{ {
@@ -10,5 +9,7 @@ namespace Bit.App.Abstractions
Task<bool> PromptAndCheckPasswordIfNeededAsync(CipherRepromptType repromptType = CipherRepromptType.Password); Task<bool> PromptAndCheckPasswordIfNeededAsync(CipherRepromptType repromptType = CipherRepromptType.Password);
Task<(string password, bool valid)> ShowPasswordPromptAndGetItAsync(); Task<(string password, bool valid)> ShowPasswordPromptAndGetItAsync();
Task<bool> ShouldByPassMasterPasswordRepromptAsync();
} }
} }

View File

@@ -1,7 +1,4 @@
using System; using Bit.Core.Enums;
using System.Collections.Generic;
using System.Threading.Tasks;
using Bit.Core.Enums;
namespace Bit.Core.Abstractions namespace Bit.Core.Abstractions
{ {
@@ -29,7 +26,7 @@ namespace Bit.Core.Abstractions
bool SupportsDuo(); bool SupportsDuo();
Task<bool> SupportsBiometricAsync(); Task<bool> SupportsBiometricAsync();
Task<bool> IsBiometricIntegrityValidAsync(string bioIntegritySrcKey = null); Task<bool> IsBiometricIntegrityValidAsync(string bioIntegritySrcKey = null);
Task<bool> AuthenticateBiometricAsync(string text = null, string fallbackText = null, Action fallback = null, bool logOutOnTooManyAttempts = false); Task<bool?> AuthenticateBiometricAsync(string text = null, string fallbackText = null, Action fallback = null, bool logOutOnTooManyAttempts = false, bool allowAlternativeAuthentication = false);
long GetActiveTime(); long GetActiveTime();
} }
} }

View File

@@ -186,6 +186,7 @@ namespace Bit.Core.Abstractions
Task<BwRegion?> GetActiveUserRegionAsync(); Task<BwRegion?> GetActiveUserRegionAsync();
Task<BwRegion?> GetPreAuthRegionAsync(); Task<BwRegion?> GetPreAuthRegionAsync();
Task SetPreAuthRegionAsync(BwRegion value); Task SetPreAuthRegionAsync(BwRegion value);
Task ReloadStateAsync();
[Obsolete("Use GetPinKeyEncryptedUserKeyAsync instead, left for migration purposes")] [Obsolete("Use GetPinKeyEncryptedUserKeyAsync instead, left for migration purposes")]
Task<string> GetPinProtectedAsync(string userId = null); Task<string> GetPinProtectedAsync(string userId = null);
[Obsolete("Use SetPinKeyEncryptedUserKeyAsync instead, left for migration purposes")] [Obsolete("Use SetPinKeyEncryptedUserKeyAsync instead, left for migration purposes")]

View File

@@ -1,9 +1,12 @@
using System.Threading.Tasks; using Bit.Core.Services;
namespace Bit.Core.Abstractions namespace Bit.Core.Abstractions
{ {
public interface IUserPinService public interface IUserPinService
{ {
Task<bool> IsPinLockEnabledAsync();
Task SetupPinAsync(string pin, bool requireMasterPasswordOnRestart); Task SetupPinAsync(string pin, bool requireMasterPasswordOnRestart);
Task<bool> VerifyPinAsync(string inputPin);
Task<bool> VerifyPinAsync(string inputPin, string email, KdfConfig kdfConfig, PinLockType pinLockType);
} }
} }

View File

@@ -0,0 +1,28 @@
using Bit.Core.Utilities;
using Bit.Core.Utilities.Fido2;
namespace Bit.Core.Abstractions
{
public interface IUserVerificationMediatorService
{
Task<CancellableResult<bool>> VerifyUserForFido2Async(Fido2UserVerificationOptions options);
Task<bool> CanPerformUserVerificationPreferredAsync(Fido2UserVerificationOptions options);
Task<bool> ShouldPerformMasterPasswordRepromptAsync(Fido2UserVerificationOptions options);
Task<bool> ShouldEnforceFido2RequiredUserVerificationAsync(Fido2UserVerificationOptions options);
Task<CancellableResult<UVResult>> PerformOSUnlockAsync();
Task<CancellableResult<UVResult>> VerifyPinCodeAsync();
Task<CancellableResult<UVResult>> VerifyMasterPasswordAsync(bool isMasterPasswordReprompt);
public struct UVResult
{
public UVResult(bool canPerform, bool isVerified)
{
CanPerform = canPerform;
IsVerified = isVerified;
}
public bool CanPerform { get; set; }
public bool IsVerified { get; set; }
}
}
}

View File

@@ -1,11 +1,11 @@
using System.Threading.Tasks; using Bit.Core.Enums;
using Bit.Core.Enums;
namespace Bit.Core.Abstractions namespace Bit.Core.Abstractions
{ {
public interface IUserVerificationService public interface IUserVerificationService
{ {
Task<bool> VerifyUser(string secret, VerificationType verificationType); Task<bool> VerifyUser(string secret, VerificationType verificationType);
Task<bool> VerifyMasterPasswordAsync(string masterPassword);
Task<bool> HasMasterPasswordAsync(bool checkMasterKeyHash = false); Task<bool> HasMasterPasswordAsync(bool checkMasterKeyHash = false);
} }
} }

View File

@@ -9,7 +9,9 @@ using Bit.Core;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Models.Data; using Bit.Core.Models.Data;
using Bit.Core.Models.Domain;
using Bit.Core.Models.Response; using Bit.Core.Models.Response;
using Bit.Core.Pages;
using Bit.Core.Services; using Bit.Core.Services;
using Bit.Core.Utilities; using Bit.Core.Utilities;
@@ -34,6 +36,8 @@ namespace Bit.App
private readonly IAccountsManager _accountsManager; private readonly IAccountsManager _accountsManager;
private readonly IPushNotificationService _pushNotificationService; private readonly IPushNotificationService _pushNotificationService;
private readonly IConfigService _configService; private readonly IConfigService _configService;
private readonly ILogger _logger;
private static bool _isResumed; private static bool _isResumed;
// these variables are static because the app is launching new activities on notification click, creating new instances of App. // these variables are static because the app is launching new activities on notification click, creating new instances of App.
private static bool _pendingCheckPasswordlessLoginRequests; private static bool _pendingCheckPasswordlessLoginRequests;
@@ -44,6 +48,99 @@ namespace Bit.App
// Links: https://github.com/dotnet/maui/issues/11501 and https://bitwarden.atlassian.net/wiki/spaces/NMME/pages/664862722/MainPage+Assignments+not+working+on+Android+on+Background+or+App+resume // Links: https://github.com/dotnet/maui/issues/11501 and https://bitwarden.atlassian.net/wiki/spaces/NMME/pages/664862722/MainPage+Assignments+not+working+on+Android+on+Background+or+App+resume
private readonly Queue<Action> _onResumeActions = new Queue<Action>(); private readonly Queue<Action> _onResumeActions = new Queue<Action>();
#if ANDROID
/*
* ** Workaround for our Android crashes when trying to use Autofill **
*
* This workaround works by managing the "Window Creation" ourselves.
* - If we get an AutofillExternalActivity we just create a "dummy" window/navigation page so that the activity can run without crashing. (no visible UI is needed)
* - If we get an FromAutofillFramework/Uri/Otp/CreateSend special Option request we create an Autofill Window
* - For everything else we use the default "mainWindow"
*/
public new static Page MainPage
{
get
{
return CurrentWindow?.Page;
}
set
{
if (CurrentWindow != null)
{
CurrentWindow.Page = value;
}
}
}
/// <summary>
/// Find the Current Active Window. There should only be one at any point in Android
/// </summary>
public static ResumeWindow CurrentWindow
{
get
{
return Application.Current?.Windows.OfType<ResumeWindow>().FirstOrDefault(w => w.IsActive);
}
}
/// <summary>
/// Allows setting Options from MainActivity before base.OnCreate
/// Note 1: This is only be used by Android due to way it's Lifecycle works
/// Note 2: This method does not replace existing Options in App.xaml.cs if it exists already.
/// It only updates properties in Options related with Autofill/CreateSend/etc..
/// </summary>
/// <param name="appOptions">Options created in Android MainActivity.cs</param>
public void SetAndroidOptions(AppOptions appOptions)
{
if (Options == null)
{
Options = appOptions ?? new AppOptions();
}
else if(appOptions != null)
{
Options.Uri = appOptions.Uri;
Options.MyVaultTile = appOptions.MyVaultTile;
Options.GeneratorTile = appOptions.GeneratorTile;
Options.FromAutofillFramework = appOptions.FromAutofillFramework;
Options.CreateSend = appOptions.CreateSend;
}
}
protected override Window CreateWindow(IActivationState activationState)
{
//When executing from AutofillExternalActivity we don't have "Options" so we need to filter "manually"
//In the AutofillExternalActivity we don't need to show any Page, so we just create a "dummy" Window with a NavigationPage to avoid crashing.
if (activationState != null
&& activationState.State.TryGetValue("autofillFramework", out string autofillFramework)
&& autofillFramework == "true"
&& activationState.State.ContainsKey("autofillFrameworkCipherId"))
{
return new Window(new NavigationPage()); //No actual page needed. Only used for auto-filling the fields directly (externally)
}
_isResumed = true;
return new ResumeWindow(new NavigationPage(new AndroidNavigationRedirectPage(Options)));
}
#else
//iOS doesn't use the CreateWindow override used in Android so we just set the Application.Current.MainPage directly
public new static Page MainPage
{
get
{
return Application.Current?.MainPage;
}
set
{
if (Application.Current != null)
{
Application.Current.MainPage = value;
}
}
}
#endif
public App() : this(null) public App() : this(null)
{ {
} }
@@ -67,139 +164,157 @@ namespace Bit.App
_accountsManager = ServiceContainer.Resolve<IAccountsManager>("accountsManager"); _accountsManager = ServiceContainer.Resolve<IAccountsManager>("accountsManager");
_pushNotificationService = ServiceContainer.Resolve<IPushNotificationService>(); _pushNotificationService = ServiceContainer.Resolve<IPushNotificationService>();
_configService = ServiceContainer.Resolve<IConfigService>(); _configService = ServiceContainer.Resolve<IConfigService>();
_logger = ServiceContainer.Resolve<ILogger>();
_accountsManager.Init(() => Options, this); _accountsManager.Init(() => Options, this);
Bootstrap(); _broadcasterService.Subscribe(nameof(App), BroadcastServiceMessageCallbackAsync);
_broadcasterService.Subscribe(nameof(App), async (message) =>
{
try
{
if (message.Command == "showDialog")
{
var details = message.Data as DialogDetails;
var confirmed = true;
var confirmText = string.IsNullOrWhiteSpace(details.ConfirmText) ?
AppResources.Ok : details.ConfirmText;
MainThread.BeginInvokeOnMainThread(async () =>
{
if (!string.IsNullOrWhiteSpace(details.CancelText))
{
confirmed = await MainPage.DisplayAlert(details.Title, details.Text, confirmText,
details.CancelText);
}
else
{
await MainPage.DisplayAlert(details.Title, details.Text, confirmText);
}
_messagingService.Send("showDialogResolve", new Tuple<int, bool>(details.DialogId, confirmed));
});
}
else if (message.Command == AppHelpers.RESUMED_MESSAGE_COMMAND)
{
if (DeviceInfo.Platform == DevicePlatform.iOS)
{
ResumedAsync().FireAndForget();
}
}
else if (message.Command == "slept")
{
if (DeviceInfo.Platform == DevicePlatform.iOS)
{
await SleptAsync();
}
}
else if (message.Command == "migrated")
{
await Task.Delay(1000);
await _accountsManager.NavigateOnAccountChangeAsync();
}
else if (message.Command == POP_ALL_AND_GO_TO_TAB_GENERATOR_MESSAGE ||
message.Command == POP_ALL_AND_GO_TO_TAB_MYVAULT_MESSAGE ||
message.Command == POP_ALL_AND_GO_TO_TAB_SEND_MESSAGE ||
message.Command == POP_ALL_AND_GO_TO_AUTOFILL_CIPHERS_MESSAGE ||
message.Command == DeepLinkContext.NEW_OTP_MESSAGE)
{
if (message.Command == DeepLinkContext.NEW_OTP_MESSAGE)
{
Options.OtpData = new OtpData((string)message.Data);
}
MainThread.InvokeOnMainThreadAsync(async () => Bootstrap();
}
private async void BroadcastServiceMessageCallbackAsync(Message message)
{
try
{
ArgumentNullException.ThrowIfNull(message);
if (message.Command == "showDialog")
{
var details = message.Data as DialogDetails;
ArgumentNullException.ThrowIfNull(details);
ArgumentNullException.ThrowIfNull(MainPage);
var confirmed = true;
var confirmText = string.IsNullOrWhiteSpace(details.ConfirmText) ?
AppResources.Ok : details.ConfirmText;
await MainThread.InvokeOnMainThreadAsync(ShowDialogAction);
async Task ShowDialogAction()
{
if (!string.IsNullOrWhiteSpace(details.CancelText))
{ {
if (MainPage is TabsPage tabsPage) confirmed = await MainPage.DisplayAlert(details.Title, details.Text, confirmText,
details.CancelText);
}
else
{
await MainPage.DisplayAlert(details.Title, details.Text, confirmText);
}
_messagingService.Send("showDialogResolve", new Tuple<int, bool>(details.DialogId, confirmed));
}
}
#if IOS
else if (message.Command == AppHelpers.RESUMED_MESSAGE_COMMAND)
{
ResumedAsync().FireAndForget();
}
else if (message.Command == "slept")
{
await SleptAsync();
}
#endif
else if (message.Command == "migrated")
{
await Task.Delay(1000);
await _accountsManager.NavigateOnAccountChangeAsync();
}
else if (message.Command == POP_ALL_AND_GO_TO_TAB_GENERATOR_MESSAGE ||
message.Command == POP_ALL_AND_GO_TO_TAB_MYVAULT_MESSAGE ||
message.Command == POP_ALL_AND_GO_TO_TAB_SEND_MESSAGE ||
message.Command == POP_ALL_AND_GO_TO_AUTOFILL_CIPHERS_MESSAGE ||
message.Command == DeepLinkContext.NEW_OTP_MESSAGE)
{
if (message.Command == DeepLinkContext.NEW_OTP_MESSAGE)
{
Options.OtpData = new OtpData((string)message.Data);
}
await MainThread.InvokeOnMainThreadAsync(ExecuteNavigationAction);
async Task ExecuteNavigationAction()
{
if (MainPage is TabsPage tabsPage)
{
ArgumentNullException.ThrowIfNull(tabsPage.Navigation);
ArgumentNullException.ThrowIfNull(tabsPage.Navigation.ModalStack);
while (tabsPage.Navigation.ModalStack.Count > 0)
{ {
while (tabsPage.Navigation.ModalStack.Count > 0) await tabsPage.Navigation.PopModalAsync(false);
{ }
await tabsPage.Navigation.PopModalAsync(false); if (message.Command == POP_ALL_AND_GO_TO_AUTOFILL_CIPHERS_MESSAGE)
} {
if (message.Command == POP_ALL_AND_GO_TO_AUTOFILL_CIPHERS_MESSAGE) MainPage = new NavigationPage(new CipherSelectionPage(Options));
{ }
MainPage = new NavigationPage(new CipherSelectionPage(Options)); else if (message.Command == POP_ALL_AND_GO_TO_TAB_MYVAULT_MESSAGE)
} {
else if (message.Command == POP_ALL_AND_GO_TO_TAB_MYVAULT_MESSAGE) Options.MyVaultTile = false;
{ tabsPage.ResetToVaultPage();
Options.MyVaultTile = false; }
tabsPage.ResetToVaultPage(); else if (message.Command == POP_ALL_AND_GO_TO_TAB_GENERATOR_MESSAGE)
} {
else if (message.Command == POP_ALL_AND_GO_TO_TAB_GENERATOR_MESSAGE) Options.GeneratorTile = false;
{ tabsPage.ResetToGeneratorPage();
Options.GeneratorTile = false; }
tabsPage.ResetToGeneratorPage(); else if (message.Command == POP_ALL_AND_GO_TO_TAB_SEND_MESSAGE)
} {
else if (message.Command == POP_ALL_AND_GO_TO_TAB_SEND_MESSAGE) tabsPage.ResetToSendPage();
{ }
tabsPage.ResetToSendPage(); else if (message.Command == DeepLinkContext.NEW_OTP_MESSAGE)
} {
else if (message.Command == DeepLinkContext.NEW_OTP_MESSAGE) tabsPage.ResetToVaultPage();
{ ArgumentNullException.ThrowIfNull(tabsPage.Navigation);
tabsPage.ResetToVaultPage(); await tabsPage.Navigation.PushModalAsync(new NavigationPage(new CipherSelectionPage(Options)));
await tabsPage.Navigation.PushModalAsync(new NavigationPage(new CipherSelectionPage(Options)));
}
} }
});
}
else if (message.Command == "convertAccountToKeyConnector")
{
MainThread.BeginInvokeOnMainThread(async () =>
{
await MainPage.Navigation.PushModalAsync(
new NavigationPage(new RemoveMasterPasswordPage()));
});
}
else if (message.Command == Constants.ForceUpdatePassword)
{
MainThread.BeginInvokeOnMainThread(async () =>
{
await MainPage.Navigation.PushModalAsync(
new NavigationPage(new UpdateTempPasswordPage()));
});
}
else if (message.Command == Constants.ForceSetPassword)
{
await MainThread.InvokeOnMainThreadAsync(() => MainPage.Navigation.PushModalAsync(
new NavigationPage(new SetPasswordPage(orgIdentifier: (string)message.Data))));
}
else if (message.Command == "syncCompleted")
{
await _configService.GetAsync(true);
}
else if (message.Command == Constants.PasswordlessLoginRequestKey
|| message.Command == "unlocked"
|| message.Command == AccountsManagerMessageCommands.ACCOUNT_SWITCH_COMPLETED)
{
lock (_processingLoginRequestLock)
{
// lock doesn't allow for async execution
CheckPasswordlessLoginRequestsAsync().Wait();
} }
} }
} }
catch (Exception ex) else if (message.Command == "convertAccountToKeyConnector")
{ {
LoggerHelper.LogEvenIfCantBeResolved(ex); ArgumentNullException.ThrowIfNull(MainPage);
await MainThread.InvokeOnMainThreadAsync(NavigateToRemoveMasterPasswordPageAction);
async Task NavigateToRemoveMasterPasswordPageAction()
{
await MainPage.Navigation.PushModalAsync(
new NavigationPage(new RemoveMasterPasswordPage()));
}
} }
}); else if (message.Command == Constants.ForceUpdatePassword)
{
ArgumentNullException.ThrowIfNull(MainPage);
await MainThread.InvokeOnMainThreadAsync(NavigateToUpdateTempPasswordPageAction);
async Task NavigateToUpdateTempPasswordPageAction()
{
await MainPage.Navigation.PushModalAsync(
new NavigationPage(new UpdateTempPasswordPage()));
}
}
else if (message.Command == Constants.ForceSetPassword)
{
ArgumentNullException.ThrowIfNull(MainPage);
await MainThread.InvokeOnMainThreadAsync(NavigateToSetPasswordPageAction);
void NavigateToSetPasswordPageAction()
{
MainPage.Navigation.PushModalAsync(
new NavigationPage(new SetPasswordPage(orgIdentifier: (string)message.Data)));
}
}
else if (message.Command == "syncCompleted")
{
await _configService.GetAsync(true);
}
else if (message.Command == Constants.PasswordlessLoginRequestKey
|| message.Command == "unlocked"
|| message.Command == AccountsManagerMessageCommands.ACCOUNT_SWITCH_COMPLETED)
{
lock (_processingLoginRequestLock)
{
// lock doesn't allow for async execution
CheckPasswordlessLoginRequestsAsync().Wait();
}
}
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
private async Task CheckPasswordlessLoginRequestsAsync() private async Task CheckPasswordlessLoginRequestsAsync()
@@ -214,7 +329,6 @@ namespace Bit.App
{ {
return; return;
} }
var notification = await _stateService.GetPasswordlessLoginNotificationAsync(); var notification = await _stateService.GetPasswordlessLoginNotificationAsync();
if (notification == null) if (notification == null)
{ {
@@ -285,40 +399,52 @@ namespace Bit.App
protected override async void OnStart() protected override async void OnStart()
{ {
System.Diagnostics.Debug.WriteLine("XF App: OnStart"); try
_isResumed = true;
await ClearCacheIfNeededAsync();
Prime();
if (string.IsNullOrWhiteSpace(Options.Uri))
{ {
var updated = await AppHelpers.PerformUpdateTasksAsync(_syncService, _deviceActionService, System.Diagnostics.Debug.WriteLine("XF App: OnStart");
_stateService); _isResumed = true;
if (!updated) await ClearCacheIfNeededAsync();
Prime();
if (string.IsNullOrWhiteSpace(Options.Uri))
{ {
SyncIfNeeded(); var updated = await AppHelpers.PerformUpdateTasksAsync(_syncService, _deviceActionService,
_stateService);
if (!updated)
{
SyncIfNeeded();
}
} }
} if (_pendingCheckPasswordlessLoginRequests)
if (_pendingCheckPasswordlessLoginRequests) {
{ _messagingService.Send(Constants.PasswordlessLoginRequestKey);
_messagingService.Send(Constants.PasswordlessLoginRequestKey); }
} #if ANDROID
if (DeviceInfo.Platform == DevicePlatform.Android)
{
await _vaultTimeoutService.CheckVaultTimeoutAsync(); await _vaultTimeoutService.CheckVaultTimeoutAsync();
// Reset delay on every start // Reset delay on every start
_vaultTimeoutService.DelayLockAndLogoutMs = null; _vaultTimeoutService.DelayLockAndLogoutMs = null;
} #endif
await _configService.GetAsync(); await _configService.GetAsync();
_messagingService.Send("startEventTimer"); _messagingService.Send("startEventTimer");
}
catch (Exception ex)
{
_logger?.Exception(ex);
throw;
}
} }
#if ANDROID
protected override async void OnSleep() protected override async void OnSleep()
#else
protected override void OnSleep()
#endif
{ {
System.Diagnostics.Debug.WriteLine("XF App: OnSleep"); try
_isResumed = false;
if (DeviceInfo.Platform == DevicePlatform.Android)
{ {
System.Diagnostics.Debug.WriteLine("XF App: OnSleep");
_isResumed = false;
#if ANDROID
var isLocked = await _vaultTimeoutService.IsLockedAsync(); var isLocked = await _vaultTimeoutService.IsLockedAsync();
if (!isLocked) if (!isLocked)
{ {
@@ -329,20 +455,34 @@ namespace Bit.App
ClearAutofillUri(); ClearAutofillUri();
} }
await SleptAsync(); await SleptAsync();
#endif
}
catch (Exception ex)
{
_logger?.Exception(ex);
throw;
} }
} }
protected override void OnResume() protected override void OnResume()
{ {
System.Diagnostics.Debug.WriteLine("XF App: OnResume"); try
_isResumed = true;
if (_pendingCheckPasswordlessLoginRequests)
{
_messagingService.Send(Constants.PasswordlessLoginRequestKey);
}
if (DeviceInfo.Platform == DevicePlatform.Android)
{ {
System.Diagnostics.Debug.WriteLine("XF App: OnResume");
_isResumed = true;
if (_pendingCheckPasswordlessLoginRequests)
{
_messagingService.Send(Constants.PasswordlessLoginRequestKey);
}
#if ANDROID
ResumedAsync().FireAndForget(); ResumedAsync().FireAndForget();
#endif
}
catch (Exception ex)
{
_logger?.Exception(ex);
throw;
} }
} }
@@ -429,14 +569,22 @@ namespace Bit.App
{ {
MainThread.BeginInvokeOnMainThread(() => MainThread.BeginInvokeOnMainThread(() =>
{ {
Options.Uri = null; try
if (isLocked)
{ {
MainPage = new NavigationPage(new LockPage()); Options.Uri = null;
if (isLocked)
{
App.MainPage = new NavigationPage(new LockPage());
}
else
{
App.MainPage = new TabsPage();
}
} }
else catch (Exception ex)
{ {
MainPage = new TabsPage(); LoggerHelper.LogEvenIfCantBeResolved(ex);
throw;
} }
}); });
}); });
@@ -461,9 +609,13 @@ namespace Bit.App
ThemeManager.SetTheme(Resources); ThemeManager.SetTheme(Resources);
RequestedThemeChanged += (s, a) => RequestedThemeChanged += (s, a) =>
{ {
UpdateThemeAsync(); UpdateThemeAsync().FireAndForget();
}; };
MainPage = new NavigationPage(new HomePage(Options)); _isResumed = true;
#if IOS
//We only set the MainPage here for iOS. Android is using the CreateWindow override for the initial page.
App.MainPage = new NavigationPage(new HomePage(Options));
#endif
_accountsManager.NavigateOnAccountChangeAsync().FireAndForget(); _accountsManager.NavigateOnAccountChangeAsync().FireAndForget();
ServiceContainer.Resolve<MobilePlatformUtilsService>("platformUtilsService").Init(); ServiceContainer.Resolve<MobilePlatformUtilsService>("platformUtilsService").Init();
} }
@@ -476,11 +628,18 @@ namespace Bit.App
} }
Task.Run(async () => Task.Run(async () =>
{ {
var lastSync = await _syncService.GetLastSyncAsync(); try
if (lastSync == null || ((DateTime.UtcNow - lastSync) > TimeSpan.FromMinutes(30)))
{ {
await Task.Delay(1000); var lastSync = await _syncService.GetLastSyncAsync();
await _syncService.FullSyncAsync(false); if (lastSync == null || ((DateTime.UtcNow - lastSync) > TimeSpan.FromMinutes(30)))
{
await Task.Delay(1000);
await _syncService.FullSyncAsync(false);
}
}
catch (Exception ex)
{
_logger.Exception(ex);
} }
}); });
} }
@@ -535,36 +694,36 @@ namespace Bit.App
switch (navTarget) switch (navTarget)
{ {
case NavigationTarget.HomeLogin: case NavigationTarget.HomeLogin:
MainPage = new NavigationPage(new HomePage(Options)); App.MainPage = new NavigationPage(new HomePage(Options));
break; break;
case NavigationTarget.Login: case NavigationTarget.Login:
if (navParams is LoginNavigationParams loginParams) if (navParams is LoginNavigationParams loginParams)
{ {
MainPage = new NavigationPage(new LoginPage(loginParams.Email, Options)); App.MainPage = new NavigationPage(new LoginPage(loginParams.Email, Options));
} }
break; break;
case NavigationTarget.Lock: case NavigationTarget.Lock:
if (navParams is LockNavigationParams lockParams) if (navParams is LockNavigationParams lockParams)
{ {
MainPage = new NavigationPage(new LockPage(Options, lockParams.AutoPromptBiometric)); App.MainPage = new NavigationPage(new LockPage(Options, lockParams.AutoPromptBiometric));
} }
else else
{ {
MainPage = new NavigationPage(new LockPage(Options)); App.MainPage = new NavigationPage(new LockPage(Options));
} }
break; break;
case NavigationTarget.Home: case NavigationTarget.Home:
MainPage = new TabsPage(Options); App.MainPage = new TabsPage(Options);
break; break;
case NavigationTarget.AddEditCipher: case NavigationTarget.AddEditCipher:
MainPage = new NavigationPage(new CipherAddEditPage(appOptions: Options)); App.MainPage = new NavigationPage(new CipherAddEditPage(appOptions: Options));
break; break;
case NavigationTarget.AutofillCiphers: case NavigationTarget.AutofillCiphers:
case NavigationTarget.OtpCipherSelection: case NavigationTarget.OtpCipherSelection:
MainPage = new NavigationPage(new CipherSelectionPage(Options)); App.MainPage = new NavigationPage(new CipherSelectionPage(Options));
break; break;
case NavigationTarget.SendAddEdit: case NavigationTarget.SendAddEdit:
MainPage = new NavigationPage(new SendAddEditPage(Options)); App.MainPage = new NavigationPage(new SendAddEditPage(Options));
break; break;
} }
} }

View File

@@ -47,6 +47,7 @@ namespace Bit.Core
public const string ConfigsKey = "configsKey"; public const string ConfigsKey = "configsKey";
public const string DisplayEuEnvironmentFlag = "display-eu-environment"; public const string DisplayEuEnvironmentFlag = "display-eu-environment";
public const string RegionEnvironment = "regionEnvironment"; public const string RegionEnvironment = "regionEnvironment";
public const string DuoCallback = "bitwarden://duo-callback";
/// <summary> /// <summary>
/// This key is used to store the value of "ShouldConnectToWatch" of the last user that had logged in /// This key is used to store the value of "ShouldConnectToWatch" of the last user that had logged in
@@ -70,10 +71,11 @@ namespace Bit.Core
public const int Argon2Parallelism = 4; public const int Argon2Parallelism = 4;
public const int MasterPasswordMinimumChars = 12; public const int MasterPasswordMinimumChars = 12;
public const int CipherKeyRandomBytesLength = 64; public const int CipherKeyRandomBytesLength = 64;
public const string CipherKeyEncryptionMinServerVersion = "2023.9.1"; public const string CipherKeyEncryptionMinServerVersion = "2024.2.0";
public const string DefaultFido2CredentialType = "public-key"; public const string DefaultFido2CredentialType = "public-key";
public const string DefaultFido2CredentialAlgorithm = "ECDSA"; public const string DefaultFido2CredentialAlgorithm = "ECDSA";
public const string DefaultFido2CredentialCurve = "P-256"; public const string DefaultFido2CredentialCurve = "P-256";
public const int LatestStateVersion = 7;
public static readonly string[] AndroidAllClearCipherCacheKeys = public static readonly string[] AndroidAllClearCipherCacheKeys =
{ {

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