[Places] フォルダ内のブックマークを列挙する

Places データベースへの問い合わせ結果から得たブックマークのノードは nsINavHistoryResultNode インタフェースを実装するオブジェクトであるが、ブックマークフォルダは nsINavHistoryContainerResultNode インタフェースも合わせて実装しており、 childCount プロパティで子ノードの数を調べたり、 getChild メソッドで指定したインデックスの子ノードを取得することができる。
例えば、[Places] ビューと nsIPlacesView インタフェース の続きとして、右クリックしたブックマークフォルダ内の子ノードにアクセスするには、以下のようにすればよい。ただし、ビュー上でフォルダが開いていることを前提とする。

// assume that node is instanceof Ci.nsINavHistoryContainerResultNode and is open.
for (var i = 0; i < node.childCount; i++) {
    var childNode = node.getChild(i);
}

一方、ビュー上でフォルダが閉じた状態になっている場合、 childCount プロパティなどを使って子ノードへアクセスしようとすると NS_ERROR_NOT_AVAILABLE 例外がスローされる。そこで、ブックマークフォルダのノードの containerOpen プロパティへ true をセットすることで一時的にフォルダを開いてから子ノードへアクセスし、処理が終わった後に false をセットしてフォルダを閉じるようにする。以下は、引数で指定したブックマークフォルダ内のすべてのブックマークを再帰的に取得し、配列として返す関数である。

function flatChildNodes(aNode) {
    var ret = [];
    var closeOriginally = !aNode.containerOpen;
    if (closeOriginally)
        // if the folder is closed, open it.
        aNode.containerOpen = true;
    for (var i = 0; i < aNode.childCount; i++) {
        var childNode = aNode.getChild(i);
        if (PlacesUtils.nodeIsBookmark(childNode))
            ret.push(childNode);
        else if (PlacesUtils.nodeIsFolder(childNode) && 
                 !PlacesUtils.nodeIsLivemarkContainer(childNode))
        // call this function recursive
        ret = ret.concat(arguments.callee(childNode));
    }
    if (closeOriginally)
        // don't forget to restore the folder's original closed state
        aNode.containerOpen = false;
    return ret;
}

上記の例では、ビュー上に表示されているブックマークフォルダ、つまりデータベースへの問い合わせ結果が取得済みのブックマークフォルダを対象としていた。ビューへの表示が無い場面でフォルダ内のノードへアクセスするには、データベースへ問い合わせを行う必要がある。通常 Places データベースへの問い合わせを行うには、 nsINavHistoryService#getNewQuery でクエリオブジェクトを生成し executeQuery で実行するという手続きが必要であるが、 PlacesUtils.getFolderContents を使えばより単純なコードでフォルダ内のノードへアクセス可能である。

var result = PlacesUtils.getFolderContents(node.itemId);    // nsINavHistoryResult
var parentNode = result.root;
for (var i = 0; i < parentNode.childCount; i++) {
    var childNode = parentNode.getChild(i);
}

以下は、ブックマークフォルダの itemId プロパティを引数に、そのフォルダ内の全ブックマークを再帰的に取得して配列として返す関数である。

function flatChildNodes(aItemId) {
    var ret = [];
    var parentNode = PlacesUtils.getFolderContents(aItemId).root;
    for (var i = 0; i < parentNode.childCount; i++) {
        var childNode = parentNode.getChild(i);
        if (PlacesUtils.nodeIsBookmark(childNode))
            ret.push(childNode);
        else if (PlacesUtils.nodeIsFolder(childNode) && 
                 !PlacesUtils.nodeIsLivemarkContainer(childNode))
            // call this function recursive
            ret = ret.concat(arguments.callee(childNode.itemId));
    }
    return ret;
}

TOP

TOP