To implement a password manager:
Add a new target to your project. Choose "Action Extension."
Add org-appextension-feature-password-management
as a URL Scheme (CFBundleURLSchemes
) that your app supports.
You can do this in the Info tab of your target. The scheme is the important part. The identifier doesn't seem to be used.
This is required so that -[OnePasswordExtension isAppExtensionAvailable]
will return true.
In your app extension's target, change the NSExtensionActivationRule
from TRUEPREDICATE
to the following:
SUBQUERY (
extensionItems,
$extensionItem,
SUBQUERY (
$extensionItem.attachments,
$attachment,
ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "org.appextension.find-login-action"
).@count == $extensionItem.attachments.@count
).@count == 1
This will make sure your extension only appears if the -[OnePasswordExtension findLoginForURLString:forViewController:sender:completion:]
method is called. If you want to match more than one of these UTIs, see Apple's more complex example here.
Note: This SUBQUERY is the same as Apple's SUBQUERY example, with the constant changed. If you're wondering about the syntax or how it works, see this answer.
To read which url should be filled:
let inputItem = extensionContext!.inputItems[0] as! NSExtensionItem
let inputItemProvider = inputItem.attachments![0] as! NSItemProvider
inputItemProvider.loadItem(forTypeIdentifier: "org.appextension.find-login-action", options: nil) { (data, err) in
if let err = err { fatalError("\(err)") }
let urlString = (data as! NSDictionary)["url_string"] as! String
}
When you're ready to send data from the extension back to the host app:
let itemProvider = NSItemProvider(
item: ["username": "foo", "password": "123"],
typeIdentifier:kUTTypePropertyList as String) // TODO: import MobileCoreServices
let extensionItem = NSExtensionItem()
extensionItem.attachments = [itemProvider]
extensionContext!.completeRequestReturningItems([extensionItem], completionHandler: nil)
If you're wondering why it's okay to register these schemes, you can read this article:
Our brand-neutral scheme should make things easier both for users and for app developers. Thus, part of our reason for using a brand neutral scheme is to encourage as many app developers as possible to use this scheme. We aren’t forcing app developers to choose between 1Password and some competitor. Instead, we are delegating the choice of which password manager to use to where that choice belongs: you.