mirror of
https://github.com/osnr/TabFS.git
synced 2024-06-14 11:45:07 +02:00
safari: more cleanup and commenting
This commit is contained in:
parent
b6b61ee093
commit
9b4abc40ee
|
@ -18,23 +18,34 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
|
||||||
guard message["op"] as! String == "safari_did_connect" else { return }
|
guard message["op"] as! String == "safari_did_connect" else { return }
|
||||||
|
|
||||||
// The XPC service is a subprocess that lives outside the macOS App Sandbox.
|
// The XPC service is a subprocess that lives outside the macOS App Sandbox.
|
||||||
|
// (Safari extension native code, including this file, has to live in the sandbox.)
|
||||||
// It can do forbidden things like spawn tabfs filesystem and set up WebSocket server.
|
// It can do forbidden things like spawn tabfs filesystem and set up WebSocket server.
|
||||||
|
|
||||||
|
// We only use one native message to bootstrap the XPC service, then do all communications
|
||||||
|
// to that service (which in turn talks to tabfs.c) over WebSocket instead.
|
||||||
|
// (Safari makes doing native messaging quite painful, so we try to avoid it.
|
||||||
|
// It forces the browser to pop to front if you message Safari in the obvious way,
|
||||||
|
// for instance: https://developer.apple.com/forums/thread/122232
|
||||||
|
// And with the WebSocket, the XPC service can talk straight to background.js, whereas
|
||||||
|
// native messaging would require us here to sit in the middle.)
|
||||||
|
|
||||||
let connection = NSXPCConnection(serviceName: "com.rsnous.TabFSService")
|
let connection = NSXPCConnection(serviceName: "com.rsnous.TabFSService")
|
||||||
connection.remoteObjectInterface = NSXPCInterface(with: TabFSServiceProtocol.self)
|
connection.remoteObjectInterface = NSXPCInterface(with: TabFSServiceProtocol.self)
|
||||||
connection.resume()
|
connection.resume()
|
||||||
|
|
||||||
let service = connection.remoteObjectProxyWithErrorHandler { error in
|
let service = connection.remoteObjectProxyWithErrorHandler { error in
|
||||||
os_log(.default, "Received error: %{public}@", error as! CVarArg)
|
os_log(.default, "Received error: %{public}@", error as CVarArg)
|
||||||
} as? TabFSServiceProtocol
|
} as? TabFSServiceProtocol
|
||||||
|
|
||||||
// need this one XPC call to actually initialize the service
|
// Need this one XPC call to actually initialize the service.
|
||||||
service?.upperCaseString("hello XPC") { response in
|
service?.start() {
|
||||||
os_log(.default, "Response from XPC service: %{public}@", response)
|
os_log(.default, "Response from XPC service")
|
||||||
|
|
||||||
// FIXME: report port back?
|
// FIXME: report port back?
|
||||||
let response = NSExtensionItem()
|
let response = NSExtensionItem()
|
||||||
response.userInfo = [ "message": [ "aResponse to": "moop" ] ]
|
response.userInfo = [ "message": "alive" ]
|
||||||
|
// This response (over native messaging) prompts background.js to
|
||||||
|
// connect to the WebSocket server that the XPC service should now be running.
|
||||||
context.completeRequest(returningItems: [response]) { (what) in
|
context.completeRequest(returningItems: [response]) { (what) in
|
||||||
print(what)
|
print(what)
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
|
@ -67,7 +67,7 @@ class TabFSService: NSObject, TabFSServiceProtocol {
|
||||||
let context = NWConnection.ContentContext(identifier: "context", metadata: [metaData])
|
let context = NWConnection.ContentContext(identifier: "context", metadata: [metaData])
|
||||||
conn.send(content: req, contentContext: context, completion: .contentProcessed({ err in
|
conn.send(content: req, contentContext: context, completion: .contentProcessed({ err in
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os_log(.default, "req %{public}@ error: %{public}@", String(data: req, encoding: .utf8) as! CVarArg, err!.debugDescription as CVarArg)
|
os_log(.default, "req %{public}@ error: %{public}@", String(data: req, encoding: .utf8)!, err!.debugDescription as CVarArg)
|
||||||
// FIXME: ERROR
|
// FIXME: ERROR
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
@ -81,6 +81,7 @@ class TabFSService: NSObject, TabFSServiceProtocol {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send the response back to tabfs.c.
|
||||||
self.fsInput.write(withUnsafeBytes(of: UInt32(resp.count)) { Data($0) })
|
self.fsInput.write(withUnsafeBytes(of: UInt32(resp.count)) { Data($0) })
|
||||||
self.fsInput.write(resp)
|
self.fsInput.write(resp)
|
||||||
read()
|
read()
|
||||||
|
@ -89,15 +90,14 @@ class TabFSService: NSObject, TabFSServiceProtocol {
|
||||||
read()
|
read()
|
||||||
}
|
}
|
||||||
|
|
||||||
// split new thread
|
|
||||||
DispatchQueue.global(qos: .default).async {
|
DispatchQueue.global(qos: .default).async {
|
||||||
while true {
|
while true {
|
||||||
// read from them
|
// Blocking read from the tabfs process.
|
||||||
let length = self.fsOutput.readData(ofLength: 4).withUnsafeBytes { $0.load(as: UInt32.self) }
|
let length = self.fsOutput.readData(ofLength: 4).withUnsafeBytes { $0.load(as: UInt32.self) }
|
||||||
let req = self.fsOutput.readData(ofLength: Int(length))
|
let req = self.fsOutput.readData(ofLength: Int(length))
|
||||||
|
|
||||||
// send to other side of WEBSOCKET
|
|
||||||
if let handleRequest = handleRequest {
|
if let handleRequest = handleRequest {
|
||||||
|
// Send the request over the WebSocket connection to background.js in browser.
|
||||||
handleRequest(req)
|
handleRequest(req)
|
||||||
} else {
|
} else {
|
||||||
// FIXME: ERROR
|
// FIXME: ERROR
|
||||||
|
@ -107,9 +107,9 @@ class TabFSService: NSObject, TabFSServiceProtocol {
|
||||||
// FIXME: disable auto termination
|
// FIXME: disable auto termination
|
||||||
}
|
}
|
||||||
|
|
||||||
func upperCaseString(_ string: String, withReply reply: @escaping (String) -> Void) {
|
func start(withReply reply: @escaping () -> Void) {
|
||||||
let response = string.uppercased()
|
// This XPC call is enough to just force the XPC service to be started.
|
||||||
reply(response)
|
reply()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,5 +8,5 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
@objc public protocol TabFSServiceProtocol {
|
@objc public protocol TabFSServiceProtocol {
|
||||||
func upperCaseString(_ string: String, withReply reply: @escaping (String) -> Void)
|
func start(withReply reply: @escaping () -> Void)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue