LoginSignup
1
2

More than 5 years have passed since last update.

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

Posted at

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はコメントで載せてあるので説明は省く.

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2