Add Share app Extension on iOS for Send (re-PR) (#1660)

* WIP Add Share app extension on iOS for Send

* Added Share app extension on iOS for Send and some code fixes as well

* Updated iOS csprojs configs to linkskip the new extension project and also added AdHoc and AppStore configurations to iOS.ShareExtension.csproj

* Code clean up and transformed bundle resources into links to the already used pngs of the main iOS project on ShareExtension

* Updated build.yml to include provisioning profile for iOS Share extension

* Adding in the missing provisioning profile

* Removed .DS_Store from the iOS.ShareExtension csproj Resources

* switching out the share extension profile

* Added Share extension provisioning profile configuration on export options app store for github and also removed custom info.plist config for localhost which is not necessary

* Moved property so that it's grouped with the full ones

* Added AppCenter Crashes package to Core and updated FireAndForget Task Extension

* Updated bundle reference of FontAwesome.ttf to bwi-font.ttf in order for it to compile on ShareExtension

Co-authored-by: Joseph Flinn <joseph.s.flinn@gmail.com>
Co-authored-by: Álison Fernandes <vvolkgang@users.noreply.github.com>
This commit is contained in:
Federico Maccaroni 2022-01-25 17:41:56 -03:00 committed by GitHub
parent ef6184a05b
commit f8a7eb4c94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 1361 additions and 130 deletions

View File

@ -12,6 +12,8 @@
<string>Dist: Autofill 2021</string>
<key>com.8bit.bitwarden.find-login-action-extension</key>
<string>Dist: Extension 2021</string>
<key>com.8bit.bitwarden.share-extension</key>
<string>Dist: Share Extension 2021</string>
</dict>
</dict>
</plist>

Binary file not shown.

View File

@ -382,6 +382,8 @@ jobs:
--output $HOME/secrets/dist_bitwarden.mobileprovision ./.github/secrets/dist_bitwarden.mobileprovision.gpg
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output $HOME/secrets/dist_extension.mobileprovision ./.github/secrets/dist_extension.mobileprovision.gpg
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output $HOME/secrets/dist_share_extension.mobileprovision ./.github/secrets/dist_share_extension.mobileprovision.gpg
shell: bash
- name: Increment version
@ -395,6 +397,7 @@ jobs:
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS/Info.plist
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Extension/Info.plist
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Autofill/Info.plist
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.ShareExtension/Info.plist
shell: bash
- name: Update Entitlements
@ -428,6 +431,7 @@ jobs:
AUTOFILL_PROFILE_PATH=$HOME/secrets/dist_autofill.mobileprovision
BITWARDEN_PROFILE_PATH=$HOME/secrets/dist_bitwarden.mobileprovision
EXTENSION_PROFILE_PATH=$HOME/secrets/dist_extension.mobileprovision
SHARE_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_share_extension.mobileprovision
PROFILES_DIR_PATH=$HOME/Library/MobileDevice/Provisioning\ Profiles
mkdir -p "$PROFILES_DIR_PATH"
@ -440,6 +444,9 @@ jobs:
EXTENSION_UUID=$(grep UUID -A1 -a $EXTENSION_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
cp $EXTENSION_PROFILE_PATH "$PROFILES_DIR_PATH/$EXTENSION_UUID.mobileprovision"
SHARE_EXTENSION_UUID=$(grep UUID -A1 -a $SHARE_EXTENSION_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
cp $SHARE_EXTENSION_PROFILE_PATH "$PROFILES_DIR_PATH/$SHARE_EXTENSION_UUID.mobileprovision"
shell: bash
- name: Restore packages

View File

@ -38,12 +38,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS", "src\iOS\iOS.csproj",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.Extension", "src\iOS.Extension\iOS.Extension.csproj", "{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.Autofill", "src\iOS.Autofill\iOS.Autofill.csproj", "{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "test\Common\Common.csproj", "{4085B0A5-12A9-4993-B8B8-4ACE72E62E39}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.Test", "test\Core.Test\Core.Test.csproj", "{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.ShareExtension", "src\iOS.ShareExtension\iOS.ShareExtension.csproj", "{F8C3F648-EA5A-4719-8005-85D1690B1655}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.Autofill", "src\iOS.Autofill\iOS.Autofill.csproj", "{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
@ -325,35 +327,6 @@ Global
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|iPhone.Build.0 = Release|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|Any CPU.Build.0 = Ad-Hoc|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|Any CPU.ActiveCfg = AppStore|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|Any CPU.Build.0 = AppStore|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|iPhone.Build.0 = AppStore|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|Any CPU.ActiveCfg = Debug|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhone.ActiveCfg = Debug|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhone.Build.0 = Debug|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhone.Deploy.0 = Debug|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|Any CPU.ActiveCfg = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|Any CPU.Build.0 = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|iPhone.ActiveCfg = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|iPhone.Build.0 = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|Any CPU.ActiveCfg = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|iPhone.ActiveCfg = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|iPhone.Build.0 = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{4085B0A5-12A9-4993-B8B8-4ACE72E62E39}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
@ -414,6 +387,65 @@ Global
{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Release|iPhone.Build.0 = Release|Any CPU
{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|Any CPU.ActiveCfg = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|Any CPU.Build.0 = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|iPhone.ActiveCfg = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|iPhone.Build.0 = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.AppStore|Any CPU.ActiveCfg = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.AppStore|Any CPU.Build.0 = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.AppStore|iPhone.ActiveCfg = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.AppStore|iPhone.Build.0 = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.AppStore|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.AppStore|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|iPhone.ActiveCfg = Debug|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|iPhone.Build.0 = Debug|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.FDroid|Any CPU.ActiveCfg = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.FDroid|Any CPU.Build.0 = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.FDroid|iPhone.ActiveCfg = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.FDroid|iPhone.Build.0 = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.FDroid|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.FDroid|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|Any CPU.ActiveCfg = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|Any CPU.Build.0 = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|iPhone.ActiveCfg = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|iPhone.Build.0 = Release|iPhone
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{F8C3F648-EA5A-4719-8005-85D1690B1655}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|Any CPU.Build.0 = Ad-Hoc|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|Any CPU.ActiveCfg = AppStore|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|Any CPU.Build.0 = AppStore|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|iPhone.Build.0 = AppStore|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|Any CPU.ActiveCfg = Debug|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhone.ActiveCfg = Debug|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhone.Build.0 = Debug|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhone.Deploy.0 = Debug|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|Any CPU.ActiveCfg = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|Any CPU.Build.0 = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|iPhone.ActiveCfg = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|iPhone.Build.0 = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|Any CPU.ActiveCfg = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|iPhone.ActiveCfg = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|iPhone.Build.0 = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -428,9 +460,10 @@ Global
{E71F3053-056C-4381-9638-048ED73BDFF6} = {D10CA4A9-F866-40E1-B658-F69051236C71}
{599E0201-420A-4C3E-A7BA-5349F72E0B15} = {D10CA4A9-F866-40E1-B658-F69051236C71}
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545} = {D10CA4A9-F866-40E1-B658-F69051236C71}
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A} = {D10CA4A9-F866-40E1-B658-F69051236C71}
{4085B0A5-12A9-4993-B8B8-4ACE72E62E39} = {8904C536-C67D-420F-9971-51B26574C3AA}
{8AE548D9-A567-4E97-995E-93EC7DB0FDE0} = {8904C536-C67D-420F-9971-51B26574C3AA}
{F8C3F648-EA5A-4719-8005-85D1690B1655} = {D10CA4A9-F866-40E1-B658-F69051236C71}
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A} = {D10CA4A9-F866-40E1-B658-F69051236C71}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7D436EA3-8B7E-45D2-8D14-0730BD2E0410}

View File

@ -21,6 +21,7 @@ namespace Bit.App.Models
public string SaveCardCode { get; set; }
public bool IosExtension { get; set; }
public Tuple<SendType, string, byte[], string> CreateSend { get; set; }
public bool CopyInsteadOfShareAfterSaving { get; set; }
public void SetAllFrom(AppOptions o)
{
@ -44,6 +45,7 @@ namespace Bit.App.Models
SaveCardCode = o.SaveCardCode;
IosExtension = o.IosExtension;
CreateSend = o.CreateSend;
CopyInsteadOfShareAfterSaving = o.CopyInsteadOfShareAfterSaving;
}
}
}

View File

@ -235,9 +235,10 @@
Margin="10,0,0,0" />
</StackLayout>
</StackLayout>
<StackLayout StyleClass="box-row, box-row-switch">
<StackLayout
StyleClass="box-row, box-row-switch">
<Label
Text="{u:I18n ShareOnSave}"
Text="{Binding ShareOnSaveText}"
StyleClass="box-label-regular"
VerticalOptions="Center"
HorizontalOptions="StartAndExpand" />

View File

@ -7,6 +7,9 @@ using Bit.App.Utilities;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Utilities;
#if !FDROID
using Microsoft.AppCenter.Crashes;
#endif
using Xamarin.Forms;
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
@ -22,6 +25,9 @@ namespace Bit.App.Pages
private AppOptions _appOptions;
private SendAddEditPageViewModel _vm;
public Action OnClose { get; set; }
public Action AfterSubmit { get; set; }
public SendAddEditPage(
AppOptions appOptions = null,
string sendId = null,
@ -82,42 +88,66 @@ namespace Bit.App.Pages
protected override async void OnAppearing()
{
base.OnAppearing();
if (!await AppHelpers.IsVaultTimeoutImmediateAsync())
try
{
await _vaultTimeoutService.CheckVaultTimeoutAsync();
}
if (await _vaultTimeoutService.IsLockedAsync())
{
return;
}
await _vm.InitAsync();
_broadcasterService.Subscribe(nameof(SendAddEditPage), message =>
{
if (message.Command == "selectFileResult")
if (!await AppHelpers.IsVaultTimeoutImmediateAsync())
{
Device.BeginInvokeOnMainThread(() =>
{
var data = message.Data as Tuple<byte[], string>;
_vm.FileData = data.Item1;
_vm.FileName = data.Item2;
});
await _vaultTimeoutService.CheckVaultTimeoutAsync();
}
});
await LoadOnAppearedAsync(_scrollView, true, async () =>
{
var success = await _vm.LoadAsync();
if (!success)
if (await _vaultTimeoutService.IsLockedAsync())
{
await Navigation.PopModalAsync();
return;
}
await HandleCreateRequest();
if (!_vm.EditMode && string.IsNullOrWhiteSpace(_vm.Send?.Name))
await _vm.InitAsync();
_broadcasterService.Subscribe(nameof(SendAddEditPage), message =>
{
RequestFocus(_nameEntry);
}
AdjustToolbar();
});
if (message.Command == "selectFileResult")
{
Device.BeginInvokeOnMainThread(() =>
{
var data = message.Data as Tuple<byte[], string>;
_vm.FileData = data.Item1;
_vm.FileName = data.Item2;
});
}
});
await LoadOnAppearedAsync(_scrollView, true, async () =>
{
var success = await _vm.LoadAsync();
if (!success)
{
await CloseAsync();
return;
}
await HandleCreateRequest();
if (!_vm.EditMode && string.IsNullOrWhiteSpace(_vm.Send?.Name))
{
RequestFocus(_nameEntry);
}
AdjustToolbar();
});
}
catch (Exception ex)
{
#if !FDROID
Crashes.TrackError(ex);
#endif
await CloseAsync();
}
}
private async Task CloseAsync()
{
if (OnClose is null)
{
await Navigation.PopModalAsync();
}
else
{
OnClose();
}
}
protected override bool OnBackButtonPressed()
@ -200,7 +230,11 @@ namespace Bit.App.Pages
{
if (DoOnce())
{
await _vm.SubmitAsync();
var submitted = await _vm.SubmitAsync();
if (submitted)
{
AfterSubmit?.Invoke();
}
}
}
@ -234,7 +268,7 @@ namespace Bit.App.Pages
{
if (await _vm.DeleteAsync())
{
await Navigation.PopModalAsync();
await CloseAsync();
}
}
}
@ -274,7 +308,7 @@ namespace Bit.App.Pages
{
if (await _vm.DeleteAsync())
{
await Navigation.PopModalAsync();
await CloseAsync();
}
}
}
@ -283,7 +317,7 @@ namespace Bit.App.Pages
{
if (DoOnce())
{
await Navigation.PopModalAsync();
await CloseAsync();
}
}
@ -306,6 +340,7 @@ namespace Bit.App.Pages
}
_vm.IsAddFromShare = true;
_vm.CopyInsteadOfShareAfterSaving = _appOptions.CopyInsteadOfShareAfterSaving;
var name = _appOptions.CreateSend.Item2;
_vm.Send.Name = name;

View File

@ -10,6 +10,9 @@ using Bit.Core.Enums;
using Bit.Core.Exceptions;
using Bit.Core.Models.View;
using Bit.Core.Utilities;
#if !FDROID
using Microsoft.AppCenter.Crashes;
#endif
using Xamarin.Essentials;
using Xamarin.Forms;
@ -46,6 +49,7 @@ namespace Bit.App.Pages
};
private bool _disableHideEmail;
private bool _sendOptionsPolicyInEffect;
private bool _copyInsteadOfShareAfterSaving;
public SendAddEditPageViewModel()
{
@ -97,6 +101,7 @@ namespace Bit.App.Pages
public bool ShareOnSave { get; set; }
public bool DisableHideEmailControl { get; set; }
public bool IsAddFromShare { get; set; }
public string ShareOnSaveText => CopyInsteadOfShareAfterSaving ? AppResources.CopySendLinkOnSave : AppResources.ShareOnSave;
public List<KeyValuePair<string, SendType>> TypeOptions { get; }
public List<KeyValuePair<string, string>> DeletionTypeOptions { get; }
public List<KeyValuePair<string, string>> ExpirationTypeOptions { get; }
@ -175,6 +180,15 @@ namespace Bit.App.Pages
}
}
}
public bool CopyInsteadOfShareAfterSaving
{
get => _copyInsteadOfShareAfterSaving;
set
{
SetProperty(ref _copyInsteadOfShareAfterSaving, value);
TriggerPropertyChanged(nameof(ShareOnSaveText));
}
}
public SendView Send
{
get => _send;
@ -397,25 +411,36 @@ namespace Bit.App.Pages
EditMode ? AppResources.SendUpdated : AppResources.NewSendCreated);
}
if (IsAddFromShare && Device.RuntimePlatform == Device.Android)
if (!CopyInsteadOfShareAfterSaving)
{
_deviceActionService.CloseMainApp();
await CloseAsync();
}
else
{
await Page.Navigation.PopModalAsync();
}
if (ShareOnSave)
{
var savedSend = await _sendService.GetAsync(sendId);
if (savedSend != null)
{
var savedSendView = await savedSend.DecryptAsync();
await AppHelpers.ShareSendUrlAsync(savedSendView);
if (CopyInsteadOfShareAfterSaving)
{
await AppHelpers.CopySendUrlAsync(savedSendView);
// wait so that the user sees the message before the view gets dismissed
await Task.Delay(1300);
}
else
{
await AppHelpers.ShareSendUrlAsync(savedSendView);
}
}
}
if (CopyInsteadOfShareAfterSaving)
{
await CloseAsync();
}
return true;
}
catch (ApiException e)
@ -427,9 +452,37 @@ namespace Bit.App.Pages
AppResources.AnErrorHasOccurred);
}
}
catch (Exception ex)
{
await _deviceActionService.HideLoadingAsync();
#if !FDROID
Crashes.TrackError(ex);
#endif
await _platformUtilsService.ShowDialogAsync(AppResources.AnErrorHasOccurred);
}
return false;
}
private async Task CloseAsync()
{
if (IsAddFromShare)
{
if (Device.RuntimePlatform == Device.Android)
{
_deviceActionService.CloseMainApp();
return;
}
if (Page is SendAddEditPage sendPage && sendPage.OnClose != null)
{
sendPage.OnClose();
return;
}
}
await Page.Navigation.PopModalAsync();
}
public async Task<bool> RemovePasswordAsync()
{
return await AppHelpers.RemoveSendPasswordAsync(SendId);
@ -455,14 +508,7 @@ namespace Bit.App.Pages
if (!SendEnabled)
{
await _platformUtilsService.ShowDialogAsync(AppResources.SendDisabledWarning);
if (IsAddFromShare && Device.RuntimePlatform == Device.Android)
{
_deviceActionService.CloseMainApp();
}
else
{
await Page.Navigation.PopModalAsync();
}
await CloseAsync();
return;
}
if (Send != null)

View File

@ -3767,6 +3767,12 @@ namespace Bit.App.Resources {
}
}
public static string CopySendLinkOnSave {
get {
return ResourceManager.GetString("CopySendLinkOnSave", resourceCulture);
}
}
public static string SendingCode {
get {
return ResourceManager.GetString("SendingCode", resourceCulture);

View File

@ -2111,12 +2111,18 @@
<data name="InvalidVerificationCode" xml:space="preserve">
<value>Invalid Verification Code.</value>
</data>
<data name="RequestOTP" xml:space="preserve">
<value>Request one-time password</value>
</data>
<data name="SendCode" xml:space="preserve">
<value>Send Code</value>
</data>
<data name="Sending" xml:space="preserve">
<value>Sending</value>
</data>
<data name="CopySendLinkOnSave" xml:space="preserve">
<value>Copy Send link on save</value>
</data>
<data name="SendingCode" xml:space="preserve">
<value>Sending code</value>
</data>

View File

@ -28,6 +28,7 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="PCLCrypto" Version="2.0.147" />
<PackageReference Include="zxcvbn-core" Version="7.0.92" />
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="4.4.0" />
</ItemGroup>
</Project>

View File

@ -64,6 +64,7 @@ namespace Bit.Core.Services {
var response = await _apiService.RenewFileUploadUrlAsync(uploadData.SendResponse.Id, uploadData.SendResponse.File.Id);
return response.Url;
};
await _azureFileUploadService.Upload(uploadData.Url, encryptedFileData, renewalCallback);
break;
default:

View File

@ -219,7 +219,7 @@ namespace Bit.Core.Services
{
response = await LegacyServerSendFileUpload(request, send, encryptedFileData);
}
catch
catch
{
if (response != default){
await _apiService.DeleteSendAsync(response.Id);

View File

@ -0,0 +1,12 @@
using System;
namespace Bit.Core.Utilities
{
public class LazyResolve<T> : Lazy<T>
{
public LazyResolve(string containerKey)
: base(() => ServiceContainer.Resolve<T>(containerKey))
{
}
}
}

View File

@ -0,0 +1,32 @@
using System;
using System.Threading.Tasks;
#if !FDROID
using Microsoft.AppCenter.Crashes;
#endif
namespace Bit.Core.Utilities
{
public static class TaskExtensions
{
/// <summary>
/// Fires a task and ignores any exception.
/// See http://stackoverflow.com/a/22864616/344182
/// </summary>
/// <param name="task">The task to be forgotten.</param>
/// <param name="onException">Action to be called on exception.</param>
public static async void FireAndForget(this Task task, Action<Exception> onException = null)
{
try
{
await task.ConfigureAwait(false);
}
catch (Exception ex)
{
#if !FDROID
Crashes.TrackError(ex);
#endif
onException?.Invoke(ex);
}
}
}
}

View File

@ -41,7 +41,7 @@
<ConsolePause>false</ConsolePause>
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSAutofill --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB</MtouchExtraArgs>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSAutofill --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB --linkskip=BitwardeniOSShareExtension</MtouchExtraArgs>
<OptimizePNGs>true</OptimizePNGs>
<CodesignKey>iPhone Distribution</CodesignKey>
<CodesignProvision>Dist: Autofill</CodesignProvision>
@ -79,7 +79,7 @@
<MtouchLink>Full</MtouchLink>
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
<OptimizePNGs>true</OptimizePNGs>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSAutofill --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB</MtouchExtraArgs>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSAutofill --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB --linkskip=BitwardeniOSShareExtension</MtouchExtraArgs>
<CodesignProvision>Dist: Autofill</CodesignProvision>
</PropertyGroup>
<PropertyGroup Condition=" '$(RunConfiguration)' == 'Default' ">
@ -93,7 +93,7 @@
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSAutofill --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB</MtouchExtraArgs>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSAutofill --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB --linkskip=BitwardeniOSShareExtension</MtouchExtraArgs>
<OptimizePNGs>true</OptimizePNGs>
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
<MtouchLink>Full</MtouchLink>
@ -101,6 +101,7 @@
<CodesignKey>iPhone Distribution</CodesignKey>
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
<CodesignProvision>Dist: Autofill</CodesignProvision>
<MtouchArch>x86_64</MtouchArch>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'AppStore|iPhone'">
<OutputPath>bin\iPhone\AppStore\</OutputPath>
@ -111,7 +112,7 @@
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<MtouchLink>Full</MtouchLink>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSAutofill --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB</MtouchExtraArgs>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSAutofill --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB --linkskip=BitwardeniOSShareExtension</MtouchExtraArgs>
<OptimizePNGs>true</OptimizePNGs>
<MtouchArch>ARM64</MtouchArch>
<MtouchSdkVersion>10.2</MtouchSdkVersion>
@ -127,7 +128,7 @@
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSAutofill --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB</MtouchExtraArgs>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSAutofill --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB --linkskip=BitwardeniOSShareExtension</MtouchExtraArgs>
<OptimizePNGs>true</OptimizePNGs>
<MtouchLink>Full</MtouchLink>
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
@ -135,6 +136,7 @@
<CodesignKey>iPhone Distribution</CodesignKey>
<CodesignProvision>Adhoc: Autofill</CodesignProvision>
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
<MtouchArch>x86_64</MtouchArch>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Ad-Hoc|iPhone'">
<OutputPath>bin\iPhone\Ad-Hoc\</OutputPath>
@ -147,7 +149,7 @@
<MtouchArch>ARM64</MtouchArch>
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
<MtouchLink>Full</MtouchLink>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSAutofill --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB</MtouchExtraArgs>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSAutofill --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB --linkskip=BitwardeniOSShareExtension</MtouchExtraArgs>
<OptimizePNGs>true</OptimizePNGs>
<CodesignKey>iPhone Distribution</CodesignKey>
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>

View File

@ -29,6 +29,7 @@
public const string UTTypeAppExtensionFillBrowserAction = "org.appextension.fill-browser-action";
public const string UTTypeAppExtensionSetup = "com.8bit.bitwarden.extension-setup";
public const string UTTypeAppExtensionUrl = "public.url";
public const string UTTypeAppExtensionImage = "public.image";
public const string AutofillNeedsIdentityReplacementKey = "autofillNeedsIdentityReplacement";
}

View File

@ -111,7 +111,7 @@ namespace Bit.iOS.Core.Utilities
NSRunLoop.Main.BeginInvokeOnMainThread(async () =>
{
var result = await deviceActionService.DisplayAlertAsync(details.Title, details.Text,
details.CancelText, details.ConfirmText);
details.CancelText, confirmText);
var confirmed = result == details.ConfirmText;
messagingService.Send("showDialogResolve", new Tuple<int, bool>(details.DialogId, confirmed));
});

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="64">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19455" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="64">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19454"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@ -14,11 +15,11 @@
<viewControllerLayoutGuide type="bottom" id="41"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="44">
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="808"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" image="logo.png" translatesAutoresizingMaskIntoConstraints="NO" id="1713">
<rect key="frame" x="66" y="316" width="282" height="44"/>
<rect key="frame" x="66" y="352" width="282" height="44"/>
</imageView>
</subviews>
<constraints>
@ -27,11 +28,11 @@
</constraints>
</view>
<connections>
<outlet property="Logo" destination="1713" id="name-outlet-1713"/>
<segue destination="oCZ-GQ-aOK" kind="show" identifier="loginListSegue" id="1679"/>
<segue destination="6855" kind="presentation" identifier="lockPasswordSegue" id="9874"/>
<segue destination="1845" kind="presentation" identifier="newLoginSegue" modalPresentationStyle="fullScreen" modalTransitionStyle="coverVertical" id="10498"/>
<segue destination="10580" kind="presentation" identifier="setupSegue" modalTransitionStyle="coverVertical" id="11089"/>
<outlet property="Logo" destination="1713" id="name-outlet-1713"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="45" userLabel="First Responder" sceneMemberID="firstResponder"/>
@ -43,7 +44,7 @@
<objects>
<navigationController definesPresentationContext="YES" id="64" sceneMemberID="viewController">
<navigationBar key="navigationBar" hidden="YES" contentMode="scaleToFill" translucent="NO" id="67">
<rect key="frame" x="0.0" y="20" width="414" height="50"/>
<rect key="frame" x="0.0" y="44" width="414" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
</navigationBar>
<connections>
@ -60,7 +61,7 @@
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="oCZ-GQ-aOK" sceneMemberID="viewController">
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" translucent="NO" id="8A5-AR-QHS">
<rect key="frame" x="0.0" y="20" width="414" height="50"/>
<rect key="frame" x="0.0" y="44" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
@ -77,7 +78,7 @@
<objects>
<navigationController definesPresentationContext="YES" id="1845" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" translucent="NO" id="1848">
<rect key="frame" x="0.0" y="20" width="414" height="50"/>
<rect key="frame" x="0.0" y="44" width="414" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
</navigationBar>
<connections>
@ -93,8 +94,9 @@
<objects>
<tableViewController id="2087" customClass="LoginAddViewController" sceneMemberID="viewController">
<tableView key="view" opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" allowsSelection="NO" rowHeight="50" sectionHeaderHeight="22" sectionFooterHeight="22" id="2088">
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="808"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.94901960784313721" green="0.94901960784313721" blue="0.96862745098039216" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<sections/>
<connections>
<outlet property="dataSource" destination="2087" id="2089"/>
@ -129,14 +131,14 @@
<objects>
<tableViewController id="2304" customClass="LoginListViewController" sceneMemberID="viewController">
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="2305">
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="808"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" textLabel="3763" detailTextLabel="3764" rowHeight="44" style="IBUITableViewCellStyleSubtitle" id="3761">
<rect key="frame" x="0.0" y="22" width="414" height="44"/>
<rect key="frame" x="0.0" y="44.5" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="3761" id="3762">
<rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="3763">
@ -190,7 +192,7 @@
<objects>
<navigationController definesPresentationContext="YES" id="4574" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" translucent="NO" id="4577">
<rect key="frame" x="0.0" y="20" width="414" height="50"/>
<rect key="frame" x="0.0" y="44" width="414" height="44"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
</navigationBar>
<connections>
@ -210,17 +212,17 @@
<viewControllerLayoutGuide type="bottom" id="4572"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="4930">
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="808"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<containerView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4933">
<rect key="frame" x="0.0" y="160.5" width="414" height="575.5"/>
<rect key="frame" x="0.0" y="90.5" width="414" height="683.5"/>
<connections>
<segue destination="4912" kind="embed" id="6480"/>
</connections>
</containerView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Label" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="4940">
<rect key="frame" x="15" y="105" width="384" height="20.5"/>
<rect key="frame" x="15" y="35" width="384" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="highlightedColor"/>
</label>
@ -265,8 +267,9 @@
<objects>
<tableViewController id="4912" sceneMemberID="viewController">
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="4913">
<rect key="frame" x="0.0" y="0.0" width="414" height="575.5"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="683.5"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.94901960784313721" green="0.94901960784313721" blue="0.96862745098039216" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<connections>
<outlet property="dataSource" destination="4912" id="4914"/>
<outlet property="delegate" destination="4912" id="4915"/>
@ -278,15 +281,11 @@
<point key="canvasLocation" x="4708" y="-194"/>
</scene>
<!--Navigation Controller-->
<!--Verify Fingerprint-->
<!--Verify PIN-->
<!--Navigation Controller-->
<!--Navigation Controller-->
<scene sceneID="6854">
<objects>
<navigationController definesPresentationContext="YES" id="6855" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" translucent="NO" id="6857">
<rect key="frame" x="0.0" y="20" width="414" height="50"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="56"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
</navigationBar>
<connections>
@ -302,8 +301,9 @@
<objects>
<tableViewController id="7413" customClass="LockPasswordViewController" sceneMemberID="viewController">
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="7414">
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="786"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.94901960784313721" green="0.94901960784313721" blue="0.96862745098039216" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<connections>
<outlet property="dataSource" destination="7413" id="7415"/>
<outlet property="delegate" destination="7413" id="7416"/>
@ -341,11 +341,11 @@
<viewControllerLayoutGuide type="bottom" id="10566"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="10575">
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="786"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Extension Activated!" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="11092">
<rect key="frame" x="15" y="100" width="384" height="20.5"/>
<rect key="frame" x="15" y="30" width="384" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="highlightedColor"/>
</label>
@ -394,7 +394,7 @@
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="10580" sceneMemberID="viewController">
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" translucent="NO" id="10583">
<rect key="frame" x="0.0" y="20" width="414" height="50"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="56"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
@ -407,8 +407,11 @@
<point key="canvasLocation" x="362" y="-267"/>
</scene>
</scenes>
<inferredMetricsTieBreakers>
<segue reference="3731"/>
</inferredMetricsTieBreakers>
<resources>
<image name="ext-icon.png" width="90" height="90"/>
<image name="logo.png" width="282" height="44"/>
</resources>
</document>
</document>

View File

@ -41,7 +41,7 @@
<ConsolePause>false</ConsolePause>
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSExtension --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB</MtouchExtraArgs>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSExtension --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB --linkskip=BitwardeniOSShareExtension</MtouchExtraArgs>
<OptimizePNGs>true</OptimizePNGs>
<MtouchSdkVersion>9.3</MtouchSdkVersion>
<CodesignKey>iPhone Distribution</CodesignKey>
@ -76,7 +76,7 @@
<MtouchArch>ARM64</MtouchArch>
<ConsolePause>false</ConsolePause>
<CodesignKey>iPhone Distribution</CodesignKey>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSExtension --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB</MtouchExtraArgs>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSExtension --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB --linkskip=BitwardeniOSShareExtension</MtouchExtraArgs>
<OptimizePNGs>true</OptimizePNGs>
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
<MtouchLink>Full</MtouchLink>
@ -95,7 +95,7 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<MtouchLink>Full</MtouchLink>
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSExtension --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB</MtouchExtraArgs>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSExtension --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB --linkskip=BitwardeniOSShareExtension</MtouchExtraArgs>
<OptimizePNGs>true</OptimizePNGs>
<MtouchSdkVersion>9.3</MtouchSdkVersion>
<CodesignKey>iPhone Distribution</CodesignKey>
@ -110,7 +110,7 @@
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSExtension --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB</MtouchExtraArgs>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSExtension --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB --linkskip=BitwardeniOSShareExtension</MtouchExtraArgs>
<OptimizePNGs>true</OptimizePNGs>
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
<MtouchArch>ARM64</MtouchArch>
@ -128,7 +128,7 @@
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSExtension --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB</MtouchExtraArgs>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSExtension --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB --linkskip=BitwardeniOSShareExtension</MtouchExtraArgs>
<OptimizePNGs>true</OptimizePNGs>
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
<MtouchLink>Full</MtouchLink>
@ -148,7 +148,7 @@
<MtouchArch>ARM64</MtouchArch>
<MtouchLink>Full</MtouchLink>
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSExtension --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB</MtouchExtraArgs>
<MtouchExtraArgs>--http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSExtension --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB --linkskip=BitwardeniOSShareExtension</MtouchExtraArgs>
<OptimizePNGs>true</OptimizePNGs>
<CodesignKey>iPhone Distribution</CodesignKey>
<CodesignProvision>Automatic:AdHoc</CodesignProvision>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.8bit.bitwarden</string>
</array>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)com.8bit.bitwarden</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDisplayName</key>
<string>Bitwarden Share</string>
<key>CFBundleName</key>
<string>Bitwarden Share Extension</string>
<key>CFBundleIdentifier</key>
<string>com.8bit.bitwarden.share-extension</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>2.14.2</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>MinimumOSVersion</key>
<string>10.0</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionMainStoryboard</key>
<string>MainInterface</string>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.share-services</string>
<key>NSExtensionAttributes</key>
<dict>
<key>NSExtensionActivationRule</key>
<dict>
<key>NSExtensionActivationSupportsFileWithMaxCount</key>
<integer>1</integer>
<key>NSExtensionActivationSupportsText</key>
<true/>
<key>NSExtensionActivationSupportsImageWithMaxCount</key>
<integer>1</integer>
</dict>
</dict>
</dict>
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>es</string>
<string>zh-Hans</string>
<string>zh-Hant</string>
<string>pt-PT</string>
<string>pt-BR</string>
<string>sv</string>
<string>sk</string>
<string>it</string>
<string>fi</string>
<string>fr</string>
<string>ro</string>
<string>id</string>
<string>hr</string>
<string>hu</string>
<string>nl</string>
<string>tr</string>
<string>uk</string>
<string>de</string>
<string>dk</string>
<string>cz</string>
<string>nb</string>
<string>ja</string>
<string>et</string>
<string>vi</string>
<string>pl</string>
<string>ko</string>
<string>fa</string>
<string>ru</string>
<string>be</string>
<string>bg</string>
<string>ca</string>
<string>cs</string>
<string>el</string>
<string>th</string>
</array>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UISupportedInterfaceOrientations</key>
<array/>
<key>UIAppFonts</key>
<array>
<string>bwi-font.ttf</string>
<string>MaterialIcons_Regular.ttf</string>
</array>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIRequiredDeviceCapabilities</key>
<dict>
<key>arm64</key>
<true/>
</dict>
<key>ITSAppUsesNonExemptEncryption</key>
<true/>
<key>ITSEncryptionExportComplianceCode</key>
<string>ecf076d3-4824-4d7b-b716-2a9a47d7d296</string>
</dict>
</plist>

View File

@ -0,0 +1,428 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using AuthenticationServices;
using Bit.App.Abstractions;
using Bit.App.Models;
using Bit.App.Pages;
using Bit.App.Utilities;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Utilities;
using Bit.iOS.Core;
using Bit.iOS.Core.Controllers;
using Bit.iOS.Core.Utilities;
using Bit.iOS.Core.Views;
using Bit.iOS.ShareExtension.Models;
using CoreNFC;
using Foundation;
using Microsoft.AppCenter.Crashes;
using MobileCoreServices;
using UIKit;
using Xamarin.Forms;
namespace Bit.iOS.ShareExtension
{
public partial class LoadingViewController : ExtendedUIViewController
{
private Context _context = new Context();
private bool _initedAppCenter;
private NFCNdefReaderSession _nfcSession = null;
private Core.NFCReaderDelegate _nfcDelegate = null;
readonly LazyResolve<IUserService> _userService = new LazyResolve<IUserService>("userService");
readonly LazyResolve<IVaultTimeoutService> _vaultTimeoutService = new LazyResolve<IVaultTimeoutService>("vaultTimeoutService");
readonly LazyResolve<IDeviceActionService> _deviceActionService = new LazyResolve<IDeviceActionService>("deviceActionService");
readonly LazyResolve<IEventService> _eventService = new LazyResolve<IEventService>("eventService");
public LoadingViewController(IntPtr handle)
: base(handle)
{ }
public override void ViewDidLoad()
{
InitApp();
base.ViewDidLoad();
Logo.Image = new UIImage(ThemeHelpers.LightTheme ? "logo.png" : "logo_white.png");
View.BackgroundColor = ThemeHelpers.SplashBackgroundColor;
_context.ExtensionContext = ExtensionContext;
foreach (var item in ExtensionContext.InputItems)
{
var processed = false;
foreach (var itemProvider in item.Attachments)
{
if (itemProvider.HasItemConformingTo(UTType.PlainText))
{
_context.ProviderType = UTType.PlainText;
processed = true;
break;
}
else if (itemProvider.HasItemConformingTo(UTType.Data))
{
_context.ProviderType = UTType.Data;
processed = true;
break;
}
}
if (processed)
{
break;
}
}
}
public override async void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
try
{
if (!await IsAuthed())
{
LaunchHomePage();
return;
}
else if (await IsLocked())
{
PerformSegue("lockPasswordSegue", this);
}
else
{
ContinueOnAsync().FireAndForget();
}
}
catch (Exception ex)
{
Crashes.TrackError(ex);
}
}
public override void PrepareForSegue(UIStoryboardSegue segue, NSObject sender)
{
if (segue.DestinationViewController is UINavigationController navController
&&
navController.TopViewController is LockPasswordViewController passwordViewController)
{
passwordViewController.LoadingController = this;
segue.DestinationViewController.PresentationController.Delegate =
new CustomPresentationControllerDelegate(passwordViewController.DismissModalAction);
}
}
public void DismissLockAndContinue()
{
Debug.WriteLine("BW Log, Dismissing lock controller.");
DismissViewController(false, () => ContinueOnAsync().FireAndForget());
}
private async Task ContinueOnAsync()
{
Tuple<SendType, string, byte[], string> createSend = null;
if (_context.ProviderType == UTType.Data)
{
var (filename, fileBytes) = await LoadDataBytesAsync();
createSend = new Tuple<SendType, string, byte[], string>(SendType.File, filename, fileBytes, null);
}
else if (_context.ProviderType == UTType.PlainText)
{
createSend = new Tuple<SendType, string, byte[], string>(SendType.Text, null, null, LoadText());
}
var appOptions = new AppOptions
{
IosExtension = true,
CreateSend = createSend,
CopyInsteadOfShareAfterSaving = true
};
var sendAddEditPage = new SendAddEditPage(appOptions)
{
OnClose = () => CompleteRequest(),
AfterSubmit = () => CompleteRequest()
};
var app = new App.App(appOptions);
ThemeManager.SetTheme(false, app.Resources);
ThemeManager.ApplyResourcesToPage(sendAddEditPage);
var navigationPage = new NavigationPage(sendAddEditPage);
var sendAddEditController = navigationPage.CreateViewController();
sendAddEditController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
PresentViewController(sendAddEditController, true, null);
}
private async Task<(string, byte[])> LoadDataBytesAsync()
{
var itemProvider = ExtensionContext?.InputItems.FirstOrDefault()?.Attachments?.FirstOrDefault();
if (itemProvider is null || !itemProvider.HasItemConformingTo(UTType.Data))
return default;
var item = await itemProvider.LoadItemAsync(UTType.Data, null);
if (item is NSUrl urlItem)
{
var filename = urlItem?.AbsoluteUrl?.LastPathComponent;
var data = NSData.FromUrl(urlItem);
var stream = NSInputStream.FromData(data);
var bytes = new byte[data.Length];
try
{
stream.Open();
stream.Read(bytes, data.Length);
}
finally
{
stream?.Close();
}
return (filename, bytes);
}
return default;
}
private string LoadText()
{
return ExtensionContext?.InputItems
.FirstOrDefault()
?.AttributedContentText?.Value;
}
public void CompleteRequest()
{
NSRunLoop.Main.BeginInvokeOnMainThread(() =>
{
ServiceContainer.Reset();
ExtensionContext?.CompleteRequest(new NSExtensionItem[0], null);
});
}
private void InitApp()
{
// Init Xamarin Forms
Forms.Init();
if (ServiceContainer.RegisteredServices.Count > 0)
{
ServiceContainer.Reset();
}
iOSCoreHelpers.RegisterLocalServices();
var messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
ServiceContainer.Init(_deviceActionService.Value.DeviceUserAgent,
Bit.Core.Constants.iOSExtensionClearCiphersCacheKey, Bit.Core.Constants.iOSAllClearCipherCacheKeys);
if (!_initedAppCenter)
{
iOSCoreHelpers.RegisterAppCenter();
_initedAppCenter = true;
}
iOSCoreHelpers.Bootstrap();
var app = new App.App(new AppOptions { IosExtension = true });
ThemeManager.SetTheme(false, app.Resources);
iOSCoreHelpers.AppearanceAdjustments();
_nfcDelegate = new NFCReaderDelegate((success, message) =>
messagingService.Send("gotYubiKeyOTP", message));
iOSCoreHelpers.SubscribeBroadcastReceiver(this, _nfcSession, _nfcDelegate);
}
private Task<bool> IsLocked()
{
return _vaultTimeoutService.Value.IsLockedAsync();
}
private Task<bool> IsAuthed()
{
return _userService.Value.IsAuthenticatedAsync();
}
private void LogoutIfAuthed()
{
NSRunLoop.Main.BeginInvokeOnMainThread(async () =>