addon-sdk/source/lib/sdk/places/host/host-bookmarks.js

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:79412fe9f1a2
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 "use strict";
6
7 module.metadata = {
8 "stability": "experimental",
9 "engines": {
10 "Firefox": "*"
11 }
12 };
13
14 const { Cc, Ci } = require('chrome');
15 const browserHistory = Cc["@mozilla.org/browser/nav-history-service;1"].
16 getService(Ci.nsIBrowserHistory);
17 const asyncHistory = Cc["@mozilla.org/browser/history;1"].
18 getService(Ci.mozIAsyncHistory);
19 const bmsrv = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
20 getService(Ci.nsINavBookmarksService);
21 const taggingService = Cc["@mozilla.org/browser/tagging-service;1"].
22 getService(Ci.nsITaggingService);
23 const ios = Cc['@mozilla.org/network/io-service;1'].
24 getService(Ci.nsIIOService);
25 const { query } = require('./host-query');
26 const {
27 defer, all, resolve, promised, reject
28 } = require('../../core/promise');
29 const { request, response } = require('../../addon/host');
30 const { send } = require('../../addon/events');
31 const { on, emit } = require('../../event/core');
32 const { filter } = require('../../event/utils');
33 const { URL, isValidURI } = require('../../url');
34 const { newURI } = require('../../url/utils');
35
36 const DEFAULT_INDEX = bmsrv.DEFAULT_INDEX;
37 const UNSORTED_ID = bmsrv.unfiledBookmarksFolder;
38 const ROOT_FOLDERS = [
39 bmsrv.unfiledBookmarksFolder, bmsrv.toolbarFolder,
40 bmsrv.tagsFolder, bmsrv.bookmarksMenuFolder
41 ];
42
43 const EVENT_MAP = {
44 'sdk-places-bookmarks-create': createBookmarkItem,
45 'sdk-places-bookmarks-save': saveBookmarkItem,
46 'sdk-places-bookmarks-last-updated': getBookmarkLastUpdated,
47 'sdk-places-bookmarks-get': getBookmarkItem,
48 'sdk-places-bookmarks-remove': removeBookmarkItem,
49 'sdk-places-bookmarks-get-all': getAllBookmarks,
50 'sdk-places-bookmarks-get-children': getChildren
51 };
52
53 function typeMap (type) {
54 if (typeof type === 'number') {
55 if (bmsrv.TYPE_BOOKMARK === type) return 'bookmark';
56 if (bmsrv.TYPE_FOLDER === type) return 'group';
57 if (bmsrv.TYPE_SEPARATOR === type) return 'separator';
58 } else {
59 if ('bookmark' === type) return bmsrv.TYPE_BOOKMARK;
60 if ('group' === type) return bmsrv.TYPE_FOLDER;
61 if ('separator' === type) return bmsrv.TYPE_SEPARATOR;
62 }
63 }
64
65 function getBookmarkLastUpdated ({id})
66 resolve(bmsrv.getItemLastModified(id))
67 exports.getBookmarkLastUpdated;
68
69 function createBookmarkItem (data) {
70 let error;
71
72 if (data.group == null) data.group = UNSORTED_ID;
73 if (data.index == null) data.index = DEFAULT_INDEX;
74
75 if (data.type === 'group')
76 data.id = bmsrv.createFolder(
77 data.group, data.title, data.index
78 );
79 else if (data.type === 'separator')
80 data.id = bmsrv.insertSeparator(
81 data.group, data.index
82 );
83 else
84 data.id = bmsrv.insertBookmark(
85 data.group, newURI(data.url), data.index, data.title
86 );
87
88 // In the event where default or no index is provided (-1),
89 // query the actual index for the response
90 if (data.index === -1)
91 data.index = bmsrv.getItemIndex(data.id);
92
93 data.updated = bmsrv.getItemLastModified(data.id);
94
95 return tag(data, true).then(() => data);
96 }
97 exports.createBookmarkItem = createBookmarkItem;
98
99 function saveBookmarkItem (data) {
100 let id = data.id;
101 if (!id)
102 reject('Item is missing id');
103
104 let group = bmsrv.getFolderIdForItem(id);
105 let index = bmsrv.getItemIndex(id);
106 let type = bmsrv.getItemType(id);
107 let title = typeMap(type) !== 'separator' ?
108 bmsrv.getItemTitle(id) :
109 undefined;
110 let url = typeMap(type) === 'bookmark' ?
111 bmsrv.getBookmarkURI(id).spec :
112 undefined;
113
114 if (url != data.url)
115 bmsrv.changeBookmarkURI(id, newURI(data.url));
116 else if (typeMap(type) === 'bookmark')
117 data.url = url;
118
119 if (title != data.title)
120 bmsrv.setItemTitle(id, data.title);
121 else if (typeMap(type) !== 'separator')
122 data.title = title;
123
124 if (data.group && data.group !== group)
125 bmsrv.moveItem(id, data.group, data.index || -1);
126 else if (data.index != null && data.index !== index) {
127 // We use moveItem here instead of setItemIndex
128 // so we don't have to manage the indicies of the siblings
129 bmsrv.moveItem(id, group, data.index);
130 } else if (data.index == null)
131 data.index = index;
132
133 data.updated = bmsrv.getItemLastModified(data.id);
134
135 return tag(data).then(() => data);
136 }
137 exports.saveBookmarkItem = saveBookmarkItem;
138
139 function removeBookmarkItem (data) {
140 let id = data.id;
141
142 if (!id)
143 reject('Item is missing id');
144
145 bmsrv.removeItem(id);
146 return resolve(null);
147 }
148 exports.removeBookmarkItem = removeBookmarkItem;
149
150 function getBookmarkItem (data) {
151 let id = data.id;
152
153 if (!id)
154 reject('Item is missing id');
155
156 let type = bmsrv.getItemType(id);
157
158 data.type = typeMap(type);
159
160 if (type === bmsrv.TYPE_BOOKMARK || type === bmsrv.TYPE_FOLDER)
161 data.title = bmsrv.getItemTitle(id);
162
163 if (type === bmsrv.TYPE_BOOKMARK) {
164 data.url = bmsrv.getBookmarkURI(id).spec;
165 // Should be moved into host-tags as a method
166 data.tags = taggingService.getTagsForURI(newURI(data.url), {});
167 }
168
169 data.group = bmsrv.getFolderIdForItem(id);
170 data.index = bmsrv.getItemIndex(id);
171 data.updated = bmsrv.getItemLastModified(data.id);
172
173 return resolve(data);
174 }
175 exports.getBookmarkItem = getBookmarkItem;
176
177 function getAllBookmarks () {
178 return query({}, { queryType: 1 }).then(bookmarks =>
179 all(bookmarks.map(getBookmarkItem)));
180 }
181 exports.getAllBookmarks = getAllBookmarks;
182
183 function getChildren ({ id }) {
184 if (typeMap(bmsrv.getItemType(id)) !== 'group') return [];
185 let ids = [];
186 for (let i = 0; ids[ids.length - 1] !== -1; i++)
187 ids.push(bmsrv.getIdForItemAt(id, i));
188 ids.pop();
189 return all(ids.map(id => getBookmarkItem({ id: id })));
190 }
191 exports.getChildren = getChildren;
192
193 /*
194 * Hook into host
195 */
196
197 let reqStream = filter(request, function (data) /sdk-places-bookmarks/.test(data.event));
198 on(reqStream, 'data', function ({event, id, data}) {
199 if (!EVENT_MAP[event]) return;
200
201 let resData = {
202 id: id,
203 event: event
204 };
205
206 promised(EVENT_MAP[event])(data).then(res => {
207 resData.data = res;
208 respond(resData);
209 }, reason => {
210 resData.error = reason;
211 respond(resData);
212 });
213 });
214
215 function respond (data) {
216 emit(response, 'data', data);
217 }
218
219 function tag (data, isNew) {
220 // If a new item, we can skip checking what other tags
221 // are on the item
222 if (data.type !== 'bookmark') {
223 return resolve();
224 } else if (!isNew) {
225 return send('sdk-places-tags-get-tags-by-url', { url: data.url })
226 .then(tags => {
227 return send('sdk-places-tags-untag', {
228 tags: tags.filter(tag => !~data.tags.indexOf(tag)),
229 url: data.url
230 });
231 }).then(() => send('sdk-places-tags-tag', {
232 url: data.url, tags: data.tags
233 }));
234 }
235 else if (data.tags && data.tags.length) {
236 return send('sdk-places-tags-tag', { url: data.url, tags: data.tags });
237 }
238 else
239 return resolve();
240 }
241

mercurial