Apr 03, 2006
NoScriptで複数サイトをまとめて許可あるいは禁止してみる
NoScriptは「基本的にJavaScriptもFlashも全て無効、でも許可したサイトだけは有効」といった使い方をする上で非常に便利な拡張機能です。さらに便利なことに「一時的に許可する」(Firefoxを終了するまでの間だけ、そのサイトでのスクリプト実行を許可する)という機能まであって、試しでJavaScriptを有効にしてみて、有用なら初めて永続的に有効に設定する、といった使い方もできます。
と、いいことずくめのようなこの拡張機能なんですが、困ったことが1点だけあります。それは、許可・禁止がスクリプトの置かれているドメイン単位か、または全体、という両極端な基準でしか設定できないため、複数のドメインのスクリプトを読み込んでいるページでは、禁止・許可を切り替えたいと思ったら、読み込まれているスクリプトのドメインの数だけ何度も操作を繰り返す必要があります(例:Webページでダイスを振るbookmarklet)。
これが死ぬほど面倒だったので、「これらのサイトをまとめて許可する」「一時的に許可する」「禁止する」の3つの機能をNoScriptに加えるような改造を考えてみました。
以下がそのスクリプトです。
var originalMethod = noscriptOverlay.prepareMenu;
noscriptOverlay.prepareMenu = function(aPopup) {
var ret = originalMethod.apply(this, [aPopup]);
var allowItems = this.getSnapshotItems(aPopup, 'allowLocal');
var tempAllowItems = this.getSnapshotItems(aPopup, 'allowTemp');
var forbidItems = this.getSnapshotItems(aPopup, 'forbidLocal');
var allowItem,
tempAllowItem,
forbidItem,
separator;
var sep = aPopup.getElementsByAttribute('class', 'noscript-sep-insert')[0];
if (sep &&
sep.previousSibling.getAttribute('inserted-custom-item') != 'true') {
allowItem = document.createElement('menuitem');
allowItem.setAttribute('class', 'menuitem-iconic');
allowItem.setAttribute('image', this.getIcon('yes'));
allowItem.setAttribute('label', 'Allow All of these sites');
allowItem.setAttribute('oncommand', 'noscriptOverlay.allowAllOfListedSites(this.parentNode,"allowLocal",true);');
allowItem.setAttribute('style', 'font-weight: bold;');
allowItem.setAttribute('inserted-custom-item', 'true');
tempAllowItem = allowItem.cloneNode(true);
tempAllowItem.setAttribute('label', 'Temporary Allow All of these sites');
tempAllowItem.setAttribute('oncommand', 'noscriptOverlay.allowAllOfListedSites(this.parentNode,"allowTemp",true,true);');
tempAllowItem.setAttribute('style', 'font-weight: bold; font-style: italic;');
forbidItem = allowItem.cloneNode(true);
forbidItem.setAttribute('image', this.getIcon('no'));
forbidItem.setAttribute('label', 'Forbid All of these sites');
forbidItem.setAttribute('oncommand', 'noscriptOverlay.allowAllOfListedSites(this.parentNode,"forbidLocal",false);');
separator = document.createElement('menuseparator')
aPopup.insertBefore(separator, sep);
aPopup.insertBefore(allowItem, sep);
aPopup.insertBefore(tempAllowItem, sep);
aPopup.insertBefore(forbidItem, sep);
}
else {
forbidItem = sep.previousSibling;
tempAllowItem = forbidItem.previousSibling;
allowItem = tempAllowItem.previousSibling;
separator = allowItem.previousSibling;
}
allowItem.collapsed = allowItems.snapshotLength < 2;
tempAllowItem.collapsed = tempAllowItems.snapshotLength < 2;
forbidItem.collapsed = forbidItems.snapshotLength < 2;
separator.collapsed = allowItem.collapsed && tempAllowItem.collapsed && forbidItem.collapsed;
return ret;
};
noscriptOverlay.allowAllOfListedSites = function(aPopup, aType, aAllow, aTemp) {
var nodes = this.getSnapshotItems(aPopup, aType);
var sites = [];
for (var i = 0, max = nodes.snapshotLength; i < max; i++)
sites.push(nodes.snapshotItem(i).getAttribute('statustext'));
for (var i = 0, max = sites.length; i < max; i++)
noscriptOverlay.safeAllow(sites[i],aAllow,aTemp);
};
noscriptOverlay.getSnapshotItems = function(aPopup, aType) {
var label = this.getString(aType, ['|||']).split('|||');
var resolver = {
lookupNamespaceURI : function() {
return 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
}
};
var type = XPathResult.ORDERED_NODE_SNAPSHOT_TYPE;
return document.evaluate('child:*[starts-with(@label, "'+label[0]+'") and contains(@label, "'+label[1]+'") and @statustext]', aPopup, resolver, type, {});
};
これをChrome Windowのスクリプトとして実行すれば、NoScriptのメニューの中に「Allow All of these sites」「Temporary Allow All of these sites」「Forbid All of these sites」の3つの機能が加わります。「Forbid~」だけうまく動かないことがありますが、まあ、ご愛敬ということで。
なお、このスクリプトは、コンテキストメニュー拡張のカスタムスクリプトとして登録すればそのまま使えます。また、userChrome.jsでも使えるものと思われます。
さて、どうやってフィードバックしたものか。
wikieditish message: Ready to edit this entry.