hitode909の日記

趣味はマリンスポーツですの日記です

Greasemonkeyのuser scriptの判定が誤爆する

Greasemonkeyのuser scriptを開くと,このようなダイアログが出て,インストールしたり,ソースコードを見たりできる.
http://gyazo.com/2ef8235deb13b2921d580e672af9fa46.png


これは,このような正規表現で実現されている.URLの末尾が.user(?:-\d+).jsならダイアログが出る.
http://github.com/greasemonkey/greasemonkey/blob/master/content/browser.js

  // Show the greasemonkey install banner if we are navigating to a .user.js
  // file in a top-level tab.  If the file was previously cached it might have
  // been given a number after .user, like gmScript.user-12.js
  if (href.match(/\.user(?:-\d+)?\.js$/) && safeWin == safeWin.top) {
    var browser = this.tabBrowser.getBrowserForDocument(safeWin.document);
    this.showInstallBanner(browser);
  }

なので,user scriptではないが,たまたま末尾が.user.jsのURLを開くと,誤ってダイアログが出てしまい,ページを見ることができない.例えば,以下のページ.

普通に暮らしていれば1番目のURLにアクセスすることはなさそうだけど,それ以外はもとからこのURLなので,Greasemonkeyがオンになっている間はこれらのページを見ることができない.
後ろに#でも書いておくと,左記の正規表現にマッチしなくなるので,見ることができる.


毎回Greasemonkeyを無効にするのもめんどうなので,user scriptとして認識されるリンク先に一度リクエストを投げて,ContentTypeがHTMLっぽいとき,リンクの遷移先の末尾に#をつけるGreasemonkeyを書いた.
根本的ではないが,とりあえずこれで対処.
http://gist.github.com/279123

// ==UserScript==
// @name      check-userjs
// @namespace http://www.hatena.ne.jp/hitode909
// @include   http://*
// @include   https://*
// ==/UserScript==

var anchors = document.querySelectorAll('a[href$=".js"]');

for (var i = 0, len = anchors.length; i < len; i++) {
    if (anchors[i].href.match(/\.user(?:-\d+)?\.js$/)) {
        check(anchors[i]);
    }
}

function check(anchor) {
    var cache = GM_getValue(anchor.href);
    if (cache == "true") {
        anchor.href += '#';
    }
    if (cache) {
        return;
    }
    GM_xmlhttpRequest({
	method  : "GET",
	url     : anchor.href,
	onload  : function (req) {
            if (req.responseHeaders.match(/^Content-Type: .*html.*$/m)) {
                GM_setValue(anchor.href, "true");
                anchor.href += '#';
            } else {
                GM_setValue(anchor.href, "false");
            }
        }
    });
}


一方,Jetpack Featureは,

<link rel="jetpack" href="boom.js" name="Boom!"/>

のようなlinkタグを見てインストールされるので,このような誤認識がなさそう.


今回の例に限らず,URLにマッチしたらいろいろする系は同様の問題が起きそうなので,自分で何か作るときは気をつけようと思った.
一度リクエストを投げてContentTypeを見るとか,リダイレクト先を見るとか,あまりやりたくないし,1つのページに100000個のリンクがあると,そういうこともできない.