OSX Cocoa 应用程序 - 获取 Safari 标签页信息

3

我想知道是否可以通过编程来获取Safari的任何选项卡/窗口信息?

有没有相应的库可以实现这个功能?

我更倾向于使用Cocoa框架,而不是苹果脚本。


你想要实现什么目标? - Willeke
目标是在用户开启此程序时了解其浏览习惯,他们将为该程序启用可访问性。 - Jono
@Jono,你找到任何答案了吗?我也卡住了,正在努力解决。 - vicky
@vicky 当时除了通过Apple脚本没有其他方法。 - Jono
1个回答

2
你可以使用Scripting Bridge辅助功能对象来完成这个操作。前者类似于将AppleScript翻译成Objective-C,而后者可以使用开发人员工具的辅助功能检查器进行检查。这两种技术都有其特点,而且文档不是很完善。

编辑:

Scripting Bridge示例:

SafariApplication *SafariApp = [SBApplication applicationWithBundleIdentifier:@"com.apple.Safari"];
for (SafariWindow *window in SafariApp.windows)
{
    for (SafariTab *tab in window.tabs)
        NSLog(@"%@", tab.name);
}

在Safari中,可访问对象的层次结构是什么。
AXApplication
 AXWindow
  AXTabGroup
   AXRadioButton

例子(不会在选美比赛中获奖):
static NSArray *getAXUIElements(AXUIElementRef theContainer, CFStringRef theRole)
{
    // get children of theContainer
    AXError error;
    NSMutableArray *array = [NSMutableArray array];
    CFTypeRef children;
    error = AXUIElementCopyAttributeValue(theContainer, kAXChildrenAttribute, &children);
    if (error != kAXErrorSuccess)
        return nil;
    // filter children whose role is theRole
    for (CFIndex i = 0; i < CFArrayGetCount(children); i++)
    {
        AXUIElementRef child = CFArrayGetValueAtIndex(children, i);
        CFTypeRef role;
        error = AXUIElementCopyAttributeValue(child, kAXRoleAttribute, &role);
        if (error == kAXErrorSuccess)
        {
            if (CFStringCompare(role, theRole, 0) == kCFCompareEqualTo)
                [array addObject:(__bridge id)child];
            CFRelease(role);
        }
    }
    CFRelease(children);
    return [NSArray arrayWithArray:array];
}

static void logTabs()
{
    // get the title of every tab of every window of Safari
    NSArray *appArray = [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.Safari"];
    AXUIElementRef SafariApp = AXUIElementCreateApplication([[appArray objectAtIndex:0] processIdentifier]);
    if (SafariApp)
    {
        NSArray *windowArray = getAXUIElements(SafariApp, kAXWindowRole);
        for (id window in windowArray)
        {
            NSArray *tabGroupArray = getAXUIElements((__bridge AXUIElementRef)(window), kAXTabGroupRole);
            for (id tabGroup in tabGroupArray)
            {
                NSArray *radioButtonArray = getAXUIElements((__bridge AXUIElementRef)(tabGroup), kAXRadioButtonRole);
                for (id radioButton in radioButtonArray)
                {
                    CFTypeRef title = NULL;
                    AXError error = AXUIElementCopyAttributeValue((__bridge AXUIElementRef)radioButton, kAXTitleAttribute, &title);
                    if (error == kAXErrorSuccess)
                    {
                        NSLog(@"%@", title);
                        CFRelease(title);
                    }
                }
            }
        }
        CFRelease(SafariApp);
    }
}

你能用一些函数式代码演示一下这个任务吗?这个任务只是获取Safari的一个或所有选项卡。 - Jono
尽管这个答案可以允许检索当前打开的标签页,但它并不是事件驱动的,并且最终会失败。 - user2317421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接