JXAでSafari, Chrome, Firefoxを操作する際の違い

  • 35
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

まとめ

Safari: Apple謹製だけど機能少ない
Chrome: なぜか異常に充実
Firefox: ほぼ何もできない


気が向いたときにちょっとずつ更新中

Safari Chrome Firefox
参照 Application( "Safari" ) Application( "Chrome" ) Application( "Firefox" )
ウィンドウ
(全て)
app.windows() app.windows() app.windows()
ウィンドウ
(最前面)
app.windows[0] app.windows[0] app.windows[0]
ウィンドウ
作成
app .Document().make() app .Window().make() -
タブ
(全て)
win.tabs() win.tabs() -
タブ
(表示中)
win .currentTab() win .activeTab() -
タブ
切り替え
win .currentTab = tab win .activeTabIndex = index -
URL移動 tab.url = "http://qiita.com" tab.url = "http://qiita.com" -
JS実行 app .doJavaScript("alert('hi.'),{in: tab}) app .execute(tab, {javascript:"alert('hi.')"}) -
ページ更新 tab.url = tab.url() tab.reload() -
読込中止 - tab.stop() -
戻る & 進む (やろうと思えばdoJavaScriptで) tab.goBack();
tab.goForward();
-
ブックマーク - 参照可(長いので省略) -
履歴 - - -

Chromeの新規ウィンドウ作成は戻り値でそのままWindowを得られる。
SafariはDocumentが返ってくるからURL移動したいときとか困る。
(app.Window().make()できればいいのに・・・)

Windowを得る場合は以下のようにするといいのかもしれない・・・

var Safari = Application("Safari");
var doc = Safari.Document().make();
var win = Safari.windows[doc.name()];

//URL移動
win.currentTab.url = "http://qiita.com"

使ってみる

以下の記事と同じことをするコードを書いてみました。

JXAを知らない方はこちら。

やること

下準備

  • 待ち秒数を指定 (DELAY)
  • アプリケーションの参照を取得
  • 最前面のウィンドウを取得

ループ

  • タブを切り替えてDELAY秒だけ待つ
  • ページを更新してDELAY秒だけ待つ

試すには30秒は長いので3秒にしました。

Safari

autoreload_safari.js
const DELAY = 3;

var Safari = Application("Safari");
var window = Safari.windows[0]; //最前面のウィンドウを取得

while(window.exists()) { //無限ループ (ウィンドウが開いてなければ実行しない)
  window.tabs().forEach(function(tab){

    // タブ切り替え
    window.currentTab = tab;
    delay(DELAY);

    // 更新
    tab.url = tab.url();
    delay(DELAY);
  });
};

ウィンドウから全タブを取得できます。
タブの切り替えは現在のタブ(currentTab)に任意のタブをセットすることで行います。

Safariには表示中のページを更新する関数がありません。
ページの更新は表示中のurlをタブのurlプロパティに再セットすることで可能です。

またはdoJavaScriptによってページ内でJavaScriptを実行して更新します。

JavaScriptで更新(doJavaScript関数)
Safari.doJavaScript("location.reload()", {in:tab});

doJavaScriptはページ内での実行結果を戻り値として返します。
ページから簡単に情報を得たい場合に便利かもです。
同じJavaScriptで書けますし。

メモ:

ブックマークにアクセスすることが出来ません。
ブックマークを整理するスクリプト書きたかったのに無理でした・・・。

リーディングリストに追加する機能はあるのですが、その一覧を取得する機能も無いです。
ビビりました。

Chrome

autoreload_chrome.js
const DELAY = 3;

var Chrome = Application("Google Chrome");
var window = Chrome.windows[0]; //最前面のウィンドウを取得

while(window.exists()){ //無限ループ (ウィンドウが開いてなければ実行しない)
  window.tabs().forEach(function(tab, i){

    // タブ切り替え
    window.activeTabIndex = i + 1;
    delay(DELAY);

    // 更新
    tab.reload();
    delay(DELAY);
  });
};

ウィンドウから全タブを取得できます。
タブの切り替えはウィンドウのactiveTabIndexにインデックスをセットすることで行います。
インデックスは1から始まることに注意。

タブからはインデックスを取得できません。
そのためforEachのカウンタを利用する必要があります。

アクティブなタブを取得する関数は.activeTab()です。
これは読み取り専用なのでSafariのように他のタブをセットすることはできません。

Chromeには表示中のページを更新する機能(.reload())があります。
更新キャンセルや「進む」「戻る」の機能もあります。

もちろんページ内でJavaScriptを実行することも可能です。

JavaScriptで更新(execute関数)
Chrome.execute(tab, {javascript:"location.reload()"});

Safariと同じようにexecuteもページ内での実行結果が戻り値になります。

メモ:

今回のブラウザの中で、スクリプト向けに用意された機能はChromeがダントツで充実してました!

ブックマークにアクセスすることもできます。
ブックマークを整理するスクリプトを書くことも可能でしょう。
やってませんが。

Firefox

autoreload_firefox.js
const DELAY = 3;

var Firefox = Application("Firefox");
var window = Firefox.windows[0]; //最前面のウィンドウを取得

SystemEvents = Application("System Events");

while(window.exists()){ //無限ループ (ウィンドウが開いてなければ実行しない)

  // タブ切り替え
  Firefox.activate();
  delay(0.3); //アクティブになるまで少し待つ
  SystemEvents.keystroke("]", {using:["command down", "shift down"]});
  delay(DELAY);

  // 更新
  Firefox.activate();
  delay(0.3); //アクティブになるまで少し待つ
  SystemEvents.keystroke("r", {using:"command down"});
  delay(DELAY);
};

ウィンドウからタブを取得できません。
ってことはApplication.documents()でページの内容を見れるのかな?

>> Firefox = Application("Firefox")
=> Application("Firefox")
>> Firefox.windows.length
=> 10
>> Firefox.documents()
=> []
>> 

!?
空の配列が返ってきました。
どうやら用語説明はテンプレそのまま使っていて、機能は何もなさそうです。多分。
ウィンドウを取得する以外、ほぼ何も出来なさそうです。

こういう場合はSystem Eventsからキーボードを押したりして操作するしかありません。
キーボードやマウス操作をする方法はこちらに書きました。

Application("Firefox")の部分を変えるだけでSafariでもChromeでも動きます。
いちいち.activate()する必要があるので他の作業中に動作させるのは無理です。

メモ:

ページの内容すら取得できないんじゃ・・・?
スクリプトで操作するなら別のブラウザを使いましょう。

追記:
windowにもdocumentプロパティがあることに気付きましたが、nullでした。

varFirefox = Application("Firefox");

Firefox.windows[0].document();
//=> undefined

Firefox.windows[0].properties();
//=> {"document":null, "closeable":true, "zoomed":true, "class":"window", "index":1, "visible":true, "name":"Yahoo! JAPAN", "modal":false, "miniaturizable":true, "titled":true, "id":6188, "miniaturized":false, "floating":false, "resizable":true, "bounds":{"x":0, "y":23, "width":1280, "height":709}, "zoomable":true}

ウィンドウからページのタイトルだけ取得できるようです。
上の例だとYahooを開いていることがnameプロパティで分かります。
ページ内容を取得する方法が存在するなら、知ってる方教えてください。

蛇足

ぜんぜん関係ないけど、Terminalでシェルスクリプトを実行するdoScriptもSafariのdoJavaScriptと同じ構文
ただし戻り値はタブの参照です。タブを指定しない場合は新しいウィンドウを開くので。

Terminal
var Terminal = Application("Terminal");
var tab = Terminal.windows[0].selectedTab(); // SafariはcurrentTab。名前統一してくれ

Terminal.doScript("echo 'hi.'", {in:tab});
var newTab = Terminal.doScript("echo 'hi new window.'");

コマンド実行の戻り値を得たい場合はdoShellScriptを使います
これはTerminalじゃなくても使えます

doShellScript
var app = Application.currentApplication();
app.includeStandardAdditions = true;

var date = app.doShellScript("date");