mirror of
https://github.com/osnr/TabFS.git
synced 2024-05-17 21:16:35 +02:00
safari: XPC service runs!
This commit is contained in:
parent
8924f946dd
commit
6f743114da
|
@ -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: []))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,17 +9,60 @@ import SafariServices
|
||||||
import SafariServices.SFSafariApplication
|
import SafariServices.SFSafariApplication
|
||||||
import os.log
|
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 {
|
class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
|
||||||
|
|
||||||
func beginRequest(with context: NSExtensionContext) {
|
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
|
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 }
|
guard let message = item.userInfo?["message"] as? [AnyHashable: Any] else { return }
|
||||||
|
|
||||||
if message["op"] as! String == "safari_did_connect" {
|
if message["op"] as! String == "safari_did_connect" {
|
||||||
FSProcessManager.shared.start()
|
|
||||||
|
os_log(.default, "TabFSmsg sdc")
|
||||||
|
TabFSServiceManager.shared.connect()
|
||||||
//
|
//
|
||||||
// let response = NSExtensionItem()
|
// let response = NSExtensionItem()
|
||||||
// response.userInfo = [ "message": [ "aResponse to": "moop" ] ]
|
// response.userInfo = [ "message": [ "aResponse to": "moop" ] ]
|
||||||
|
@ -27,11 +70,11 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TabFSServiceManager.shared.response(message)
|
||||||
//
|
//
|
||||||
// os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@", op as! CVarArg)
|
// os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@", op as! CVarArg)
|
||||||
|
|
||||||
FSProcessManager.shared.respond(message)
|
|
||||||
//
|
|
||||||
// let response = NSExtensionItem()
|
// let response = NSExtensionItem()
|
||||||
// response.userInfo = [ "message": [ "Response to": op ] ]
|
// response.userInfo = [ "message": [ "Response to": op ] ]
|
||||||
//
|
//
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
F028D2BC25D0B7370095C2D5 /* TabFSService.xpc in Embed XPC Services */ = {isa = PBXBuildFile; fileRef = F028D2B125D0B7370095C2D5 /* TabFSService.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
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 */; };
|
F028D2D725D0B8500095C2D5 /* TabFSServiceProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = F028D2B325D0B7370095C2D5 /* TabFSServiceProtocols.swift */; };
|
||||||
F028D2DE25D0B8590095C2D5 /* 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 */; };
|
F04429F625C7507200D998A5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F04429F525C7507200D998A5 /* AppDelegate.swift */; };
|
||||||
F04429F925C7507200D998A5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F04429F725C7507200D998A5 /* Main.storyboard */; };
|
F04429F925C7507200D998A5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F04429F725C7507200D998A5 /* Main.storyboard */; };
|
||||||
F04429FB25C7507200D998A5 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F04429FA25C7507200D998A5 /* ViewController.swift */; };
|
F04429FB25C7507200D998A5 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F04429FA25C7507200D998A5 /* ViewController.swift */; };
|
||||||
|
@ -23,7 +24,6 @@
|
||||||
F0442A1E25C7507500D998A5 /* safari in Resources */ = {isa = PBXBuildFile; fileRef = F0442A1A25C7507500D998A5 /* safari */; };
|
F0442A1E25C7507500D998A5 /* safari in Resources */ = {isa = PBXBuildFile; fileRef = F0442A1A25C7507500D998A5 /* safari */; };
|
||||||
F0442A1F25C7507500D998A5 /* manifest.json in Resources */ = {isa = PBXBuildFile; fileRef = F0442A1B25C7507500D998A5 /* manifest.json */; };
|
F0442A1F25C7507500D998A5 /* manifest.json in Resources */ = {isa = PBXBuildFile; fileRef = F0442A1B25C7507500D998A5 /* manifest.json */; };
|
||||||
F0442A2025C7507500D998A5 /* vendor in Resources */ = {isa = PBXBuildFile; fileRef = F0442A1C25C7507500D998A5 /* vendor */; };
|
F0442A2025C7507500D998A5 /* vendor in Resources */ = {isa = PBXBuildFile; fileRef = F0442A1C25C7507500D998A5 /* vendor */; };
|
||||||
F068D65625C7C66700DB3AB5 /* FSProcessManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F068D65225C77F7600DB3AB5 /* FSProcessManager.swift */; };
|
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
@ -55,6 +55,16 @@
|
||||||
name = "Embed XPC Services";
|
name = "Embed XPC Services";
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
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 */ = {
|
F0442A1425C7507400D998A5 /* Embed App Extensions */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -90,7 +100,6 @@
|
||||||
F0442A1A25C7507500D998A5 /* safari */ = {isa = PBXFileReference; lastKnownFileType = folder; name = safari; path = ../..; sourceTree = "<group>"; };
|
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>"; };
|
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>"; };
|
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 */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
@ -175,7 +184,6 @@
|
||||||
F0442A0A25C7507400D998A5 /* TabFS Extension */ = {
|
F0442A0A25C7507400D998A5 /* TabFS Extension */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
F068D65225C77F7600DB3AB5 /* FSProcessManager.swift */,
|
|
||||||
F0442A1825C7507500D998A5 /* Resources */,
|
F0442A1825C7507500D998A5 /* Resources */,
|
||||||
F0442A0B25C7507400D998A5 /* SafariWebExtensionHandler.swift */,
|
F0442A0B25C7507400D998A5 /* SafariWebExtensionHandler.swift */,
|
||||||
F0442A0D25C7507400D998A5 /* Info.plist */,
|
F0442A0D25C7507400D998A5 /* Info.plist */,
|
||||||
|
@ -244,6 +252,7 @@
|
||||||
F04429FF25C7507400D998A5 /* Sources */,
|
F04429FF25C7507400D998A5 /* Sources */,
|
||||||
F0442A0025C7507400D998A5 /* Frameworks */,
|
F0442A0025C7507400D998A5 /* Frameworks */,
|
||||||
F0442A0125C7507400D998A5 /* Resources */,
|
F0442A0125C7507400D998A5 /* Resources */,
|
||||||
|
F028D2E525D106BB0095C2D5 /* CopyFiles */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
|
@ -349,7 +358,6 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
F028D2DE25D0B8590095C2D5 /* TabFSServiceProtocols.swift in Sources */,
|
F028D2DE25D0B8590095C2D5 /* TabFSServiceProtocols.swift in Sources */,
|
||||||
F068D65625C7C66700DB3AB5 /* FSProcessManager.swift in Sources */,
|
|
||||||
F0442A0C25C7507400D998A5 /* SafariWebExtensionHandler.swift in Sources */,
|
F0442A0C25C7507400D998A5 /* SafariWebExtensionHandler.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|
Binary file not shown.
|
@ -14,8 +14,8 @@
|
||||||
filePath = "TabFS Extension/SafariWebExtensionHandler.swift"
|
filePath = "TabFS Extension/SafariWebExtensionHandler.swift"
|
||||||
startingColumnNumber = "9223372036854775807"
|
startingColumnNumber = "9223372036854775807"
|
||||||
endingColumnNumber = "9223372036854775807"
|
endingColumnNumber = "9223372036854775807"
|
||||||
startingLineNumber = "18"
|
startingLineNumber = "57"
|
||||||
endingLineNumber = "18"
|
endingLineNumber = "57"
|
||||||
landmarkName = "beginRequest(with:)"
|
landmarkName = "beginRequest(with:)"
|
||||||
landmarkType = "7">
|
landmarkType = "7">
|
||||||
</BreakpointContent>
|
</BreakpointContent>
|
||||||
|
@ -46,8 +46,8 @@
|
||||||
filePath = "TabFS Extension/SafariWebExtensionHandler.swift"
|
filePath = "TabFS Extension/SafariWebExtensionHandler.swift"
|
||||||
startingColumnNumber = "9223372036854775807"
|
startingColumnNumber = "9223372036854775807"
|
||||||
endingColumnNumber = "9223372036854775807"
|
endingColumnNumber = "9223372036854775807"
|
||||||
startingLineNumber = "19"
|
startingLineNumber = "60"
|
||||||
endingLineNumber = "19"
|
endingLineNumber = "60"
|
||||||
landmarkName = "beginRequest(with:)"
|
landmarkName = "beginRequest(with:)"
|
||||||
landmarkType = "7">
|
landmarkType = "7">
|
||||||
</BreakpointContent>
|
</BreakpointContent>
|
||||||
|
@ -62,8 +62,8 @@
|
||||||
filePath = "TabFS Extension/SafariWebExtensionHandler.swift"
|
filePath = "TabFS Extension/SafariWebExtensionHandler.swift"
|
||||||
startingColumnNumber = "9223372036854775807"
|
startingColumnNumber = "9223372036854775807"
|
||||||
endingColumnNumber = "9223372036854775807"
|
endingColumnNumber = "9223372036854775807"
|
||||||
startingLineNumber = "16"
|
startingLineNumber = "55"
|
||||||
endingLineNumber = "16"
|
endingLineNumber = "55"
|
||||||
landmarkName = "beginRequest(with:)"
|
landmarkName = "beginRequest(with:)"
|
||||||
landmarkType = "7">
|
landmarkType = "7">
|
||||||
</BreakpointContent>
|
</BreakpointContent>
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import os.log
|
||||||
|
|
||||||
class TabFSService: NSObject, TabFSServiceProtocol {
|
class TabFSService: NSObject, TabFSServiceProtocol {
|
||||||
var fs: Process!
|
var fs: Process!
|
||||||
|
@ -28,7 +29,9 @@ class TabFSService: NSObject, TabFSServiceProtocol {
|
||||||
fsInput = inputPipe.fileHandleForWriting
|
fsInput = inputPipe.fileHandleForWriting
|
||||||
fsOutput = outputPipe.fileHandleForReading
|
fsOutput = outputPipe.fileHandleForReading
|
||||||
|
|
||||||
|
os_log(.default, "TabFSmsg tfs service: willrun")
|
||||||
try! fs.run()
|
try! fs.run()
|
||||||
|
os_log(.default, "TabFSmsg tfs service: ran")
|
||||||
|
|
||||||
// split new thread
|
// split new thread
|
||||||
DispatchQueue.global(qos: .default).async {
|
DispatchQueue.global(qos: .default).async {
|
||||||
|
@ -57,6 +60,10 @@ class TabFSService: NSObject, TabFSServiceProtocol {
|
||||||
|
|
||||||
class TabFSServiceDelegate: NSObject, NSXPCListenerDelegate {
|
class TabFSServiceDelegate: NSObject, NSXPCListenerDelegate {
|
||||||
func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool {
|
func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool {
|
||||||
|
|
||||||
|
|
||||||
|
os_log(.default, "TabFSmsg tfs service: starting delegate")
|
||||||
|
|
||||||
newConnection.remoteObjectInterface = NSXPCInterface(with: TabFSServiceConsumerProtocol.self)
|
newConnection.remoteObjectInterface = NSXPCInterface(with: TabFSServiceConsumerProtocol.self)
|
||||||
|
|
||||||
let exportedObject = TabFSService(app: newConnection.remoteObjectProxy as! TabFSServiceConsumerProtocol)
|
let exportedObject = TabFSService(app: newConnection.remoteObjectProxy as! TabFSServiceConsumerProtocol)
|
||||||
|
|
Loading…
Reference in a new issue