読者です 読者をやめる 読者になる 読者になる

Places のブックマークへの変更をnsITransaction経由で行う

Firefox は Places と呼ばれるブックマークと履歴のデータベースを持っていて、これには nsINavBookmarksService や nsINavHistoryService からアクセスできる(詳しくは Places - MDN 参照)。

単純にブックマークを保存するだけなら、上の XPCOM インターフェースを使えばいいんだけど、上のサービス経由で操作した登録したブックマークに対しては、「元に戻す・やり直し」処理が働かない。

Firefox での「元に戻す・やり直し」処理自体は nsITransactionManagernsITransaction を介することで実現しているので、これを使うのが正攻法ではあるけれども、正直、nsITransaction のインターフェースをいちいち実装するのは手間がかかる(参考:SCRAPBLOG : nsITransactionManager を使ったトランザクション管理))。

とは言え、ブックマークへの変更に限れば、Firefox が標準で nsITransaction を実装したコンストラクタを提供してくれているので結構簡単だったりする、というのが今回の話。

resource://gre/modules/PlacesUtils.jsm という JavaScript コードモジュールを読み込むとインポートされるコンストラクタ、Places****Transaction がそれ。いくつか種類があるけれども、基本的なブックマークの操作に関して必要なものは一通りそろっている。余談になるけど、MDNのPlacesUtilsのドキュメントは最終更新日がかなり古いものなので、直接モジュールのコードおよびコードのコメントを読むべき。
また、ここでインポートされるオブジェクトおよび PlacesUtils.transactionManagerPlacesUIUtils.ptm を参照することによってアクセスすることができるけれども、これは古い API なので使うべきではない。

基本的な使い方は以下の通り。

  1. Places****Transaction のコンストラクタからオブジェクトを生成
  2. PlacesUtils.transactionManager.doTransaction() に渡してトランザクション実行

尚、一部の Places****Transaction コンストラクタでは、引数に子となるトランザクションの配列を渡せるので、複数の処理を順番につなぐことができる。
簡単ですね。

PlacesAggregatedTransaction

一連のコンストラクタには PlacesAggregatedTransaction というものが含まれているが、これは他のものとは機能が異なる。他のコンストラクタはブックマークへの処理を直接行うものであるのに対し、このコンストラクタは、一連の Placesブックマークへの処理を行う nsITransaction を実装したオブジェクトを配列にして渡すことで、一気に処理を行うためのものである。尚、名前の割にブックマーク限定なのは、後述するバッチ処理モードが nsINavBookmarksServicerunInBatchMode() を使って記述されているから。たぶん履歴操作には使えない。

PlacesAggregatedTransaction を使うことで複数トランザクションをまとめて実行することができるため、大規模な操作の場合は自動的にバッチモードで処理してくれる(MIN_TRANSACTIONS_FOR_BATCH を参照)。

使い方としては以下の通り。さっきとあんまり変わらない。

  1. PlacesAggregatedTransactionトランザクションの配列を渡す
  2. PlacesUtils.transactionManager.doTransaction() に渡してトランザクション実行

簡単ですね。

実装例

  • Places のブックマーク操作系のコードでよく使われてる。
  • 拙作 LinkPlaces でも使うようにしてる。

ブックマークはわかったから履歴操作用の便利機能無いの?

無いです。DIY