Greasemonkey0.9.12以降でMinibufferとLDRizeが動かない理由とかGreasemonkey0.9.12以降でMinibufferとLDRizeが動かない理由とか

<< | コメント(2) | トラックバック(2) このエントリーを含むはてなブックマーク >>

Firefox8が出てたので更新してみたんですが、一通り問題なく動いてるようで安心安心。

グリモンも最新が出たようなのでそちらもついでに更新。

 

僕はMinibufferとLDRizeを使ってなかったんだけど、回りの人はけっこう活用してるようで動かないと問題になっているよう。

ついでにvimpとの連携のも動いてないとの事なのでちょっと導入して、勉強がてら見てみた。

 

なお、ここまでたどり着く過程でmashironに聞いたり、mashironに確認したり、mashironに教えを請うたりしました。

mashironありがとう。


最新のMinibufferとLDRize

Minibuffer for Greasemonkey

LDRize for Greasemonkey

 

以上が大元のコードだと思うが、これは最新のグリモンでは動いていない。

Minibufferに関してはこの辺の修正が必要。

Firefox 4.0b8~b9 でLDRize (Minibufferの修正) - wltの日記

実際に適用されてるっぽいコードがこちら。

for firefox4 via http://d.hatena.ne.jp/wlt/20110106/1294306315 -- Gist

 

んで、LDRizeはFirefox8でmatchがundefineを見なくなった云々で修正が要るようだ。

firefox 8 で LDRize 動いたっぽい - yutamoty.vimp - vimperatorグループ

 

んで、ここには註釈でGreasemonkey0.9.11でしか動かないと書いてる通り、最新だと動かないです。

でも実は、0.9.11だけでも動かないです。

 

解決方法はコチラ

Firefox 4.0b10でGreasemonkey 0.9.1のユーザスクリプトのwindowを共通にする改造(開発者orVimper向け) - wltの日記

グリモンにパッチ充てるか、Tomblooかvimpelator使ってるなら特定のコードを仕込めば動くようになるよ、と。

 

でもGreasemonkey0.9.12以降では動かないです。

 

(セキュリティを無視して『window.』を全部『unsafeWindow.』に置換しても動くんだがな。もしくは1ファイルにブチこむ。)

 

グリモンは何が変わっているのか

0.9.1では使えなくなり、その対処コードも0.9.12では動かなくなった。

グリモンの中では何が行なわれているのか。

 

0.9.0と.0.9.1あたりの変遷についてはこの辺りが詳しい。最終的な結論が、画像付きで示してある。

ああ、やられた (greasemonkey 0.9 顛末記) - twwp

new XPCNativeWrapper(unsafeContentWin)がいつも同じオブジェクトを返します。ただしサンドボックス内のwindowへのプロパティ追加などは無かった事になるので、共有不可

厳しい。

 

具体的に動かなくなっていた原因は

Commit 6a4ffd52c90091714e6f49376ef07e2ce5009f79 to greasemonkey/greasemonkey - GitHub

こちらの修正で、sandbox.__proto__に渡されていたオブジェクトがラッピングされているのが分かる。

 

この修正が導入された経緯。

#1258: eval() does not work as expected - Issues - greasemonkey/greasemonkey - GitHub

これ要するにバグの回避策だったっつー事よね。

 

これに対応する為に、先程のパッチなり何なりではsharedWindowというのを作って、sandbox.windowをそれで置き換えるような事をしていた。

 

しかし例のパッチは0.9.12では動かない。

(そもそもgreasemonkey.jsの構造が書き変わった為、そのままパッチが適用されなくなったというのもあるけど、それを最新のソースに合わせた所で動かなかった。)

 

0.9.12の更新内容を見てみる。

Greasespot: Greasemonkey 0.9.12 Release

 

Bug fixに『Shared window object.』というのがある。

Before 0.9.0, it was possible to set properties on the window object, and other scripts would be able to read those properties.  This behavior was never supported, but as the compatibility fix that broke it is no longer necessary, it has been reverted.  It is still not suggested that you leverage this quirk, it is not a fully supported feature and may break again in the future.

英語分からないけど、google先生に聞きながら適当に意訳すると。

0.9.0以前ではwindowの共有が行なえた為、他のスクリプトから設定したプロパティを読む事が出来た。

この動作はサポートしなくなっていたが、それを出来なくしていた修正プログラムが不要になった為、元に戻しました。

ただしこれはこの挙動の癖を活用する事を推奨するものではなく、完全にサポートするものではありません。

将来的に再び使えなくなる可能性があります。

要するにwindow共有できなくしてたけど、ギャーギャーうっせぇから元に戻しといてやったぜ!

という事か。

 

付随する議論はteramakoさんの投稿された このissueに纏まってる。

#1278: RFE: a shared object among user-scripts - Issues - greasemonkey/greasemonkey - GitHub

 

なお、当該する修正はこれ。

Commit de35812d921856e26ebffc04e373b7cddefe0ed0 to arantius/greasemonkey - GitHub

確かにラッパーされなくなった。

 

ならば別にパッチを充てなくても元のコードで動くんじゃないか?

しかし、それでもやはり動かない。

 

そもそも何で不要になったのかがイマイチ分からんのだが、要するに対策してたバグが無くなったんだろう。

 

実際にコードを見てみよう。

最新のgreasemonkeyのコードはここ。

components/greasemonkey.js at master from greasemonkey/greasemonkey - GitHub

 

ここを見る限りではinjectScripts内でcreateSandboxに渡されているwrappedContentWinは、runScriptから入ってきたaWrappedContentWinそのものであり。

またcreateSandbox内部でもそのままプロトタイプに設定している。

何故共有されないのか???

 

sandboxが何かしているのだろうか?

という事でリファレンスを確認してみる。

Components.utils.evalInSandbox - MDN

Components.utils.Sandbox - MDN

 

見た感じXPCNativeWrapperしない代わりに、sandboxに特定のフラグをオプションとして指定しないとXrayWrapperしてしまうといった感じだろうか?

試しにgreasemonkey.jsの当該コードを以下のように書き変えてみるとwindowの共有に成功した。

var sandbox = new Components.utils.Sandbox(aContentWin,{wantXrays:false});

まぁでもセキュリティ的なの解除したらunsafeWindow使うのと大差ないよね(というか他のuser.jsにも影響あたえてイクナイ

 

これ結局、sandboxがwindowの変化を強固にガードするようになったという事だと思うので、どうしようもないのではないか、、、

(ってか0.9.1で対応された大元のバグが正しくsandboxでwindowがwrapされないというモノで、そのバグが直ったから消したって事なら、そもそも 0.9.12のリリースで「元に戻しました」ってアナウンスに何の意味もねぇじゃねぇかクソがー)

 

結局どうすりゃいいんだ?

個人的にはteramakoさんがissueで書いていたようにsharedObjectをsandboxに持たせるのがいいんじゃないかと思う。

 

greasemonkey.jsをこのように書き変える。

 

service.prototype.injectScripts = function(
    scripts, url, wrappedContentWin, chromeWin
) {
  var sharedObject = {};

  var firebugConsole = getFirebugConsole(wrappedContentWin, chromeWin);

  for (var i = 0, script = null; script = scripts[i]; i++) {
    var sandbox = createSandbox(
        script, wrappedContentWin, chromeWin, firebugConsole, url);

    sandbox.sharedObject = sharedObject;

    var requires = [];
    var offsets = [];
    var offset = 0;

    script.requires.forEach(function(req){
      var contents = req.textContent;
      var lineCount = contents.split("\n").length;
      requires.push(contents);
      offset += lineCount;
      offsets.push(offset);
    });
    script.offsets = offsets;

    // These newlines are critical for error line calculation.  The last handles
    // a script whose final line is a line comment, to not break the wrapper
    // function.
    var scriptSrc = requires.join("\n") + "\n" + script.textContent + "\n";
    if (!script.unwrap) {
      scriptSrc = "(function(){"+ scriptSrc +"})()";
    }
    if (!runScriptInSandbox(scriptSrc, sandbox, script) && script.unwrap) {
      // Wrap anyway on early return.
      runScriptInSandbox("(function(){"+ scriptSrc +"})()", sandbox, script);
    }
  }
  return sharedObject;
};

 

もしくはVimperator使いなら、以下のパッチを書く。

 

 

" Greasemonkey 0.9.13 patch
" cf.http://d.hatena.ne.jp/littlefolk/20110625/p1
js <<EOM
autocommands.add(
  'VimperatorEnter', '.*',
  function () {
    let Cc = Components.classes['@greasemonkey.mozdev.org/greasemonkey-service;1'];
    if (Cc) {
      Cc = Cc.getService().wrappedJSObject;
      if (Cc.injectScripts.toSource().search('sharedObject') == -1) {
        Cc.injectScripts = liberator.eval(
          Cc.injectScripts.toSource()
            .replace(/(?=(?:var|let) (?:firebugConsole))/,'var sharedObject = {};')
            .replace(/(?=var requires)/, 'sandbox.sharedObject = sharedObject;')
            .replace(/(?=}$)/, 'return sharedObject;'),
        Cc.injectScripts);
      };
    };
  });
EOM

(最後にshareObject返してるのは、vimpのプラグインとかからinjectScriptsをhookする形で参照できるように。(実際できるかは分からん。

(これ使ってldrize_cooperation.js書き変えればvimpからのコマンドの呼出しもいけるようになると思うんだけど、まだ動く段階まできてないので宿題という事で。


次にLDRizeとMinibufferのwindow.Minibufferとwindow.LDRizeのwindow.をsharedObjectに書き変える。

めんどくさいだろうから書き変えたもの置いといた。

 ldrize.user.js

 minibuffer.user.js

 

この形で唯一残る問題は、eventでのやりとりが出来ないから、LDRizeを先に読んだ場合にMinibufferの読み込みを待つみたいな所の実装が動いてない。

そこだけunsafeWindowに置き換えてもいいんだけど、正直user.jsの実行順序指定が非常に簡単に出来るようになってんだから、そんくらい自分で順番通りに並べろやって感じでほっといていい気はする。


でも一番真っ当な解決は、LDRizeがグリモンから独立する事だと思う。



でまぁ色々長々と書いたけど、(暫定の)解決方法あるんだったらそれだけ独立した記事でちゃっちゃと書けやって話しなんだが。

まぁせっかく調べたんだし書きたいじゃない。

トラックバック(2)

トラックバックURL: http://exe.tyo.ro/mt/mt-tb.cgi/1258

社長が訊く 任天堂のサイトにあるゲーム製作の舞台裏紹介ページ「社長が訊く」。現行のAutoPagerizeだとsriptタグで追加されるムービーへのリンクが変なことになるので、それをどうにかするスクリプトを書いた。 おそらくgreasemonkey版のAutoPagerizeでないと動かないので 続きを読む

まだ下書きだよ 2012/11/26 1:26 肝心な部分だけ追記したよ 2012/11/28 2:45 リンクもだいたい整備したよ 2012/11/29 8:55 続きを読む

コメント(2)

通りすがりですが、個人的にここ数か月で一番有用な記事でした。
やっとGreasemonkeyを0.9.13に更新できました。
Googleの検索結果をjkで移動すると、1件目から11件目に飛ぶ現象は解消されないのですね。
でも、思わずコメントせずにはいられません。
ありがとうございます。

greasemonkey.jsの書き換えについて、教えてください。
grease monkey.jsは一部だけを書き換えるのでしょうか?

全体を書き換えたり、それっぽいところを置換してみたりしましたが、
なんだか上手くうごきません。

コメントする

2014年10月

      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  

月別 アーカイブ

2014年
2013年
2012年
2011年
2010年
2009年
2008年
2007年