mirror of
https://github.com/bitwarden/android.git
synced 2024-12-20 08:12:26 +03:00
Added support for find login, save login, and change password app extension provider types.
This commit is contained in:
parent
72c1a987c9
commit
fac4401e97
2 changed files with 198 additions and 55 deletions
|
@ -18,7 +18,25 @@ namespace Bit.iOS.Extension
|
||||||
public partial class ActionViewController : UIViewController
|
public partial class ActionViewController : UIViewController
|
||||||
{
|
{
|
||||||
private const string AppExtensionVersionNumberKey = "version_number";
|
private const string AppExtensionVersionNumberKey = "version_number";
|
||||||
|
|
||||||
private const string AppExtensionUrlStringKey = "url_string";
|
private const string AppExtensionUrlStringKey = "url_string";
|
||||||
|
private const string AppExtensionUsernameKey = "username";
|
||||||
|
private const string AppExtensionPasswordKey = "password";
|
||||||
|
private const string AppExtensionTotpKey = "totp";
|
||||||
|
private const string AppExtensionTitleKey = "login_title";
|
||||||
|
private const string AppExtensionNotesKey = "notes";
|
||||||
|
private const string AppExtensionSectionTitleKey = "section_title";
|
||||||
|
private const string AppExtensionFieldsKey = "fields";
|
||||||
|
private const string AppExtensionReturnedFieldsKey = "returned_fields";
|
||||||
|
private const string AppExtensionOldPasswordKey = "old_password";
|
||||||
|
private const string AppExtensionPasswordGeneratorOptionsKey = "password_generator_options";
|
||||||
|
|
||||||
|
private const string AppExtensionGeneratedPasswordMinLengthKey = "password_min_length";
|
||||||
|
private const string AppExtensionGeneratedPasswordMaxLengthKey = "password_max_length";
|
||||||
|
private const string AppExtensionGeneratedPasswordRequireDigitsKey = "password_require_digits";
|
||||||
|
private const string AppExtensionGeneratedPasswordRequireSymbolsKey = "password_require_symbols";
|
||||||
|
private const string AppExtensionGeneratedPasswordForbiddenCharactersKey = "password_forbidden_characters";
|
||||||
|
|
||||||
private const string UTTypeAppExtensionFindLoginAction = "org.appextension.find-login-action";
|
private const string UTTypeAppExtensionFindLoginAction = "org.appextension.find-login-action";
|
||||||
private const string UTTypeAppExtensionSaveLoginAction = "org.appextension.save-login-action";
|
private const string UTTypeAppExtensionSaveLoginAction = "org.appextension.save-login-action";
|
||||||
private const string UTTypeAppExtensionChangePasswordAction = "org.appextension.change-password-action";
|
private const string UTTypeAppExtensionChangePasswordAction = "org.appextension.change-password-action";
|
||||||
|
@ -33,9 +51,14 @@ namespace Bit.iOS.Extension
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string HtmlContent { get; set; }
|
public string ProviderType { get; set; }
|
||||||
public Uri BaseUri { get; set; }
|
|
||||||
public Uri Url { get; set; }
|
public Uri Url { get; set; }
|
||||||
|
public string SiteTitle { get; set; }
|
||||||
|
public string Username { get; set; }
|
||||||
|
public string Password { get; set; }
|
||||||
|
public string OldPassword { get; set; }
|
||||||
|
public string Notes { get; set; }
|
||||||
|
public PasswordGenerationOptions PasswordOptions { get; set; }
|
||||||
|
|
||||||
private void SetIoc()
|
private void SetIoc()
|
||||||
{
|
{
|
||||||
|
@ -72,35 +95,8 @@ namespace Bit.iOS.Extension
|
||||||
base.DidReceiveMemoryWarning();
|
base.DidReceiveMemoryWarning();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async override void LoadView()
|
public override void LoadView()
|
||||||
{
|
{
|
||||||
View = new UIView(new CGRect(x: 0.0, y: 0, width: 320.0, height: 200.0));
|
|
||||||
var button = new UIButton(new CGRect(x: 10.0, y: 50.0, width: 200.0, height: 30.0));
|
|
||||||
button.SetTitle("Done", UIControlState.Normal);
|
|
||||||
button.TouchUpInside += Button_TouchUpInside;
|
|
||||||
View.AddSubview(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Button_TouchUpInside(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
var itemData = new NSDictionary(
|
|
||||||
"username", "me@example.com",
|
|
||||||
"password", "mypassword",
|
|
||||||
"autoSubmit", true);
|
|
||||||
|
|
||||||
var resultsProvider = new NSItemProvider(
|
|
||||||
new NSDictionary(NSJavaScriptExtension.FinalizeArgumentKey, itemData), UTType.PropertyList);
|
|
||||||
|
|
||||||
var resultsItem = new NSExtensionItem { Attachments = new NSItemProvider[] { resultsProvider } };
|
|
||||||
var returningItems = new NSExtensionItem[] { resultsItem };
|
|
||||||
|
|
||||||
ExtensionContext.CompleteRequest(returningItems, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ViewDidLoad()
|
|
||||||
{
|
|
||||||
base.ViewDidLoad();
|
|
||||||
|
|
||||||
foreach(var item in ExtensionContext.InputItems)
|
foreach(var item in ExtensionContext.InputItems)
|
||||||
{
|
{
|
||||||
foreach(var itemProvider in item.Attachments)
|
foreach(var itemProvider in item.Attachments)
|
||||||
|
@ -113,65 +109,214 @@ namespace Bit.iOS.Extension
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if(ProcessSaveLoginProvider(itemProvider))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(ProcessChangePasswordProvider(itemProvider))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
View = new UIView(new CGRect(x: 0.0, y: 0, width: 320.0, height: 200.0));
|
||||||
|
var button = new UIButton(new CGRect(x: 10.0, y: 50.0, width: 200.0, height: 30.0));
|
||||||
|
button.SetTitle("Done", UIControlState.Normal);
|
||||||
|
button.TouchUpInside += Button_TouchUpInside;
|
||||||
|
View.AddSubview(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ProcessWebUrlProvider(NSItemProvider itemProvider)
|
private void Button_TouchUpInside(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if(!itemProvider.HasItemConformingTo(UTType.PropertyList))
|
NSDictionary itemData = null;
|
||||||
|
if(ProviderType == UTType.PropertyList)
|
||||||
|
{
|
||||||
|
itemData = new NSDictionary(
|
||||||
|
"username", "me@example.com",
|
||||||
|
"password", "mypassword",
|
||||||
|
"autoSubmit", true);
|
||||||
|
}
|
||||||
|
else if(ProviderType == UTTypeAppExtensionFindLoginAction)
|
||||||
|
{
|
||||||
|
itemData = new NSDictionary(
|
||||||
|
AppExtensionUsernameKey, "me@example.com",
|
||||||
|
AppExtensionPasswordKey, "mypassword");
|
||||||
|
}
|
||||||
|
else if(ProviderType == UTTypeAppExtensionSaveLoginAction)
|
||||||
|
{
|
||||||
|
itemData = new NSDictionary(
|
||||||
|
AppExtensionUsernameKey, "me@example.com",
|
||||||
|
AppExtensionPasswordKey, "mypassword");
|
||||||
|
}
|
||||||
|
else if(ProviderType == UTTypeAppExtensionChangePasswordAction)
|
||||||
|
{
|
||||||
|
itemData = new NSDictionary(
|
||||||
|
AppExtensionPasswordKey, "mynewpassword",
|
||||||
|
AppExtensionOldPasswordKey, "myoldpassword");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var resultsProvider = new NSItemProvider(itemData, UTType.PropertyList);
|
||||||
|
var resultsItem = new NSExtensionItem { Attachments = new NSItemProvider[] { resultsProvider } };
|
||||||
|
var returningItems = new NSExtensionItem[] { resultsItem };
|
||||||
|
|
||||||
|
ExtensionContext.CompleteRequest(returningItems, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ViewDidLoad()
|
||||||
|
{
|
||||||
|
base.ViewDidLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ProcessItemProvider(NSItemProvider itemProvider, string type, Action<NSDictionary> action)
|
||||||
|
{
|
||||||
|
if(!itemProvider.HasItemConformingTo(type))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
itemProvider.LoadItem(UTType.PropertyList, null, (NSObject list, NSError error) =>
|
itemProvider.LoadItem(type, null, (NSObject list, NSError error) =>
|
||||||
{
|
{
|
||||||
if(list == null)
|
if(list == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProviderType = type;
|
||||||
var dict = list as NSDictionary;
|
var dict = list as NSDictionary;
|
||||||
|
action(dict);
|
||||||
|
|
||||||
|
Debug.WriteLine("BW LOG, ProviderType: " + ProviderType);
|
||||||
|
Debug.WriteLine("BW LOG, Url: " + Url);
|
||||||
|
Debug.WriteLine("BW LOG, Title: " + SiteTitle);
|
||||||
|
Debug.WriteLine("BW LOG, Username: " + Username);
|
||||||
|
Debug.WriteLine("BW LOG, Password: " + Password);
|
||||||
|
Debug.WriteLine("BW LOG, Old Password: " + OldPassword);
|
||||||
|
Debug.WriteLine("BW LOG, Notes: " + Notes);
|
||||||
|
|
||||||
|
if(PasswordOptions != null)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("BW LOG, PasswordOptions Min Length: " + PasswordOptions.MinLength);
|
||||||
|
Debug.WriteLine("BW LOG, PasswordOptions Max Length: " + PasswordOptions.MaxLength);
|
||||||
|
Debug.WriteLine("BW LOG, PasswordOptions Require Digits: " + PasswordOptions.RequireDigits);
|
||||||
|
Debug.WriteLine("BW LOG, PasswordOptions Require Symbols: " + PasswordOptions.RequireSymbols);
|
||||||
|
Debug.WriteLine("BW LOG, PasswordOptions Forbidden Chars: " + PasswordOptions.ForbiddenCharacters);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ProcessWebUrlProvider(NSItemProvider itemProvider)
|
||||||
|
{
|
||||||
|
return ProcessItemProvider(itemProvider, UTType.PropertyList, (dict) =>
|
||||||
|
{
|
||||||
var result = dict[NSJavaScriptExtension.PreprocessingResultsKey];
|
var result = dict[NSJavaScriptExtension.PreprocessingResultsKey];
|
||||||
if(result == null)
|
if(result == null)
|
||||||
{
|
{
|
||||||
return;
|
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);
|
Url = new Uri(result.ValueForKey(new NSString("url")) as NSString);
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ProcessFindLoginProvider(NSItemProvider itemProvider)
|
private bool ProcessFindLoginProvider(NSItemProvider itemProvider)
|
||||||
{
|
{
|
||||||
if(!itemProvider.HasItemConformingTo(UTTypeAppExtensionFindLoginAction))
|
return ProcessItemProvider(itemProvider, UTTypeAppExtensionFindLoginAction, (dict) =>
|
||||||
{
|
{
|
||||||
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 version = dict[AppExtensionVersionNumberKey] as NSNumber;
|
||||||
var url = dict[AppExtensionUrlStringKey] as NSString;
|
var url = dict[AppExtensionUrlStringKey] as NSString;
|
||||||
if(url == null)
|
|
||||||
|
if(url != null)
|
||||||
{
|
{
|
||||||
return;
|
Url = new Uri(url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ProcessSaveLoginProvider(NSItemProvider itemProvider)
|
||||||
|
{
|
||||||
|
return ProcessItemProvider(itemProvider, UTTypeAppExtensionSaveLoginAction, (dict) =>
|
||||||
|
{
|
||||||
|
var version = dict[AppExtensionVersionNumberKey] as NSNumber;
|
||||||
|
var url = dict[AppExtensionUrlStringKey] as NSString;
|
||||||
|
var title = dict[AppExtensionTitleKey] as NSString;
|
||||||
|
var sectionTitle = dict[AppExtensionSectionTitleKey] as NSString;
|
||||||
|
var username = dict[AppExtensionUsernameKey] as NSString;
|
||||||
|
var password = dict[AppExtensionPasswordKey] as NSString;
|
||||||
|
var notes = dict[AppExtensionNotesKey] as NSString;
|
||||||
|
var fields = dict[AppExtensionFieldsKey] as NSDictionary;
|
||||||
|
var passwordGenerationOptions = dict[AppExtensionPasswordGeneratorOptionsKey] as NSDictionary;
|
||||||
|
|
||||||
|
if(url != null)
|
||||||
|
{
|
||||||
|
Url = new Uri(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
Url = new Uri(url);
|
Url = new Uri(url);
|
||||||
|
SiteTitle = title;
|
||||||
|
Username = username;
|
||||||
|
Password = password;
|
||||||
|
Notes = notes;
|
||||||
|
PasswordOptions = new PasswordGenerationOptions(passwordGenerationOptions);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
private bool ProcessChangePasswordProvider(NSItemProvider itemProvider)
|
||||||
|
{
|
||||||
|
return ProcessItemProvider(itemProvider, UTTypeAppExtensionChangePasswordAction, (dict) =>
|
||||||
|
{
|
||||||
|
var version = dict[AppExtensionVersionNumberKey] as NSNumber;
|
||||||
|
var url = dict[AppExtensionUrlStringKey] as NSString;
|
||||||
|
var title = dict[AppExtensionTitleKey] as NSString;
|
||||||
|
var sectionTitle = dict[AppExtensionSectionTitleKey] as NSString;
|
||||||
|
var username = dict[AppExtensionUsernameKey] as NSString;
|
||||||
|
var password = dict[AppExtensionPasswordKey] as NSString;
|
||||||
|
var oldPassword = dict[AppExtensionOldPasswordKey] as NSString;
|
||||||
|
var notes = dict[AppExtensionNotesKey] as NSString;
|
||||||
|
var fields = dict[AppExtensionFieldsKey] as NSDictionary;
|
||||||
|
var passwordGenerationOptions = dict[AppExtensionPasswordGeneratorOptionsKey] as NSDictionary;
|
||||||
|
|
||||||
|
if(url != null)
|
||||||
|
{
|
||||||
|
Url = new Uri(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
SiteTitle = title;
|
||||||
|
Username = username;
|
||||||
|
Password = password;
|
||||||
|
OldPassword = oldPassword;
|
||||||
|
Notes = notes;
|
||||||
|
PasswordOptions = new PasswordGenerationOptions(passwordGenerationOptions);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PasswordGenerationOptions
|
||||||
|
{
|
||||||
|
public PasswordGenerationOptions(NSDictionary dict)
|
||||||
|
{
|
||||||
|
if(dict == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(dict));
|
||||||
|
}
|
||||||
|
|
||||||
|
MinLength = (dict[AppExtensionGeneratedPasswordMinLengthKey] as NSNumber)?.Int32Value ?? 0;
|
||||||
|
MaxLength = (dict[AppExtensionGeneratedPasswordMaxLengthKey] as NSNumber)?.Int32Value ?? 0;
|
||||||
|
RequireDigits = (dict[AppExtensionGeneratedPasswordRequireDigitsKey] as NSNumber)?.BoolValue ?? false;
|
||||||
|
RequireSymbols = (dict[AppExtensionGeneratedPasswordRequireSymbolsKey] as NSNumber)?.BoolValue ?? false;
|
||||||
|
ForbiddenCharacters = (dict[AppExtensionGeneratedPasswordForbiddenCharactersKey] as NSString)?.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MinLength { get; set; }
|
||||||
|
public int MaxLength { get; set; }
|
||||||
|
public bool RequireDigits { get; set; }
|
||||||
|
public bool RequireSymbols { get; set; }
|
||||||
|
public string ForbiddenCharacters { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,9 +6,7 @@ BitwardenExtension.prototype = {
|
||||||
console.log(arguments);
|
console.log(arguments);
|
||||||
|
|
||||||
var args = {
|
var args = {
|
||||||
baseUri: document.baseURI,
|
url: document.URL
|
||||||
url: document.URL,
|
|
||||||
htmlContent: document.body.innerHTML
|
|
||||||
};
|
};
|
||||||
arguments.completionFunction(args);
|
arguments.completionFunction(args);
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue