mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-15 06:15:43 +00:00
Bug 1150678 - Changing url of a bookmark with a keyword breaks the keyword forever. r=adw
MozReview-Commit-ID: 89Od4PKpQse --HG-- extra : rebase_source : 4fc77a9e4c2241787041a57da10907f32250babd
This commit is contained in:
parent
ac2f0b721a
commit
d399b52d03
@ -131,14 +131,18 @@ var gEditItemOverlay = {
|
||||
PlacesUIUtils.getItemDescription(this._paneInfo.itemId));
|
||||
},
|
||||
|
||||
_initKeywordField: Task.async(function* (aNewKeyword) {
|
||||
if (!this._paneInfo.isBookmark)
|
||||
_initKeywordField: Task.async(function* (newKeyword = "") {
|
||||
if (!this._paneInfo.isBookmark) {
|
||||
throw new Error("_initKeywordField called unexpectedly");
|
||||
}
|
||||
|
||||
let newKeyword = aNewKeyword;
|
||||
if (newKeyword === undefined) {
|
||||
let itemId = this._paneInfo.itemId;
|
||||
newKeyword = PlacesUtils.bookmarks.getKeywordForBookmark(itemId);
|
||||
if (!newKeyword) {
|
||||
let entries = [];
|
||||
yield PlacesUtils.keywords.fetch({ url: this._paneInfo.uri.spec },
|
||||
e => entries.push(e));
|
||||
if (entries.length > 0) {
|
||||
this._keyword = newKeyword = entries[0].keyword;
|
||||
}
|
||||
}
|
||||
this._initTextField(this._keywordField, newKeyword);
|
||||
}),
|
||||
@ -215,7 +219,7 @@ var gEditItemOverlay = {
|
||||
}
|
||||
|
||||
if (showOrCollapse("keywordRow", isBookmark, "keyword")) {
|
||||
this._initKeywordField();
|
||||
this._initKeywordField().catch(Components.utils.reportError);
|
||||
this._keywordField.readOnly = this.readOnly;
|
||||
}
|
||||
|
||||
@ -568,7 +572,7 @@ var gEditItemOverlay = {
|
||||
: this._paneInfo.itemGuid;
|
||||
PlacesTransactions.EditTitle({ guid, title: newTitle })
|
||||
.transact().catch(Components.utils.reportError);
|
||||
}).catch(Cu.reportError);
|
||||
}).catch(Components.utils.reportError);
|
||||
}
|
||||
},
|
||||
|
||||
@ -625,14 +629,19 @@ var gEditItemOverlay = {
|
||||
return;
|
||||
|
||||
let itemId = this._paneInfo.itemId;
|
||||
let newKeyword = this._keywordField.value;
|
||||
let oldKeyword = this._keyword;
|
||||
let keyword = this._keyword = this._keywordField.value;
|
||||
let postData = this._paneInfo.postData;
|
||||
if (!PlacesUIUtils.useAsyncTransactions) {
|
||||
let txn = new PlacesEditBookmarkKeywordTransaction(itemId, newKeyword, this._paneInfo.postData);
|
||||
let txn = new PlacesEditBookmarkKeywordTransaction(itemId,
|
||||
keyword,
|
||||
postData,
|
||||
oldKeyword);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
return;
|
||||
}
|
||||
let guid = this._paneInfo.itemGuid;
|
||||
PlacesTransactions.EditKeyword({ guid, keyword: newKeyword })
|
||||
PlacesTransactions.EditKeyword({ guid, keyword, postData, oldKeyword })
|
||||
.transact().catch(Components.utils.reportError);
|
||||
},
|
||||
|
||||
@ -1085,7 +1094,7 @@ var gEditItemOverlay = {
|
||||
break;
|
||||
case "keyword":
|
||||
if (this._paneInfo.visibleRows.has("keywordRow"))
|
||||
this._initKeywordField(aValue);
|
||||
this._initKeywordField(aValue).catch(Components.utils.reportError);
|
||||
break;
|
||||
case PlacesUIUtils.DESCRIPTION_ANNO:
|
||||
if (this._paneInfo.visibleRows.has("descriptionRow"))
|
||||
|
@ -854,6 +854,13 @@ Database::InitSchema(bool* aDatabaseMigrated)
|
||||
|
||||
// Firefox 50 uses schema version 33.
|
||||
|
||||
if (currentSchemaVersion < 34) {
|
||||
rv = MigrateV34Up();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Firefox 51 uses schema version 34.
|
||||
|
||||
// Schema Upgrades must add migration code here.
|
||||
|
||||
rv = UpdateBookmarkRootTitles();
|
||||
@ -1813,6 +1820,21 @@ Database::MigrateV33Up() {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Database::MigrateV34Up() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsresult rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"DELETE FROM moz_keywords WHERE id IN ( "
|
||||
"SELECT id FROM moz_keywords k "
|
||||
"WHERE NOT EXISTS (SELECT 1 FROM moz_places h WHERE k.place_id = h.id) "
|
||||
")"
|
||||
));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
Database::Shutdown()
|
||||
{
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
// This is the schema version. Update it at any schema change and add a
|
||||
// corresponding migrateVxx method below.
|
||||
#define DATABASE_SCHEMA_VERSION 33
|
||||
#define DATABASE_SCHEMA_VERSION 34
|
||||
|
||||
// Fired after Places inited.
|
||||
#define TOPIC_PLACES_INIT_COMPLETE "places-init-complete"
|
||||
@ -269,6 +269,7 @@ protected:
|
||||
nsresult MigrateV31Up();
|
||||
nsresult MigrateV32Up();
|
||||
nsresult MigrateV33Up();
|
||||
nsresult MigrateV34Up();
|
||||
|
||||
nsresult UpdateBookmarkRootTitles();
|
||||
|
||||
|
@ -885,7 +885,7 @@ DefineTransaction.defineInputProps(["guid", "parentGuid", "newParentGuid"],
|
||||
DefineTransaction.guidValidate);
|
||||
DefineTransaction.defineInputProps(["title"],
|
||||
DefineTransaction.strOrNullValidate, null);
|
||||
DefineTransaction.defineInputProps(["keyword", "postData", "tag",
|
||||
DefineTransaction.defineInputProps(["keyword", "oldKeyword", "postData", "tag",
|
||||
"excludingAnnotation"],
|
||||
DefineTransaction.strValidate, "");
|
||||
DefineTransaction.defineInputProps(["index", "newIndex"],
|
||||
@ -1000,8 +1000,12 @@ function* createItemsFromBookmarksTree(aBookmarksTree, aRestoring = false,
|
||||
let uri = NetUtil.newURI(aItem.uri);
|
||||
itemId = PlacesUtils.bookmarks.insertBookmark(
|
||||
parentId, uri, aIndex, aItem.title, guid);
|
||||
if ("keyword" in aItem)
|
||||
PlacesUtils.bookmarks.setKeywordForBookmark(itemId, aItem.keyword);
|
||||
if ("keyword" in aItem) {
|
||||
yield PlacesUtils.keywords.insert({
|
||||
keyword: aItem.keyword,
|
||||
url: uri.spec
|
||||
});
|
||||
}
|
||||
if ("tags" in aItem) {
|
||||
PlacesUtils.tagging.tagURI(uri, aItem.tags.split(","));
|
||||
}
|
||||
@ -1084,15 +1088,20 @@ PT.NewBookmark.prototype = Object.seal({
|
||||
execute: function (aParentGuid, aURI, aIndex, aTitle,
|
||||
aKeyword, aPostData, aAnnos, aTags) {
|
||||
return ExecuteCreateItem(this, aParentGuid,
|
||||
function (parentId, guidToRestore = "") {
|
||||
function* (parentId, guidToRestore = "") {
|
||||
let itemId = PlacesUtils.bookmarks.insertBookmark(
|
||||
parentId, aURI, aIndex, aTitle, guidToRestore);
|
||||
if (aKeyword)
|
||||
PlacesUtils.bookmarks.setKeywordForBookmark(itemId, aKeyword);
|
||||
if (aPostData)
|
||||
PlacesUtils.setPostDataForBookmark(itemId, aPostData);
|
||||
if (aAnnos.length)
|
||||
|
||||
if (aKeyword) {
|
||||
yield PlacesUtils.keywords.insert({
|
||||
url: aURI.spec,
|
||||
keyword: aKeyword,
|
||||
postData: aPostData
|
||||
});
|
||||
}
|
||||
if (aAnnos.length) {
|
||||
PlacesUtils.setAnnotationsForItem(itemId, aAnnos);
|
||||
}
|
||||
if (aTags.length > 0) {
|
||||
let currentTags = PlacesUtils.tagging.getTagsForURI(aURI);
|
||||
aTags = aTags.filter(t => !currentTags.includes(t));
|
||||
@ -1102,8 +1111,9 @@ PT.NewBookmark.prototype = Object.seal({
|
||||
return itemId;
|
||||
},
|
||||
function _additionalOnUndo() {
|
||||
if (aTags.length > 0)
|
||||
if (aTags.length > 0) {
|
||||
PlacesUtils.tagging.untagURI(aURI, aTags);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -1121,7 +1131,7 @@ PT.NewFolder = DefineTransaction(["parentGuid", "title"],
|
||||
PT.NewFolder.prototype = Object.seal({
|
||||
execute: function (aParentGuid, aTitle, aIndex, aAnnos) {
|
||||
return ExecuteCreateItem(this, aParentGuid,
|
||||
function(parentId, guidToRestore = "") {
|
||||
function* (parentId, guidToRestore = "") {
|
||||
let itemId = PlacesUtils.bookmarks.createFolder(
|
||||
parentId, aTitle, aIndex, guidToRestore);
|
||||
if (aAnnos.length > 0)
|
||||
@ -1144,7 +1154,7 @@ PT.NewSeparator = DefineTransaction(["parentGuid"], ["index"]);
|
||||
PT.NewSeparator.prototype = Object.seal({
|
||||
execute: function (aParentGuid, aIndex) {
|
||||
return ExecuteCreateItem(this, aParentGuid,
|
||||
function (parentId, guidToRestore = "") {
|
||||
function* (parentId, guidToRestore = "") {
|
||||
let itemId = PlacesUtils.bookmarks.insertSeparator(
|
||||
parentId, aIndex, guidToRestore);
|
||||
return itemId;
|
||||
@ -1336,14 +1346,36 @@ PT.Annotate.prototype = {
|
||||
*
|
||||
* Required Input Properties: guid, keyword.
|
||||
*/
|
||||
PT.EditKeyword = DefineTransaction(["guid", "keyword"]);
|
||||
PT.EditKeyword = DefineTransaction(["guid", "keyword"],
|
||||
["postData", "oldKeyword"]);
|
||||
PT.EditKeyword.prototype = Object.seal({
|
||||
execute: function* (aGuid, aKeyword) {
|
||||
let itemId = yield PlacesUtils.promiseItemId(aGuid),
|
||||
oldKeyword = PlacesUtils.bookmarks.getKeywordForBookmark(itemId);
|
||||
PlacesUtils.bookmarks.setKeywordForBookmark(itemId, aKeyword);
|
||||
this.undo = () => {
|
||||
PlacesUtils.bookmarks.setKeywordForBookmark(itemId, oldKeyword);
|
||||
execute: function* (aGuid, aKeyword, aPostData, aOldKeyword) {
|
||||
let url;
|
||||
let oldKeywordEntry;
|
||||
if (aOldKeyword) {
|
||||
oldKeywordEntry = yield PlacesUtils.keywords.fetch(aOldKeyword);
|
||||
url = oldKeywordEntry.url;
|
||||
yield PlacesUtils.keywords.remove(aOldKeyword);
|
||||
}
|
||||
|
||||
if (aKeyword) {
|
||||
if (!url) {
|
||||
url = (yield PlacesUtils.bookmarks.fetch(aGuid)).url;
|
||||
}
|
||||
yield PlacesUtils.keywords.insert({
|
||||
url: url,
|
||||
keyword: aKeyword,
|
||||
postData: aPostData || (oldKeywordEntry ? oldKeywordEntry.postData : "")
|
||||
});
|
||||
}
|
||||
|
||||
this.undo = function* () {
|
||||
if (aKeyword) {
|
||||
yield PlacesUtils.keywords.remove(aKeyword);
|
||||
}
|
||||
if (oldKeywordEntry) {
|
||||
yield PlacesUtils.keywords.insert(oldKeywordEntry);
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
@ -1827,7 +1827,8 @@ this.PlacesUtils = {
|
||||
}.bind(this);
|
||||
|
||||
const QUERY_STR =
|
||||
`WITH RECURSIVE
|
||||
`/* do not warn (bug no): cannot use an index */
|
||||
WITH RECURSIVE
|
||||
descendants(fk, level, type, id, guid, parent, parentGuid, position,
|
||||
title, dateAdded, lastModified) AS (
|
||||
SELECT b1.fk, 0, b1.type, b1.id, b1.guid, b1.parent,
|
||||
@ -2356,29 +2357,54 @@ XPCOMUtils.defineLazyGetter(this, "gKeywordsCachePromise", () =>
|
||||
}).catch(Cu.reportError);
|
||||
},
|
||||
|
||||
onItemChanged(id, prop, isAnno, val, lastMod, itemType, parentId, guid) {
|
||||
if (gIgnoreKeywordNotifications ||
|
||||
prop != "keyword")
|
||||
onItemChanged(id, prop, isAnno, val, lastMod, itemType, parentId, guid,
|
||||
parentGuid, oldVal) {
|
||||
if (gIgnoreKeywordNotifications) {
|
||||
return;
|
||||
}
|
||||
|
||||
Task.spawn(function* () {
|
||||
let bookmark = yield PlacesUtils.bookmarks.fetch(guid);
|
||||
// By this time the bookmark could have gone, there's nothing we can do.
|
||||
if (!bookmark)
|
||||
return;
|
||||
if (prop == "keyword") {
|
||||
this._onKeywordChanged(guid, val).catch(Cu.reportError);
|
||||
} else if (prop == "uri") {
|
||||
this._onUrlChanged(guid, val, oldVal).catch(Cu.reportError);
|
||||
}
|
||||
},
|
||||
|
||||
if (val.length == 0) {
|
||||
// We are removing a keyword.
|
||||
let keywords = keywordsForHref(bookmark.url.href)
|
||||
for (let keyword of keywords) {
|
||||
cache.delete(keyword);
|
||||
}
|
||||
} else {
|
||||
// We are adding a new keyword.
|
||||
cache.set(val, { keyword: val, url: bookmark.url });
|
||||
_onKeywordChanged: Task.async(function* (guid, keyword) {
|
||||
let bookmark = yield PlacesUtils.bookmarks.fetch(guid);
|
||||
// Due to mixed sync/async operations, by this time the bookmark could
|
||||
// have disappeared and we already handle removals in onItemRemoved.
|
||||
if (!bookmark) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (keyword.length == 0) {
|
||||
// We are removing a keyword.
|
||||
let keywords = keywordsForHref(bookmark.url.href)
|
||||
for (let kw of keywords) {
|
||||
cache.delete(kw);
|
||||
}
|
||||
}).catch(Cu.reportError);
|
||||
}
|
||||
} else {
|
||||
// We are adding a new keyword.
|
||||
cache.set(keyword, { keyword, url: bookmark.url });
|
||||
}
|
||||
}),
|
||||
|
||||
_onUrlChanged: Task.async(function* (guid, url, oldUrl) {
|
||||
// Check if the old url is associated with keywords.
|
||||
let entries = [];
|
||||
yield PlacesUtils.keywords.fetch({ url: oldUrl }, e => entries.push(e));
|
||||
if (entries.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Move the keywords to the new url.
|
||||
for (let entry of entries) {
|
||||
yield PlacesUtils.keywords.remove(entry.keyword);
|
||||
entry.url = new URL(url);
|
||||
yield PlacesUtils.keywords.insert(entry);
|
||||
}
|
||||
}),
|
||||
};
|
||||
|
||||
PlacesUtils.bookmarks.addObserver(observer, false);
|
||||
@ -3423,14 +3449,18 @@ PlacesSetPageAnnotationTransaction.prototype = {
|
||||
* new keyword for the bookmark
|
||||
* @param aNewPostData [optional]
|
||||
* new keyword's POST data, if available
|
||||
* @param aOldKeyword [optional]
|
||||
* old keyword of the bookmark
|
||||
*
|
||||
* @return nsITransaction object
|
||||
*/
|
||||
this.PlacesEditBookmarkKeywordTransaction =
|
||||
function PlacesEditBookmarkKeywordTransaction(aItemId, aNewKeyword, aNewPostData)
|
||||
{
|
||||
function PlacesEditBookmarkKeywordTransaction(aItemId, aNewKeyword,
|
||||
aNewPostData, aOldKeyword) {
|
||||
this.item = new TransactionItemCache();
|
||||
this.item.id = aItemId;
|
||||
this.item.keyword = aOldKeyword;
|
||||
this.item.href = (PlacesUtils.bookmarks.getBookmarkURI(aItemId)).spec;
|
||||
this.new = new TransactionItemCache();
|
||||
this.new.keyword = aNewKeyword;
|
||||
this.new.postData = aNewPostData
|
||||
@ -3441,22 +3471,55 @@ PlacesEditBookmarkKeywordTransaction.prototype = {
|
||||
|
||||
doTransaction: function EBKTXN_doTransaction()
|
||||
{
|
||||
// Store the current values.
|
||||
this.item.keyword = PlacesUtils.bookmarks.getKeywordForBookmark(this.item.id);
|
||||
if (this.item.keyword)
|
||||
this.item.postData = PlacesUtils.getPostDataForBookmark(this.item.id);
|
||||
let done = false;
|
||||
Task.spawn(function* () {
|
||||
if (this.item.keyword) {
|
||||
let oldEntry = yield PlacesUtils.keywords.fetch(this.item.keyword);
|
||||
this.item.postData = oldEntry.postData;
|
||||
yield PlacesUtils.keywords.remove(this.item.keyword);
|
||||
}
|
||||
|
||||
// Update the keyword.
|
||||
PlacesUtils.bookmarks.setKeywordForBookmark(this.item.id, this.new.keyword);
|
||||
if (this.new.keyword && this.new.postData)
|
||||
PlacesUtils.setPostDataForBookmark(this.item.id, this.new.postData);
|
||||
if (this.new.keyword) {
|
||||
yield PlacesUtils.keywords.insert({
|
||||
url: this.item.href,
|
||||
keyword: this.new.keyword,
|
||||
postData: this.new.postData || this.item.postData
|
||||
});
|
||||
}
|
||||
}.bind(this)).catch(Cu.reportError)
|
||||
.then(() => done = true);
|
||||
// TODO: Until we can move to PlacesTransactions.jsm, we must spin the
|
||||
// events loop :(
|
||||
let thread = Services.tm.currentThread;
|
||||
while (!done) {
|
||||
thread.processNextEvent(true);
|
||||
}
|
||||
},
|
||||
|
||||
undoTransaction: function EBKTXN_undoTransaction()
|
||||
{
|
||||
PlacesUtils.bookmarks.setKeywordForBookmark(this.item.id, this.item.keyword);
|
||||
if (this.item.postData)
|
||||
PlacesUtils.setPostDataForBookmark(this.item.id, this.item.postData);
|
||||
|
||||
let done = false;
|
||||
Task.spawn(function* () {
|
||||
if (this.new.keyword) {
|
||||
yield PlacesUtils.keywords.remove(this.new.keyword);
|
||||
}
|
||||
|
||||
if (this.item.keyword) {
|
||||
yield PlacesUtils.keywords.insert({
|
||||
url: this.item.href,
|
||||
keyword: this.item.keyword,
|
||||
postData: this.item.postData
|
||||
});
|
||||
}
|
||||
}.bind(this)).catch(Cu.reportError)
|
||||
.then(() => done = true);
|
||||
// TODO: Until we can move to PlacesTransactions.jsm, we must spin the
|
||||
// events loop :(
|
||||
let thread = Services.tm.currentThread;
|
||||
while (!done) {
|
||||
thread.processNextEvent(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* 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/. */
|
||||
|
||||
const CURRENT_SCHEMA_VERSION = 33;
|
||||
const CURRENT_SCHEMA_VERSION = 34;
|
||||
const FIRST_UPGRADABLE_SCHEMA_VERSION = 11;
|
||||
|
||||
const NS_APP_USER_PROFILE_50_DIR = "ProfD";
|
||||
|
BIN
toolkit/components/places/tests/migration/places_v34.sqlite
Normal file
BIN
toolkit/components/places/tests/migration/places_v34.sqlite
Normal file
Binary file not shown.
@ -20,6 +20,7 @@ support-files =
|
||||
places_v31.sqlite
|
||||
places_v32.sqlite
|
||||
places_v33.sqlite
|
||||
places_v34.sqlite
|
||||
|
||||
[test_current_from_downgraded.js]
|
||||
[test_current_from_v6.js]
|
||||
|
@ -681,11 +681,12 @@ add_task(function* test_remove_folder() {
|
||||
});
|
||||
|
||||
add_task(function* test_add_and_remove_bookmarks_with_additional_info() {
|
||||
const testURI = NetUtil.newURI("http://add.remove.tag")
|
||||
, TAG_1 = "TestTag1", TAG_2 = "TestTag2"
|
||||
, KEYWORD = "test_keyword"
|
||||
, POST_DATA = "post_data"
|
||||
, ANNO = { name: "TestAnno", value: "TestAnnoValue" };
|
||||
const testURI = NetUtil.newURI("http://add.remove.tag");
|
||||
const TAG_1 = "TestTag1";
|
||||
const TAG_2 = "TestTag2";
|
||||
const KEYWORD = "test_keyword";
|
||||
const POST_DATA = "post_data";
|
||||
const ANNO = { name: "TestAnno", value: "TestAnnoValue" };
|
||||
|
||||
let folder_info = createTestFolderInfo();
|
||||
folder_info.guid = yield PT.NewFolder(folder_info).transact();
|
||||
@ -749,9 +750,14 @@ add_task(function* test_add_and_remove_bookmarks_with_additional_info() {
|
||||
ensureTags([TAG_1]);
|
||||
|
||||
// Check if Remove correctly restores keywords, tags and annotations.
|
||||
// Since both bookmarks share the same uri, they also share the keyword that
|
||||
// is not removed along with one of the bookmarks.
|
||||
observer.reset();
|
||||
yield PT.redo();
|
||||
ensureItemsChanged(...b2_post_creation_changes);
|
||||
ensureItemsChanged({ guid: b2_info.guid
|
||||
, isAnnoProperty: true
|
||||
, property: ANNO.name
|
||||
, newValue: ANNO.value });
|
||||
ensureTags([TAG_1, TAG_2]);
|
||||
|
||||
// Test Remove for multiple items.
|
||||
@ -761,6 +767,10 @@ add_task(function* test_add_and_remove_bookmarks_with_additional_info() {
|
||||
yield PT.Remove(folder_info.guid).transact();
|
||||
yield ensureItemsRemoved(b1_info, b2_info, folder_info);
|
||||
ensureTags([]);
|
||||
// There is no keyword removal notification cause all bookmarks are removed
|
||||
// before the keyword itself, so there's no one to notify.
|
||||
let entry = yield PlacesUtils.keywords.fetch(KEYWORD);
|
||||
Assert.equal(entry, null, "keyword has been removed");
|
||||
|
||||
observer.reset();
|
||||
yield PT.undo();
|
||||
@ -1021,16 +1031,24 @@ add_task(function* test_edit_keyword() {
|
||||
bm_info.guid = yield PT.NewBookmark(bm_info).transact();
|
||||
|
||||
observer.reset();
|
||||
yield PT.EditKeyword({ guid: bm_info.guid, keyword: KEYWORD }).transact();
|
||||
yield PT.EditKeyword({ guid: bm_info.guid, keyword: KEYWORD, postData: "postData" }).transact();
|
||||
ensureKeywordChange(KEYWORD);
|
||||
let entry = yield PlacesUtils.keywords.fetch(KEYWORD);
|
||||
Assert.equal(entry.url.href, bm_info.url.spec);
|
||||
Assert.equal(entry.postData, "postData");
|
||||
|
||||
observer.reset();
|
||||
yield PT.undo();
|
||||
ensureKeywordChange();
|
||||
entry = yield PlacesUtils.keywords.fetch(KEYWORD);
|
||||
Assert.equal(entry, null);
|
||||
|
||||
observer.reset();
|
||||
yield PT.redo();
|
||||
ensureKeywordChange(KEYWORD);
|
||||
entry = yield PlacesUtils.keywords.fetch(KEYWORD);
|
||||
Assert.equal(entry.url.href, bm_info.url.spec);
|
||||
Assert.equal(entry.postData, "postData");
|
||||
|
||||
// Cleanup
|
||||
observer.reset();
|
||||
@ -1043,6 +1061,68 @@ add_task(function* test_edit_keyword() {
|
||||
ensureUndoState();
|
||||
});
|
||||
|
||||
add_task(function* test_edit_specific_keyword() {
|
||||
let bm_info = { parentGuid: rootGuid
|
||||
, url: NetUtil.newURI("http://test.edit.keyword") };
|
||||
bm_info.guid = yield PT.NewBookmark(bm_info).transact();
|
||||
function ensureKeywordChange(aCurrentKeyword = "", aPreviousKeyword = "") {
|
||||
ensureItemsChanged({ guid: bm_info.guid
|
||||
, property: "keyword"
|
||||
, newValue: aCurrentKeyword
|
||||
});
|
||||
}
|
||||
|
||||
yield PlacesUtils.keywords.insert({ keyword: "kw1", url: bm_info.url.spec, postData: "postData1" });
|
||||
yield PlacesUtils.keywords.insert({ keyword: "kw2", url: bm_info.url.spec, postData: "postData2" });
|
||||
bm_info.guid = yield PT.NewBookmark(bm_info).transact();
|
||||
|
||||
observer.reset();
|
||||
yield PT.EditKeyword({ guid: bm_info.guid, keyword: "keyword", oldKeyword: "kw2" }).transact();
|
||||
ensureKeywordChange("keyword", "kw2");
|
||||
let entry = yield PlacesUtils.keywords.fetch("kw1");
|
||||
Assert.equal(entry.url.href, bm_info.url.spec);
|
||||
Assert.equal(entry.postData, "postData1");
|
||||
entry = yield PlacesUtils.keywords.fetch("keyword");
|
||||
Assert.equal(entry.url.href, bm_info.url.spec);
|
||||
Assert.equal(entry.postData, "postData2");
|
||||
entry = yield PlacesUtils.keywords.fetch("kw2");
|
||||
Assert.equal(entry, null);
|
||||
|
||||
observer.reset();
|
||||
yield PT.undo();
|
||||
ensureKeywordChange("kw2", "keyword");
|
||||
entry = yield PlacesUtils.keywords.fetch("kw1");
|
||||
Assert.equal(entry.url.href, bm_info.url.spec);
|
||||
Assert.equal(entry.postData, "postData1");
|
||||
entry = yield PlacesUtils.keywords.fetch("kw2");
|
||||
Assert.equal(entry.url.href, bm_info.url.spec);
|
||||
Assert.equal(entry.postData, "postData2");
|
||||
entry = yield PlacesUtils.keywords.fetch("keyword");
|
||||
Assert.equal(entry, null);
|
||||
|
||||
observer.reset();
|
||||
yield PT.redo();
|
||||
ensureKeywordChange("keyword", "kw2");
|
||||
entry = yield PlacesUtils.keywords.fetch("kw1");
|
||||
Assert.equal(entry.url.href, bm_info.url.spec);
|
||||
Assert.equal(entry.postData, "postData1");
|
||||
entry = yield PlacesUtils.keywords.fetch("keyword");
|
||||
Assert.equal(entry.url.href, bm_info.url.spec);
|
||||
Assert.equal(entry.postData, "postData2");
|
||||
entry = yield PlacesUtils.keywords.fetch("kw2");
|
||||
Assert.equal(entry, null);
|
||||
|
||||
// Cleanup
|
||||
observer.reset();
|
||||
yield PT.undo();
|
||||
ensureKeywordChange("kw2");
|
||||
yield PT.undo();
|
||||
ensureItemsRemoved(bm_info);
|
||||
|
||||
yield PT.clearTransactionsHistory();
|
||||
ensureUndoState();
|
||||
});
|
||||
|
||||
add_task(function* test_tag_uri() {
|
||||
// This also tests passing uri specs.
|
||||
let bm_info_a = { url: "http://bookmarked.uri"
|
||||
|
@ -525,6 +525,24 @@ add_task(function* test_oldKeywordsAPI() {
|
||||
check_no_orphans();
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
add_task(function* test_bookmarkURLChange() {
|
||||
let fc1 = yield foreign_count("http://example1.com/");
|
||||
let fc2 = yield foreign_count("http://example2.com/");
|
||||
let bookmark = yield PlacesUtils.bookmarks.insert({ url: "http://example1.com/",
|
||||
type: PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid });
|
||||
yield PlacesUtils.keywords.insert({ keyword: "keyword",
|
||||
url: "http://example1.com/" });
|
||||
|
||||
yield check_keyword(true, "http://example1.com/", "keyword");
|
||||
Assert.equal((yield foreign_count("http://example1.com/")), fc1 + 2); // +1 bookmark +1 keyword
|
||||
|
||||
yield PlacesUtils.bookmarks.update({ guid: bookmark.guid,
|
||||
url: "http://example2.com/"});
|
||||
yield promiseKeyword("keyword", "http://example2.com/");
|
||||
|
||||
yield check_keyword(false, "http://example1.com/", "keyword");
|
||||
yield check_keyword(true, "http://example2.com/", "keyword");
|
||||
Assert.equal((yield foreign_count("http://example1.com/")), fc1); // -1 bookmark -1 keyword
|
||||
Assert.equal((yield foreign_count("http://example2.com/")), fc2 + 2); // +1 bookmark +1 keyword
|
||||
});
|
||||
|
@ -555,6 +555,40 @@ add_task(function* test_edit_keyword() {
|
||||
do_check_eq(PlacesUtils.getPostDataForBookmark(testBkmId), null);
|
||||
});
|
||||
|
||||
add_task(function* test_edit_specific_keyword() {
|
||||
const KEYWORD = "keyword-test_edit_keyword2";
|
||||
|
||||
let testURI = NetUtil.newURI("http://test_edit_keyword2.com");
|
||||
let testBkmId = bmsvc.insertBookmark(root, testURI, bmsvc.DEFAULT_INDEX, "Test edit keyword");
|
||||
// Add multiple keyword to this uri.
|
||||
yield PlacesUtils.keywords.insert({ keyword: "kw1", url: testURI.spec, postData: "postData1" });
|
||||
yield PlacesUtils.keywords.insert({keyword: "kw2", url: testURI.spec, postData: "postData2" });
|
||||
|
||||
// Try to change only kw2.
|
||||
let txn = new PlacesEditBookmarkKeywordTransaction(testBkmId, KEYWORD, "postData2", "kw2");
|
||||
|
||||
txn.doTransaction();
|
||||
do_check_eq(observer._itemChangedId, testBkmId);
|
||||
do_check_eq(observer._itemChangedProperty, "keyword");
|
||||
do_check_eq(observer._itemChangedValue, KEYWORD);
|
||||
let entry = yield PlacesUtils.keywords.fetch("kw1");
|
||||
Assert.equal(entry.url.href, testURI.spec);
|
||||
Assert.equal(entry.postData, "postData1");
|
||||
yield promiseKeyword(KEYWORD, testURI.spec, "postData2");
|
||||
yield promiseKeyword("kw2", null);
|
||||
|
||||
txn.undoTransaction();
|
||||
do_check_eq(observer._itemChangedId, testBkmId);
|
||||
do_check_eq(observer._itemChangedProperty, "keyword");
|
||||
do_check_eq(observer._itemChangedValue, "kw2");
|
||||
do_check_eq(PlacesUtils.getPostDataForBookmark(testBkmId), "postData1");
|
||||
entry = yield PlacesUtils.keywords.fetch("kw1");
|
||||
Assert.equal(entry.url.href, testURI.spec);
|
||||
Assert.equal(entry.postData, "postData1");
|
||||
yield promiseKeyword("kw2", testURI.spec, "postData2");
|
||||
yield promiseKeyword("keyword", null);
|
||||
});
|
||||
|
||||
add_task(function* test_LoadInSidebar_transaction() {
|
||||
let testURI = NetUtil.newURI("http://test_LoadInSidebar_transaction.com");
|
||||
let testBkmId = bmsvc.insertBookmark(root, testURI, bmsvc.DEFAULT_INDEX, "Test LoadInSidebar transaction");
|
||||
|
Loading…
Reference in New Issue
Block a user