Hatena::Groupmoz-addon

hogezilla RSSフィード

当ページに書かれているコードは、修正BSDライセンスのもと、再頒布して頂いて構いません。

2013-07-06

要素の ARIA role 値を得る

| 20:05 | はてなブックマーク - 要素の ARIA role 値を得る - hogezilla

HTMLの要素には暗黙的に付くARIA roleが定められているものある。これってどうやって取るの? って話

"use strict";
const gAccRetrieval = Cc["@mozilla.org/accessibleRetrieval;1"]
                      .getService(Ci.nsIAccessibleRetrieval);

function getAccessible (elm) {
  return gAccRetrieval.getAccessibleFor(elm);
}

function getARIARole (elm) {
  var acc = getAccessible(elm);
  if (acc) {
    var attrs = acc.attributes;
    if (attrs.has("xml-roles"))
      return attrs.getStringProperty("xml-roles");
  }
  return "";
}
  1. 対象要素の nsIAccessible インスタンスを得る
  2. その属性値からxml-rolesキーの値を得る

参考

トラックバック - http://moz-addon.g.hatena.ne.jp/teramako/20130706

2013-06-03

nsIXULSortService

| 23:19 | はてなブックマーク - nsIXULSortService - hogezilla

使用可能なメソッドは sort のみ。

引数:

  1. コンテナとなる親要素
  2. ソートに使用する値を持つ属性名
  3. ソート種類(以下の値を空白区切りで指定)
    • ascending: 昇順
    • descending: 降順
    • comparecase: 大文字小文字を区別
    • integer: 値を整数とみなす
    • twostate: ?

XUL と付いているけど DOM なら OK だと思われる。

<ol id="container">
  <li value="3">b</li>
  <li value="10">a</li>
  <li value="4">c</li>
  <li value="5">d</li>
</ol>
const sortSerive = Cc["@mozilla.org/xul/xul-sort-service;1"].getService(Ci.nsIXULSortService);

var ol = document.getElementById("container");

sortService.sort(ol, "value", "integer descending");

とすると

<ol id="container">
  <li value="10">a</li>
  <li value="5">d</li>
  <li value="4">c</li>
  <li value="3">b</li>
</ol>

と並び替えられる。

トラックバック - http://moz-addon.g.hatena.ne.jp/teramako/20130603

2013-02-11

UTF-8以外の文字列のURIエンコード/デコード

| 22:35 | はてなブックマーク - UTF-8以外の文字列のURIエンコード/デコード - hogezilla

XMLHttpReuqest の GET でクエリー文字列にUTF-8以外のURIエンコードされたものを使用したい場合がある。

例えば、Web辞書から検索してきたいが、相手はShift_JISだったり、EUC-JPだったりする場合だ。

そんな時にこれを使う。

const TTSU = Cc["@mozilla.org/intl/texttosuburi;1"].getService(Ci.nsITextToSubURI);

/**
 * @param {String} aUnicodeString
 * @param {String} [aCharset="UTF-8"]
 * @return {String} encoded ascii string
 */
function encodeURIComponent (aUnicodeString, aCharset = "UTF-8") {
  return TTSU.ConvertAndEscape(aCharset, aUnicodeString);
}

/**
 * @param {String} aUnicodeString
 * @param {String} [aCharset="UTF-8"]
 * @return {String} decoded Unicode string
 */
function decodeURIComponent (aEncodedString, aCharset = "UTF-8") {
  return TTSU.UnEscapeAndConvert(aCharset, aEncodedString);
}
var query = encodeURIComponent("あいうえお", "Shift_JIS");
// "%82%A0%82%A2%82%A4%82%A6%82%A8"

var str = decodeURIComponent(query, "Shift_JIS");
// "あいうえお"

その他

nsITextToSubURIには他にも

  • unEscapeNonAsciiURI(charset, str)
  • unEscapeURIForUI(charset, str

がある。

どちらも似たような動きだが、後者のunEscapeURIForUIはデコードに失敗しても例外を返さない特徴がある。

var url = TTSU.unEscapeNonAsciiURI("Shift_JIS", "http://example.com/?q=%82%A0%82%A2%82%A4%82%A6%82%A8");
// "http://example.com/?q=あいうえお"
url = TTSU.unEscapeNonAsciiURI("UTF-8", "http://example.com/?q=%82%A0%82%A2%82%A4%82%A6%82%A8");
// 例外: NS_ERROR_ILLEGAL_INPUT

url = TTSU.unEscapeURIForUI("UTF-8", "http://example.com/?q=%82%A0%82%A2%82%A4%82%A6%82%A8");
// "http://example.com/?q=%82%A0%82%A2%82%A4%82%A6%82%A8"

piro_orpiro_or2013/02/12 01:55検証しないままコメントするんですが、writable:trueで上書きしてしまうと元のセキュリティ脆弱性が再導入されてしまうということはないでしょうか?(といっても、元のバグが非公開のようなので検証しようがないんですけど……)

teramakoteramako2013/02/12 12:38あ、はい、おっしゃるとおりですね...。何となくwritable: trueにしてしまいました。
どちらかと言うと、configurable: true のみ(enumerableは任意)にするのが良かったですね。(変更予定がないならconfigurableすら不要)

セキュリティ脆弱性についてですが、詳細が分からないので、そもそも何故、普通の代入を不可にしてObject.definePropertyは許可で脆弱性を回避できるのかさっぱりです。RESOLVED FIXEDされたセキュリティバグって公開にならないんでしたっけ?

トラックバック - http://moz-addon.g.hatena.ne.jp/teramako/20130211

2012-12-09

windowを開いた親windowを得る

| 08:24 | はてなブックマーク - windowを開いた親windowを得る - hogezilla

ちょっとタイトルが分り難いなw えーと、ダイアログとかタブとかサイドバーに新たなXUL Windowを開いた時、その新たなコンテンツから親となるルートのウィンドウ(navigator:browser)を得たい場合のこと。

通常なら以下のコードで良い。

Cu.import("resource://gre/modules/Services.jsm");

var parentWindow = Services.wm.getMostRecentWindow("navigator:browser");

しかし、例えばタイマーによる発動でウィンドウが開いた場合、親のウィンドウがアクティブであるかの保障はなく、別のウィンドウが得られてしまうかもしれない。

また、以下の方法もあるが、browser要素やiframe要素にtype="content"等の属性が付いていると親ウィンドウを得ることはできない。

var parentWindow = window.top;

ということでアレコレ試しつつ悩んでいた。が、ようやく発見した。

var rootWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
                       .getInterface(Ci.nsIWebNavigation)
                       .QueryInterface(Ci.nsIDocShellTreeItem)
                       .parent /* rootTreeItem にすると最上位windowになる */
                       .QueryInterface(Ci.nsIInterfaceRequestor)
                       .getInterface(Ci.nsIDOMWindow);
トラックバック - http://moz-addon.g.hatena.ne.jp/teramako/20121209

2012-07-14

base64エンコード

| 17:31 | はてなブックマーク - base64エンコード - hogezilla

base64エンコードしたい場合、window.btoaは楽ではあるが、問題もある。

var str = window.btoa("あいうえお");
/*
[Exception... "String contains an invalid character"  code: "5" nsresult: "0x80530005 (InvalidCharacterError)"  location: "chrome://liberator/content/eval.js Line: 1"]
*/

非アスキー文字があると、InvalidCharacterErrorが発生する。JavaScriptは基本的にUnicode(UTF-16)なので、これをそのままbase64化してもうまく扱えないのだ。UTF-8あたりに変換してあげる必要がある。

ってことで、XPCOM的には以下を使用する

実はファイルのドラッグ&ドロップ - hogezillaのサンプルコードで既に書いているんだけどね。

function encodeBase64 (aStr) {
  const base64= Cc["@mozilla.org/scriptablebase64encoder;1"].getService(Ci.nsIScriptableBase64Encoder);

  var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
  converter.charset = "UTF-8";
  var input = converter.convertToInputStream(aStr);

  return base64.encodeToString(input, input.available());
}

nsIScriptableBase64Encoder.encodeToStringメソッドは引数にnsIInputStreamが必要。よって文字列をnsIInputSteramに変換する必要がある。

そこで、nsIScriptableUnicodeConverter.convertToInputStremを使用すれば、Unicode文字をUTF-8に変換しつつ、nsIInputStreamを作成できる。

トラックバック - http://moz-addon.g.hatena.ne.jp/teramako/20120714