josh- / CloudyTabs

CloudyTabs is a simple menu bar application that lists your iCloud Tabs.
http://joshparnham.com/projects/cloudytabs/
789 stars 52 forks source link

Refreshed only when I open Safari #45

Open timscha opened 6 years ago

timscha commented 6 years ago

Hi! I tried the latest version on macOS 10.13. My problem is that the App refresh the tabs only, everytime I re-open Safari on my Mac. Do you need some more informations?

mynameistechno commented 6 years ago

Same problem for me. The tabs in CloudyTabs are stale until I open Safari, then they update. Of course this defeats the purpose of CloudyTabs...

jamie--stewart commented 6 years ago

Hi, I'm seeing the same behaviour where only opening safari will update the tabs.

macOS 10.13.5 (High Sierra), CloudyTabs 1.9.1

If you need any logs or anything to help with reproduction, shout out!

josh- commented 6 years ago

Thanks for the feedback @timscha, @mynameistechno and @jamie--stewart! I've done a bit of digging to try and resolve this but unfortunately haven't been able to come up with a solution as of yet. If anyone has any thoughts I'd love to hear them!

Technical investigation:

The SafariBookmarksSyncAgent (located at /System/Library/CoreServices/SafariSupport.bundle/Contents/MacOS/SafariBookmarksSyncAgent) is the daemon that is responsible for syncing iCloud Tabs in recent macOS version. It receives notifications from Apple's Push Notification Service (through apsd) and is registered with it at startup.

SafariCore (located at /System/Library/PrivateFrameworks/SafariCore.framework/Versions/A/SafariCore) is the executable responsible for establishing a connection to this XPC service and writing the resulting data to the CloudTabs.db database (at /Users/josh/Library/Safari/CloudTabs.db – read by CloudyTabs). It is used by the Safari application and thus will only write these values to the database when Safari is running. This is observable by using the "File Activity" report in Instruments.app and observing SafariCore modifying the database through its WBSSQLiteStatement statements.

I've tried to establish an XPC connection to the SafariBookmarksSyncAgent in the same manner that SafariCore does by using the code in this Gist (which was from an otool reverse-engineering of SafariCore). However the invalidationHandler is always immediately called and thus I can't establish a connection to the service. This seems strange because SafariBookmarksSyncAgent's shouldAcceptNewConnection method seems to just return YES without checking for a callers bundle or anything:

screen shot 2018-05-20 at 12 11 28 pm

This leads me to believe that I am somehow incorrectly trying to connect to the service (probably because, the initWithMachServiceName:options: seems to only look in /Library/LaunchAgents or ~/Library/LaunchAgents). Furthermore, the SafariBookmarksSyncAgent is sandboxed so that might cause some further considerations.

I'll keep investigating but if anyone else has any further insight I'd be extremely grateful to hear it 🙌

josh- commented 6 years ago

Update

Turns out all that needed to be done was actually link against SafariSupport.bundle and then the XPC connection works totally fine 😂 (after removing the NSXPCConnectionPrivileged flag)

I've been able to successfully view tabs updating without having Safari open. 👍 The next steps will be to try and integrate this into CloudyTabs – I'll keep you posted with how that's going!

jamie--stewart commented 6 years ago

Great, thanks! Good spot 👌

timscha commented 6 years ago

@josh- If you need some testers or other help let me know. :)

felixradtke commented 3 years ago

Any update here? I have the same issue on 2.0.0.

incanus commented 2 years ago

Not ideal, but I've made a pretty lightweight way to automatically open and close Safari on an interval to help with this. I use SwiftBar/xbar/BitBar and a script run on a 15-minute interval (so named bouncesafari.15m.sh) containing the following:

#!/usr/bin/env sh

open -g -j /Applications/Safari.app
sleep 10
osascript -e 'tell app "Safari" to quit'

This doesn't take keyboard focus as -g opens in the background and -j starts hidden, then after 10 seconds Safari is quit. You do see it briefly in the Dock, but I can live with that for now.

Hope it helps someone else!

incanus commented 2 years ago

A tweak to the above, which helps if you start using Safari for some reason and it's the active, frontmost app:

#!/usr/bin/env bash

open -g -j /Applications/Safari.app
sleep 10
FRONT=`osascript -e 'tell app "System Events" to get name of processes whose frontmost is true'`
if [ $FRONT != "Safari" ]; then
    osascript -e 'tell app "Safari" to quit'
fi
incanus commented 2 years ago

I've homed in on a better solution for my case, which is a Hammerspoon action to open Safari in the background (not stealing focus) based on a key shortcut, then quit after five seconds in order to sync bookmarks.

hs.hotkey.bind({'cmd', 'alt', 'ctrl'}, 's', function()
  hs.task.new('/usr/bin/open', nil, {'-g', '-j', '-a', 'Safari'}):start()
  hs.timer.doAfter(5, function()
    _, _, front = hs.osascript.applescript('tell app "System Events" to get name of processes whose frontmost is true')
    if front ~= 'Safari' then
      hs.appfinder.appFromName('Safari'):kill()
    end
  end)
end)
Bicheng-G commented 1 year ago

Update

Turns out all that needed to be done was actually link against SafariSupport.bundle and then the XPC connection works totally fine 😂 (after removing the NSXPCConnectionPrivileged flag)

I've been able to successfully view tabs updating without having Safari open. 👍 The next steps will be to try and integrate this into CloudyTabs – I'll keep you posted with how that's going!

Hi @josh-, may I know is this fixed? As of now, I still need to run safari to have the tabs updated in CloudyTabs, would love to hear back from you.