Bug 1070479 - Allow passing uri specs to transactions. r=mak.

This commit is contained in:
Asaf Romano 2014-09-23 08:44:41 +03:00
Родитель 33627a20f5
Коммит 5a42d8ad31
2 изменённых файлов: 67 добавлений и 28 удалений

Просмотреть файл

@ -54,7 +54,7 @@ this.EXPORTED_SYMBOLS = ["PlacesTransactions"];
* valid values across all transactions which accept it in the input object. * valid values across all transactions which accept it in the input object.
* Here is a list of all supported input properties along with their expected * Here is a list of all supported input properties along with their expected
* values: * values:
* - uri: an nsIURI object. * - uri: an nsIURI object or an uri spec string.
* - feedURI: an nsIURI object, holding the url for a live bookmark. * - feedURI: an nsIURI object, holding the url for a live bookmark.
* - siteURI: an nsIURI object, holding the url for the site with which * - siteURI: an nsIURI object, holding the url for the site with which
* a live bookmark is associated. * a live bookmark is associated.
@ -576,15 +576,28 @@ function DefineTransaction(aRequiredProps = [], aOptionalProps = []) {
return ctor; return ctor;
} }
DefineTransaction.isStr = v => typeof(v) == "string"; function simpleValidateFunc(aCheck) {
DefineTransaction.isStrOrNull = v => typeof(v) == "string" || v === null; return v => {
DefineTransaction.isURI = v => v instanceof Components.interfaces.nsIURI; if (!aCheck(v))
DefineTransaction.isIndex = v => Number.isInteger(v) && throw new Error("Invalid value");
v >= PlacesUtils.bookmarks.DEFAULT_INDEX; return v;
DefineTransaction.isGuid = v => /^[a-zA-Z0-9\-_]{12}$/.test(v); };
DefineTransaction.isPrimitive = v => v === null || (typeof(v) != "object" && }
typeof(v) != "function");
DefineTransaction.isAnnotationObject = function (obj) { DefineTransaction.strValidate = simpleValidateFunc(v => typeof(v) == "string");
DefineTransaction.strOrNullValidate =
simpleValidateFunc(v => typeof(v) == "string" || v === null);
DefineTransaction.indexValidate =
simpleValidateFunc(v => Number.isInteger(v) &&
v >= PlacesUtils.bookmarks.DEFAULT_INDEX);
DefineTransaction.guidValidate =
simpleValidateFunc(v => /^[a-zA-Z0-9\-_]{12}$/.test(v));
function isPrimitive(v) {
return v === null || (typeof(v) != "object" && typeof(v) != "function");
}
DefineTransaction.annotationObjectValidate = function (obj) {
let checkProperty = (aPropName, aRequired, aCheckFunc) => { let checkProperty = (aPropName, aRequired, aCheckFunc) => {
if (aPropName in obj) if (aPropName in obj)
return aCheckFunc(obj[aPropName]); return aCheckFunc(obj[aPropName]);
@ -593,22 +606,27 @@ DefineTransaction.isAnnotationObject = function (obj) {
}; };
if (obj && if (obj &&
checkProperty("name", true, DefineTransaction.isStr) && checkProperty("name", true, v => typeof(v) == "string" && v.length > 0) &&
checkProperty("expires", false, Number.isInteger) && checkProperty("expires", false, Number.isInteger) &&
checkProperty("flags", false, Number.isInteger) && checkProperty("flags", false, Number.isInteger) &&
checkProperty("value", false, DefineTransaction.isPrimitive) ) { checkProperty("value", false, isPrimitive) ) {
// Nothing else should be set // Nothing else should be set
let validKeys = ["name", "value", "flags", "expires"]; let validKeys = ["name", "value", "flags", "expires"];
if (Object.keys(obj).every( (k) => validKeys.indexOf(k) != -1 )) if (Object.keys(obj).every( (k) => validKeys.indexOf(k) != -1 ))
return true; return obj;
} }
return false; throw new Error("Invalid annotation object");
};
DefineTransaction.uriValidate = function(uriOrSpec) {
if (uriOrSpec instanceof Components.interfaces.nsIURI)
return uriOrSpec;
return NetUtil.newURI(uriOrSpec);
}; };
DefineTransaction.inputProps = new Map(); DefineTransaction.inputProps = new Map();
DefineTransaction.defineInputProps = DefineTransaction.defineInputProps =
function (aNames, aValidationFunction, function (aNames, aValidationFunction, aDefaultValue) {
aDefaultValue, aTransformFunction = null) {
for (let name of aNames) { for (let name of aNames) {
// Workaround bug 449811. // Workaround bug 449811.
let propName = name; let propName = name;
@ -616,9 +634,12 @@ function (aNames, aValidationFunction,
validateValue: function (aValue) { validateValue: function (aValue) {
if (aValue === undefined) if (aValue === undefined)
return aDefaultValue; return aDefaultValue;
if (!aValidationFunction(aValue)) try {
return aValidationFunction(aValue);
}
catch(ex) {
throw new Error(`Invalid value for input property ${propName}`); throw new Error(`Invalid value for input property ${propName}`);
return aTransformFunction ? aTransformFunction(aValue) : aValue; }
}, },
validateInput: function (aInput, aRequired) { validateInput: function (aInput, aRequired) {
@ -720,7 +741,7 @@ function (aInput, aRequiredProps = [], aOptionalProps = []) {
// the moment anyway). // the moment anyway).
let input = aInput; let input = aInput;
let isSinglePropertyInput = let isSinglePropertyInput =
this.isPrimitive(aInput) || isPrimitive(aInput) ||
Array.isArray(aInput) || Array.isArray(aInput) ||
(aInput instanceof Components.interfaces.nsISupports); (aInput instanceof Components.interfaces.nsISupports);
if (isSinglePropertyInput) { if (isSinglePropertyInput) {
@ -743,19 +764,19 @@ function (aInput, aRequiredProps = [], aOptionalProps = []) {
// Update the documentation at the top of this module if you add or // Update the documentation at the top of this module if you add or
// remove properties. // remove properties.
DefineTransaction.defineInputProps(["uri", "feedURI", "siteURI"], DefineTransaction.defineInputProps(["uri", "feedURI", "siteURI"],
DefineTransaction.isURI, null); DefineTransaction.uriValidate, null);
DefineTransaction.defineInputProps(["guid", "parentGuid", "newParentGuid"], DefineTransaction.defineInputProps(["guid", "parentGuid", "newParentGuid"],
DefineTransaction.isGuid); DefineTransaction.guidValidate);
DefineTransaction.defineInputProps(["title"], DefineTransaction.defineInputProps(["title"],
DefineTransaction.isStrOrNull, null); DefineTransaction.strOrNullValidate, null);
DefineTransaction.defineInputProps(["keyword", "postData", "tag", DefineTransaction.defineInputProps(["keyword", "postData", "tag",
"excludingAnnotation"], "excludingAnnotation"],
DefineTransaction.isStr, ""); DefineTransaction.strValidate, "");
DefineTransaction.defineInputProps(["index", "newIndex"], DefineTransaction.defineInputProps(["index", "newIndex"],
DefineTransaction.isIndex, DefineTransaction.indexValidate,
PlacesUtils.bookmarks.DEFAULT_INDEX); PlacesUtils.bookmarks.DEFAULT_INDEX);
DefineTransaction.defineInputProps(["annotation"], DefineTransaction.defineInputProps(["annotation"],
DefineTransaction.isAnnotationObject); DefineTransaction.annotationObjectValidate);
DefineTransaction.defineArrayInputProp("uris", "uri"); DefineTransaction.defineArrayInputProp("uris", "uri");
DefineTransaction.defineArrayInputProp("tags", "tag"); DefineTransaction.defineArrayInputProp("tags", "tag");
DefineTransaction.defineArrayInputProp("annotations", "annotation"); DefineTransaction.defineArrayInputProp("annotations", "annotation");

Просмотреть файл

@ -1078,8 +1078,9 @@ add_task(function* test_edit_keyword() {
ensureUndoState(); ensureUndoState();
}); });
add_task(function* doTest() { add_task(function* test_tag_uri() {
let bm_info_a = { uri: NetUtil.newURI("http://bookmarked.uri") // This also tests passing uri specs.
let bm_info_a = { uri: "http://bookmarked.uri"
, parentGuid: yield PlacesUtils.promiseItemGuid(root) }; , parentGuid: yield PlacesUtils.promiseItemGuid(root) };
let bm_info_b = { uri: NetUtil.newURI("http://bookmarked2.uri") let bm_info_b = { uri: NetUtil.newURI("http://bookmarked2.uri")
, parentGuid: yield PlacesUtils.promiseItemGuid(root) }; , parentGuid: yield PlacesUtils.promiseItemGuid(root) };
@ -1102,6 +1103,9 @@ add_task(function* doTest() {
let uris = "uri" in aInfo ? [aInfo.uri] : aInfo.uris; let uris = "uri" in aInfo ? [aInfo.uri] : aInfo.uris;
let tags = "tag" in aInfo ? [aInfo.tag] : aInfo.tags; let tags = "tag" in aInfo ? [aInfo.tag] : aInfo.tags;
let ensureURI = uri => typeof(uri) == "string" ? NetUtil.newURI(uri) : uri;
uris = [for (uri of uris) ensureURI(uri)];
let tagWillAlsoBookmark = new Set(); let tagWillAlsoBookmark = new Set();
for (let uri of uris) { for (let uri of uris) {
if (!(yield promiseIsBookmarked(uri))) { if (!(yield promiseIsBookmarked(uri))) {
@ -1557,3 +1561,17 @@ add_task(function* test_copy_excluding_annotations() {
yield PT.undo(); yield PT.undo();
yield PT.clearTransactionsHistory(); yield PT.clearTransactionsHistory();
}); });
add_task(function* test_invalid_uri_spec_throws() {
let rootGuid = yield PlacesUtils.promiseItemGuid(root);
Assert.throws(() =>
PT.NewBookmark({ parentGuid: rootGuid
, uri: "invalid uri spec"
, title: "test bookmark" }));
Assert.throws(() =>
PT.Tag({ tag: "TheTag"
, uris: ["invalid uri spec"] }));
Assert.throws(() =>
PT.Tag({ tag: "TheTag"
, uris: ["about:blank", "invalid uri spec"] }));
});