integrating ios extension with onepassword-app-extension

This commit is contained in:
Kyle Spearrin 2016-05-30 03:08:12 -04:00
parent 48db0e8d13
commit 72c1a987c9
4 changed files with 109 additions and 43 deletions

View file

@ -17,6 +17,14 @@ namespace Bit.iOS.Extension
{ {
public partial class ActionViewController : UIViewController public partial class ActionViewController : UIViewController
{ {
private const string AppExtensionVersionNumberKey = "version_number";
private const string AppExtensionUrlStringKey = "url_string";
private const string UTTypeAppExtensionFindLoginAction = "org.appextension.find-login-action";
private const string UTTypeAppExtensionSaveLoginAction = "org.appextension.save-login-action";
private const string UTTypeAppExtensionChangePasswordAction = "org.appextension.change-password-action";
private const string UTTypeAppExtensionFillWebViewAction = "org.appextension.fill-webview-action";
private const string UTTypeAppExtensionFillBrowserAction = "org.appextension.fill-browser-action";
public ActionViewController() : base("ActionViewController", null) public ActionViewController() : base("ActionViewController", null)
{ {
if(!Resolver.IsSet) if(!Resolver.IsSet)
@ -50,11 +58,11 @@ namespace Bit.iOS.Extension
.RegisterType<ISiteRepository, SiteRepository>(new ContainerControlledLifetimeManager()) .RegisterType<ISiteRepository, SiteRepository>(new ContainerControlledLifetimeManager())
.RegisterType<ISiteApiRepository, SiteApiRepository>(new ContainerControlledLifetimeManager()) .RegisterType<ISiteApiRepository, SiteApiRepository>(new ContainerControlledLifetimeManager())
.RegisterType<IAuthApiRepository, AuthApiRepository>(new ContainerControlledLifetimeManager()); .RegisterType<IAuthApiRepository, AuthApiRepository>(new ContainerControlledLifetimeManager());
// Other // Other
//.RegisterInstance(CrossSettings.Current, new ContainerControlledLifetimeManager()) //.RegisterInstance(CrossSettings.Current, new ContainerControlledLifetimeManager())
//.RegisterInstance(CrossConnectivity.Current, new ContainerControlledLifetimeManager()) //.RegisterInstance(CrossConnectivity.Current, new ContainerControlledLifetimeManager())
//.RegisterInstance(UserDialogs.Instance, new ContainerControlledLifetimeManager()) //.RegisterInstance(UserDialogs.Instance, new ContainerControlledLifetimeManager())
//.RegisterInstance(CrossFingerprint.Current, new ContainerControlledLifetimeManager()); //.RegisterInstance(CrossFingerprint.Current, new ContainerControlledLifetimeManager());
Resolver.SetResolver(new UnityResolver(container)); Resolver.SetResolver(new UnityResolver(container));
} }
@ -97,34 +105,73 @@ namespace Bit.iOS.Extension
{ {
foreach(var itemProvider in item.Attachments) foreach(var itemProvider in item.Attachments)
{ {
if(!itemProvider.HasItemConformingTo(UTType.PropertyList)) if(ProcessWebUrlProvider(itemProvider))
{ {
continue; break;
} }
else if(ProcessFindLoginProvider(itemProvider))
itemProvider.LoadItem(UTType.PropertyList, null, (NSObject list, NSError error) =>
{ {
if(list == null) break;
{ }
return;
}
var dict = list as NSDictionary;
var result = dict[NSJavaScriptExtension.PreprocessingResultsKey];
if(result == null)
{
return;
}
HtmlContent = result.ValueForKey(new NSString("htmlContent")) as NSString;
BaseUri = new Uri(result.ValueForKey(new NSString("baseUri")) as NSString);
Url = new Uri(result.ValueForKey(new NSString("url")) as NSString);
});
break;
} }
} }
} }
private bool ProcessWebUrlProvider(NSItemProvider itemProvider)
{
if(!itemProvider.HasItemConformingTo(UTType.PropertyList))
{
return false;
}
itemProvider.LoadItem(UTType.PropertyList, null, (NSObject list, NSError error) =>
{
if(list == null)
{
return;
}
var dict = list as NSDictionary;
var result = dict[NSJavaScriptExtension.PreprocessingResultsKey];
if(result == null)
{
return;
}
HtmlContent = result.ValueForKey(new NSString("htmlContent")) as NSString;
BaseUri = new Uri(result.ValueForKey(new NSString("baseUri")) as NSString);
Url = new Uri(result.ValueForKey(new NSString("url")) as NSString);
});
return true;
}
private bool ProcessFindLoginProvider(NSItemProvider itemProvider)
{
if(!itemProvider.HasItemConformingTo(UTTypeAppExtensionFindLoginAction))
{
return false;
}
itemProvider.LoadItem(UTTypeAppExtensionFindLoginAction, null, (NSObject list, NSError error) =>
{
if(list == null)
{
return;
}
var dict = list as NSDictionary;
var version = dict[AppExtensionVersionNumberKey] as NSNumber;
var url = dict[AppExtensionUrlStringKey] as NSString;
if(url == null)
{
return;
}
Url = new Uri(url);
});
return true;
}
} }
} }

View file

@ -29,18 +29,20 @@
<key>NSExtensionJavaScriptPreprocessingFile</key> <key>NSExtensionJavaScriptPreprocessingFile</key>
<string>extension</string> <string>extension</string>
<key>NSExtensionActivationRule</key> <key>NSExtensionActivationRule</key>
<dict> <string>SUBQUERY (
<key>NSExtensionActivationSupportsFileWithMaxCount</key> extensionItems,
<integer>0</integer> $extensionItem,
<key>NSExtensionActivationSupportsImageWithMaxCount</key> SUBQUERY (
<integer>0</integer> $extensionItem.attachments,
<key>NSExtensionActivationSupportsMovieWithMaxCount</key> $attachment,
<integer>0</integer> ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.url"
<key>NSExtensionActivationSupportsText</key> || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "org.appextension.find-login-action"
<false/> || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "org.appextension.save-login-action"
<key>NSExtensionActivationSupportsWebURLWithMaxCount</key> || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "org.appextension.change-password-action"
<integer>1</integer> || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "org.appextension.fill-webview-action"
</dict> || ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "org.appextension.fill-browser-action"
).@count == $extensionItem.attachments.@count
).@count == 1</string>
<key>NSExtensionPointName</key> <key>NSExtensionPointName</key>
<string>com.apple.ui-services</string> <string>com.apple.ui-services</string>
<key>NSExtensionPointVersion</key> <key>NSExtensionPointVersion</key>

View file

@ -107,6 +107,11 @@ namespace Bit.iOS
Debug.WriteLine("WillEnterForeground"); Debug.WriteLine("WillEnterForeground");
} }
public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
{
return true;
}
private void SendLockMessage() private void SendLockMessage()
{ {
MessagingCenter.Send(Xamarin.Forms.Application.Current, "Lock", false); MessagingCenter.Send(Xamarin.Forms.Application.Current, "Lock", false);

View file

@ -22,7 +22,7 @@
<string>UIInterfaceOrientationLandscapeRight</string> <string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>MinimumOSVersion</key> <key>MinimumOSVersion</key>
<string>9.3</string> <string>9.0</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>bitwarden</string> <string>bitwarden</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
@ -57,8 +57,20 @@
<key>UIMainStoryboardFile~ipad</key> <key>UIMainStoryboardFile~ipad</key>
<string>LaunchScreen</string> <string>LaunchScreen</string>
<key>UIStatusBarStyle</key> <key>UIStatusBarStyle</key>
+ <string>UIStatusBarStyleLightContent</string> <string>UIStatusBarStyleLightContent</string>
+ <key>UIViewControllerBasedStatusBarAppearance</key> <key>UIViewControllerBasedStatusBarAppearance</key>
+ <false/> <false/>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>bitwarden</string>
<string>org-appextension-feature-password-management</string>
</array>
<key>CFBundleURLName</key>
<string>com.bitwarden.vault.url</string>
</dict>
</array>
</dict> </dict>
</plist> </plist>