Posted at

Conkeror(Webブラウザ)で終了時のバッファの保存,復元をする

More than 3 years have passed since last update.

Webブラウザとして良くconkerorを使い始めたのだが,前回終了時のバッファ(いわゆるタブ)を保存することがデフォルトではできない.

公式のWikiや適当にググった結果を見る限り,そのような設定ファイルは見つからなかったので,自分で書いてみた.


Conkerorとは

Mozilla XULRunnerをベースにしたWebブラウザで,


  • CUI/TUIでの利用がベース

  • Emacsとかviのように,設定ファイルで動作をカスタマイズ可能

という特徴がある.KeySnailが使えなくなる日に備えて徐々にconkerorへの移動を自分は開始してみたが,まだまだ先は長い.


設定ファイル

/**

* The browser restore the windows and buffers from last time.
*/

var ioService = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);

var startup_filename = ".conkeror_startup";
var startup_file = get_home_directory();

startup_file.append(startup_filename);

function can_restore_windows_and_buffers() {
var count = 0;
var flag = true;
for_each_buffer(function (buffer) {
count += 1;

var uri = buffer.current_uri.resolve(null);
if (uri != null && uri != homepage) {
flag = false;
}
});
return count <= 1 && flag;
}

function should_save_windows_and_buffers() {
var count = 0;
for_each_window(function (w) {
count += 1;
});
// if the number of windows is 1, save windows and buffers.
return count == 1;
}
/* save windows and buffers */
function save_windows_and_buffers() {
try {
var windows = [];
for_each_window(function (w) {
var buffers = [];
w.buffers.for_each(function (buffer) {
buffers.push(buffer.current_uri.resolve(null));
});
windows.push(buffers);
});

var data = JSON.stringify(windows);

/* write file
(https://developer.mozilla.org/ja/docs/Code_snippets/File_I_O#.E3.83.95.E3.82.A1.E3.82.A4.E3.83.AB.E3.81.AB.E6.9B.B8.E3.81.8D.E5.87.BA.E3.81.99)
*/

var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
.createInstance(Components.interfaces.nsIFileOutputStream);
foStream.init(startup_file, 0x02 | 0x08 | 0x20, 0664, 0);
foStream.write(data, data.length);
foStream.close();
} catch (e) {
dumpln("Error in save buffers: " + e);
}
}

// add hook to save the windows and buffers when the conkeror exit.
add_hook("quit_hook", save_windows_and_buffers);
add_hook("window_before_close_hook", function(w) {
if (should_save_windows_and_buffers()) {
save_windows_and_buffers();
}
return true;
});

if (!startup_file.exists()) {
return ;
}

/* read file
(https://developer.mozilla.org/ja/docs/Code_snippets/File_I_O#.E3.83.95.E3.82.A1.E3.82.A4.E3.83.AB.E3.81.AB.E6.9B.B8.E3.81.8D.E5.87.BA.E3.81.99)
*/

var data = "";
var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]
.createInstance(Components.interfaces.nsIFileInputStream);
var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"]
.createInstance(Components.interfaces.nsIScriptableInputStream);
fstream.init(startup_file, -1, 0, 0);
sstream.init(fstream);
var str = sstream.read(4096);
while (str.length > 0) {
data += str;
str = sstream.read(4096);
}
sstream.close();
fstream.close();

var windows = JSON.parse(data);

add_hook("window_initialize_late_hook", function(w) {
if (!can_restore_windows_and_buffers()) return ;

var buffer = null;
w.buffers.for_each(function(b) {
buffer = b;
});

if (buffer == null) return ;

for (var i = 0, l1 = windows.length; i < l1; i++) {
var window = windows[i];
for (var j = 0, l2 = window.length; j < l2; j++) {
var uri = ioService.newURI(window[j], null, null);
if (j == 0) {
if (i != 0) {
browser_object_follow(buffer, OPEN_NEW_WINDOW, uri.spec);
} else {
browser_object_follow(buffer, OPEN_CURRENT_BUFFER, uri.spec);
}
} else {
browser_object_follow(buffer, OPEN_NEW_BUFFER, uri.spec);
}
}
}
});

${HOME}/.conkeror_startupファイルに,前回終了時のバッファ一覧が保存され,起動時にはそのファイルを読んで復元するようになっている.

書いているときにハマったのは,


  1. conkerorの終了は,次の2つのhookを併用して検出する必要がある(ここが結構ハマった).



    • quit_hook



      • C-x C-c等での終了時のhook




    • window_before_close_hookが呼び出され,かつ,windowの個数が1個


      • 何らかの手段で,最後のwindowを閉じたときのhook





  2. スクリプトが呼び出されているタイミングでは,まだwindowは初期化されていない



    • window_initialize_late_hookを使って,windowが開かれたときに復元処理を行う必要がある



の2箇所.この2点を除けば難しいところのないスクリプトだったし,参考URLはコメントで載せてあるので説明は省く.