Hatena::Groupmoz-addon

hogezilla RSSフィード

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

 | 

2012-07-09

ファイルのドラッグ&ドロップ

| 07:55 | はてなブックマーク - ファイルのドラッグ&ドロップ - hogezilla

デスクトップやファイラーからFirefoxウィンドウに、ではなく、デスクトップやファイラーにドロップしてファイルを作成する方法。

ファイルが既存であれば、MDNに記述があり、DataTransferapplicatioin/x-moz-fileとしてnsIFileをくっ付けてやれば良い。

しかし、既存にはなく、新たに書き出す場合のやり方は載っていない。ドラッグ開始時にファイルに書き出せば話は早いが、それでは非効率だし、一時的にゴミファイルを作成することになる。できれば、それはしたくない。

結構探し回った結果。data URLでデータを突っ込んでやる方法が分かった。メモとして書いておく。

使用するのは、以下3つ

  • application/x-moz-file-promise
  • application/x-moz-file-promise-url
  • application/x-moz-file-promise-dest-filename
function onDragStart (aEvent) {
  var dt = aEvent.dataTransfer;

  new FileDataFlaver(dt, "ほげほげ", "hoge.txt");

  aEvent.stopPropagation();
}

/**
 * @param {nsIDataTransfer} dt
 * @param {String} data
 * @param {String} filename
 */
function FileDataFlaver (dt, data, filename) {
  this.data = data;
  dt.mozSetDataAt("application/x-moz-file-promise", null, 0);
  dt.mozSetDataAt("application/x-moz-file-promise-url", this, 0);
  dt.mozSetDataAt("application/x-moz-file-promise-dest-filename", filename, 0);
}
FileDataFlaver.prototype = {
  QueryInterface: XPCOMUtils.generateQI(["nsIFlavorDataProvider"]),
  get URLString () {
    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 inputStream = converter.convertToInputStream(this.data);

    var str = "data:application/octet-stream;base64," +
              base64.encodeToString(inputStream, inputStream.available());
    var supportsString = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
    supportsString.data = str;
    Object.defineProperty(this, "URLString", { value: supportsString });
    return supportsString;
  },
  getFlavorData: function FDP_getFlaverData (aTransferable, aFlavor, aData, aDataLen) {
    if (aFlavor !== "application/x-moz-file-promise-url")
      return;

    aData.value = this.URLString;
    aDataLen.value = this.URLString.data.length;
  },
}

application/x-moz-file-promise-urlに直にdata URLの文字列を入れても良いが、できるだけ遅らせたいので、nsIFlavorDataProviderを実装したオブジェクトを作成する。

nsIFlavorDataProviderで必要なのはgetFlaverDataメソッド。このメソッド内では以下を設定する必要がある。

  • 第3引数のvalueプロパティにnsISupportString型でdata URL文字列
  • 第4引数のvalueプロパティに文字列の長さ

何度か呼ばれる*1ので、遅延ロード的にURLStringというgetterから固定プロパティに変換されるように工夫している。

あと、URLStringのgetterでは、Unicode文字列に対応するために、一旦UTF-8nsIInputStreamを生成して、nsIScriptableBase64Encoderエンコードという手段を取っている。

*1:dragenterあたりのタイミングだと思う

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