summaryrefslogtreecommitdiff
path: root/extension
diff options
context:
space:
mode:
authorOmar Rizwan <omar@omar.website>2021-02-08 13:45:26 -0800
committerOmar Rizwan <omar@omar.website>2021-02-08 13:45:26 -0800
commit0f2ab4b4de7e828757091e323be1caab0a70b770 (patch)
tree39d35441314690e45235af7e2ecee91c92a19264 /extension
parent2f639e2a0276efb3dbb8a470e61ee8ffc2503f5b (diff)
downloadTabFS-0f2ab4b4de7e828757091e323be1caab0a70b770.tar.gz
TabFS-0f2ab4b4de7e828757091e323be1caab0a70b770.zip
safari: fix some races when you reload Web inspector, make ws connection retry
Diffstat (limited to 'extension')
-rw-r--r--extension/background.js25
-rw-r--r--extension/safari/README.md10
-rw-r--r--extension/safari/TabFS/TabFS Extension/SafariWebExtensionHandler.swift17
-rw-r--r--extension/safari/TabFS/TabFS.xcodeproj/project.xcworkspace/xcuserdata/osnr.xcuserdatad/UserInterfaceState.xcuserstatebin61961 -> 64115 bytes
-rw-r--r--extension/safari/TabFS/TabFSServer/main.swift9
-rw-r--r--extension/safari/TabFS/TabFSService/TabFSService.swift31
6 files changed, 68 insertions, 24 deletions
diff --git a/extension/background.js b/extension/background.js
index 62ec7d0..e31a4c4 100644
--- a/extension/background.js
+++ b/extension/background.js
@@ -720,15 +720,26 @@ function tryConnect() {
if (chrome.runtime.getURL('/').startsWith('safari-web-extension://')) { // Safari-only
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));
- });
+ let socket;
+ function connectSocket(checkAfterTime) {
+ socket = new WebSocket('ws://localhost:9991');
+ socket.addEventListener('message', event => {
+ onMessage(JSON.parse(event.data));
+ });
+
+ port = { postMessage(message) {
+ socket.send(JSON.stringify(message));
+ } };
- port = { postMessage(message) {
- socket.send(JSON.stringify(message));
- } };
+ setTimeout(() => {
+ if (socket.readyState !== 1) {
+ console.log('ws connection failed, retrying in', checkAfterTime);
+ connectSocket(checkAfterTime * 2);
+ }
+ }, checkAfterTime);
+ }
+ connectSocket(200);
});
return;
}
diff --git a/extension/safari/README.md b/extension/safari/README.md
index 9ceafdc..8a47d23 100644
--- a/extension/safari/README.md
+++ b/extension/safari/README.md
@@ -24,8 +24,12 @@ it's mounted.
### tips
- To open Web inspector: Safari -> Develop menu -> Web Extension
- Background Pages -> TabFS
+ Background Pages -> TabFS.
-- You need to rebuild if you change background.js. This is pretty
- annoying.
+ Refreshing this inspector should reload the tabfs filesystem, also.
+
+- You need to rebuild in Xcode any time you change background.js
+ (because the extension files are copied into the extension, rather
+ than running directly from folder as in Firefox and Chrome). This is
+ pretty annoying.
diff --git a/extension/safari/TabFS/TabFS Extension/SafariWebExtensionHandler.swift b/extension/safari/TabFS/TabFS Extension/SafariWebExtensionHandler.swift
index 75790fa..dc30cc4 100644
--- a/extension/safari/TabFS/TabFS Extension/SafariWebExtensionHandler.swift
+++ b/extension/safari/TabFS/TabFS Extension/SafariWebExtensionHandler.swift
@@ -17,16 +17,20 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
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 process that can live 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.
- // 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.
+ // We only use one native message, to bootstrap the XPC service (TabFSService).
+ // Then the XPC service starts TabFSServer. TabFSServer is separate because
+ // XPC services get killed by the OS after a minute or two; TabFSServer
+ // is just a normal process that can live on. It talks straight
+ // to background.js (which in turn talks to tabfs.c) over a WebSocket.
+
// (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
+ // And with the WebSocket, the server 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")
@@ -44,8 +48,9 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
// FIXME: report port back?
let response = NSExtensionItem()
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.
+ // This response (over native messaging) will prompt background.js to
+ // connect to the WebSocket server of TabFSServer, which should
+ // now be running.
context.completeRequest(returningItems: [response]) { (what) in
print(what)
}
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 db4d28a..96586ef 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/TabFSServer/main.swift b/extension/safari/TabFS/TabFSServer/main.swift
index 245bfb1..76da2a0 100644
--- a/extension/safari/TabFS/TabFSServer/main.swift
+++ b/extension/safari/TabFS/TabFSServer/main.swift
@@ -75,8 +75,9 @@ class TabFSServer {
func read() {
conn.receiveMessage { (resp, context, isComplete, err) in
guard let resp = resp else {
- // FIXME err
- os_log(.default, "resp error: %{public}@", err!.debugDescription as CVarArg)
+ if let err = err {
+ os_log(.default, "resp error: %{public}@", err.debugDescription as CVarArg)
+ }
return
}
@@ -104,10 +105,10 @@ class TabFSServer {
}
}
- // FIXME: notify
-
+ print("OK")
}
}
let server = TabFSServer()
+
dispatchMain()
diff --git a/extension/safari/TabFS/TabFSService/TabFSService.swift b/extension/safari/TabFS/TabFSService/TabFSService.swift
index 4a86dd6..5bf55ee 100644
--- a/extension/safari/TabFS/TabFSService/TabFSService.swift
+++ b/extension/safari/TabFS/TabFSService/TabFSService.swift
@@ -12,13 +12,36 @@ import os.log
class TabFSService: NSObject, TabFSServiceProtocol {
func start(withReply reply: @escaping () -> Void) {
// This XPC call is enough to just force the XPC service to be started.
- os_log("HELLO")
+
+ // kill old copies of TabFSServer
+ let killall = Process()
+ killall.launchPath = "/usr/bin/killall"
+ killall.arguments = ["TabFSServer"]
+ killall.launch()
+ killall.waitUntilExit()
+
+ // spin until old TabFSServer (if any) is gone
+ while true {
+ let pgrep = Process()
+ pgrep.launchPath = "/usr/bin/pgrep"
+ pgrep.arguments = ["TabFSServer"]
+ pgrep.launch()
+ pgrep.waitUntilExit()
+ if pgrep.terminationStatus != 0 { break }
+
+ Thread.sleep(forTimeInterval: 0.01)
+ }
+
let server = Process()
- os_log("HOW ARE YOU?")
+ let serverOutput = Pipe()
server.executableURL = Bundle.main.url(forResource: "TabFSServer", withExtension: "")!
- os_log("I AM GOOD")
+ server.standardOutput = serverOutput
server.launch()
- os_log("GREAT")
+
+ // FIXME: should we wait for some signal that the server is ready?
+ // right now, background.js will just periodically retry until it can connect.
+
+ // tell background.js to try to connect.
reply()
}
}