隠居日録

隠居日録

2016年(世にいう平成28年)、発作的に会社を辞め、隠居生活に入る。日々を読書と散歩に費やす

Firefox Quantumとgreasemonkeyとlibron

PCを再起動したら(あの日はWindows updateの日だったので)firefox 57 (Quantum)に更新され、そしたらaddonが動かなくなったりして、困ってしまっているのだが、なんとなく以前のように使えるようになってきた。ただ、greasemonkeyも4に更新しなければならず、4は以前の物に対して後方互換がなくなってしまったので、スクリプトを更新しなければならない場合もある。そのうちの一つがlibronなのだが、公式からはまだ新しいスクリプトが公開されていないので、自力で何とかするしかない。

問題なのは、GM_で始まる関数群がGM.に置き換えられたことで、単なる名前の変更だけなら、どうということはないのだが、GM.getValueが非同期で呼び出さなければならないようで、これを書いている時点でもまだ正しく理解しているとはいいがたい状態であるが、動作させるのにずいぶん苦労した。公式のwikiによると、

// ==UserScript==
// @name     GM set/get demo
// @grant    GM.getValue
// @grant    GM.setValue
// ==/UserScript==

(async function() {
console.log('Starting the get/set demo ...');
let i = await GM.getValue('i', 0);
console.log(`This time, i was ${i}.`);
GM.setValue('i', i+1);
})();

と書けば、直接値が戻ってくるようになると書かれている。それで以下のような関数を定義して(複数の値を読みだすと遅くなるということなので、JSON形式で設定を保存するようにした)、mainから呼び出して、保存している設定を読みだそうとしたのだが、値が読み出せないのだ。

async function readLibronConfig() {
  var options = JSON.parse (await GM.getValue('libron', "{}"));
 
  libron.selectedSystemId = options.systemid ? options.systemid : 'Tokyo_Pref';
  libron.selectedSystemName = options.systemname ? options.systemname : '東京都立図書館';
  libron.selectedPrefecture = options.prefecture ? options.prefecture : '東京都';
  libron.univChecked = (options.univChecked == true) ? true : false;
}

この関数の中で値を調べると呼び出せているようなのだが、その値が呼び出したmainでは参照できない。全ての設定がundefinedのままだ。いろいろ動作を調べてみて、ようやく気付いたのだが、aync ~ awaitによって、この処理は呼び出した側では即時完了してしまい、その時点で値は読みだせていない。そして、呼び出された側では、非同期にこの処理の動作を継続していて、値が読みだされた後に、その後の処理が継続しているようなのだ。なので、実際のmainの処理は値が読み出せた後に、実行しなければならない。結局、mainの呼び出しの所を、以下の様にして、設定を読みだした後に、mainを実行するように修正した。

if (isGreasemonkey()) {
  readLibronConfig ().then (() => main ());
} else {
  function onReadyGM(){
    main();
  }
}

長いので、パッチの全体以下の続きを読むから。

以下がパッチの全体。ほしいものリストが遅延更新されるようになったので、後でロードされた本に対してはチェックできていないが、とりあえずは動作するようになった。

*** D:/temp/libron.user.0.js	Mon Nov 27 08:19:05 2017
--- D:/temp/libron.user.1.js	Mon Nov 27 11:41:16 2017
***************
*** 5,17 ****
  // @author        Junya Ishihara(http://champierre.com)
  // @include       https://www.amazon.*
  // @include       http://www.amazon.*
! // @license       MIT License(http://en.wikipedia.org/wiki/MIT_License)
  // @version       3.0.9
  // @updateURL     https://userscripts.org/scripts/source/73877.meta.js
  // @downloadURL   https://userscripts.org/scripts/source/73877.user.js
! // @grant         GM_setValue
! // @grant         GM_getValue
! // @grant         GM_xmlhttpRequest
  // ==/UserScript==
  
  var libron = libron ? libron : new Object();
--- 5,17 ----
  // @author        Junya Ishihara(http://champierre.com)
  // @include       https://www.amazon.*
  // @include       http://www.amazon.*
! // *license       MIT License(http://en.wikipedia.org/wiki/MIT_License)
  // @version       3.0.9
  // @updateURL     https://userscripts.org/scripts/source/73877.meta.js
  // @downloadURL   https://userscripts.org/scripts/source/73877.user.js
! // @grant         GM.setValue
! // @grant         GM.getValue
! // @grant         GM.xmlHttpRequest
  // ==/UserScript==
  
  var libron = libron ? libron : new Object();
***************
*** 118,125 ****
    return dom;
  }
  
  if (isGreasemonkey()) {
!   main();
  } else {
    function onReadyGM(){
      main();
--- 118,134 ----
    return dom;
  }
  
+ async function readLibronConfig() {
+   var options = JSON.parse (await GM.getValue('libron', "{}"));
+  
+   libron.selectedSystemId = options.systemid ? options.systemid : 'Tokyo_Pref';
+   libron.selectedSystemName = options.systemname ? options.systemname : '東京都立図書館';
+   libron.selectedPrefecture = options.prefecture ? options.prefecture : '東京都';
+   libron.univChecked = (options.univChecked == true) ? true : false;
+ }
+ 
  if (isGreasemonkey()) {
!   readLibronConfig ().then (() => main ());
  } else {
    function onReadyGM(){
      main();
***************
*** 135,144 ****
      safari.self.addEventListener("message", getResponse, false);
    }
  
!   libron.selectedSystemId = GM_getValue("selectedSystemId") ? decodeURIComponent(GM_getValue("selectedSystemId")) : 'Tokyo_Pref';
!   libron.selectedSystemName = GM_getValue("selectedSystemName") ? decodeURIComponent(GM_getValue("selectedSystemName")) : '東京都立図書館';
!   libron.selectedPrefecture = GM_getValue("selectedPrefecture") ? decodeURIComponent(GM_getValue("selectedPrefecture")) : '東京都';
!   libron.univChecked = (GM_getValue("univChecked") === "true") ? true : false;
    libron.systemNames = {};
  
    var href = document.location.href;
--- 144,156 ----
      safari.self.addEventListener("message", getResponse, false);
    }
  
!   if (!libron.selectedSystemId)
!   {
!     libron.selectedSystemId = 'Tokyo_Pref';
!     libron.selectedSystemName = '東京都立図書館';
!     libron.selectedPrefecture = '東京都';
!     libron.univChecked = false;
!   }
    libron.systemNames = {};
  
    var href = document.location.href;
***************
*** 311,317 ****
    if (isSafariExtension()) {
      safari.self.tab.dispatchMessage("getNews");
    } else {
!     GM_xmlhttpRequest({
        method: "GET",
        url: "http://libron.net/news.txt",
        onload: function(response) {
--- 323,329 ----
    if (isSafariExtension()) {
      safari.self.tab.dispatchMessage("getNews");
    } else {
!     GM.xmlHttpRequest({
        method: "GET",
        url: "http://libron.net/news.txt",
        onload: function(response) {
***************
*** 491,501 ****
      if (isSafariExtension()) {
        safari.self.tab.dispatchMessage("retrieveLibraryInfo", [url, prefecture, univ]);
      } else {
!       GM_xmlhttpRequest({
          method: "GET",
          url: url,
          onload: function(response){
!           GM_xmlhttpRequest({
              method: "GET",
              url: "http://calil.jp/city_list",
              onload: function(city_list_response) {
--- 503,513 ----
      if (isSafariExtension()) {
        safari.self.tab.dispatchMessage("retrieveLibraryInfo", [url, prefecture, univ]);
      } else {
!       GM.xmlHttpRequest({
          method: "GET",
          url: url,
          onload: function(response){
!           GM.xmlHttpRequest({
              method: "GET",
              url: "http://calil.jp/city_list",
              onload: function(city_list_response) {
***************
*** 549,559 ****
    return select;
  }
  
! function saveSelection(options){
!   GM_setValue("selectedPrefecture", encodeURIComponent(options.prefecture));
!   GM_setValue("selectedSystemId", encodeURIComponent(options.systemid));
!   GM_setValue("selectedSystemName", encodeURIComponent(options.systemname));
!   GM_setValue("univChecked", options.univChecked === true ? "true" : "false");
  }
  
  /*
--- 561,568 ----
    return select;
  }
  
! async function saveSelection(options){
!   await GM.setValue ('libron', JSON.stringify (options));
  }
  
  /*
***************
*** 615,621 ****
    for (var i = 0; i < objects.snapshotLength; i++) {
      var object = objects.snapshotItem(i);
      if (object) {
!       var matched = object.href.match(/\/dp\/([\dX]{10})\/ref/);
        if (matched && matched[1]) {
          var isbn = matched[1];
          isbns.push(encodeURIComponent(isbn));
--- 624,630 ----
    for (var i = 0; i < objects.snapshotLength; i++) {
      var object = objects.snapshotItem(i);
      if (object) {
!       var matched = object.href.match(/\/dp\/([\dX]{10})\//);
        if (matched && matched[1]) {
          var isbn = matched[1];
          isbns.push(encodeURIComponent(isbn));
***************
*** 648,654 ****
    }
    :
    function(url) {
!     GM_xmlhttpRequest({
        method: "GET",
        url: url,
        onload: function(response){
--- 657,663 ----
    }
    :
    function(url) {
!     GM.xmlHttpRequest({
        method: "GET",
        url: url,
        onload: function(response){