117 lines
3.8 KiB
Swift
117 lines
3.8 KiB
Swift
import SafariServices
|
|
import os.log
|
|
|
|
let SFExtensionMessageKey = "message"
|
|
|
|
class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
|
|
|
|
func beginRequest(with context: NSExtensionContext) {
|
|
let item = context.inputItems[0] as! NSExtensionItem
|
|
let message = item.userInfo?[SFExtensionMessageKey] as AnyObject?
|
|
os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@", message as! CVarArg)
|
|
|
|
let response = NSExtensionItem()
|
|
|
|
guard let command = message?["command"] as? String else {
|
|
return
|
|
}
|
|
|
|
switch (command) {
|
|
case "readFromClipboard":
|
|
let pasteboard = NSPasteboard.general
|
|
response.userInfo = [ SFExtensionMessageKey: pasteboard.pasteboardItems?.first?.string(forType: .string) as Any ]
|
|
break
|
|
case "copyToClipboard":
|
|
guard let msg = message?["data"] as? String else {
|
|
return
|
|
}
|
|
let pasteboard = NSPasteboard.general
|
|
pasteboard.clearContents()
|
|
pasteboard.setString(msg, forType: .string)
|
|
case "showPopover":
|
|
SFSafariApplication.getActiveWindow { win in
|
|
win?.getToolbarItem(completionHandler: { item in
|
|
item?.showPopover()
|
|
})
|
|
}
|
|
break
|
|
case "downloadFile":
|
|
guard let jsonData = message?["data"] as? String else {
|
|
return
|
|
}
|
|
guard let dlMsg: DownloadFileMessage = jsonDeserialize(json: jsonData) else {
|
|
return
|
|
}
|
|
var blobData: Data?
|
|
if dlMsg.blobOptions?.type == "text/plain" {
|
|
blobData = dlMsg.blobData?.data(using: .utf8)
|
|
} else if let blob = dlMsg.blobData {
|
|
blobData = Data(base64Encoded: blob)
|
|
}
|
|
guard let data = blobData else {
|
|
return
|
|
}
|
|
let panel = NSSavePanel()
|
|
panel.canCreateDirectories = true
|
|
panel.nameFieldStringValue = dlMsg.fileName
|
|
panel.begin { response in
|
|
if response == NSApplication.ModalResponse.OK {
|
|
if let url = panel.url {
|
|
do {
|
|
let fileManager = FileManager.default
|
|
if !fileManager.fileExists(atPath: url.absoluteString) {
|
|
fileManager.createFile(atPath: url.absoluteString, contents: Data(),
|
|
attributes: nil)
|
|
}
|
|
try data.write(to: url)
|
|
} catch {
|
|
print(error)
|
|
NSLog("ERROR in downloadFile, \(error)")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break
|
|
|
|
default:
|
|
return
|
|
}
|
|
|
|
context.completeRequest(returningItems: [response], completionHandler: nil)
|
|
}
|
|
|
|
}
|
|
|
|
func jsonSerialize<T: Encodable>(obj: T?) -> String? {
|
|
let encoder = JSONEncoder()
|
|
do {
|
|
let data = try encoder.encode(obj)
|
|
return String(data: data, encoding: .utf8) ?? "null"
|
|
} catch _ {
|
|
return "null"
|
|
}
|
|
}
|
|
|
|
func jsonDeserialize<T: Decodable>(json: String?) -> T? {
|
|
if json == nil {
|
|
return nil
|
|
}
|
|
let decoder = JSONDecoder()
|
|
do {
|
|
let obj = try decoder.decode(T.self, from: json!.data(using: .utf8)!)
|
|
return obj
|
|
} catch _ {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
class DownloadFileMessage: Decodable, Encodable {
|
|
var fileName: String
|
|
var blobData: String?
|
|
var blobOptions: DownloadFileMessageBlobOptions?
|
|
}
|
|
|
|
class DownloadFileMessageBlobOptions: Decodable, Encodable {
|
|
var type: String?
|
|
}
|