gecko-dev/browser/components/extensions/ext-bookmarks.js
Kris Maglione b729a30707 Bug 1229874: Part 3 - Enable ESLint in WebExtension code. r=billm
The base .eslintrc is essentially a merge of the root Toolkit .eslintrc and
the devtools .eslintrc, with some minor changes to match our prevalent style.

For the most enforces the coding styles that we've been using most
consistently. There are a couple of significant differences, though:

 * The rule for opening brace alignment can only be applied globally, and
   doesn't make exceptions for top-level functions. I chose to turn it on, and
   change the brace style of existing top-level functions that violated it,
   since the rule seemed worth using, and that's the direction most Toolkit JS
   code has been headed anyway.

 * The rule for switch/case statements requires an added indentation level for
   case statements. Most of our switch statements did not use an extra level
   of indentation, and I initially wrote the rule to enforce that style, until
   I came across case statements that used blocks, and required the extra
   indentation level for sanity.

--HG--
rename : devtools/.eslintrc => toolkit/components/extensions/.eslintrc
extra : commitid : 4aDZOi5MNPc
extra : rebase_source : f34ba43aeb8046a0c971cb76b76410497bd12b42
extra : source : 2a7eb4ef7b375e5fd52d843ca206a071367a6475
2015-12-02 16:58:53 -08:00

264 lines
6.6 KiB
JavaScript

/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/PlacesUtils.jsm");
var Bookmarks = PlacesUtils.bookmarks;
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
var {
runSafe,
} = ExtensionUtils;
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
function getTree(rootGuid, onlyChildren) {
function convert(node, parent) {
let treenode = {
id: node.guid,
title: node.title || "",
index: node.index,
dateAdded: node.dateAdded / 1000,
};
if (parent && node.guid != Bookmarks.rootGuid) {
treenode.parentId = parent.guid;
}
if (node.type == PlacesUtils.TYPE_X_MOZ_PLACE) {
// This isn't quite correct. Recently Bookmarked ends up here ...
treenode.url = node.uri;
} else {
treenode.dateGroupModified = node.lastModified / 1000;
if (node.children && !onlyChildren) {
treenode.children = node.children.map(child => convert(child, node));
}
}
return treenode;
}
return PlacesUtils.promiseBookmarksTree(rootGuid, {
excludeItemsCallback: item => {
if (item.type == PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR) {
return true;
}
return item.annos &&
item.annos.find(a => a.name == PlacesUtils.EXCLUDE_FROM_BACKUP_ANNO);
},
}).then(root => {
if (onlyChildren) {
let children = root.children || [];
return children.map(child => convert(child, root));
} else {
// It seems like the array always just contains the root node.
return [convert(root, null)];
}
});
}
function convert(result) {
let node = {
id: result.guid,
title: result.title || "",
index: result.index,
dateAdded: result.dateAdded.getTime(),
};
if (result.guid != Bookmarks.rootGuid) {
node.parentId = result.parentGuid;
}
if (result.type == Bookmarks.TYPE_BOOKMARK) {
node.url = result.url.href; // Output is always URL object.
} else {
node.dateGroupModified = result.lastModified.getTime();
}
return node;
}
extensions.registerPrivilegedAPI("bookmarks", (extension, context) => {
return {
bookmarks: {
get: function(idOrIdList, callback) {
let list = Array.isArray(idOrIdList) ? idOrIdList : [idOrIdList];
Task.spawn(function* () {
let bookmarks = [];
for (let id of list) {
let bookmark;
try {
bookmark = yield Bookmarks.fetch({guid: id});
if (!bookmark) {
// TODO: set lastError, not found
return [];
}
} catch (e) {
// TODO: set lastError, probably an invalid guid
return [];
}
bookmarks.push(convert(bookmark));
}
return bookmarks;
}).then(results => runSafe(context, callback, results));
},
getChildren: function(id, callback) {
// TODO: We should optimize this.
getTree(id, true).then(result => {
runSafe(context, callback, result);
}, reason => {
// TODO: Set lastError
runSafe(context, callback, []);
});
},
getTree: function(callback) {
getTree(Bookmarks.rootGuid, false).then(result => {
runSafe(context, callback, result);
}, reason => {
runSafe(context, callback, []);
});
},
getSubTree: function(id, callback) {
getTree(id, false).then(result => {
runSafe(context, callback, result);
}, reason => {
runSafe(context, callback, []);
});
},
// search
create: function(bookmark, callback) {
let info = {
title: bookmark.title || "",
};
// If url is NULL or missing, it will be a folder.
if ("url" in bookmark && bookmark.url !== null) {
info.type = Bookmarks.TYPE_BOOKMARK;
info.url = bookmark.url || "";
} else {
info.type = Bookmarks.TYPE_FOLDER;
}
if ("index" in bookmark) {
info.index = bookmark.index;
}
if ("parentId" in bookmark) {
info.parentGuid = bookmark.parentId;
} else {
info.parentGuid = Bookmarks.unfiledGuid;
}
let failure = reason => {
// TODO: set lastError.
if (callback) {
runSafe(context, callback, null);
}
};
try {
Bookmarks.insert(info).then(result => {
if (callback) {
runSafe(context, callback, convert(result));
}
}, failure);
} catch (e) {
failure(e);
}
},
move: function(id, destination, callback) {
let info = {
guid: id,
};
if ("parentId" in destination) {
info.parentGuid = destination.parentId;
}
if ("index" in destination) {
info.index = destination.index;
}
let failure = reason => {
if (callback) {
runSafe(context, callback, null);
}
};
try {
Bookmarks.update(info).then(result => {
if (callback) {
runSafe(context, callback, convert(result));
}
}, failure);
} catch (e) {
failure(e);
}
},
update: function(id, changes, callback) {
let info = {
guid: id,
};
if ("title" in changes) {
info.title = changes.title;
}
if ("url" in changes) {
info.url = changes.url;
}
let failure = reason => {
if (callback) {
runSafe(context, callback, null);
}
};
try {
Bookmarks.update(info).then(result => {
if (callback) {
runSafe(context, callback, convert(result));
}
}, failure);
} catch (e) {
failure(e);
}
},
remove: function(id, callback) {
let info = {
guid: id,
};
let failure = reason => {
if (callback) {
runSafe(context, callback, null);
}
};
try {
Bookmarks.remove(info).then(result => {
if (callback) {
// The API doesn't give you the old bookmark at the moment
runSafe(context, callback);
}
}, failure);
} catch (e) {
failure(e);
}
},
},
};
});