summaryrefslogtreecommitdiff
path: root/extension
diff options
context:
space:
mode:
authorOmar Rizwan <omar@omar.website>2021-02-08 02:32:21 -0800
committerOmar Rizwan <omar@omar.website>2021-02-08 02:32:21 -0800
commit7211a5fdead06a3c1b4cb15af7ce2cf883b19346 (patch)
tree7b8437dc312fb86890276e029b568dbbbf3f8d0d /extension
parent930352dd42f432886897d7bf66c522a41d8a0486 (diff)
downloadTabFS-7211a5fdead06a3c1b4cb15af7ce2cf883b19346.tar.gz
TabFS-7211a5fdead06a3c1b4cb15af7ce2cf883b19346.zip
safari: start migration to using out-of-band WebSocket to do extension<=>fs comm
Diffstat (limited to 'extension')
-rw-r--r--extension/background.js29
-rw-r--r--extension/safari/TabFS/TabFS Extension/SafariWebExtensionHandler.swift82
-rw-r--r--extension/safari/TabFS/TabFS.xcodeproj/project.xcworkspace/xcuserdata/osnr.xcuserdatad/UserInterfaceState.xcuserstatebin61059 -> 58463 bytes
-rw-r--r--extension/safari/TabFS/TabFS.xcodeproj/xcuserdata/osnr.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist12
-rw-r--r--extension/safari/TabFS/TabFSService/TabFSService.swift78
-rw-r--r--extension/safari/TabFS/TabFSService/TabFSServiceProtocols.swift5
-rw-r--r--extension/safari/TabFS/TabFSService/main.swift2
7 files changed, 111 insertions, 97 deletions
diff --git a/extension/background.js b/extension/background.js
index f38f29e..62ec7d0 100644
--- a/extension/background.js
+++ b/extension/background.js
@@ -713,24 +713,29 @@ async function onMessage(req) {
};
function tryConnect() {
- console.log('start tryConnect');
- port = chrome.runtime.connectNative('com.rsnous.tabfs');
- console.log('start tryConnect - did connectNative');
- port.onMessage.addListener(onMessage);
- port.onDisconnect.addListener(p => {console.log('disconnect', p)});
-
- console.log('tryConnect - about to sNM');
// Safari is very weird -- it has this native app that we have to talk to,
- // so we poke that app to wake it up, get it to start the TabFS process,
- // and get it to start calling us whenever TabFS wants to do an FS call.
+ // so we poke that app to wake it up, get it to start the TabFS process
+ // and boot a WebSocket, then connect to it.
// Is there a better way to do this?
if (chrome.runtime.getURL('/').startsWith('safari-web-extension://')) { // Safari-only
- chrome.runtime.sendNativeMessage('com.rsnous.tabfs', {op: 'safari_did_connect'}, function(resp) {
- console.log('didConnect resp');
+ chrome.runtime.sendNativeMessage('com.rsnous.tabfs', {op: 'safari_did_connect'}, resp => {
console.log(resp);
+ const socket = new WebSocket('ws://localhost:9991');
+
+ socket.addEventListener('message', event => {
+ onMessage(JSON.parse(event.data));
+ });
+
+ port = { postMessage(message) {
+ socket.send(JSON.stringify(message));
+ } };
});
+ return;
}
- console.log('tryConnect - did sNM');
+
+ port = chrome.runtime.connectNative('com.rsnous.tabfs');
+ port.onMessage.addListener(onMessage);
+ port.onDisconnect.addListener(p => {console.log('disconnect', p)});
}
if (!TESTING) {
diff --git a/extension/safari/TabFS/TabFS Extension/SafariWebExtensionHandler.swift b/extension/safari/TabFS/TabFS Extension/SafariWebExtensionHandler.swift
index 67da485..a1ae4ff 100644
--- a/extension/safari/TabFS/TabFS Extension/SafariWebExtensionHandler.swift
+++ b/extension/safari/TabFS/TabFS Extension/SafariWebExtensionHandler.swift
@@ -6,48 +6,8 @@
//
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) {
@@ -60,27 +20,35 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
guard let message = item.userInfo?["message"] as? [AnyHashable: Any] else { return }
if message["op"] as! String == "safari_did_connect" {
-
os_log(.default, "TabFSmsg sdc")
- TabFSServiceManager.shared.connect()
-//
-// let response = NSExtensionItem()
-// response.userInfo = [ "message": [ "aResponse to": "moop" ] ]
-// context.completeRequest(returningItems: [response], completionHandler: nil)
+
+ // The XPC service is a subprocess that lives outside the macOS App Sandbox.
+ // It can do forbidden things like spawn tabfs filesystem and set up WebSocket server.
+
+ let connection = NSXPCConnection(serviceName: "com.rsnous.TabFSService")
+
+ connection.remoteObjectInterface = NSXPCInterface(with: TabFSServiceProtocol.self)
+
+ connection.resume()
+
+ let service = connection.remoteObjectProxyWithErrorHandler { error in
+ os_log(.default, "Received error: %{public}@", error as! CVarArg)
+ } as? TabFSServiceProtocol
+
+ // need this one XPC call to actually initialize the service
+ service?.upperCaseString("hello XPC") { response in
+ os_log(.default, "Response from XPC service: %{public}@", response)
+ }
+
+ // FIXME: report port back?
+ let response = NSExtensionItem()
+ response.userInfo = [ "message": [ "aResponse to": "moop" ] ]
+ context.completeRequest(returningItems: [response]) { (what) in
+ print(what)
+ }
return
}
-
- TabFSServiceManager.shared.response(message)
-//
-// os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@", op as! CVarArg)
-
-// let response = NSExtensionItem()
-// response.userInfo = [ "message": [ "Response to": op ] ]
-//
-// // How do I get too the app????
-//
-// context.completeRequest(returningItems: [response], completionHandler: nil)
}
}
diff --git a/extension/safari/TabFS/TabFS.xcodeproj/project.xcworkspace/xcuserdata/osnr.xcuserdatad/UserInterfaceState.xcuserstate b/extension/safari/TabFS/TabFS.xcodeproj/project.xcworkspace/xcuserdata/osnr.xcuserdatad/UserInterfaceState.xcuserstate
index 1fff19a..93b8259 100644
--- a/extension/safari/TabFS/TabFS.xcodeproj/project.xcworkspace/xcuserdata/osnr.xcuserdatad/UserInterfaceState.xcuserstate
+++ b/extension/safari/TabFS/TabFS.xcodeproj/project.xcworkspace/xcuserdata/osnr.xcuserdatad/UserInterfaceState.xcuserstate
Binary files differ
diff --git a/extension/safari/TabFS/TabFS.xcodeproj/xcuserdata/osnr.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/extension/safari/TabFS/TabFS.xcodeproj/xcuserdata/osnr.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
index 87a2930..0a7caef 100644
--- a/extension/safari/TabFS/TabFS.xcodeproj/xcuserdata/osnr.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
+++ b/extension/safari/TabFS/TabFS.xcodeproj/xcuserdata/osnr.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
@@ -14,8 +14,8 @@
filePath = "TabFS Extension/SafariWebExtensionHandler.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "57"
- endingLineNumber = "57"
+ startingLineNumber = "17"
+ endingLineNumber = "17"
landmarkName = "beginRequest(with:)"
landmarkType = "7">
</BreakpointContent>
@@ -46,8 +46,8 @@
filePath = "TabFS Extension/SafariWebExtensionHandler.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "60"
- endingLineNumber = "60"
+ startingLineNumber = "20"
+ endingLineNumber = "20"
landmarkName = "beginRequest(with:)"
landmarkType = "7">
</BreakpointContent>
@@ -62,8 +62,8 @@
filePath = "TabFS Extension/SafariWebExtensionHandler.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
- startingLineNumber = "55"
- endingLineNumber = "55"
+ startingLineNumber = "15"
+ endingLineNumber = "15"
landmarkName = "beginRequest(with:)"
landmarkType = "7">
</BreakpointContent>
diff --git a/extension/safari/TabFS/TabFSService/TabFSService.swift b/extension/safari/TabFS/TabFSService/TabFSService.swift
index eb7508f..e49d80f 100644
--- a/extension/safari/TabFS/TabFSService/TabFSService.swift
+++ b/extension/safari/TabFS/TabFSService/TabFSService.swift
@@ -6,16 +6,14 @@
//
import Foundation
+import Network
import os.log
class TabFSService: NSObject, TabFSServiceProtocol {
var fs: Process!
var fsInput: FileHandle!
var fsOutput: FileHandle!
-
- init(app: TabFSServiceConsumerProtocol) {
- super.init()
-
+ func startFs() {
fs = Process()
fs.executableURL = URL(fileURLWithPath: "/Users/osnr/Code/tabfs/fs/tabfs")
fs.currentDirectoryURL = fs.executableURL?.deletingLastPathComponent()
@@ -32,6 +30,52 @@ class TabFSService: NSObject, TabFSServiceProtocol {
os_log(.default, "TabFSmsg tfs service: willrun")
try! fs.run()
os_log(.default, "TabFSmsg tfs service: ran")
+ }
+
+ var ws: NWListener!
+ func startWs() {
+ // websocket server
+ let port = NWEndpoint.Port(rawValue: 9991)!
+ let parameters = NWParameters(tls: nil)
+ parameters.allowLocalEndpointReuse = true
+ parameters.includePeerToPeer = true
+ let opts = NWProtocolWebSocket.Options()
+ opts.autoReplyPing = true
+ parameters.defaultProtocolStack.applicationProtocols.insert(opts, at: 0)
+
+ ws = try! NWListener(using: parameters, on: port)
+ ws.start(queue: .main)
+ }
+
+ override init() {
+ super.init()
+
+ startFs()
+ startWs()
+
+ var handleRequest: ((_ req: Data) -> Void)?
+ ws.newConnectionHandler = { conn in
+ conn.start(queue: .main)
+ handleRequest = { req in
+ conn.send(content: req, completion: .contentProcessed({ err in
+ if err != nil {
+ // FIXME: ERROR
+ }
+ }))
+ }
+
+ func read() {
+ conn.receiveMessage { (resp, context, isComplete, err) in
+ guard let resp = resp else {
+ // FIXME err
+ return
+ }
+ self.fsInput.write(withUnsafeBytes(of: UInt32(resp.count)) { Data($0) })
+ self.fsInput.write(resp)
+ read()
+ }
+ }
+ }
// split new thread
DispatchQueue.global(qos: .default).async {
@@ -40,11 +84,15 @@ class TabFSService: NSObject, TabFSServiceProtocol {
let length = self.fsOutput.readData(ofLength: 4).withUnsafeBytes { $0.load(as: UInt32.self) }
os_log(.default, "TabFSmsg tfs service: read %{public}d", length)
let req = self.fsOutput.readData(ofLength: Int(length))
- // send to other side of XPC conn
- app.request(req)
+
+ // send to other side of WEBSOCKET
+ if let handleRequest = handleRequest {
+ handleRequest(req)
+ } else {
+ // FIXME: ERROR
+ }
}
}
-
// FIXME: disable auto termination
}
@@ -52,22 +100,18 @@ class TabFSService: NSObject, TabFSServiceProtocol {
let response = string.uppercased()
reply(response)
}
-
- func response(_ resp: Data) {
- fsInput.write(withUnsafeBytes(of: UInt32(resp.count)) { Data($0) })
- fsInput.write(resp)
- }
+//
+// func response(_ resp: Data) {
+// fsInput.write(withUnsafeBytes(of: UInt32(resp.count)) { Data($0) })
+// fsInput.write(resp)
+// }
}
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)
+ let exportedObject = TabFSService()
newConnection.exportedInterface = NSXPCInterface(with: TabFSServiceProtocol.self)
newConnection.exportedObject = exportedObject
diff --git a/extension/safari/TabFS/TabFSService/TabFSServiceProtocols.swift b/extension/safari/TabFS/TabFSService/TabFSServiceProtocols.swift
index 298015a..8aedd87 100644
--- a/extension/safari/TabFS/TabFSService/TabFSServiceProtocols.swift
+++ b/extension/safari/TabFS/TabFSService/TabFSServiceProtocols.swift
@@ -7,11 +7,6 @@
import Foundation
-@objc public protocol TabFSServiceConsumerProtocol {
- func request(_ req: Data)
-}
@objc public protocol TabFSServiceProtocol {
func upperCaseString(_ string: String, withReply reply: @escaping (String) -> Void)
-
- func response(_ resp: Data)
}
diff --git a/extension/safari/TabFS/TabFSService/main.swift b/extension/safari/TabFS/TabFSService/main.swift
index 39c5a75..f0a4486 100644
--- a/extension/safari/TabFS/TabFSService/main.swift
+++ b/extension/safari/TabFS/TabFSService/main.swift
@@ -7,6 +7,8 @@
import Foundation
+ProcessInfo.processInfo.disableAutomaticTermination("ok")
+
let delegate = TabFSServiceDelegate()
let listener = NSXPCListener.service()
listener.delegate = delegate