1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 cr
.define('bmm', function() {
9 * Whether a node contains another node.
10 * TODO(yosin): Once JavaScript style guide is updated and linter follows
11 * that, we'll remove useless documentations for |parent| and |descendant|.
12 * TODO(yosin): bmm.contains() should be method of BookmarkTreeNode.
13 * @param {!BookmarkTreeNode} parent .
14 * @param {!BookmarkTreeNode} descendant .
15 * @return {boolean} Whether the parent contains the descendant.
17 function contains(parent
, descendant
) {
18 if (descendant
.parentId
== parent
.id
)
20 // the bmm.treeLookup contains all folders
21 var parentTreeItem
= bmm
.treeLookup
[descendant
.parentId
];
22 if (!parentTreeItem
|| !parentTreeItem
.bookmarkNode
)
24 return this.contains(parent
, parentTreeItem
.bookmarkNode
);
28 * @param {!BookmarkTreeNode} node The node to test.
29 * @return {boolean} Whether a bookmark node is a folder.
31 function isFolder(node
) {
32 return !('url' in node
);
35 var loadingPromises
= {};
38 * Promise version of chrome.bookmarkManagerPrivate.getSubtree.
39 * @param {string} id .
40 * @param {boolean} foldersOnly .
41 * @return {!Promise<!Array<!BookmarkTreeNode>>} .
43 function getSubtreePromise(id
, foldersOnly
) {
44 return new Promise(function(resolve
, reject
) {
45 chrome
.bookmarkManagerPrivate
.getSubtree(id
, foldersOnly
, function(node
) {
46 if (chrome
.runtime
.lastError
) {
47 reject(new Error(chrome
.runtime
.lastError
.message
));
56 * Loads a subtree of the bookmark tree and returns a {@code Promise} that
57 * will be fulfilled when done. This reuses multiple loads so that we do not
58 * load the same subtree more than once at the same time.
59 * @return {!Promise<!BookmarkTreeNode>} The future promise for the load.
61 function loadSubtree(id
) {
62 if (!loadingPromises
[id
]) {
63 loadingPromises
[id
] = getSubtreePromise(id
, false).then(function(nodes
) {
64 return nodes
&& nodes
[0];
66 console
.error(error
.message
);
68 loadingPromises
[id
].then(function() {
69 delete loadingPromises
[id
];
72 return loadingPromises
[id
];
76 * Loads the entire bookmark tree and returns a {@code Promise} that will
77 * be fulfilled when done. This reuses multiple loads so that we do not load
78 * the same tree more than once at the same time.
79 * @return {!Promise<!BookmarkTreeNode>} The future promise for the load.
82 return loadSubtree('');
87 * Removes the cached item from both the list and tree lookups.
89 remove: function(id
) {
90 var treeItem
= bmm
.treeLookup
[id
];
92 var items
= treeItem
.items
; // is an HTMLCollection
93 for (var i
= 0; i
< items
.length
; ++i
) {
95 var bookmarkNode
= item
.bookmarkNode
;
96 delete bmm
.treeLookup
[bookmarkNode
.id
];
98 delete bmm
.treeLookup
[id
];
103 * Updates the underlying bookmark node for the tree items and list items by
104 * querying the bookmark backend.
105 * @param {string} id The id of the node to update the children for.
106 * @param {Function=} opt_f A funciton to call when done.
108 updateChildren: function(id
, opt_f
) {
109 function updateItem(bookmarkNode
) {
110 var treeItem
= bmm
.treeLookup
[bookmarkNode
.id
];
112 treeItem
.bookmarkNode
= bookmarkNode
;
116 chrome
.bookmarks
.getChildren(id
, function(children
) {
118 children
.forEach(updateItem
);
127 * Called when the title of a bookmark changes.
128 * @param {string} id The id of changed bookmark node.
129 * @param {!Object} changeInfo The information about how the node changed.
131 function handleBookmarkChanged(id
, changeInfo
) {
133 bmm
.tree
.handleBookmarkChanged(id
, changeInfo
);
135 bmm
.list
.handleBookmarkChanged(id
, changeInfo
);
139 * Callback for when the user reorders by title.
140 * @param {string} id The id of the bookmark folder that was reordered.
141 * @param {!Object} reorderInfo The information about how the items where
144 function handleChildrenReordered(id
, reorderInfo
) {
146 bmm
.tree
.handleChildrenReordered(id
, reorderInfo
);
148 bmm
.list
.handleChildrenReordered(id
, reorderInfo
);
149 bookmarkCache
.updateChildren(id
);
153 * Callback for when a bookmark node is created.
154 * @param {string} id The id of the newly created bookmark node.
155 * @param {!Object} bookmarkNode The new bookmark node.
157 function handleCreated(id
, bookmarkNode
) {
159 bmm
.list
.handleCreated(id
, bookmarkNode
);
161 bmm
.tree
.handleCreated(id
, bookmarkNode
);
162 bookmarkCache
.updateChildren(bookmarkNode
.parentId
);
166 * Callback for when a bookmark node is moved.
167 * @param {string} id The id of the moved bookmark node.
168 * @param {!Object} moveInfo The information about move.
170 function handleMoved(id
, moveInfo
) {
172 bmm
.list
.handleMoved(id
, moveInfo
);
174 bmm
.tree
.handleMoved(id
, moveInfo
);
176 bookmarkCache
.updateChildren(moveInfo
.parentId
);
177 if (moveInfo
.parentId
!= moveInfo
.oldParentId
)
178 bookmarkCache
.updateChildren(moveInfo
.oldParentId
);
182 * Callback for when a bookmark node is removed.
183 * @param {string} id The id of the removed bookmark node.
184 * @param {!Object} removeInfo The information about removed.
186 function handleRemoved(id
, removeInfo
) {
188 bmm
.list
.handleRemoved(id
, removeInfo
);
190 bmm
.tree
.handleRemoved(id
, removeInfo
);
192 bookmarkCache
.updateChildren(removeInfo
.parentId
);
193 bookmarkCache
.remove(id
);
197 * Callback for when all bookmark nodes have been deleted.
199 function handleRemoveAll() {
200 // Reload the list and the tree.
208 * Callback for when importing bookmark is started.
210 function handleImportBegan() {
211 chrome
.bookmarks
.onCreated
.removeListener(handleCreated
);
212 chrome
.bookmarks
.onChanged
.removeListener(handleBookmarkChanged
);
216 * Callback for when importing bookmark node is finished.
218 function handleImportEnded() {
219 // When importing is done we reload the tree and the list.
222 bmm
.tree
.removeEventListener('load', f
);
224 chrome
.bookmarks
.onCreated
.addListener(handleCreated
);
225 chrome
.bookmarks
.onChanged
.addListener(handleBookmarkChanged
);
230 // TODO(estade): this should navigate to the newly imported folder, which
231 // may be the bookmark bar if there were no previous bookmarks.
236 bmm
.tree
.addEventListener('load', f
);
242 * Adds the listeners for the bookmark model change events.
244 function addBookmarkModelListeners() {
245 chrome
.bookmarks
.onChanged
.addListener(handleBookmarkChanged
);
246 chrome
.bookmarks
.onChildrenReordered
.addListener(handleChildrenReordered
);
247 chrome
.bookmarks
.onCreated
.addListener(handleCreated
);
248 chrome
.bookmarks
.onMoved
.addListener(handleMoved
);
249 chrome
.bookmarks
.onRemoved
.addListener(handleRemoved
);
250 chrome
.bookmarks
.onImportBegan
.addListener(handleImportBegan
);
251 chrome
.bookmarks
.onImportEnded
.addListener(handleImportEnded
);
257 loadSubtree
: loadSubtree
,
259 addBookmarkModelListeners
: addBookmarkModelListeners