1

I have installed chrome-cli in my Mac. I'm trying to execute chrome-cli commands from Swift with following code:

    import Foundation

func shell(_ command: String) -> String {
    let task = Process()
    let pipe = Pipe()

    task.standardOutput = pipe
    task.arguments = ["-c", command]
    task.launchPath = "/bin/bash"
    task.launch()

    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    let output = String(data: data, encoding: .utf8)!

    return output
}

// Example 1: 
let example1 = shell("/usr/local/bin/chrome-cli --help") //returns expected result
let example2 = shell("/usr/local/bin/chrome-cli list tabs") // return ""

Here, example 1 is calling with single argument and works well, i.e it print same result like we execute the command in Terminal.

but for example 2, we have more than 1 argument and it always returns empty result. While the same command on Terminal print list of tab currently opened.

I think the process doesn't wait for command to return the result as it takes 1-2 seconds to list tabs in Terminal app. or its some other issue?

Please help. Thanks.

1 Answers1

1

Since chrome-cli 1.6.0 was released in 2018 but new Chrome versions with new features appear regularly I suggest to use Chrome directly via SBApplication to access to any needed info e.g.:

import ScriptingBridge

@objc protocol ChromeTab {
    @objc optional var id: Int {get}
    @objc optional var title: String {get}
}
extension SBObject: ChromeTab {}

@objc protocol ChromeWindow {
    @objc optional var tabs: [ChromeTab] {get}
}
extension SBObject: ChromeWindow {}

@objc protocol ChromeApplication {
    @objc optional var windows: [ChromeWindow] {get}
}
extension SBApplication : ChromeApplication {}

// Print all tabs
if let chrome = SBApplication(bundleIdentifier: "com.google.Chrome") as ChromeApplication? {
    if let window = chrome.windows?.first {
        window.tabs?.forEach {
            if let id = $0.id, let title = $0.title {
                print("[\(id)] -", title)
            }
        }
    }
}

For more info about Chrome Extensions look at https://developer.chrome.com/extensions/devguide

iUrii
  • 11,742
  • 1
  • 33
  • 48
  • That seems cool alternative but I ```chrome.windows``` return 0 element while I have 2 windows open. Do I need some permission? Moreover, I also need to bring a selected tab to front from swift. If you can help about that, it would be awesome. I'm also checking referenced documentation and seems very helpful. – Zahid Usman Cheema Nov 19 '20 at 06:05
  • @ZahidUsmanCheema On macos Catalina the system asks to grant access from my app to Chrome and this settings are in System Preferences > Security & Privacy > Automation and after I have access to all data. Maybe it's permission with your user account because both scripts yours and my work OK. – iUrii Nov 19 '20 at 09:02
  • @ZahidUsmanCheema try to add `NSAppleEventsUsageDescription` in your Info.plist (https://stackoverflow.com/questions/61445371/applescriptingbridge-for-music-app-not-returning-sources`) – iUrii Nov 19 '20 at 21:14
  • I did. Still no. Should I try with Sandbox mode on or off? – Zahid Usman Cheema Nov 21 '20 at 20:00
  • This worked: "After adding NSAppleEventsUsageDescription to info.plist and enabling events in hardended runtime it works now. Thank you." – Zahid Usman Cheema Nov 21 '20 at 20:12
  • just one more thing. How can I execute a function. I want to call chrome.tabs.hightligh(hightlightInfo) but I can't pass params. – Zahid Usman Cheema Nov 25 '20 at 10:56
  • @ZahidUsmanCheema Unfortunately you can't use all props/funcs from chrome extentions js api via Scripting Bridge but you can use available selectors from `chrome._ctx->_thunksForSelectors` which you can look in 'Variables View' by setting a breakpoint while debugging. For instance for setting an active tab you should add next method to ChromeWindow object: `@objc optional func setActiveTabIndex(_ index: Int)` etc. – iUrii Nov 25 '20 at 14:12