X-0011 ローカルにあるファイルについて、パスと URL を相互変換する

現在開いているローカルのファイルを他のアプリに渡す場合など、 URL をプラットフォームごとに適切な形式のパスに変換する操作が必要になると思います。これは、 XPCOM の機能を使えば、どのプラットフォームでもきちんと変換することができます。

以下は、 URL をパスに変換する方法の一例です。

function convertURIToFilePath(aURI) {
    const ioService = Components.classes['@mozilla.org/network/io-service;1']
                                .getService(Components.interfaces.nsIIOService);

    // nsIIOServiceのnewURIメソッドで新しいURIオブジェクトを作る。
    var URI = ioService.newURI(aURI, null, null);

    if (!URI.schemeIs('file')) return ''; // リモートのリソースの場合は処理しない

    var tempLocalFile;
    try {
        var fileHandler = ioService.getProtocolHandler('file')
                                   .QueryInterface(Components.interfaces.nsIFileProtocolHandler);
        tempLocalFile = fileHandler.getFileFromURLSpec(aURI); // 「 URL 文字列からファイルを得る」機能
    }
    catch(e) {
        try {
            // Mozilla 1.1 までは nsIIOService のメソッドを使う
            tempLocalFile = ioService.getFileFromURLSpec(aURI);
        }
        catch(ex) { // for Mozilla 1.0.x
            try {
                // 仮のファイルオブジェクトを作る
                tempLocalFile = Components.classes['@mozilla.org/file/local;1']
                                          .createInstance(Components.interfaces.nsILocalFile);
                ioService.initFileFromURLSpec(tempLocalFile, aURI); // nsIIOService の「 URIURL からファイルを初期化する」機能を使う
            }
            catch(ex) {
                tempLocalFile.URL = aURI; // NS6 の時点の仕様では、 URL プロパティに URI を代入するだけでいい
            }
        }
    }
    return tempLocalFile.path; // ファイルのパスを帰す
}

古い例では、URIオブジェクトの生成方法として

    var URI = Components.classes['@mozilla.org/network/standard-url;1']
                        .createInstance(Components.interfaces.nsIURI);
        URI.spec = aURI; // spec プロパティに URI を代入して、 URI オブジェクトを初期化する

……と書いていましたが、これは正しくない書き方だそうなので、以上の通り修正しました。

次は、その逆に、パスを URL に変換する方法です。

function convertFilePathToURI(aFilePath) {
    var tempLocalFile = Components.classes['@mozilla.org/file/local;1']
                                  .createInstance(Components.interfaces.nsILocalFile);
    tempLocalFile.initWithPath(aFilePath); // パスを渡してファイルオブジェクトを初期化する

    const ioService = Components.classes['@mozilla.org/network/io-service;1']
                                .getService(Components.interfaces.nsIIOService);
    try {
        // nsIIOService の「ファイルから URI のオブジェクトを得る」機能を使う
        return ioService.newFileURI(tempLocalFile).spec;
    }
    catch(e) { // for Mozilla 1.0~1.1
        try {
            return ioService.getURLSpecFromFile(tempLocalFile); // nsIIOService の「ファイルから URL の文字列を得る」機能を使う
        } catch(ex) { // for NS6
            return tempLocalFile.URL; // NS6 の時点の仕様では、初期化した時点で URL プロパティに URL の文字列が入っている
        }
    }
}

なお、この例では、 Mozilla のバージョンによって処理が違うために try-catch で処理を振り分けていますが、対象の Mozilla のバージョンが決まっている場合はいずれかの方法で決め打ちしてしまって構いません。