123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- "use strict";
- module.metadata = {
- "stability": "experimental",
- "engines": {
- "Firefox": "*"
- }
- };
- const { Cc, Ci } = require('chrome');
- const browserHistory = Cc["@mozilla.org/browser/nav-history-service;1"].
- getService(Ci.nsIBrowserHistory);
- const asyncHistory = Cc["@mozilla.org/browser/history;1"].
- getService(Ci.mozIAsyncHistory);
- const bmsrv = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
- getService(Ci.nsINavBookmarksService);
- const taggingService = Cc["@mozilla.org/browser/tagging-service;1"].
- getService(Ci.nsITaggingService);
- const ios = Cc['@mozilla.org/network/io-service;1'].
- getService(Ci.nsIIOService);
- const { query } = require('./host-query');
- const {
- defer, all, resolve, promised, reject
- } = require('../../core/promise');
- const { request, response } = require('../../addon/host');
- const { send } = require('../../addon/events');
- const { on, emit } = require('../../event/core');
- const { filter } = require('../../event/utils');
- const { URL, isValidURI } = require('../../url');
- const { newURI } = require('../../url/utils');
- const DEFAULT_INDEX = bmsrv.DEFAULT_INDEX;
- const UNSORTED_ID = bmsrv.unfiledBookmarksFolder;
- const ROOT_FOLDERS = [
- bmsrv.unfiledBookmarksFolder, bmsrv.toolbarFolder,
- bmsrv.tagsFolder, bmsrv.bookmarksMenuFolder
- ];
- const EVENT_MAP = {
- 'sdk-places-bookmarks-create': createBookmarkItem,
- 'sdk-places-bookmarks-save': saveBookmarkItem,
- 'sdk-places-bookmarks-last-updated': getBookmarkLastUpdated,
- 'sdk-places-bookmarks-get': getBookmarkItem,
- 'sdk-places-bookmarks-remove': removeBookmarkItem,
- 'sdk-places-bookmarks-get-all': getAllBookmarks,
- 'sdk-places-bookmarks-get-children': getChildren
- };
- function typeMap (type) {
- if (typeof type === 'number') {
- if (bmsrv.TYPE_BOOKMARK === type) return 'bookmark';
- if (bmsrv.TYPE_FOLDER === type) return 'group';
- if (bmsrv.TYPE_SEPARATOR === type) return 'separator';
- } else {
- if ('bookmark' === type) return bmsrv.TYPE_BOOKMARK;
- if ('group' === type) return bmsrv.TYPE_FOLDER;
- if ('separator' === type) return bmsrv.TYPE_SEPARATOR;
- }
- }
- function getBookmarkLastUpdated ({id})
- resolve(bmsrv.getItemLastModified(id))
- exports.getBookmarkLastUpdated;
- function createBookmarkItem (data) {
- let error;
- if (data.group == null) data.group = UNSORTED_ID;
- if (data.index == null) data.index = DEFAULT_INDEX;
- if (data.type === 'group')
- data.id = bmsrv.createFolder(
- data.group, data.title, data.index
- );
- else if (data.type === 'separator')
- data.id = bmsrv.insertSeparator(
- data.group, data.index
- );
- else
- data.id = bmsrv.insertBookmark(
- data.group, newURI(data.url), data.index, data.title
- );
- // In the event where default or no index is provided (-1),
- // query the actual index for the response
- if (data.index === -1)
- data.index = bmsrv.getItemIndex(data.id);
- data.updated = bmsrv.getItemLastModified(data.id);
- return tag(data, true).then(() => data);
- }
- exports.createBookmarkItem = createBookmarkItem;
- function saveBookmarkItem (data) {
- let id = data.id;
- if (!id)
- reject('Item is missing id');
- let group = bmsrv.getFolderIdForItem(id);
- let index = bmsrv.getItemIndex(id);
- let type = bmsrv.getItemType(id);
- let title = typeMap(type) !== 'separator' ?
- bmsrv.getItemTitle(id) :
- undefined;
- let url = typeMap(type) === 'bookmark' ?
- bmsrv.getBookmarkURI(id).spec :
- undefined;
- if (url != data.url)
- bmsrv.changeBookmarkURI(id, newURI(data.url));
- else if (typeMap(type) === 'bookmark')
- data.url = url;
- if (title != data.title)
- bmsrv.setItemTitle(id, data.title);
- else if (typeMap(type) !== 'separator')
- data.title = title;
- if (data.group && data.group !== group)
- bmsrv.moveItem(id, data.group, data.index || -1);
- else if (data.index != null && data.index !== index) {
- // We use moveItem here instead of setItemIndex
- // so we don't have to manage the indicies of the siblings
- bmsrv.moveItem(id, group, data.index);
- } else if (data.index == null)
- data.index = index;
- data.updated = bmsrv.getItemLastModified(data.id);
- return tag(data).then(() => data);
- }
- exports.saveBookmarkItem = saveBookmarkItem;
- function removeBookmarkItem (data) {
- let id = data.id;
- if (!id)
- reject('Item is missing id');
- bmsrv.removeItem(id);
- return resolve(null);
- }
- exports.removeBookmarkItem = removeBookmarkItem;
- function getBookmarkItem (data) {
- let id = data.id;
- if (!id)
- reject('Item is missing id');
- let type = bmsrv.getItemType(id);
- data.type = typeMap(type);
- if (type === bmsrv.TYPE_BOOKMARK || type === bmsrv.TYPE_FOLDER)
- data.title = bmsrv.getItemTitle(id);
- if (type === bmsrv.TYPE_BOOKMARK) {
- data.url = bmsrv.getBookmarkURI(id).spec;
- // Should be moved into host-tags as a method
- data.tags = taggingService.getTagsForURI(newURI(data.url), {});
- }
- data.group = bmsrv.getFolderIdForItem(id);
- data.index = bmsrv.getItemIndex(id);
- data.updated = bmsrv.getItemLastModified(data.id);
- return resolve(data);
- }
- exports.getBookmarkItem = getBookmarkItem;
- function getAllBookmarks () {
- return query({}, { queryType: 1 }).then(bookmarks =>
- all(bookmarks.map(getBookmarkItem)));
- }
- exports.getAllBookmarks = getAllBookmarks;
- function getChildren ({ id }) {
- if (typeMap(bmsrv.getItemType(id)) !== 'group') return [];
- let ids = [];
- for (let i = 0; ids[ids.length - 1] !== -1; i++)
- ids.push(bmsrv.getIdForItemAt(id, i));
- ids.pop();
- return all(ids.map(id => getBookmarkItem({ id: id })));
- }
- exports.getChildren = getChildren;
- /*
- * Hook into host
- */
- let reqStream = filter(request, function (data) /sdk-places-bookmarks/.test(data.event));
- on(reqStream, 'data', function ({event, id, data}) {
- if (!EVENT_MAP[event]) return;
- let resData = {
- id: id,
- event: event
- };
- promised(EVENT_MAP[event])(data).then(res => {
- resData.data = res;
- respond(resData);
- }, reason => {
- resData.error = reason;
- respond(resData);
- });
- });
- function respond (data) {
- emit(response, 'data', data);
- }
- function tag (data, isNew) {
- // If a new item, we can skip checking what other tags
- // are on the item
- if (data.type !== 'bookmark') {
- return resolve();
- } else if (!isNew) {
- return send('sdk-places-tags-get-tags-by-url', { url: data.url })
- .then(tags => {
- return send('sdk-places-tags-untag', {
- tags: tags.filter(tag => !~data.tags.indexOf(tag)),
- url: data.url
- });
- }).then(() => send('sdk-places-tags-tag', {
- url: data.url, tags: data.tags
- }));
- }
- else if (data.tags && data.tags.length) {
- return send('sdk-places-tags-tag', { url: data.url, tags: data.tags });
- }
- else
- return resolve();
- }
|