API Check
http://d.hatena.ne.jp/Constellation/20090928/1254125755
http://d.hatena.ne.jp/taizooo/20101108/1289214694#c
という話ですー.
具体的には, GM_apiLeakCheck関数でのcheckが入りました. このcheckはComponents.stack https://developer.mozilla.org/en/Components.stack を使って実行中のscriptファイル名を取得(こんなことできるんですね), そのファイル名が, nullでない+GMファイルでない(userscript)+chrome空間内のファイル(他の拡張)でない => web上のscriptファイル がGM_APIを読んでいる => errorを発する, という割と厳しいCheckです. これで,
unsafeWindow.GM_xmlHttpRequest = GM_xmlHttpRequest;として, web page内で参照することはできなくなりました.
http://d.hatena.ne.jp/Constellation/20090927/1254057213
const gmSvcFilename = Components.stack.filename;
https://github.com/greasemonkey/greasemonkey/blob/master/components/greasemonkey.js#L22
// Examines the stack to determine if an API should be callable. function GM_apiLeakCheck(apiName) { var stack = Components.stack; do { // Valid stack frames for GM api calls are: native and js when coming from // chrome:// URLs and the greasemonkey.js component's file:// URL. if (2 == stack.language) { // NOTE: In FF 2.0.0.0, I saw that stack.filename can be null for JS/XPCOM // services. This didn't happen in FF 2.0.0.11; I'm not sure when it // changed. if (stack.filename != null && stack.filename != gmSvcFilename && stack.filename.substr(0, 6) != "chrome") { GM_logError(new Error("Greasemonkey access violation: unsafeWindow " + "cannot call " + apiName + ".")); return false; } } stack = stack.caller; } while (stack); return true; }https://github.com/greasemonkey/greasemonkey/blob/master/components/greasemonkey.js#L47
例えば, いままでLDR上で書いていた
var win = unsafeWindow; win.Keybind.add('J', function(){ var item = win.get_active_item(true); if (!item) return; GM_openInTab(item.link); win.Control.go_next(); });なんていうscriptが当然のように動かなくなります. これは登録functionが実際にはLDRのjs上から実行されているため, 由来(Components.stack.filenameの先頭)がweb上scriptになってるんですね.
で, せっかくのAPI Checkなんですが,
var win = unsafeWindow; win.Keybind.add('J', function(){ var item = win.get_active_item(true); if (!item) return; setTimeout(GM_openInTab, 0, item.link); win.Control.go_next(); });ってかいたら動きます. setTimeoutによって, GM_openInTabのstack.filenameが切り替わっているからです.
http://d.hatena.ne.jp/Constellation/20090928/1254125755
基本の基本がわかってないんだけど、
document.addEventListener("DOMNodeInserted", hogehoge(e), false);
で呼び出された hogehoge は unsafeWindow 上で実行されてるって事なのね。で、
document.addEventListener("DOMNodeInserted", function(e){setTimeout(hogehoge(e),0)}, false);
ってすると?