mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-20 23:37:33 +09:00
Move Add-on SDK source to toolkit/jetpack
This commit is contained in:
parent
0a03067ee3
commit
23b67db438
993 changed files with 484 additions and 100663 deletions
238
toolkit/jetpack/sdk/places/host/host-bookmarks.js
Normal file
238
toolkit/jetpack/sdk/places/host/host-bookmarks.js
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
/* 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": "*",
|
||||
"SeaMonkey": "*"
|
||||
}
|
||||
};
|
||||
|
||||
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}) {
|
||||
return 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);
|
||||
|
||||
try {
|
||||
data.updated = bmsrv.getItemLastModified(data.id);
|
||||
}
|
||||
catch (e) {
|
||||
console.exception(e);
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
var reqStream = filter(request, (data) => /sdk-places-bookmarks/.test(data.event));
|
||||
on(reqStream, 'data', ({ event, id, data }) => {
|
||||
if (!EVENT_MAP[event]) return;
|
||||
|
||||
let resData = { id: id, event: event };
|
||||
|
||||
promised(EVENT_MAP[event])(data).
|
||||
then(res => resData.data = res, e => resData.error = e).
|
||||
then(() => emit(response, 'data', resData));
|
||||
});
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
179
toolkit/jetpack/sdk/places/host/host-query.js
Normal file
179
toolkit/jetpack/sdk/places/host/host-query.js
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
/* 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": "*",
|
||||
"SeaMonkey": "*"
|
||||
}
|
||||
};
|
||||
|
||||
const { Cc, Ci } = require('chrome');
|
||||
const { all } = require('../../core/promise');
|
||||
const { safeMerge, omit } = require('../../util/object');
|
||||
const historyService = Cc['@mozilla.org/browser/nav-history-service;1']
|
||||
.getService(Ci.nsINavHistoryService);
|
||||
const bookmarksService = Cc['@mozilla.org/browser/nav-bookmarks-service;1']
|
||||
.getService(Ci.nsINavBookmarksService);
|
||||
const { request, response } = require('../../addon/host');
|
||||
const { newURI } = require('../../url/utils');
|
||||
const { send } = require('../../addon/events');
|
||||
const { on, emit } = require('../../event/core');
|
||||
const { filter } = require('../../event/utils');
|
||||
|
||||
const ROOT_FOLDERS = [
|
||||
bookmarksService.unfiledBookmarksFolder, bookmarksService.toolbarFolder,
|
||||
bookmarksService.bookmarksMenuFolder
|
||||
];
|
||||
|
||||
const EVENT_MAP = {
|
||||
'sdk-places-query': queryReceiver
|
||||
};
|
||||
|
||||
// Properties that need to be manually
|
||||
// copied into a nsINavHistoryQuery object
|
||||
const MANUAL_QUERY_PROPERTIES = [
|
||||
'uri', 'folder', 'tags', 'url', 'folder'
|
||||
];
|
||||
|
||||
const PLACES_PROPERTIES = [
|
||||
'uri', 'title', 'accessCount', 'time'
|
||||
];
|
||||
|
||||
function execute (queries, options) {
|
||||
return new Promise(resolve => {
|
||||
let root = historyService
|
||||
.executeQueries(queries, queries.length, options).root;
|
||||
// Let's extract an eventual uri wildcard, if both domain and uri are set.
|
||||
// See utils.js::urlQueryParser() for more details.
|
||||
// In case of multiple queries, we only retain the first found wildcard.
|
||||
let uriWildcard = queries.reduce((prev, query) => {
|
||||
if (query.uri && query.domain) {
|
||||
if (!prev)
|
||||
prev = query.uri.spec;
|
||||
query.uri = null;
|
||||
}
|
||||
return prev;
|
||||
}, "");
|
||||
resolve(collect([], root, uriWildcard));
|
||||
});
|
||||
}
|
||||
|
||||
function collect (acc, node, uriWildcard) {
|
||||
node.containerOpen = true;
|
||||
for (let i = 0; i < node.childCount; i++) {
|
||||
let child = node.getChild(i);
|
||||
|
||||
if (!uriWildcard || child.uri.startsWith(uriWildcard)) {
|
||||
acc.push(child);
|
||||
}
|
||||
if (child.type === child.RESULT_TYPE_FOLDER) {
|
||||
let container = child.QueryInterface(Ci.nsINavHistoryContainerResultNode);
|
||||
collect(acc, container, uriWildcard);
|
||||
}
|
||||
}
|
||||
node.containerOpen = false;
|
||||
return acc;
|
||||
}
|
||||
|
||||
function query (queries, options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
queries = queries || [];
|
||||
options = options || {};
|
||||
let optionsObj, queryObjs;
|
||||
|
||||
optionsObj = historyService.getNewQueryOptions();
|
||||
queryObjs = [].concat(queries).map(createQuery);
|
||||
if (!queryObjs.length) {
|
||||
queryObjs = [historyService.getNewQuery()];
|
||||
}
|
||||
safeMerge(optionsObj, options);
|
||||
|
||||
/*
|
||||
* Currently `places:` queries are not supported
|
||||
*/
|
||||
optionsObj.excludeQueries = true;
|
||||
|
||||
execute(queryObjs, optionsObj).then((results) => {
|
||||
if (optionsObj.queryType === 0) {
|
||||
return results.map(normalize);
|
||||
}
|
||||
else if (optionsObj.queryType === 1) {
|
||||
// Formats query results into more standard
|
||||
// data structures for returning
|
||||
return all(results.map(({itemId}) =>
|
||||
send('sdk-places-bookmarks-get', { id: itemId })));
|
||||
}
|
||||
}).then(resolve, reject);
|
||||
});
|
||||
}
|
||||
exports.query = query;
|
||||
|
||||
function createQuery (query) {
|
||||
query = query || {};
|
||||
let queryObj = historyService.getNewQuery();
|
||||
|
||||
safeMerge(queryObj, omit(query, MANUAL_QUERY_PROPERTIES));
|
||||
|
||||
if (query.tags && Array.isArray(query.tags))
|
||||
queryObj.tags = query.tags;
|
||||
if (query.uri || query.url)
|
||||
queryObj.uri = newURI(query.uri || query.url);
|
||||
if (query.folder)
|
||||
queryObj.setFolders([query.folder], 1);
|
||||
return queryObj;
|
||||
}
|
||||
|
||||
function queryReceiver (message) {
|
||||
let queries = message.data.queries || message.data.query;
|
||||
let options = message.data.options;
|
||||
let resData = {
|
||||
id: message.id,
|
||||
event: message.event
|
||||
};
|
||||
|
||||
query(queries, options).then(results => {
|
||||
resData.data = results;
|
||||
respond(resData);
|
||||
}, reason => {
|
||||
resData.error = reason;
|
||||
respond(resData);
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts a nsINavHistoryResultNode into a plain object
|
||||
*
|
||||
* https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsINavHistoryResultNode
|
||||
*/
|
||||
function normalize (historyObj) {
|
||||
return PLACES_PROPERTIES.reduce((obj, prop) => {
|
||||
if (prop === 'uri')
|
||||
obj.url = historyObj.uri;
|
||||
else if (prop === 'time') {
|
||||
// Cast from microseconds to milliseconds
|
||||
obj.time = Math.floor(historyObj.time / 1000)
|
||||
}
|
||||
else if (prop === 'accessCount')
|
||||
obj.visitCount = historyObj[prop];
|
||||
else
|
||||
obj[prop] = historyObj[prop];
|
||||
return obj;
|
||||
}, {});
|
||||
}
|
||||
|
||||
/*
|
||||
* Hook into host
|
||||
*/
|
||||
|
||||
var reqStream = filter(request, data => /sdk-places-query/.test(data.event));
|
||||
on(reqStream, 'data', function (e) {
|
||||
if (EVENT_MAP[e.event]) EVENT_MAP[e.event](e);
|
||||
});
|
||||
|
||||
function respond (data) {
|
||||
emit(response, 'data', data);
|
||||
}
|
||||
92
toolkit/jetpack/sdk/places/host/host-tags.js
Normal file
92
toolkit/jetpack/sdk/places/host/host-tags.js
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/* 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": "*",
|
||||
"SeaMonkey": "*"
|
||||
}
|
||||
};
|
||||
|
||||
const { Cc, Ci } = require('chrome');
|
||||
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 { URL } = require('../../url');
|
||||
const { newURI } = require('../../url/utils');
|
||||
const { request, response } = require('../../addon/host');
|
||||
const { on, emit } = require('../../event/core');
|
||||
const { filter } = require('../../event/utils');
|
||||
|
||||
const EVENT_MAP = {
|
||||
'sdk-places-tags-tag': tag,
|
||||
'sdk-places-tags-untag': untag,
|
||||
'sdk-places-tags-get-tags-by-url': getTagsByURL,
|
||||
'sdk-places-tags-get-urls-by-tag': getURLsByTag
|
||||
};
|
||||
|
||||
function tag (message) {
|
||||
let data = message.data;
|
||||
let resData = {
|
||||
id: message.id,
|
||||
event: message.event
|
||||
};
|
||||
|
||||
resData.data = taggingService.tagURI(newURI(data.url), data.tags);
|
||||
respond(resData);
|
||||
}
|
||||
|
||||
function untag (message) {
|
||||
let data = message.data;
|
||||
let resData = {
|
||||
id: message.id,
|
||||
event: message.event
|
||||
};
|
||||
|
||||
resData.data = taggingService.untagURI(newURI(data.url), data.tags);
|
||||
respond(resData);
|
||||
}
|
||||
|
||||
function getURLsByTag (message) {
|
||||
let data = message.data;
|
||||
let resData = {
|
||||
id: message.id,
|
||||
event: message.event
|
||||
};
|
||||
|
||||
resData.data = taggingService
|
||||
.getURIsForTag(data.tag).map(uri => uri.spec);
|
||||
respond(resData);
|
||||
}
|
||||
|
||||
function getTagsByURL (message) {
|
||||
let data = message.data;
|
||||
let resData = {
|
||||
id: message.id,
|
||||
event: message.event
|
||||
};
|
||||
|
||||
resData.data = taggingService.getTagsForURI(newURI(data.url), {});
|
||||
respond(resData);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hook into host
|
||||
*/
|
||||
|
||||
var reqStream = filter(request, function (data) {
|
||||
return /sdk-places-tags/.test(data.event);
|
||||
});
|
||||
|
||||
on(reqStream, 'data', function (e) {
|
||||
if (EVENT_MAP[e.event]) EVENT_MAP[e.event](e);
|
||||
});
|
||||
|
||||
function respond (data) {
|
||||
emit(response, 'data', data);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue