safari: XPC service runs!

This commit is contained in:
Omar Rizwan 2021-02-07 21:44:46 -08:00
parent 8924f946dd
commit 6f743114da
6 changed files with 72 additions and 90 deletions

View File

@ -1,76 +0,0 @@
//
// FSProcessManager.swift
// TabFS
//
// Created by Omar Rizwan on 1/31/21.
//
import Foundation
import SafariServices.SFSafariApplication
import os.log
let extensionBundleIdentifier = "com.rsnous.TabFS-Extension"
class FSProcessManager {
static let shared = FSProcessManager()
// FIXME: should accept XPC connection to extension
// so it can get replies (??)
var fs: Process!
var fsInput: FileHandle!
var fsOutput: FileHandle!
func start() {
fs = Process()
fs.executableURL = URL(fileURLWithPath: "/Users/osnr/Code/tabfs/fs/tabfs")
os_log(.default, "url: %{public}@", fs.executableURL as! NSURL)
fs.arguments = []
let inputPipe = Pipe(), outputPipe = Pipe()
fs.standardInput = inputPipe
fs.standardOutput = outputPipe
try! fs.run()
fsInput = inputPipe.fileHandleForWriting
fsOutput = outputPipe.fileHandleForReading
//
// SFSafariApplication.dispatchMessage(
// withName: "ToSafari",
// toExtensionWithIdentifier: extensionBundleIdentifier,
// userInfo: [:]
// ) { error in
// debugPrint("Message attempted. Error info: \(String.init(describing: error))")
// }
DispatchQueue.global(qos: .background).async {
while true {
let req = self.awaitRequest()
SFSafariApplication.dispatchMessage(
withName: "ToSafari",
toExtensionWithIdentifier: extensionBundleIdentifier,
userInfo: req
) { error in
debugPrint("Message attempted. Error info: \(String.init(describing: error))")
}
}
}
}
func awaitRequest() -> [String: Any] {
let length = fsOutput.readData(ofLength: 4).withUnsafeBytes {
$0.load(as: UInt32.self)
}
let data = fsOutput.readData(ofLength: Int(length))
return try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
}
func respond(_ resp: [AnyHashable: Any]) {
try! fsInput.write(JSONSerialization.data(withJSONObject: resp, options: []))
}
}

View File

@ -9,17 +9,60 @@ import SafariServices
import SafariServices.SFSafariApplication
import os.log
class TabFSServiceManager: TabFSServiceConsumerProtocol {
static let shared = TabFSServiceManager()
var service: TabFSServiceProtocol!
func connect() {
let connection = NSXPCConnection(serviceName: "com.rsnous.TabFSService")
connection.remoteObjectInterface = NSXPCInterface(with: TabFSServiceProtocol.self)
connection.exportedInterface = NSXPCInterface(with: TabFSServiceConsumerProtocol.self)
connection.exportedObject = self
connection.resume()
service = connection.remoteObjectProxyWithErrorHandler { error in
os_log(.default, "Received error: %{public}@", error as! CVarArg)
} as? TabFSServiceProtocol
service?.upperCaseString("hello XPC") { response in
os_log(.default, "Response from XPC service: %{public}@", response)
}
}
func request(_ req: Data) {
SFSafariApplication.dispatchMessage(
withName: "ToSafari",
toExtensionWithIdentifier: "com.rsnous.TabFS-Extension",
userInfo: try! JSONSerialization.jsonObject(with: req, options: []) as! [String : Any]
) { error in
debugPrint("Message attempted. Error info: \(String.init(describing: error))")
}
}
func response(_ resp: [AnyHashable: Any]) {
try! service.response(JSONSerialization.data(withJSONObject: resp, options: []))
}
}
class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
func beginRequest(with context: NSExtensionContext) {
os_log(.default, "Received message from browser.runtime.sendNativefffMessage: %@", context as! CVarArg)
os_log(.default, "TabFSmsg Received message from browser.runtime.sendNativefffMessage: %@", context as! CVarArg)
let item = context.inputItems[0] as! NSExtensionItem
os_log(.default, "TabFSmsg item.userInfo %{public}@", item.userInfo as! CVarArg)
guard let message = item.userInfo?["message"] as? [AnyHashable: Any] else { return }
if message["op"] as! String == "safari_did_connect" {
FSProcessManager.shared.start()
os_log(.default, "TabFSmsg sdc")
TabFSServiceManager.shared.connect()
//
// let response = NSExtensionItem()
// response.userInfo = [ "message": [ "aResponse to": "moop" ] ]
@ -27,11 +70,11 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
return
}
TabFSServiceManager.shared.response(message)
//
// os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@", op as! CVarArg)
FSProcessManager.shared.respond(message)
//
// let response = NSExtensionItem()
// response.userInfo = [ "message": [ "Response to": op ] ]
//

View File

@ -12,6 +12,7 @@
F028D2BC25D0B7370095C2D5 /* TabFSService.xpc in Embed XPC Services */ = {isa = PBXBuildFile; fileRef = F028D2B125D0B7370095C2D5 /* TabFSService.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
F028D2D725D0B8500095C2D5 /* TabFSServiceProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = F028D2B325D0B7370095C2D5 /* TabFSServiceProtocols.swift */; };
F028D2DE25D0B8590095C2D5 /* TabFSServiceProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = F028D2B325D0B7370095C2D5 /* TabFSServiceProtocols.swift */; };
F028D2ED25D106F10095C2D5 /* TabFSService.xpc in CopyFiles */ = {isa = PBXBuildFile; fileRef = F028D2B125D0B7370095C2D5 /* TabFSService.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
F04429F625C7507200D998A5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F04429F525C7507200D998A5 /* AppDelegate.swift */; };
F04429F925C7507200D998A5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F04429F725C7507200D998A5 /* Main.storyboard */; };
F04429FB25C7507200D998A5 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F04429FA25C7507200D998A5 /* ViewController.swift */; };
@ -23,7 +24,6 @@
F0442A1E25C7507500D998A5 /* safari in Resources */ = {isa = PBXBuildFile; fileRef = F0442A1A25C7507500D998A5 /* safari */; };
F0442A1F25C7507500D998A5 /* manifest.json in Resources */ = {isa = PBXBuildFile; fileRef = F0442A1B25C7507500D998A5 /* manifest.json */; };
F0442A2025C7507500D998A5 /* vendor in Resources */ = {isa = PBXBuildFile; fileRef = F0442A1C25C7507500D998A5 /* vendor */; };
F068D65625C7C66700DB3AB5 /* FSProcessManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F068D65225C77F7600DB3AB5 /* FSProcessManager.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -55,6 +55,16 @@
name = "Embed XPC Services";
runOnlyForDeploymentPostprocessing = 0;
};
F028D2E525D106BB0095C2D5 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "$(CONTENTS_FOLDER_PATH)/XPCServices";
dstSubfolderSpec = 16;
files = (
F028D2ED25D106F10095C2D5 /* TabFSService.xpc in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F0442A1425C7507400D998A5 /* Embed App Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@ -90,7 +100,6 @@
F0442A1A25C7507500D998A5 /* safari */ = {isa = PBXFileReference; lastKnownFileType = folder; name = safari; path = ../..; sourceTree = "<group>"; };
F0442A1B25C7507500D998A5 /* manifest.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; name = manifest.json; path = ../../../manifest.json; sourceTree = "<group>"; };
F0442A1C25C7507500D998A5 /* vendor */ = {isa = PBXFileReference; lastKnownFileType = folder; name = vendor; path = ../../../vendor; sourceTree = "<group>"; };
F068D65225C77F7600DB3AB5 /* FSProcessManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FSProcessManager.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -175,7 +184,6 @@
F0442A0A25C7507400D998A5 /* TabFS Extension */ = {
isa = PBXGroup;
children = (
F068D65225C77F7600DB3AB5 /* FSProcessManager.swift */,
F0442A1825C7507500D998A5 /* Resources */,
F0442A0B25C7507400D998A5 /* SafariWebExtensionHandler.swift */,
F0442A0D25C7507400D998A5 /* Info.plist */,
@ -244,6 +252,7 @@
F04429FF25C7507400D998A5 /* Sources */,
F0442A0025C7507400D998A5 /* Frameworks */,
F0442A0125C7507400D998A5 /* Resources */,
F028D2E525D106BB0095C2D5 /* CopyFiles */,
);
buildRules = (
);
@ -349,7 +358,6 @@
buildActionMask = 2147483647;
files = (
F028D2DE25D0B8590095C2D5 /* TabFSServiceProtocols.swift in Sources */,
F068D65625C7C66700DB3AB5 /* FSProcessManager.swift in Sources */,
F0442A0C25C7507400D998A5 /* SafariWebExtensionHandler.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@ -14,8 +14,8 @@
filePath = "TabFS Extension/SafariWebExtensionHandler.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "18"
endingLineNumber = "18"
startingLineNumber = "57"
endingLineNumber = "57"
landmarkName = "beginRequest(with:)"
landmarkType = "7">
</BreakpointContent>
@ -46,8 +46,8 @@
filePath = "TabFS Extension/SafariWebExtensionHandler.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "19"
endingLineNumber = "19"
startingLineNumber = "60"
endingLineNumber = "60"
landmarkName = "beginRequest(with:)"
landmarkType = "7">
</BreakpointContent>
@ -62,8 +62,8 @@
filePath = "TabFS Extension/SafariWebExtensionHandler.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "16"
endingLineNumber = "16"
startingLineNumber = "55"
endingLineNumber = "55"
landmarkName = "beginRequest(with:)"
landmarkType = "7">
</BreakpointContent>

View File

@ -6,6 +6,7 @@
//
import Foundation
import os.log
class TabFSService: NSObject, TabFSServiceProtocol {
var fs: Process!
@ -28,7 +29,9 @@ class TabFSService: NSObject, TabFSServiceProtocol {
fsInput = inputPipe.fileHandleForWriting
fsOutput = outputPipe.fileHandleForReading
os_log(.default, "TabFSmsg tfs service: willrun")
try! fs.run()
os_log(.default, "TabFSmsg tfs service: ran")
// split new thread
DispatchQueue.global(qos: .default).async {
@ -57,6 +60,10 @@ class TabFSService: NSObject, TabFSServiceProtocol {
class TabFSServiceDelegate: NSObject, NSXPCListenerDelegate {
func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool {
os_log(.default, "TabFSmsg tfs service: starting delegate")
newConnection.remoteObjectInterface = NSXPCInterface(with: TabFSServiceConsumerProtocol.self)
let exportedObject = TabFSService(app: newConnection.remoteObjectProxy as! TabFSServiceConsumerProtocol)