Stupid Mac::Glue Tricks: Saving Safari URLs with Tabs

| | Comments (0)
I don't know if Gruber-man ever came up with a solution to the unscriptable tabs, I have a workaround.

You cannot use Apple events to get every URL of every open document in Safari: the documents in nonvisible tabs are unavailable. So this workaround uses UI Scripting (turn it on in System Preferences -> Universal Access -> Enable access for assistive devices) to flip through the tabs. It (perhaps unreliably, if you have the same URL open in more than one tab) stops when the first URL fetched is equal to the last.

It does this for each window, then closes the window and moves on (it is not a simple matter to switch windows, and since I use this for quitting Safari, I want the windows closed anyway). It then simply prints out all the URLs into a Data::Dumper data structure.

#!/usr/bin/perl
use warnings;
use strict;
 
use Mac::Glue ':all';
 
my $safari = new Mac::Glue 'Safari';
my $sysevt = new Mac::Glue 'System Events';
 
my $next_tab = $sysevt->obj(
    menu_item               => 'Select Next Tab',
    menu                    => 1,
    menu_bar_item           => 'Window',
    menu_bar                => 1,
    application_process     => 'Safari'
);
 
$safari->activate;
 
my @windows;
my $win = 0;
 
my $windows = $safari->obj('windows');
for my $window ($windows->get) {
    my $url;
    while (defined(my $url = get_doc_url($window))) {
        push @{$windows[$win]}, $url if length $url;
    }
    $win++ if defined $windows[$win];
    $window->close;
}
 
use Data::Dumper;
print Dumper \@windows;
 
sub get_doc_url {
    my($window) = @_;
    my $document = $window->prop('document')->get;
    return unless $document;
 
    my $url = $document->prop('url')->get;
    $url = '' unless defined($url);
    return if @windows && $windows[$win] && @{$windows[$win]} &&
        $url eq $windows[$win][0];
 
    $next_tab->click;
 
    return $url;
}

Then you can do what you want the data structure. Here's what I do:

#!/usr/bin/perl
use warnings;
use strict;
 
use Mac::Glue ':all';
 
my $safari = new Mac::Glue 'Safari';
 
$safari->activate;
 
sub open_windows {
    my($windows) = @_;
    for my $window (@$windows) {
        $safari->make(new => 'document'); sleep 2;
        $safari->open_location($_) for @$window;
    }
 
}
 
my $VAR1;
 
$VAR1 = [
          [
            'https://pudge.net/',
            'https://pudge.net/tunes/'
          ],
          [
            'http://projects.pudge.net/'
          ]
        ];
 
open_windows($VAR1);

Saving and restoring to a file instead of copying/pasting the data structure is an exercise left to the reader. use.perl.org

Leave a comment

<pudge/*> (pronounced "PudgeGlob") is thousands of posts over many years by Pudge.

"It is the common fate of the indolent to see their rights become a prey to the active. The condition upon which God hath given liberty to man is eternal vigilance; which condition if he break, servitude is at once the consequence of his crime and the punishment of his guilt."

About this Entry

This page contains a single entry by pudge published on May 17, 2007 8:35 AM.

Mental institution, Michael. Might be something you oughtta think about. was the previous entry in this site.

Pudge Pwns PBS is the next entry in this site.

Find recent content on the main index or look in the archives to find all content.