passforios/passExtension/Controllers/ExtensionViewController.swift

166 lines
5.4 KiB
Swift
Raw Normal View History

//
// PasswordsViewController.swift
// pass
//
// Created by Yishi Lin on 13/6/17.
// Copyright © 2017 Bob Sun. All rights reserved.
//
import Foundation
import MobileCoreServices
import passKit
2021-01-10 13:40:17 -08:00
class ExtensionViewController: UIViewController {
var passcodelock: PasscodeExtensionDisplay {
2021-01-31 13:17:37 +01:00
PasscodeExtensionDisplay(extensionContext: extensionContext!)
2021-01-10 13:40:17 -08:00
}
2018-12-09 16:59:07 -08:00
2021-01-10 13:40:17 -08:00
var embeddedNavigationController: UINavigationController {
children.first as! UINavigationController
}
2018-12-09 16:59:07 -08:00
2021-01-10 13:40:17 -08:00
var passwordsViewController: PasswordsViewController {
embeddedNavigationController.viewControllers.first as! PasswordsViewController
}
2018-12-09 16:59:07 -08:00
2017-06-23 21:57:03 +08:00
enum Action {
case findLogin, fillBrowser, unknown
}
2018-12-09 16:59:07 -08:00
2021-01-10 13:40:17 -08:00
private var action = Action.unknown
2018-12-09 16:59:07 -08:00
2021-01-10 13:40:17 -08:00
lazy var credentialProvider = CredentialProvider(viewController: self, extensionContext: self.extensionContext!)
2018-12-09 16:59:07 -08:00
2021-01-10 13:40:17 -08:00
override func viewDidLoad() {
super.viewDidLoad()
passcodelock.presentPasscodeLockIfNeeded(self)
2021-01-10 13:40:17 -08:00
let passwordsTableEntries = PasswordStore.shared.fetchPasswordEntityCoreData(withDir: false).compactMap { PasswordTableEntry($0) }
let dataSource = PasswordsTableDataSource(entries: passwordsTableEntries)
passwordsViewController.dataSource = dataSource
passwordsViewController.selectionDelegate = self
passwordsViewController.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancel))
}
2018-12-09 16:59:07 -08:00
2017-06-14 19:14:56 +08:00
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
2021-01-10 13:40:17 -08:00
prepareCredentialList()
2017-06-14 19:14:56 +08:00
}
2018-12-09 16:59:07 -08:00
2021-01-10 13:40:17 -08:00
@objc
private func cancel(_: AnyObject?) {
2021-01-31 13:17:37 +01:00
extensionContext?.completeRequest(returningItems: nil)
2021-01-10 13:40:17 -08:00
}
2018-12-09 16:59:07 -08:00
2021-01-10 13:40:17 -08:00
func prepareCredentialList() {
2021-01-31 13:17:37 +01:00
guard let attachments = extensionContext?.attachments else {
2017-06-25 12:52:08 +08:00
return
2017-06-23 21:57:03 +08:00
}
2018-12-09 16:59:07 -08:00
2021-01-10 13:40:17 -08:00
func completeTask(_ text: String?) {
DispatchQueue.main.async {
self.passwordsViewController.showPasswordsWithSuggstion(matching: text ?? "")
self.passwordsViewController.navigationItem.prompt = text
2017-06-25 12:52:08 +08:00
}
}
2021-01-10 13:40:17 -08:00
DispatchQueue.global(qos: .userInitiated).async {
for attachment in attachments {
if attachment.hasURL {
self.action = .fillBrowser
attachment.extractSearchText { completeTask($0) }
} else if attachment.hasFindLoginAction {
self.action = .findLogin
attachment.extractSearchText { completeTask($0) }
} else if attachment.hasPropertyList {
self.action = .fillBrowser
attachment.extractSearchText { completeTask($0) }
} else {
self.action = .unknown
}
}
}
}
2021-01-10 13:40:17 -08:00
}
2018-12-09 16:59:07 -08:00
2021-01-10 13:40:17 -08:00
extension ExtensionViewController: PasswordSelectionDelegate {
func selected(password: PasswordTableEntry) {
switch action {
case .findLogin:
credentialProvider.provideCredentialsFindLogin(with: password.passwordEntity.getPath())
case .fillBrowser:
credentialProvider.provideCredentialsBrowser(with: password.passwordEntity.getPath())
default:
2021-01-31 13:17:37 +01:00
extensionContext?.completeRequest(returningItems: nil, completionHandler: nil)
}
}
2021-01-10 13:40:17 -08:00
}
2021-01-10 13:40:17 -08:00
extension NSDictionary {
func extractSearchText() -> String? {
if let value = self[PassExtensionKey.URLStringKey] as? String {
if let host = URL(string: value)?.host {
return host
}
2021-01-31 13:34:37 +01:00
return value
2021-01-10 13:40:17 -08:00
} else if let value = self[NSExtensionJavaScriptPreprocessingResultsKey] as? String {
if let host = URL(string: value)?.host {
return host
}
2021-01-31 13:34:37 +01:00
return value
}
2021-01-10 13:40:17 -08:00
return nil
}
2021-01-10 13:40:17 -08:00
}
2018-12-09 16:59:07 -08:00
2021-01-10 13:40:17 -08:00
extension NSItemProvider {
var hasFindLoginAction: Bool {
hasItemConformingToTypeIdentifier(PassExtensionActions.findLogin)
}
2018-12-09 16:59:07 -08:00
2021-01-10 13:40:17 -08:00
var hasURL: Bool {
hasItemConformingToTypeIdentifier(kUTTypeURL as String) && registeredTypeIdentifiers.count == 1
}
2018-12-09 16:59:07 -08:00
2021-01-10 13:40:17 -08:00
var hasPropertyList: Bool {
hasItemConformingToTypeIdentifier(kUTTypePropertyList as String)
}
2021-01-10 13:40:17 -08:00
}
2018-12-09 16:59:07 -08:00
2021-01-10 13:40:17 -08:00
extension NSExtensionContext {
/// Get all the attachments to this post.
var attachments: [NSItemProvider] {
guard let items = inputItems as? [NSExtensionItem] else {
return []
}
return items.flatMap { $0.attachments ?? [] }
}
2021-01-10 13:40:17 -08:00
}
2018-12-09 16:59:07 -08:00
2021-01-10 13:40:17 -08:00
extension NSItemProvider {
/// Extracts the URL from the item provider
func extractSearchText(completion: @escaping (String?) -> Void) {
2021-01-31 13:17:37 +01:00
loadItem(forTypeIdentifier: kUTTypeURL as String) { item, _ in
2021-01-10 13:40:17 -08:00
if let url = item as? NSURL {
completion(url.host)
} else {
completion(nil)
}
}
2018-12-09 16:59:07 -08:00
2021-01-31 13:17:37 +01:00
loadItem(forTypeIdentifier: kUTTypePropertyList as String) { item, _ in
2021-01-10 13:40:17 -08:00
if let dict = item as? NSDictionary {
if let result = dict[NSExtensionJavaScriptPreprocessingResultsKey] as? NSDictionary {
completion(result.extractSearchText())
}
}
}
2018-12-09 16:59:07 -08:00
2021-01-31 13:17:37 +01:00
loadItem(forTypeIdentifier: PassExtensionActions.findLogin) { item, _ in
2021-01-10 13:40:17 -08:00
if let dict = item as? NSDictionary {
let text = dict.extractSearchText()
completion(text)
}
}
}
}