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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/addon-sdk/source/lib/sdk/places/host/host-bookmarks.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,241 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +"use strict";
     1.9 +
    1.10 +module.metadata = {
    1.11 +  "stability": "experimental",
    1.12 +  "engines": {
    1.13 +    "Firefox": "*"
    1.14 +  }
    1.15 +};
    1.16 +
    1.17 +const { Cc, Ci } = require('chrome');
    1.18 +const browserHistory = Cc["@mozilla.org/browser/nav-history-service;1"].
    1.19 +                       getService(Ci.nsIBrowserHistory);
    1.20 +const asyncHistory = Cc["@mozilla.org/browser/history;1"].
    1.21 +                     getService(Ci.mozIAsyncHistory);
    1.22 +const bmsrv = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
    1.23 +                        getService(Ci.nsINavBookmarksService);
    1.24 +const taggingService = Cc["@mozilla.org/browser/tagging-service;1"].
    1.25 +                       getService(Ci.nsITaggingService);
    1.26 +const ios = Cc['@mozilla.org/network/io-service;1'].
    1.27 +            getService(Ci.nsIIOService);
    1.28 +const { query } = require('./host-query');
    1.29 +const {
    1.30 +  defer, all, resolve, promised, reject
    1.31 +} = require('../../core/promise');
    1.32 +const { request, response } = require('../../addon/host');
    1.33 +const { send } = require('../../addon/events');
    1.34 +const { on, emit } = require('../../event/core');
    1.35 +const { filter } = require('../../event/utils');
    1.36 +const { URL, isValidURI } = require('../../url');
    1.37 +const { newURI } = require('../../url/utils');
    1.38 +
    1.39 +const DEFAULT_INDEX = bmsrv.DEFAULT_INDEX;
    1.40 +const UNSORTED_ID = bmsrv.unfiledBookmarksFolder;
    1.41 +const ROOT_FOLDERS = [
    1.42 +  bmsrv.unfiledBookmarksFolder, bmsrv.toolbarFolder,
    1.43 +  bmsrv.tagsFolder, bmsrv.bookmarksMenuFolder
    1.44 +];
    1.45 +
    1.46 +const EVENT_MAP = {
    1.47 +  'sdk-places-bookmarks-create': createBookmarkItem,
    1.48 +  'sdk-places-bookmarks-save': saveBookmarkItem,
    1.49 +  'sdk-places-bookmarks-last-updated': getBookmarkLastUpdated,
    1.50 +  'sdk-places-bookmarks-get': getBookmarkItem,
    1.51 +  'sdk-places-bookmarks-remove': removeBookmarkItem,
    1.52 +  'sdk-places-bookmarks-get-all': getAllBookmarks,
    1.53 +  'sdk-places-bookmarks-get-children': getChildren
    1.54 +};
    1.55 +
    1.56 +function typeMap (type) {
    1.57 +  if (typeof type === 'number') {
    1.58 +    if (bmsrv.TYPE_BOOKMARK === type) return 'bookmark';
    1.59 +    if (bmsrv.TYPE_FOLDER === type) return 'group';
    1.60 +    if (bmsrv.TYPE_SEPARATOR === type) return 'separator';
    1.61 +  } else {
    1.62 +    if ('bookmark' === type) return bmsrv.TYPE_BOOKMARK;
    1.63 +    if ('group' === type) return bmsrv.TYPE_FOLDER;
    1.64 +    if ('separator' === type) return bmsrv.TYPE_SEPARATOR;
    1.65 +  }
    1.66 +}
    1.67 +
    1.68 +function getBookmarkLastUpdated ({id})
    1.69 +  resolve(bmsrv.getItemLastModified(id))
    1.70 +exports.getBookmarkLastUpdated;
    1.71 +
    1.72 +function createBookmarkItem (data) {
    1.73 +  let error;
    1.74 +
    1.75 +  if (data.group == null) data.group = UNSORTED_ID;
    1.76 +  if (data.index == null) data.index = DEFAULT_INDEX;
    1.77 +
    1.78 +  if (data.type === 'group')
    1.79 +    data.id = bmsrv.createFolder(
    1.80 +      data.group, data.title, data.index
    1.81 +    );
    1.82 +  else if (data.type === 'separator')
    1.83 +    data.id = bmsrv.insertSeparator(
    1.84 +      data.group, data.index
    1.85 +    );
    1.86 +  else
    1.87 +    data.id = bmsrv.insertBookmark(
    1.88 +      data.group, newURI(data.url), data.index, data.title
    1.89 +    );
    1.90 +
    1.91 +  // In the event where default or no index is provided (-1),
    1.92 +  // query the actual index for the response
    1.93 +  if (data.index === -1)
    1.94 +    data.index = bmsrv.getItemIndex(data.id);
    1.95 +
    1.96 +  data.updated = bmsrv.getItemLastModified(data.id);
    1.97 +
    1.98 +  return tag(data, true).then(() => data);
    1.99 +}
   1.100 +exports.createBookmarkItem = createBookmarkItem;
   1.101 +
   1.102 +function saveBookmarkItem (data) {
   1.103 +  let id = data.id;
   1.104 +  if (!id)
   1.105 +    reject('Item is missing id');
   1.106 +
   1.107 +  let group = bmsrv.getFolderIdForItem(id);
   1.108 +  let index = bmsrv.getItemIndex(id);
   1.109 +  let type = bmsrv.getItemType(id);
   1.110 +  let title = typeMap(type) !== 'separator' ?
   1.111 +    bmsrv.getItemTitle(id) :
   1.112 +    undefined;
   1.113 +  let url = typeMap(type) === 'bookmark' ?
   1.114 +    bmsrv.getBookmarkURI(id).spec :
   1.115 +    undefined;
   1.116 +
   1.117 +  if (url != data.url)
   1.118 +    bmsrv.changeBookmarkURI(id, newURI(data.url));
   1.119 +  else if (typeMap(type) === 'bookmark')
   1.120 +    data.url = url;
   1.121 +
   1.122 +  if (title != data.title)
   1.123 +    bmsrv.setItemTitle(id, data.title);
   1.124 +  else if (typeMap(type) !== 'separator')
   1.125 +    data.title = title;
   1.126 +
   1.127 +  if (data.group && data.group !== group)
   1.128 +    bmsrv.moveItem(id, data.group, data.index || -1);
   1.129 +  else if (data.index != null && data.index !== index) {
   1.130 +    // We use moveItem here instead of setItemIndex
   1.131 +    // so we don't have to manage the indicies of the siblings
   1.132 +    bmsrv.moveItem(id, group, data.index);
   1.133 +  } else if (data.index == null)
   1.134 +    data.index = index;
   1.135 +
   1.136 +  data.updated = bmsrv.getItemLastModified(data.id);
   1.137 +
   1.138 +  return tag(data).then(() => data);
   1.139 +}
   1.140 +exports.saveBookmarkItem = saveBookmarkItem;
   1.141 +
   1.142 +function removeBookmarkItem (data) {
   1.143 +  let id = data.id;
   1.144 +
   1.145 +  if (!id)
   1.146 +    reject('Item is missing id');
   1.147 +
   1.148 +  bmsrv.removeItem(id);
   1.149 +  return resolve(null);
   1.150 +}
   1.151 +exports.removeBookmarkItem = removeBookmarkItem;
   1.152 +
   1.153 +function getBookmarkItem (data) {
   1.154 +  let id = data.id;
   1.155 +
   1.156 +  if (!id)
   1.157 +    reject('Item is missing id');
   1.158 +
   1.159 +  let type = bmsrv.getItemType(id);
   1.160 +
   1.161 +  data.type = typeMap(type);
   1.162 +
   1.163 +  if (type === bmsrv.TYPE_BOOKMARK || type === bmsrv.TYPE_FOLDER)
   1.164 +    data.title = bmsrv.getItemTitle(id);
   1.165 +
   1.166 +  if (type === bmsrv.TYPE_BOOKMARK) {
   1.167 +    data.url = bmsrv.getBookmarkURI(id).spec;
   1.168 +    // Should be moved into host-tags as a method
   1.169 +    data.tags = taggingService.getTagsForURI(newURI(data.url), {});
   1.170 +  }
   1.171 +
   1.172 +  data.group = bmsrv.getFolderIdForItem(id);
   1.173 +  data.index = bmsrv.getItemIndex(id);
   1.174 +  data.updated = bmsrv.getItemLastModified(data.id);
   1.175 +
   1.176 +  return resolve(data);
   1.177 +}
   1.178 +exports.getBookmarkItem = getBookmarkItem;
   1.179 +
   1.180 +function getAllBookmarks () {
   1.181 +  return query({}, { queryType: 1 }).then(bookmarks =>
   1.182 +    all(bookmarks.map(getBookmarkItem)));
   1.183 +}
   1.184 +exports.getAllBookmarks = getAllBookmarks;
   1.185 +
   1.186 +function getChildren ({ id }) {
   1.187 +  if (typeMap(bmsrv.getItemType(id)) !== 'group') return [];
   1.188 +  let ids = [];
   1.189 +  for (let i = 0; ids[ids.length - 1] !== -1; i++)
   1.190 +    ids.push(bmsrv.getIdForItemAt(id, i));
   1.191 +  ids.pop();
   1.192 +  return all(ids.map(id => getBookmarkItem({ id: id })));
   1.193 +}
   1.194 +exports.getChildren = getChildren;
   1.195 +
   1.196 +/*
   1.197 + * Hook into host
   1.198 + */
   1.199 +
   1.200 +let reqStream = filter(request, function (data) /sdk-places-bookmarks/.test(data.event));
   1.201 +on(reqStream, 'data', function ({event, id, data}) {
   1.202 +  if (!EVENT_MAP[event]) return;
   1.203 +
   1.204 +  let resData = {
   1.205 +    id: id,
   1.206 +    event: event
   1.207 +  };
   1.208 +
   1.209 +  promised(EVENT_MAP[event])(data).then(res => {
   1.210 +    resData.data = res;
   1.211 +    respond(resData);
   1.212 +  }, reason => {
   1.213 +    resData.error = reason;
   1.214 +    respond(resData);
   1.215 +  });
   1.216 +});
   1.217 +
   1.218 +function respond (data) {
   1.219 +  emit(response, 'data', data);
   1.220 +}
   1.221 +
   1.222 +function tag (data, isNew) {
   1.223 +  // If a new item, we can skip checking what other tags
   1.224 +  // are on the item
   1.225 +  if (data.type !== 'bookmark') {
   1.226 +    return resolve();
   1.227 +  } else if (!isNew) {
   1.228 +    return send('sdk-places-tags-get-tags-by-url', { url: data.url })
   1.229 +      .then(tags => {
   1.230 +        return send('sdk-places-tags-untag', {
   1.231 +          tags: tags.filter(tag => !~data.tags.indexOf(tag)),
   1.232 +          url: data.url
   1.233 +        });
   1.234 +      }).then(() => send('sdk-places-tags-tag', {
   1.235 +        url: data.url, tags: data.tags
   1.236 +      }));
   1.237 +  }
   1.238 +  else if (data.tags && data.tags.length) {
   1.239 +    return send('sdk-places-tags-tag', { url: data.url, tags: data.tags });
   1.240 +  }
   1.241 +  else
   1.242 +    return resolve();
   1.243 +}
   1.244 +

mercurial