зеркало из https://github.com/mozilla/pjs.git
fix for bug #371827: places bookmarks need additional metadate for lastModified and dateAdded.
fix for bug #381209: don't write out ID attributes to bookmarks.html, as it will confuse Firefox 2. patch by dietrich, sspitzer. r=mano,dietrich,sspitzer
This commit is contained in:
Родитель
ffe74a9a39
Коммит
785bb1ccbf
|
@ -398,10 +398,10 @@
|
|||
<treecol label="&col.url.label;" id="url" flex="5"
|
||||
persist="width hidden ordinal sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol label="&col.lastvisit.label;" id="date" flex="1"
|
||||
<treecol label="&col.lastvisit.label;" id="date" flex="1"
|
||||
persist="width hidden ordinal sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol label="&col.visitcount.label;" id="visitCount" flex="1" hidden="true"
|
||||
<treecol label="&col.visitcount.label;" id="visitCount" flex="1" hidden="true"
|
||||
persist="width hidden ordinal sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol label="&col.keyword.label;" id="keyword" flex="1" hidden="true"
|
||||
|
@ -409,6 +409,12 @@
|
|||
<splitter class="tree-splitter"/>
|
||||
<treecol label="&col.description.label;" id="description" flex="1" hidden="true"
|
||||
persist="width hidden ordinal sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol label="&col.dateadded.label;" id="dateAdded" flex="1" hidden="true"
|
||||
persist="width hidden ordinal sortActive sortDirection"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol label="&col.lastmodified.label;" id="lastModified" flex="1" hidden="true"
|
||||
persist="width hidden ordinal sortActive sortDirection"/>
|
||||
</treecols>
|
||||
<treechildren id="placeContentChildren" view="placeContent" flex="1"/>
|
||||
</tree>
|
||||
|
|
|
@ -387,7 +387,35 @@ PlacesTreeView.prototype = {
|
|||
aShowThisOne.value = aTop.time < aNext.time;
|
||||
return true;
|
||||
},
|
||||
|
||||
_convertPRTimeToString: function PTV__convertPRTimeToString(aTime) {
|
||||
var timeInMilliseconds = aTime / 1000; // PRTime is in microseconds
|
||||
var timeObj = new Date(timeInMilliseconds);
|
||||
|
||||
// Check if it is today and only display the time. Only bother
|
||||
// checking for today if it's within the last 24 hours, since
|
||||
// computing midnight is not really cheap. Sometimes we may get dates
|
||||
// in the future, so always show those.
|
||||
var ago = new Date(Date.now() - timeInMilliseconds);
|
||||
var dateFormat = Ci.nsIScriptableDateFormat.dateFormatShort;
|
||||
if (ago > -10000 && ago < (1000 * 24 * 60 * 60)) {
|
||||
var midnight = new Date(timeInMilliseconds);
|
||||
midnight.setHours(0);
|
||||
midnight.setMinutes(0);
|
||||
midnight.setSeconds(0);
|
||||
midnight.setMilliseconds(0);
|
||||
|
||||
if (timeInMilliseconds > midnight.getTime())
|
||||
dateFormat = Ci.nsIScriptableDateFormat.dateFormatNone;
|
||||
}
|
||||
|
||||
return (this._dateService.FormatDateTime("", dateFormat,
|
||||
Ci.nsIScriptableDateFormat.timeFormatNoSeconds,
|
||||
timeObj.getFullYear(), timeObj.getMonth() + 1,
|
||||
timeObj.getDate(), timeObj.getHours(),
|
||||
timeObj.getMinutes(), timeObj.getSeconds()));
|
||||
},
|
||||
|
||||
COLUMN_TYPE_UNKNOWN: 0,
|
||||
COLUMN_TYPE_TITLE: 1,
|
||||
COLUMN_TYPE_URI: 2,
|
||||
|
@ -395,6 +423,8 @@ PlacesTreeView.prototype = {
|
|||
COLUMN_TYPE_VISITCOUNT: 4,
|
||||
COLUMN_TYPE_KEYWORD: 5,
|
||||
COLUMN_TYPE_DESCRIPTION: 6,
|
||||
COLUMN_TYPE_DATEADDED: 7,
|
||||
COLUMN_TYPE_LASTMODIFIED: 8,
|
||||
|
||||
_getColumnType: function PTV__getColumnType(aColumn) {
|
||||
switch (aColumn.id) {
|
||||
|
@ -410,6 +440,10 @@ PlacesTreeView.prototype = {
|
|||
return this.COLUMN_TYPE_KEYWORD;
|
||||
case "description":
|
||||
return this.COLUMN_TYPE_DESCRIPTION;
|
||||
case "dateAdded":
|
||||
return this.COLUMN_TYPE_DATEADDED;
|
||||
case "lastModified":
|
||||
return this.COLUMN_TYPE_LASTMODIFIED;
|
||||
}
|
||||
return this.COLUMN_TYPE_UNKNOWN;
|
||||
},
|
||||
|
@ -421,9 +455,9 @@ PlacesTreeView.prototype = {
|
|||
case Ci.nsINavHistoryQueryOptions.SORT_BY_TITLE_DESCENDING:
|
||||
return [this.COLUMN_TYPE_TITLE, true];
|
||||
case Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_ASCENDING:
|
||||
return [this.COLUMN_TYPE_DATA, false];
|
||||
return [this.COLUMN_TYPE_DATE, false];
|
||||
case Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING:
|
||||
return [this.COLUMN_TYPE_DATA, true];
|
||||
return [this.COLUMN_TYPE_DATE, true];
|
||||
case Ci.nsINavHistoryQueryOptions.SORT_BY_URI_ASCENDING:
|
||||
return [this.COLUMN_TYPE_URI, false];
|
||||
case Ci.nsINavHistoryQueryOptions.SORT_BY_URI_DESCENDING:
|
||||
|
@ -443,6 +477,14 @@ PlacesTreeView.prototype = {
|
|||
case Ci.nsINavHistoryQueryOptions.SORT_BY_ANNOTATION_DESCENDING:
|
||||
if (this._result.sortingAnnotation == DESCRIPTION_ANNO)
|
||||
return [this.COLUMN_TYPE_DESCRIPTION, true];
|
||||
case Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_ASCENDING:
|
||||
return [this.COLUMN_TYPE_DATEADDED, false];
|
||||
case Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING:
|
||||
return [this.COLUMN_TYPE_DATEADDED, true];
|
||||
case Ci.nsINavHistoryQueryOptions.SORT_BY_LASTMODIFIED_ASCENDING:
|
||||
return [this.COLUMN_TYPE_LASTMODIFIED, false];
|
||||
case Ci.nsINavHistoryQueryOptions.SORT_BY_LASTMODIFIED_DESCENDING:
|
||||
return [this.COLUMN_TYPE_LASTMODIFIED, true];
|
||||
}
|
||||
return [this.COLUMN_TYPE_UNKNOWN, false];
|
||||
},
|
||||
|
@ -976,7 +1018,6 @@ PlacesTreeView.prototype = {
|
|||
case this.COLUMN_TYPE_URI:
|
||||
if (PlacesUtils.nodeIsURI(node))
|
||||
return node.uri;
|
||||
|
||||
return "";
|
||||
case this.COLUMN_TYPE_DATE:
|
||||
if (node.time == 0 || !PlacesUtils.nodeIsURI(node)) {
|
||||
|
@ -987,33 +1028,8 @@ PlacesTreeView.prototype = {
|
|||
// Only show this for URI-based items.
|
||||
return "";
|
||||
}
|
||||
if (this._getRowSessionStatus(aRow) != this.SESSION_STATUS_CONTINUE) {
|
||||
var nodeTime = node.time / 1000; // PRTime is in microseconds
|
||||
var nodeTimeObj = new Date(nodeTime);
|
||||
|
||||
// Check if it is today and only display the time. Only bother
|
||||
// checking for today if it's within the last 24 hours, since
|
||||
// computing midnight is not really cheap. Sometimes we may get dates
|
||||
// in the future, so always show those.
|
||||
var ago = new Date(Date.now() - nodeTime);
|
||||
var dateFormat = Ci.nsIScriptableDateFormat.dateFormatShort;
|
||||
if (ago > -10000 && ago < (1000 * 24 * 60 * 60)) {
|
||||
var midnight = new Date(nodeTime);
|
||||
midnight.setHours(0);
|
||||
midnight.setMinutes(0);
|
||||
midnight.setSeconds(0);
|
||||
midnight.setMilliseconds(0);
|
||||
|
||||
if (nodeTime > midnight.getTime())
|
||||
dateFormat = Ci.nsIScriptableDateFormat.dateFormatNone;
|
||||
}
|
||||
|
||||
return (this._dateService.FormatDateTime("", dateFormat,
|
||||
Ci.nsIScriptableDateFormat.timeFormatNoSeconds,
|
||||
nodeTimeObj.getFullYear(), nodeTimeObj.getMonth() + 1,
|
||||
nodeTimeObj.getDate(), nodeTimeObj.getHours(),
|
||||
nodeTimeObj.getMinutes(), nodeTimeObj.getSeconds()));
|
||||
}
|
||||
if (this._getRowSessionStatus(aRow) != this.SESSION_STATUS_CONTINUE)
|
||||
return this._convertPRTimeToString(node.time);
|
||||
return "";
|
||||
case this.COLUMN_TYPE_VISITCOUNT:
|
||||
return node.accessCount;
|
||||
|
@ -1025,7 +1041,14 @@ PlacesTreeView.prototype = {
|
|||
const annos = PlacesUtils.annotations;
|
||||
if (annos.itemHasAnnotation(node.itemId, DESCRIPTION_ANNO))
|
||||
return annos.getItemAnnotationString(node.itemId, DESCRIPTION_ANNO)
|
||||
|
||||
return "";
|
||||
case this.COLUMN_TYPE_DATEADDED:
|
||||
if (node.dateAdded)
|
||||
return this._convertPRTimeToString(node.dateAdded);
|
||||
return "";
|
||||
case this.COLUMN_TYPE_LASTMODIFIED:
|
||||
if (node.lastModified)
|
||||
return this._convertPRTimeToString(node.lastModified);
|
||||
return "";
|
||||
}
|
||||
return "";
|
||||
|
@ -1161,6 +1184,26 @@ PlacesTreeView.prototype = {
|
|||
newSort = NHQO.SORT_BY_ANNOTATION_ASCENDING;
|
||||
newSortingAnnotation = DESCRIPTION_ANNO;
|
||||
}
|
||||
break;
|
||||
case this.COLUMN_TYPE_DATEADDED:
|
||||
if (oldSort == NHQO.SORT_BY_DATEADDED_ASCENDING)
|
||||
newSort = NHQO.SORT_BY_DATEADDED_DESCENDING;
|
||||
else if (allowTriState &&
|
||||
oldSort == NHQO.SORT_BY_DATEADDED_DESCENDING)
|
||||
newSort = NHQO.SORT_BY_NONE;
|
||||
else
|
||||
newSort = NHQO.SORT_BY_DATEADDED_ASCENDING;
|
||||
|
||||
break;
|
||||
case this.COLUMN_TYPE_LASTMODIFIED:
|
||||
if (oldSort == NHQO.SORT_BY_LASTMODIFIED_ASCENDING)
|
||||
newSort = NHQO.SORT_BY_LASTMODIFIED_DESCENDING;
|
||||
else if (allowTriState &&
|
||||
oldSort == NHQO.SORT_BY_LASTMODIFIED_DESCENDING)
|
||||
newSort = NHQO.SORT_BY_NONE;
|
||||
else
|
||||
newSort = NHQO.SORT_BY_LASTMODIFIED_ASCENDING;
|
||||
|
||||
break;
|
||||
default:
|
||||
throw Cr.NS_ERROR_INVALID_ARG;
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
* ICON_URI is new for places bookmarks.html, it refers to the original
|
||||
* URI of the favicon so we don't have to make up favicon URLs.
|
||||
* Text of the <a> container is the name of the bookmark
|
||||
* Ignored: ADD_DATE, LAST_VISIT, LAST_MODIFIED, ID
|
||||
* Ignored: LAST_VISIT, ID (writing out non-RDF IDs can confuse Firefox 2)
|
||||
* Bookmark comment := dd
|
||||
* This affects the previosly added bookmark
|
||||
* Separator := hr
|
||||
|
@ -116,10 +116,12 @@ static NS_DEFINE_CID(kParserCID, NS_PARSER_CID);
|
|||
#define KEY_ICON_URI_LOWER "icon_uri"
|
||||
#define KEY_SHORTCUTURL_LOWER "shortcuturl"
|
||||
#define KEY_POST_DATA_LOWER "post_data"
|
||||
#define KEY_ID_LOWER "id"
|
||||
#define KEY_ITEM_ID_LOWER "item_id"
|
||||
#define KEY_NAME_LOWER "name"
|
||||
#define KEY_MICSUM_GEN_URI_LOWER "micsum_gen_uri"
|
||||
#define KEY_GENERATED_TITLE "generated_title"
|
||||
#define KEY_GENERATED_TITLE_LOWER "generated_title"
|
||||
#define KEY_DATE_ADDED_LOWER "add_date"
|
||||
#define KEY_LAST_MODIFIED_LOWER "last_modified"
|
||||
|
||||
#define LOAD_IN_SIDEBAR_ANNO NS_LITERAL_CSTRING("bookmarkProperties/loadInSidebar")
|
||||
#define DESCRIPTION_ANNO NS_LITERAL_CSTRING("bookmarkProperties/description")
|
||||
|
@ -149,7 +151,10 @@ public:
|
|||
mContainerID(aID),
|
||||
mContainerNesting(0),
|
||||
mLastContainerType(Container_Normal),
|
||||
mInDescription(PR_FALSE)
|
||||
mInDescription(PR_FALSE),
|
||||
mPreviousId(0),
|
||||
mPreviousDateAdded(0),
|
||||
mPreviousLastModifiedDate(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -217,6 +222,11 @@ public:
|
|||
|
||||
// Contains the id of an imported, or newly created bookmark.
|
||||
PRInt64 mPreviousId;
|
||||
|
||||
// Contains the date-added and last-modified-date of an imported item.
|
||||
// Used to override the values set by insertItem, createFolder, etc.
|
||||
PRTime mPreviousDateAdded;
|
||||
PRTime mPreviousLastModifiedDate;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -392,6 +402,11 @@ protected:
|
|||
NS_ASSERTION(mFrames.Length() > 0, "Asking for frame when there are none!");
|
||||
return mFrames[mFrames.Length() - 1];
|
||||
}
|
||||
BookmarkImportFrame& PreviousFrame()
|
||||
{
|
||||
NS_ASSERTION(mFrames.Length() > 1, "Asking for frame when there are not enough!");
|
||||
return mFrames[mFrames.Length() - 2];
|
||||
}
|
||||
nsresult NewFrame();
|
||||
nsresult PopFrame();
|
||||
|
||||
|
@ -400,6 +415,7 @@ protected:
|
|||
nsresult SetFaviconForFolder(PRInt64 aFolder, const nsACString& aFavicon);
|
||||
|
||||
PRInt64 ConvertImportedIdToInternalId(const nsCString& aId);
|
||||
PRTime ConvertImportedDateToInternalDate(const nsACString& aDate);
|
||||
|
||||
#ifdef DEBUG_IMPORT
|
||||
// prints spaces for indenting to the current frame depth
|
||||
|
@ -493,13 +509,15 @@ BookmarkContentSink::OpenContainer(const nsIParserNode& aNode)
|
|||
NS_IMETHODIMP
|
||||
BookmarkContentSink::CloseContainer(const nsHTMLTag aTag)
|
||||
{
|
||||
BookmarkImportFrame& frame = CurFrame();
|
||||
|
||||
// see the comment for the definition of mInDescription. Basically, we commit
|
||||
// any text in mPreviousText to the description of the node/folder if there
|
||||
// is any.
|
||||
BookmarkImportFrame& frame = CurFrame();
|
||||
if (frame.mInDescription) {
|
||||
frame.mPreviousText.Trim(kWhitespace); // important!
|
||||
if (!frame.mPreviousText.IsEmpty()) {
|
||||
|
||||
PRInt64 itemId = !frame.mPreviousLink ?
|
||||
frame.mContainerID : frame.mPreviousId;
|
||||
|
||||
|
@ -513,6 +531,29 @@ BookmarkContentSink::CloseContainer(const nsHTMLTag aTag)
|
|||
nsIAnnotationService::EXPIRE_NEVER);
|
||||
}
|
||||
frame.mPreviousText.Truncate();
|
||||
|
||||
// Set last-modified a 2nd time for all items with descriptions
|
||||
// we need to set last-modified as the *last* step in processing
|
||||
// any item type in the bookmarks.html file, so that we do
|
||||
// not overwrite the imported value. for items without descriptions,
|
||||
// setting this value after setting the item title is that
|
||||
// last point at which we can save this value before it gets reset.
|
||||
// for items with descriptions, it must set after that point.
|
||||
// however, at the point at which we set the title, there's no way
|
||||
// to determine if there will be a description following,
|
||||
// so we need to set the last-modified-date at both places.
|
||||
|
||||
PRTime lastModified;
|
||||
if (!frame.mPreviousLink) {
|
||||
lastModified = PreviousFrame().mPreviousLastModifiedDate;
|
||||
} else {
|
||||
lastModified = frame.mPreviousLastModifiedDate;
|
||||
}
|
||||
|
||||
if (itemId > 0 && lastModified > 0) {
|
||||
rv = mBookmarksService->SetItemLastModified(itemId, lastModified);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "SetItemLastModified failed");
|
||||
}
|
||||
}
|
||||
frame.mInDescription = PR_FALSE;
|
||||
}
|
||||
|
@ -693,9 +734,15 @@ BookmarkContentSink::HandleHeadBegin(const nsIParserNode& node)
|
|||
} else if (node.GetKeyAt(i).LowerCaseEqualsLiteral(KEY_PLACESROOT_LOWER)) {
|
||||
frame.mLastContainerType = BookmarkImportFrame::Container_Places;
|
||||
break;
|
||||
} else if (node.GetKeyAt(i).LowerCaseEqualsLiteral(KEY_ID_LOWER)) {
|
||||
} else if (node.GetKeyAt(i).LowerCaseEqualsLiteral(KEY_ITEM_ID_LOWER)) {
|
||||
frame.mLastContainerId =
|
||||
ConvertImportedIdToInternalId(NS_ConvertUTF16toUTF8(node.GetValueAt(i)));
|
||||
} else if (node.GetKeyAt(i).LowerCaseEqualsLiteral(KEY_DATE_ADDED_LOWER)) {
|
||||
frame.mPreviousDateAdded =
|
||||
ConvertImportedDateToInternalDate(NS_ConvertUTF16toUTF8(node.GetValueAt(i)));
|
||||
} else if (node.GetKeyAt(i).LowerCaseEqualsLiteral(KEY_LAST_MODIFIED_LOWER)) {
|
||||
frame.mPreviousLastModifiedDate =
|
||||
ConvertImportedDateToInternalDate(NS_ConvertUTF16toUTF8(node.GetValueAt(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -737,7 +784,7 @@ BookmarkContentSink::HandleLinkBegin(const nsIParserNode& node)
|
|||
|
||||
// mPreviousText will hold our link text, clear it so that can be appended to
|
||||
frame.mPreviousText.Truncate();
|
||||
|
||||
|
||||
// get the attributes we care about
|
||||
nsAutoString href;
|
||||
nsAutoString feedUrl;
|
||||
|
@ -747,9 +794,12 @@ BookmarkContentSink::HandleLinkBegin(const nsIParserNode& node)
|
|||
nsAutoString keyword;
|
||||
nsAutoString postData;
|
||||
nsAutoString webPanel;
|
||||
nsAutoString id;
|
||||
nsAutoString itemId;
|
||||
nsAutoString micsumGenURI;
|
||||
nsAutoString generatedTitle;
|
||||
nsAutoString dateAdded;
|
||||
nsAutoString lastModified;
|
||||
|
||||
PRInt32 attrCount = node.GetAttributeCount();
|
||||
for (PRInt32 i = 0; i < attrCount; i ++) {
|
||||
const nsAString& key = node.GetKeyAt(i);
|
||||
|
@ -769,12 +819,16 @@ BookmarkContentSink::HandleLinkBegin(const nsIParserNode& node)
|
|||
postData = node.GetValueAt(i);
|
||||
} else if (key.LowerCaseEqualsLiteral(KEY_WEB_PANEL_LOWER)) {
|
||||
webPanel = node.GetValueAt(i);
|
||||
} else if (key.LowerCaseEqualsLiteral(KEY_ID_LOWER)) {
|
||||
id = node.GetValueAt(i);
|
||||
} else if (key.LowerCaseEqualsLiteral(KEY_ITEM_ID_LOWER)) {
|
||||
itemId = node.GetValueAt(i);
|
||||
} else if (key.LowerCaseEqualsLiteral(KEY_MICSUM_GEN_URI_LOWER)) {
|
||||
micsumGenURI = node.GetValueAt(i);
|
||||
} else if (key.LowerCaseEqualsLiteral(KEY_GENERATED_TITLE)) {
|
||||
} else if (key.LowerCaseEqualsLiteral(KEY_GENERATED_TITLE_LOWER)) {
|
||||
generatedTitle = node.GetValueAt(i);
|
||||
} else if (key.LowerCaseEqualsLiteral(KEY_DATE_ADDED_LOWER)) {
|
||||
dateAdded = node.GetValueAt(i);
|
||||
} else if (key.LowerCaseEqualsLiteral(KEY_LAST_MODIFIED_LOWER)) {
|
||||
lastModified = node.GetValueAt(i);
|
||||
}
|
||||
}
|
||||
href.Trim(kWhitespace);
|
||||
|
@ -785,9 +839,11 @@ BookmarkContentSink::HandleLinkBegin(const nsIParserNode& node)
|
|||
keyword.Trim(kWhitespace);
|
||||
postData.Trim(kWhitespace);
|
||||
webPanel.Trim(kWhitespace);
|
||||
id.Trim(kWhitespace);
|
||||
itemId.Trim(kWhitespace);
|
||||
micsumGenURI.Trim(kWhitespace);
|
||||
generatedTitle.Trim(kWhitespace);
|
||||
dateAdded.Trim(kWhitespace);
|
||||
lastModified.Trim(kWhitespace);
|
||||
|
||||
// For feeds, get the feed URL. If it is invalid, it will leave mPreviousFeed
|
||||
// NULL and we'll continue trying to create it as a normal bookmark.
|
||||
|
@ -816,8 +872,13 @@ BookmarkContentSink::HandleLinkBegin(const nsIParserNode& node)
|
|||
}
|
||||
}
|
||||
|
||||
// if there's a pre-existing Places bookmark id, use it
|
||||
frame.mPreviousId = ConvertImportedIdToInternalId(NS_ConvertUTF16toUTF8(id));
|
||||
// if there's a pre-existing Places bookmark ITEM_ID, use it
|
||||
frame.mPreviousId = ConvertImportedIdToInternalId(NS_ConvertUTF16toUTF8(itemId));
|
||||
|
||||
// Save last-modified-date, for setting after all the bookmark properties have been set.
|
||||
if (!lastModified.IsEmpty()) {
|
||||
frame.mPreviousLastModifiedDate = ConvertImportedDateToInternalDate(NS_ConvertUTF16toUTF8(lastModified));
|
||||
}
|
||||
|
||||
// if there is a feedURL, this is a livemark, which is a special case
|
||||
// that we handle in HandleLinkEnd(): don't create normal bookmarks
|
||||
|
@ -838,6 +899,17 @@ BookmarkContentSink::HandleLinkBegin(const nsIParserNode& node)
|
|||
rv = mBookmarksService->InsertItem(frame.mContainerID, frame.mPreviousLink,
|
||||
mBookmarksService->DEFAULT_INDEX, &frame.mPreviousId);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "InsertItem failed");
|
||||
|
||||
// set the date added value, if we have it
|
||||
// important: this has to happen after InsertItem
|
||||
// so that we set the imported value
|
||||
if (!dateAdded.IsEmpty()) {
|
||||
PRTime convertedDateAdded = ConvertImportedDateToInternalDate(NS_ConvertUTF16toUTF8(dateAdded));
|
||||
if (convertedDateAdded) {
|
||||
rv = mBookmarksService->SetItemDateAdded(frame.mPreviousId, convertedDateAdded);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "SetItemDateAdded failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// save the favicon, ignore errors
|
||||
|
@ -940,11 +1012,6 @@ BookmarkContentSink::HandleLinkEnd()
|
|||
}
|
||||
|
||||
if (!isLivemark) {
|
||||
#ifdef DEBUG_IMPORT
|
||||
PrintNesting();
|
||||
printf("Creating livemark '%s' %lld\n",
|
||||
NS_ConvertUTF16toUTF8(frame.mPreviousText).get(), frame.mPreviousId);
|
||||
#endif
|
||||
if (mIsImportDefaults) {
|
||||
rv = mLivemarkService->CreateLivemarkFolderOnly(mBookmarksService,
|
||||
frame.mContainerID,
|
||||
|
@ -963,16 +1030,32 @@ BookmarkContentSink::HandleLinkEnd()
|
|||
&frame.mPreviousId);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "CreateLivemark failed!");
|
||||
}
|
||||
#ifdef DEBUG_IMPORT
|
||||
PrintNesting();
|
||||
printf("Creating livemark '%s' %lld\n",
|
||||
NS_ConvertUTF16toUTF8(frame.mPreviousText).get(), frame.mPreviousId);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (frame.mPreviousLink) {
|
||||
#ifdef DEBUG_IMPORT
|
||||
PrintNesting();
|
||||
printf("Creating bookmark '%s'\n",
|
||||
NS_ConvertUTF16toUTF8(frame.mPreviousText).get());
|
||||
printf("Creating bookmark '%s' %lld\n",
|
||||
NS_ConvertUTF16toUTF8(frame.mPreviousText).get(), frame.mPreviousId);
|
||||
#endif
|
||||
mBookmarksService->SetItemTitle(frame.mPreviousId, frame.mPreviousText);
|
||||
}
|
||||
|
||||
// Set last-modified-date for bookmarks and livemarks here so that the
|
||||
// imported date overrides the date from the call to that sets the description
|
||||
// that we made above.
|
||||
if (frame.mPreviousId > 0 && frame.mPreviousLastModifiedDate > 0) {
|
||||
rv = mBookmarksService->SetItemLastModified(frame.mPreviousId, frame.mPreviousLastModifiedDate);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "SetItemLastModified failed");
|
||||
// Note: don't clear mPreviousLastModifiedDate, because if this item has a
|
||||
// description, we'll need to set it again.
|
||||
}
|
||||
|
||||
frame.mPreviousText.Truncate();
|
||||
}
|
||||
|
||||
|
@ -987,17 +1070,17 @@ BookmarkContentSink::HandleSeparator(const nsIParserNode& aNode)
|
|||
|
||||
// check for pre-existing id
|
||||
PRInt64 id = 0;
|
||||
nsAutoString idAttr;
|
||||
nsAutoString itemIdAttr;
|
||||
PRInt32 attrCount = aNode.GetAttributeCount();
|
||||
for (PRInt32 i = 0; i < attrCount; i ++) {
|
||||
const nsAString& key = aNode.GetKeyAt(i);
|
||||
if (key.LowerCaseEqualsLiteral(KEY_ID_LOWER)) {
|
||||
idAttr = aNode.GetValueAt(i);
|
||||
if (key.LowerCaseEqualsLiteral(KEY_ITEM_ID_LOWER)) {
|
||||
itemIdAttr = aNode.GetValueAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
idAttr.Trim(kWhitespace);
|
||||
id = ConvertImportedIdToInternalId(NS_ConvertUTF16toUTF8(idAttr));
|
||||
itemIdAttr.Trim(kWhitespace);
|
||||
id = ConvertImportedIdToInternalId(NS_ConvertUTF16toUTF8(itemIdAttr));
|
||||
|
||||
// check id validity
|
||||
if (id > 0) {
|
||||
|
@ -1040,6 +1123,11 @@ BookmarkContentSink::HandleSeparator(const nsIParserNode& aNode)
|
|||
|
||||
if (!name.IsEmpty())
|
||||
mBookmarksService->SetItemTitle(itemId, name);
|
||||
|
||||
// Note: we do not need to import ADD_DATE or LAST_MODIFIED for separators
|
||||
// because pre-Places bookmarks does not support them.
|
||||
// and we can't write them out because attributes other than NAME make Firefox 2.x
|
||||
// crash/hang - see bug #381129
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1142,6 +1230,18 @@ BookmarkContentSink::NewFrame()
|
|||
printf("\n");
|
||||
#endif
|
||||
|
||||
BookmarkImportFrame& frame = CurFrame();
|
||||
if (frame.mPreviousDateAdded > 0) {
|
||||
nsresult rv = mBookmarksService->SetItemDateAdded(ourID, frame.mPreviousDateAdded);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "SetItemDateAdded failed");
|
||||
frame.mPreviousDateAdded = 0;
|
||||
}
|
||||
if (frame.mPreviousLastModifiedDate > 0) {
|
||||
nsresult rv = mBookmarksService->SetItemLastModified(ourID, frame.mPreviousLastModifiedDate);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "SetItemLastModified failed");
|
||||
// don't clear last-modified, in case there's a description
|
||||
}
|
||||
|
||||
if (!mFrames.AppendElement(BookmarkImportFrame(ourID)))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
return NS_OK;
|
||||
|
@ -1211,7 +1311,7 @@ BookmarkContentSink::SetFaviconForURI(nsIURI* aPageURI, nsIURI* aIconURI,
|
|||
faviconSpec.AssignLiteral("http://www.mozilla.org/2005/made-up-favicon/");
|
||||
faviconSpec.AppendInt(serialNumber);
|
||||
faviconSpec.AppendLiteral("-");
|
||||
faviconSpec.AppendInt(PR_Now());
|
||||
faviconSpec.AppendInt(PR_Now()); // casting from PRInt64 -> PRInt32, data loss, fix me
|
||||
rv = NS_NewURI(getter_AddRefs(faviconURI), faviconSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
serialNumber ++;
|
||||
|
@ -1295,11 +1395,11 @@ BookmarkContentSink::SetFaviconForFolder(PRInt64 aFolder,
|
|||
return faviconService->SetFaviconUrlForPage(folderURI, faviconURI);
|
||||
}
|
||||
|
||||
// Converts a string id (legacy rdf or contemporary) into an int id
|
||||
// Converts a string id (ITEM_ID) into an int id
|
||||
PRInt64
|
||||
BookmarkContentSink::ConvertImportedIdToInternalId(const nsCString& aId) {
|
||||
PRInt64 intId = 0;
|
||||
if (aId.IsEmpty() || Substring(aId, 0, 4).Equals(NS_LITERAL_CSTRING("rdf:"), CaseInsensitiveCompare))
|
||||
if (aId.IsEmpty())
|
||||
return intId;
|
||||
nsresult rv;
|
||||
intId = aId.ToInteger(&rv);
|
||||
|
@ -1308,6 +1408,22 @@ BookmarkContentSink::ConvertImportedIdToInternalId(const nsCString& aId) {
|
|||
return intId;
|
||||
}
|
||||
|
||||
// Converts a string date in seconds to an int date in microseconds
|
||||
PRTime
|
||||
BookmarkContentSink::ConvertImportedDateToInternalDate(const nsACString& aDate) {
|
||||
PRTime convertedDate = 0;
|
||||
if (!aDate.IsEmpty()) {
|
||||
nsresult rv;
|
||||
convertedDate = aDate.ToInteger(&rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
convertedDate *= 1000000; // in bookmarks.html this value is in seconds, not microseconds
|
||||
}
|
||||
else {
|
||||
convertedDate = 0;
|
||||
}
|
||||
}
|
||||
return convertedDate;
|
||||
}
|
||||
|
||||
// SyncChannelStatus
|
||||
//
|
||||
|
@ -1363,9 +1479,11 @@ static const char kFeedURIAttribute[] = " FEEDURL=\"";
|
|||
static const char kWebPanelAttribute[] = " WEB_PANEL=\"true\"";
|
||||
static const char kKeywordAttribute[] = " SHORTCUTURL=\"";
|
||||
static const char kPostDataAttribute[] = " POST_DATA=\"";
|
||||
static const char kIdAttribute[] = " ID=\"";
|
||||
static const char kItemIdAttribute[] = " ITEM_ID=\"";
|
||||
static const char kNameAttribute[] = " NAME=\"";
|
||||
static const char kMicsumGenURIEquals[] = " MICSUM_GEN_URI=\"";
|
||||
static const char kMicsumGenURIAttribute[] = " MICSUM_GEN_URI=\"";
|
||||
static const char kDateAddedAttribute[] = " ADD_DATE=\"";
|
||||
static const char kLastModifiedAttribute[] = " LAST_MODIFIED=\"";
|
||||
|
||||
// WriteContainerPrologue
|
||||
//
|
||||
|
@ -1491,6 +1609,27 @@ WriteFaviconAttribute(const nsACString& aURI, nsIOutputStream* aOutput)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// WriteDateAttribute
|
||||
//
|
||||
// This writes the '{attr value=}"{time in seconds}"' attribute for
|
||||
// an item.
|
||||
|
||||
static nsresult
|
||||
WriteDateAttribute(const char aAttributeStart[], PRInt32 aLength, PRTime aAttributeValue, nsIOutputStream* aOutput)
|
||||
{
|
||||
// write attribute start
|
||||
PRUint32 dummy;
|
||||
nsresult rv = aOutput->Write(aAttributeStart, aLength, &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// write attribute value
|
||||
nsCAutoString dateInSeconds;
|
||||
aAttributeValue/= 1000000; // in bookmarks.html this value is in seconds, not microseconds
|
||||
dateInSeconds.AppendInt(aAttributeValue); // casting from PRInt64 -> PRInt32, data loss, fix me
|
||||
rv = aOutput->Write(dateInSeconds.get(), dateInSeconds.Length(), &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return aOutput->Write(kQuoteStr, sizeof(kQuoteStr)-1, &dummy);
|
||||
}
|
||||
|
||||
|
||||
// nsPlacesImportExportService::WriteContainer
|
||||
//
|
||||
|
@ -1537,6 +1676,26 @@ nsPlacesImportExportService::WriteContainerHeader(PRInt64 aFolder, const nsACStr
|
|||
rv = aOutput->Write(kContainerIntro, sizeof(kContainerIntro)-1, &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// write ADD_DATE
|
||||
PRTime dateAdded = 0;
|
||||
rv = mBookmarksService->GetItemDateAdded(aFolder, &dateAdded);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (dateAdded) {
|
||||
rv = WriteDateAttribute(kDateAddedAttribute, sizeof(kDateAddedAttribute)-1, dateAdded, aOutput);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// write LAST_MODIFIED
|
||||
PRTime lastModified = 0;
|
||||
rv = mBookmarksService->GetItemLastModified(aFolder, &lastModified);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (lastModified) {
|
||||
rv = WriteDateAttribute(kLastModifiedAttribute, sizeof(kLastModifiedAttribute)-1, lastModified, aOutput);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
PRInt64 placesRoot;
|
||||
rv = mBookmarksService->GetPlacesRoot(&placesRoot);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
@ -1560,13 +1719,13 @@ nsPlacesImportExportService::WriteContainerHeader(PRInt64 aFolder, const nsACStr
|
|||
rv = aOutput->Write(kToolbarFolderAttribute, sizeof(kToolbarFolderAttribute)-1, &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// id
|
||||
rv = aOutput->Write(kIdAttribute, sizeof(kIdAttribute)-1, &dummy);
|
||||
|
||||
// write id as ITEM_ID as non-rdf IDs can confuse Firefox 2
|
||||
rv = aOutput->Write(kItemIdAttribute, sizeof(kItemIdAttribute)-1, &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCAutoString id;
|
||||
id.AppendInt(aFolder);
|
||||
rv = aOutput->Write(id.get(), id.Length(), &dummy);
|
||||
nsCAutoString itemIdAttr;
|
||||
itemIdAttr.AppendInt(aFolder); // casting from PRInt64 -> PRInt32, data loss, fix me
|
||||
rv = aOutput->Write(itemIdAttr.get(), itemIdAttr.Length(), &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aOutput->Write(kQuoteStr, sizeof(kQuoteStr)-1, &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -1692,6 +1851,26 @@ nsPlacesImportExportService::WriteItem(nsINavHistoryResultNode* aItem,
|
|||
rv = aOutput->Write(kQuoteStr, sizeof(kQuoteStr)-1, &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// write ADD_DATE
|
||||
PRTime dateAdded = 0;
|
||||
rv = aItem->GetDateAdded(&dateAdded);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (dateAdded) {
|
||||
rv = WriteDateAttribute(kDateAddedAttribute, sizeof(kDateAddedAttribute)-1, dateAdded, aOutput);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// write LAST_MODIFIED
|
||||
PRTime lastModified = 0;
|
||||
rv = aItem->GetLastModified(&lastModified);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (lastModified) {
|
||||
rv = WriteDateAttribute(kLastModifiedAttribute, sizeof(kLastModifiedAttribute)-1, lastModified, aOutput);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// ' ICON="..."'
|
||||
rv = WriteFaviconAttribute(uri, aOutput);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -1701,12 +1880,12 @@ nsPlacesImportExportService::WriteItem(nsINavHistoryResultNode* aItem,
|
|||
rv = aItem->GetItemId(&itemId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// write id
|
||||
rv = aOutput->Write(kIdAttribute, sizeof(kIdAttribute)-1, &dummy);
|
||||
// write id as ITEM_ID as non-rdf IDs can confuse Firefox 2
|
||||
rv = aOutput->Write(kItemIdAttribute, sizeof(kItemIdAttribute)-1, &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCAutoString id;
|
||||
id.AppendInt(itemId);
|
||||
rv = aOutput->Write(id.get(), id.Length(), &dummy);
|
||||
nsCAutoString itemIdAttr;
|
||||
itemIdAttr.AppendInt(itemId); // casting from PRInt64 -> PRInt32, data loss, fix me
|
||||
rv = aOutput->Write(itemIdAttr.get(), itemIdAttr.Length(), &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aOutput->Write(kQuoteStr, sizeof(kQuoteStr)-1, &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -1775,7 +1954,7 @@ nsPlacesImportExportService::WriteItem(nsINavHistoryResultNode* aItem,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// write out generator URI
|
||||
rv = aOutput->Write(kMicsumGenURIEquals, sizeof(kMicsumGenURIEquals)-1, &dummy);
|
||||
rv = aOutput->Write(kMicsumGenURIAttribute, sizeof(kMicsumGenURIAttribute)-1, &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = WriteEscapedUrl(spec, aOutput);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -1868,12 +2047,12 @@ nsPlacesImportExportService::WriteLivemark(PRInt64 aFolderId, const nsACString&
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// write id
|
||||
rv = aOutput->Write(kIdAttribute, sizeof(kIdAttribute)-1, &dummy);
|
||||
// write id as ITEM_ID as non-rdf IDs can confuse Firefox 2
|
||||
rv = aOutput->Write(kItemIdAttribute, sizeof(kItemIdAttribute)-1, &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCAutoString id;
|
||||
id.AppendInt(aFolderId);
|
||||
rv = aOutput->Write(id.get(), id.Length(), &dummy);
|
||||
nsCAutoString itemIdAttr;
|
||||
itemIdAttr.AppendInt(aFolderId); // casting from PRInt64 -> PRInt32, data loss, fix me
|
||||
rv = aOutput->Write(itemIdAttr.get(), itemIdAttr.Length(), &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aOutput->Write(kQuoteStr, sizeof(kQuoteStr)-1, &dummy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -1925,7 +2104,7 @@ nsPlacesImportExportService::WriteSeparator(nsINavHistoryResultNode* aItem,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Note: we can't write the separator ID or anything else other than NAME
|
||||
// because it makes Firefox 2.x crash/hang - see bug 381129
|
||||
// because it makes Firefox 2.x crash/hang - see bug #381129
|
||||
|
||||
nsAutoString title;
|
||||
rv = mBookmarksService->GetItemTitle(itemId, title);
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<DT><A HREF="http://en-US.www.mozilla.com/en-US/firefox/community/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg==" ID="rdf:#$42iCK1">Get Involved</A>
|
||||
<DT><A HREF="http://en-US.www.mozilla.com/en-US/firefox/about/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg==" ID="rdf:#$52iCK1">About Us</A>
|
||||
</DL><p>
|
||||
<DT><H3 ADD_DATE="1177541020" LAST_MODIFIED="1177541047" ID="rdf:#$74Gpx2">test</H3>
|
||||
<DT><H3 ADD_DATE="1177541020" LAST_MODIFIED="1177541050" ID="rdf:#$74Gpx2">test</H3>
|
||||
<DD>folder test comment
|
||||
<DL><p>
|
||||
<DT><A HREF="http://test/post" ADD_DATE="1177375336" LAST_MODIFIED="1177375423" SHORTCUTURL="test" WEB_PANEL="true" POST_DATA="hidden1%3Dbar&text1%3D%25s" LAST_CHARSET="ISO-8859-1" ID="rdf:#$pYFe7">test post keyword</A>
|
||||
|
|
|
@ -196,7 +196,6 @@ function testCanonicalBookmarks(aFolder) {
|
|||
toolbar.containerOpen = true;
|
||||
do_check_eq(toolbar.childCount, 2);
|
||||
|
||||
|
||||
// livemark
|
||||
var livemark = toolbar.getChild(1);
|
||||
// title
|
||||
|
@ -216,6 +215,12 @@ function testCanonicalBookmarks(aFolder) {
|
|||
var testFolder = rootNode.getChild(5);
|
||||
do_check_eq(testFolder.type, testFolder.RESULT_TYPE_FOLDER);
|
||||
do_check_eq(testFolder.title, "test");
|
||||
|
||||
// add date
|
||||
do_check_eq(bmsvc.getItemDateAdded(testFolder.itemId)/1000000, 1177541020);
|
||||
// last modified
|
||||
do_check_eq(bmsvc.getItemLastModified(testFolder.itemId)/1000000, 1177541050);
|
||||
|
||||
testFolder = testFolder.QueryInterface(Ci.nsINavHistoryQueryResultNode);
|
||||
do_check_eq(testFolder.hasChildren, true);
|
||||
// folder description
|
||||
|
@ -243,7 +248,11 @@ function testCanonicalBookmarks(aFolder) {
|
|||
do_check_true(annosvc.itemHasAnnotation(testBookmark1.itemId,
|
||||
LOAD_IN_SIDEBAR_ANNO));
|
||||
// add date
|
||||
do_check_eq(testBookmark1.dateAdded/1000000, 1177375336);
|
||||
|
||||
// last modified
|
||||
do_check_eq(testBookmark1.lastModified/1000000, 1177375423);
|
||||
|
||||
// post data
|
||||
var pageURI = iosvc.newURI(testBookmark1.uri, "", null);
|
||||
do_check_true(annosvc.pageHasAnnotation(pageURI, POST_DATA_ANNO));
|
||||
|
|
|
@ -207,6 +207,10 @@
|
|||
"Keyword">
|
||||
<!ENTITY col.description.label
|
||||
"Description">
|
||||
<!ENTITY col.dateadded.label
|
||||
"Added">
|
||||
<!ENTITY col.lastmodified.label
|
||||
"Last Modified">
|
||||
|
||||
<!ENTITY search.label
|
||||
"Search:">
|
||||
|
|
|
@ -170,7 +170,7 @@ interface nsINavBookmarkObserver : nsISupports
|
|||
* folders. A URI in history can be contained in one or more such folders.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(d0dcc4b9-3f41-4489-aec5-117f8ed26a68)]
|
||||
[scriptable, uuid(5e44a4e2-5db6-412a-b153-c732c9c62fd5)]
|
||||
interface nsINavBookmarksService : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -354,6 +354,24 @@ interface nsINavBookmarksService : nsISupports
|
|||
*/
|
||||
AString getItemTitle(in long long aItemId);
|
||||
|
||||
/**
|
||||
* Set the date added time for an item.
|
||||
*/
|
||||
void setItemDateAdded(in long long aItemId, in PRTime aDateAdded);
|
||||
/**
|
||||
* Get the date added time for an item.
|
||||
*/
|
||||
PRTime getItemDateAdded(in long long aItemId);
|
||||
|
||||
/**
|
||||
* Set the last modified time for an item.
|
||||
*/
|
||||
void setItemLastModified(in long long aItemId, in PRTime aLastModified);
|
||||
/**
|
||||
* Get the last modified time for an item.
|
||||
*/
|
||||
PRTime getItemLastModified(in long long aItemId);
|
||||
|
||||
/**
|
||||
* Get the URI for a bookmark item.
|
||||
*/
|
||||
|
|
|
@ -49,7 +49,7 @@ interface nsINavHistoryResult;
|
|||
interface nsITreeColumn;
|
||||
interface nsIWritablePropertyBag;
|
||||
|
||||
[scriptable, uuid(2cce631e-d7dd-4162-a05b-e8ecfbc34367)]
|
||||
[scriptable, uuid(ff6f0168-f3f6-4f3a-9dfb-810a8eb4e545)]
|
||||
interface nsINavHistoryResultNode : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -163,6 +163,18 @@ interface nsINavHistoryResultNode : nsISupports
|
|||
* set to -1.
|
||||
*/
|
||||
readonly attribute PRInt64 itemId;
|
||||
|
||||
/**
|
||||
* If the node is an item (bookmark, folder or a separator) this value is the
|
||||
* time that the item was created. For other nodes, this value is 0.
|
||||
*/
|
||||
readonly attribute PRTime dateAdded;
|
||||
|
||||
/**
|
||||
* If the node is an item (bookmark, folder or a separator) this value is the
|
||||
* time that the item was last modified. For other nodes, this value is 0.
|
||||
*/
|
||||
readonly attribute PRTime lastModified;
|
||||
};
|
||||
|
||||
|
||||
|
@ -990,8 +1002,13 @@ interface nsINavHistoryQueryOptions : nsISupports
|
|||
const unsigned short SORT_BY_VISITCOUNT_DESCENDING = 8;
|
||||
const unsigned short SORT_BY_KEYWORD_ASCENDING = 9;
|
||||
const unsigned short SORT_BY_KEYWORD_DESCENDING = 10;
|
||||
const unsigned short SORT_BY_ANNOTATION_ASCENDING = 11;
|
||||
const unsigned short SORT_BY_ANNOTATION_DESCENDING = 12;
|
||||
const unsigned short SORT_BY_DATEADDED_ASCENDING = 11;
|
||||
const unsigned short SORT_BY_DATEADDED_DESCENDING = 12;
|
||||
const unsigned short SORT_BY_LASTMODIFIED_ASCENDING = 13;
|
||||
const unsigned short SORT_BY_LASTMODIFIED_DESCENDING = 14;
|
||||
const unsigned short SORT_BY_ANNOTATION_ASCENDING = 15;
|
||||
const unsigned short SORT_BY_ANNOTATION_DESCENDING = 16;
|
||||
|
||||
|
||||
/**
|
||||
* "URI" results, one for each URI visited in the range. Individual result
|
||||
|
|
|
@ -56,9 +56,9 @@ const PRInt32 nsNavBookmarks::kFindBookmarksIndex_Position = 4;
|
|||
const PRInt32 nsNavBookmarks::kFindBookmarksIndex_Title = 5;
|
||||
|
||||
// These columns sit to the right of the kGetInfoIndex_* columns.
|
||||
const PRInt32 nsNavBookmarks::kGetChildrenIndex_Position = 9;
|
||||
const PRInt32 nsNavBookmarks::kGetChildrenIndex_Type = 10;
|
||||
const PRInt32 nsNavBookmarks::kGetChildrenIndex_ForeignKey = 11;
|
||||
const PRInt32 nsNavBookmarks::kGetChildrenIndex_Position = 11;
|
||||
const PRInt32 nsNavBookmarks::kGetChildrenIndex_Type = 12;
|
||||
const PRInt32 nsNavBookmarks::kGetChildrenIndex_ForeignKey = 13;
|
||||
|
||||
const PRInt32 nsNavBookmarks::kGetItemPropertiesIndex_ID = 0;
|
||||
const PRInt32 nsNavBookmarks::kGetItemPropertiesIndex_URI = 1;
|
||||
|
@ -68,6 +68,8 @@ const PRInt32 nsNavBookmarks::kGetItemPropertiesIndex_PlaceID = 4;
|
|||
const PRInt32 nsNavBookmarks::kGetItemPropertiesIndex_Parent = 5;
|
||||
const PRInt32 nsNavBookmarks::kGetItemPropertiesIndex_Type = 6;
|
||||
const PRInt32 nsNavBookmarks::kGetItemPropertiesIndex_FolderType = 7;
|
||||
const PRInt32 nsNavBookmarks::kGetItemPropertiesIndex_DateAdded = 8;
|
||||
const PRInt32 nsNavBookmarks::kGetItemPropertiesIndex_LastModified = 9;
|
||||
|
||||
nsNavBookmarks* nsNavBookmarks::sInstance = nsnull;
|
||||
|
||||
|
@ -144,7 +146,9 @@ nsNavBookmarks::Init()
|
|||
NS_LITERAL_CSTRING("SELECT h.id, h.url, a.title, "
|
||||
"h.rev_host, h.visit_count, "
|
||||
"(SELECT MAX(visit_date) FROM moz_historyvisits WHERE place_id = h.id), "
|
||||
"f.url, null, a.id, a.position, a.type, a.fk "
|
||||
"f.url, null, a.id, "
|
||||
"a.dateAdded, a.lastModified, "
|
||||
"a.position, a.type, a.fk "
|
||||
"FROM moz_bookmarks a "
|
||||
"LEFT JOIN moz_places h ON a.fk = h.id "
|
||||
"LEFT OUTER JOIN moz_favicons f ON h.favicon_id = f.id "
|
||||
|
@ -171,7 +175,7 @@ nsNavBookmarks::Init()
|
|||
|
||||
// get bookmark/folder/separator properties
|
||||
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT b.id, (SELECT url from moz_places WHERE id = b.fk), b.title, b.position, b.fk, b.parent, b.type, b.folder_type "
|
||||
"SELECT b.id, (SELECT url from moz_places WHERE id = b.fk), b.title, b.position, b.fk, b.parent, b.type, b.folder_type, b.dateAdded, b.lastModified "
|
||||
"FROM moz_bookmarks b "
|
||||
"WHERE b.id = ?1"),
|
||||
getter_AddRefs(mDBGetItemProperties));
|
||||
|
@ -243,7 +247,6 @@ nsNavBookmarks::Init()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsNavBookmarks::InitTables
|
||||
//
|
||||
// All commands that initialize the schema of the DB go in here. This is
|
||||
|
@ -267,7 +270,9 @@ nsNavBookmarks::InitTables(mozIStorageConnection* aDBConn)
|
|||
"position INTEGER, "
|
||||
"title LONGVARCHAR, "
|
||||
"keyword_id INTEGER, "
|
||||
"folder_type TEXT)"));
|
||||
"folder_type TEXT, "
|
||||
"dateAdded INTEGER, "
|
||||
"lastModified INTEGER)"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// this index will make it faster to determine if a given item is
|
||||
|
@ -869,7 +874,7 @@ nsNavBookmarks::InsertItem(PRInt64 aFolder, nsIURI *aItem, PRInt32 aIndex, PRInt
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCAutoString buffer;
|
||||
buffer.AssignLiteral("INSERT INTO moz_bookmarks (fk, type, parent, position) VALUES (");
|
||||
buffer.AssignLiteral("INSERT INTO moz_bookmarks (fk, type, parent, position, dateAdded) VALUES (");
|
||||
buffer.AppendInt(childID);
|
||||
buffer.AppendLiteral(", ");
|
||||
buffer.AppendInt(TYPE_BOOKMARK);
|
||||
|
@ -877,6 +882,8 @@ nsNavBookmarks::InsertItem(PRInt64 aFolder, nsIURI *aItem, PRInt32 aIndex, PRInt
|
|||
buffer.AppendInt(aFolder);
|
||||
buffer.AppendLiteral(", ");
|
||||
buffer.AppendInt(index);
|
||||
buffer.AppendLiteral(", ");
|
||||
buffer.AppendInt(PR_Now());
|
||||
buffer.AppendLiteral(")");
|
||||
|
||||
rv = dbConn->ExecuteSimpleSQL(buffer);
|
||||
|
@ -995,16 +1002,16 @@ nsNavBookmarks::CreateFolderWithID(PRInt64 aFolder, PRInt64 aParent,
|
|||
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
if (aFolder == -1) {
|
||||
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("INSERT INTO moz_bookmarks (title, type, parent, position, folder_type) VALUES (?1, ?2, ?3, ?4, null)"),
|
||||
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("INSERT INTO moz_bookmarks (title, type, parent, position, folder_type, dateAdded) VALUES (?1, ?2, ?3, ?4, null, ?5)"),
|
||||
getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("INSERT INTO moz_bookmarks (id, title, type, parent, position, folder_type) VALUES (?5, ?1, ?2, ?3, ?4, null)"),
|
||||
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("INSERT INTO moz_bookmarks (id, title, type, parent, position, folder_type, dateAdded) VALUES (?6, ?1, ?2, ?3, ?4, null, ?5)"),
|
||||
getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->BindInt64Parameter(4, aFolder);
|
||||
rv = statement->BindInt64Parameter(5, aFolder);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -1016,6 +1023,8 @@ nsNavBookmarks::CreateFolderWithID(PRInt64 aFolder, PRInt64 aParent,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->BindInt32Parameter(3, index);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->BindInt64Parameter(4, PR_Now());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -1094,7 +1103,7 @@ nsNavBookmarks::InsertSeparator(PRInt64 aParent, PRInt32 aIndex,
|
|||
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("INSERT INTO moz_bookmarks "
|
||||
"(type, parent, position) VALUES (?1, ?2, ?3)"),
|
||||
"(type, parent, position, dateAdded) VALUES (?1, ?2, ?3, ?4)"),
|
||||
getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
@ -1104,6 +1113,8 @@ nsNavBookmarks::InsertSeparator(PRInt64 aParent, PRInt32 aIndex,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->BindInt32Parameter(2, index);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->BindInt64Parameter(3, PR_Now());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -1522,6 +1533,98 @@ nsNavBookmarks::GetChildFolder(PRInt64 aFolder, const nsAString& aSubFolder,
|
|||
return statement->GetInt64(0, _result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::SetItemDateAdded(PRInt64 aItemId, PRTime aDateAdded)
|
||||
{
|
||||
mozIStorageConnection *dbConn = DBConn();
|
||||
mozStorageTransaction transaction(dbConn, PR_FALSE);
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
nsresult rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("UPDATE moz_bookmarks SET dateAdded = ?1 WHERE id = ?2"),
|
||||
getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->BindInt64Parameter(0, aDateAdded);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->BindInt64Parameter(1, aItemId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// note, we are not notifying the observers
|
||||
// that the item has changed.
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::GetItemDateAdded(PRInt64 aItemId, PRTime *aDateAdded)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDateAdded);
|
||||
|
||||
mozStorageStatementScoper scope(mDBGetItemProperties);
|
||||
nsresult rv = mDBGetItemProperties->BindInt64Parameter(0, aItemId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool results;
|
||||
rv = mDBGetItemProperties->ExecuteStep(&results);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!results)
|
||||
return NS_ERROR_INVALID_ARG; // invalid item id
|
||||
|
||||
return mDBGetItemProperties->GetInt64(kGetItemPropertiesIndex_DateAdded, aDateAdded);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::SetItemLastModified(PRInt64 aItemId, PRTime aLastModified)
|
||||
{
|
||||
mozIStorageConnection *dbConn = DBConn();
|
||||
mozStorageTransaction transaction(dbConn, PR_FALSE);
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
nsresult rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("UPDATE moz_bookmarks SET lastModified = ?1 WHERE id = ?2"),
|
||||
getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->BindInt64Parameter(0, aLastModified);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->BindInt64Parameter(1, aItemId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// note, we are not notifying the observers
|
||||
// that the item has changed.
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::GetItemLastModified(PRInt64 aItemId, PRTime *aLastModified)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLastModified);
|
||||
|
||||
mozStorageStatementScoper scope(mDBGetItemProperties);
|
||||
nsresult rv = mDBGetItemProperties->BindInt64Parameter(0, aItemId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool results;
|
||||
rv = mDBGetItemProperties->ExecuteStep(&results);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!results)
|
||||
return NS_ERROR_INVALID_ARG; // invalid item id
|
||||
|
||||
return mDBGetItemProperties->GetInt64(kGetItemPropertiesIndex_LastModified, aLastModified);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::SetItemTitle(PRInt64 aItemId, const nsAString &aTitle)
|
||||
{
|
||||
|
@ -1543,10 +1646,12 @@ nsNavBookmarks::SetItemTitle(PRInt64 aItemId, const nsAString &aTitle)
|
|||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = SetItemLastModified(aItemId, PR_Now());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
|
||||
OnItemChanged(aItemId, NS_LITERAL_CSTRING("title"),
|
||||
PR_FALSE, NS_ConvertUTF16toUTF8(aTitle)));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1904,6 +2009,9 @@ nsNavBookmarks::ChangeBookmarkURI(PRInt64 aBookmarkId, nsIURI *aNewURI)
|
|||
rv = aNewURI->GetSpec(spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = SetItemLastModified(aBookmarkId, PR_Now());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Pass the new URI to OnItemChanged.
|
||||
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
|
||||
OnItemChanged(aBookmarkId, NS_LITERAL_CSTRING("uri"), PR_FALSE, spec))
|
||||
|
@ -2100,11 +2208,15 @@ nsNavBookmarks::SetKeywordForBookmark(PRInt64 aBookmarkId, const nsAString& aKey
|
|||
rv = updateKeywordStmnt->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
transaction.Commit();
|
||||
|
||||
rv = SetItemLastModified(aBookmarkId, PR_Now());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Pass the new keyword to OnItemChanged.
|
||||
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
|
||||
OnItemChanged(aBookmarkId, NS_LITERAL_CSTRING("keyword"),
|
||||
PR_FALSE, NS_ConvertUTF16toUTF8(aKeyword)))
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2354,8 +2466,12 @@ nsNavBookmarks::OnPageAnnotationSet(nsIURI* aPage, const nsACString& aName)
|
|||
NS_IMETHODIMP
|
||||
nsNavBookmarks::OnItemAnnotationSet(PRInt64 aItemId, const nsACString& aName)
|
||||
{
|
||||
nsresult rv = SetItemLastModified(aItemId, PR_Now());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
|
||||
OnItemChanged(aItemId, aName, PR_TRUE, EmptyCString()));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2368,8 +2484,12 @@ nsNavBookmarks::OnPageAnnotationRemoved(nsIURI* aPage, const nsACString& aName)
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::OnItemAnnotationRemoved(PRInt64 aItemId, const nsACString& aName)
|
||||
{
|
||||
{
|
||||
nsresult rv = SetItemLastModified(aItemId, PR_Now());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
|
||||
OnItemChanged(aItemId, aName, PR_TRUE, EmptyCString()));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -190,6 +190,8 @@ private:
|
|||
static const PRInt32 kGetItemPropertiesIndex_Parent;
|
||||
static const PRInt32 kGetItemPropertiesIndex_Type;
|
||||
static const PRInt32 kGetItemPropertiesIndex_FolderType;
|
||||
static const PRInt32 kGetItemPropertiesIndex_DateAdded;
|
||||
static const PRInt32 kGetItemPropertiesIndex_LastModified;
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> mDBGetRedirectDestinations;
|
||||
|
||||
|
|
|
@ -208,6 +208,8 @@ const PRInt32 nsNavHistory::kGetInfoIndex_VisitDate = 5;
|
|||
const PRInt32 nsNavHistory::kGetInfoIndex_FaviconURL = 6;
|
||||
const PRInt32 nsNavHistory::kGetInfoIndex_SessionId = 7;
|
||||
const PRInt32 nsNavHistory::kGetInfoIndex_ItemId = 8;
|
||||
const PRInt32 nsNavHistory::kGetInfoIndex_ItemDateAdded = 9;
|
||||
const PRInt32 nsNavHistory::kGetInfoIndex_ItemLastModified = 10;
|
||||
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_URL = 0;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_Title = 1;
|
||||
|
@ -385,7 +387,7 @@ nsNavHistory::Init()
|
|||
//
|
||||
|
||||
|
||||
#define PLACES_SCHEMA_VERSION 4
|
||||
#define PLACES_SCHEMA_VERSION 5
|
||||
|
||||
nsresult
|
||||
nsNavHistory::InitDB(PRBool *aDoImport)
|
||||
|
@ -488,13 +490,13 @@ nsNavHistory::InitDB(PRBool *aDoImport)
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Migrate bookmarks tables up to V4
|
||||
if (DBSchemaVersion < 4) {
|
||||
// Migrate bookmarks tables up to V5
|
||||
if (DBSchemaVersion < 5) {
|
||||
rv = ForceMigrateBookmarksDB(mDBConn);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// XXX Upgrades >V4 must add migration code here.
|
||||
// XXX Upgrades >V5 must add migration code here.
|
||||
|
||||
} else {
|
||||
// Downgrading
|
||||
|
@ -502,9 +504,9 @@ nsNavHistory::InitDB(PRBool *aDoImport)
|
|||
// XXX Need to prompt user or otherwise notify of
|
||||
// potential dataloss when downgrading.
|
||||
|
||||
// XXX Downgrades from >V4 must add migration code here.
|
||||
// XXX Downgrades from >V5 must add migration code here.
|
||||
|
||||
// Downgrade v1,2,4
|
||||
// Downgrade v1,2,4,5
|
||||
// V3 had no backwards incompatible changes.
|
||||
if (DBSchemaVersion > 2) {
|
||||
// perform downgrade to v2
|
||||
|
@ -780,7 +782,7 @@ nsNavHistory::InitStatements()
|
|||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT b.fk, h.url, b.title, h.rev_host, h.visit_count, "
|
||||
"(SELECT MAX(visit_date) FROM moz_historyvisits WHERE place_id = b.fk), "
|
||||
"f.url, null, null "
|
||||
"f.url, null, null, b.dateAdded, b.lastModified "
|
||||
"FROM moz_bookmarks b "
|
||||
"JOIN moz_places h ON b.fk = h.id "
|
||||
"LEFT OUTER JOIN moz_favicons f ON h.favicon_id = f.id "
|
||||
|
@ -2067,7 +2069,7 @@ nsNavHistory::GetQueryResults(const nsCOMArray<nsNavHistoryQuery>& aQueries,
|
|||
queryString = NS_LITERAL_CSTRING(
|
||||
"SELECT b.fk, h.url, b.title, h.rev_host, h.visit_count, "
|
||||
"(SELECT MAX(visit_date) FROM moz_historyvisits WHERE place_id = b.fk), "
|
||||
"f.url, null, b.id "
|
||||
"f.url, null, b.id, b.dateAdded, b.lastModified "
|
||||
"FROM moz_bookmarks b "
|
||||
"JOIN moz_places h ON b.fk = h.id "
|
||||
"LEFT OUTER JOIN moz_historyvisits v ON b.fk = v.place_id "
|
||||
|
@ -2133,13 +2135,13 @@ nsNavHistory::GetQueryResults(const nsCOMArray<nsNavHistoryQuery>& aQueries,
|
|||
// a sort by date here (see the IDL definition for maxResults). We'll
|
||||
// still do the official sort by title later.
|
||||
if (aOptions->MaxResults() > 0)
|
||||
queryString += NS_LITERAL_CSTRING(" ORDER BY 6 DESC"); // v.vist_date
|
||||
queryString += NS_LITERAL_CSTRING(" ORDER BY 6 DESC"); // v.visit_date
|
||||
break;
|
||||
case nsINavHistoryQueryOptions::SORT_BY_DATE_ASCENDING:
|
||||
queryString += NS_LITERAL_CSTRING(" ORDER BY 6 ASC"); // v.vist_date
|
||||
queryString += NS_LITERAL_CSTRING(" ORDER BY 6 ASC"); // v.visit_date
|
||||
break;
|
||||
case nsINavHistoryQueryOptions::SORT_BY_DATE_DESCENDING:
|
||||
queryString += NS_LITERAL_CSTRING(" ORDER BY 6 DESC"); // v.vist_date
|
||||
queryString += NS_LITERAL_CSTRING(" ORDER BY 6 DESC"); // v.visit_date
|
||||
break;
|
||||
case nsINavHistoryQueryOptions::SORT_BY_URI_ASCENDING:
|
||||
queryString += NS_LITERAL_CSTRING(" ORDER BY 2 ASC"); // h.url
|
||||
|
@ -3931,6 +3933,8 @@ nsNavHistory::RowToResult(mozIStorageValueArray* aRow,
|
|||
if (NS_SUCCEEDED(aRow->GetIsNull(kGetInfoIndex_ItemId, &isNull)) &&
|
||||
!isNull) {
|
||||
(*aResult)->mItemId = aRow->AsInt64(kGetInfoIndex_ItemId);
|
||||
(*aResult)->mDateAdded = aRow->AsInt64(kGetInfoIndex_ItemDateAdded);
|
||||
(*aResult)->mLastModified = aRow->AsInt64(kGetInfoIndex_ItemLastModified);
|
||||
}
|
||||
NS_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
|
|
|
@ -221,6 +221,8 @@ public:
|
|||
static const PRInt32 kGetInfoIndex_RevHost;
|
||||
static const PRInt32 kGetInfoIndex_VisitCount;
|
||||
static const PRInt32 kGetInfoIndex_ItemId;
|
||||
static const PRInt32 kGetInfoIndex_ItemDateAdded;
|
||||
static const PRInt32 kGetInfoIndex_ItemLastModified;
|
||||
|
||||
// select a history row by URL, with visit date info (extra work)
|
||||
mozIStorageStatement* DBGetURLPageInfoFull()
|
||||
|
|
|
@ -116,6 +116,8 @@ nsNavHistoryResultNode::nsNavHistoryResultNode(
|
|||
mFaviconURI(aIconURI),
|
||||
mBookmarkIndex(-1),
|
||||
mItemId(-1),
|
||||
mDateAdded(0),
|
||||
mLastModified(0),
|
||||
mIndentLevel(-1),
|
||||
mViewIndex(-1)
|
||||
{
|
||||
|
@ -595,6 +597,14 @@ nsNavHistoryContainerResultNode::GetSortingComparator(PRUint16 aSortType)
|
|||
return &SortComparison_AnnotationLess;
|
||||
case nsINavHistoryQueryOptions::SORT_BY_ANNOTATION_DESCENDING:
|
||||
return &SortComparison_AnnotationGreater;
|
||||
case nsINavHistoryQueryOptions::SORT_BY_DATEADDED_ASCENDING:
|
||||
return &SortComparison_DateAddedLess;
|
||||
case nsINavHistoryQueryOptions::SORT_BY_DATEADDED_DESCENDING:
|
||||
return &SortComparison_DateAddedGreater;
|
||||
case nsINavHistoryQueryOptions::SORT_BY_LASTMODIFIED_ASCENDING:
|
||||
return &SortComparison_LastModifiedLess;
|
||||
case nsINavHistoryQueryOptions::SORT_BY_LASTMODIFIED_DESCENDING:
|
||||
return &SortComparison_LastModifiedGreater;
|
||||
default:
|
||||
NS_NOTREACHED("Bad sorting type");
|
||||
return nsnull;
|
||||
|
@ -789,6 +799,48 @@ PRInt32 PR_CALLBACK nsNavHistoryContainerResultNode::SortComparison_DateGreater(
|
|||
return -nsNavHistoryContainerResultNode::SortComparison_DateLess(a, b, closure);
|
||||
}
|
||||
|
||||
// nsNavHistoryContainerResultNode::SortComparison_DateAdded*
|
||||
//
|
||||
|
||||
PRInt32 PR_CALLBACK nsNavHistoryContainerResultNode::SortComparison_DateAddedLess(
|
||||
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure)
|
||||
{
|
||||
PRInt32 value = ComparePRTime(a->mDateAdded, b->mDateAdded);
|
||||
if (value == 0) {
|
||||
value = SortComparison_StringLess(NS_ConvertUTF8toUTF16(a->mTitle),
|
||||
NS_ConvertUTF8toUTF16(b->mTitle));
|
||||
if (value == 0)
|
||||
value = nsNavHistoryContainerResultNode::SortComparison_Bookmark(a, b, closure);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
PRInt32 PR_CALLBACK nsNavHistoryContainerResultNode::SortComparison_DateAddedGreater(
|
||||
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure)
|
||||
{
|
||||
return -nsNavHistoryContainerResultNode::SortComparison_DateAddedLess(a, b, closure);
|
||||
}
|
||||
|
||||
|
||||
// nsNavHistoryContainerResultNode::SortComparison_LastModified*
|
||||
//
|
||||
|
||||
PRInt32 PR_CALLBACK nsNavHistoryContainerResultNode::SortComparison_LastModifiedLess(
|
||||
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure)
|
||||
{
|
||||
PRInt32 value = ComparePRTime(a->mLastModified, b->mLastModified);
|
||||
if (value == 0) {
|
||||
value = SortComparison_StringLess(NS_ConvertUTF8toUTF16(a->mTitle),
|
||||
NS_ConvertUTF8toUTF16(b->mTitle));
|
||||
if (value == 0)
|
||||
value = nsNavHistoryContainerResultNode::SortComparison_Bookmark(a, b, closure);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
PRInt32 PR_CALLBACK nsNavHistoryContainerResultNode::SortComparison_LastModifiedGreater(
|
||||
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure)
|
||||
{
|
||||
return -nsNavHistoryContainerResultNode::SortComparison_LastModifiedLess(a, b, closure);
|
||||
}
|
||||
|
||||
// nsNavHistoryContainerResultNode::SortComparison_URI*
|
||||
//
|
||||
|
@ -2515,6 +2567,7 @@ nsNavHistoryQueryResultNode::OnItemChanged(PRInt64 aItemId,
|
|||
NS_NOTREACHED("Everything observers should not get OnItemChanged, but should get the corresponding history notifications instead");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryResultNode::OnItemVisited(PRInt64 aItemId,
|
||||
PRInt64 aVisitId, PRTime aTime)
|
||||
|
@ -3121,6 +3174,27 @@ nsNavHistoryFolderResultNode::OnItemChanged(PRInt64 aItemId,
|
|||
NS_NOTREACHED("Unknown bookmark property changing.");
|
||||
}
|
||||
|
||||
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
|
||||
NS_ENSURE_TRUE(bookmarks, NS_ERROR_UNEXPECTED);
|
||||
|
||||
PRTime lastModified;
|
||||
nsresult rv = bookmarks->GetItemLastModified(aItemId, &lastModified);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
node->mLastModified = lastModified;
|
||||
}
|
||||
else {
|
||||
node->mLastModified = 0;
|
||||
}
|
||||
|
||||
PRTime dateAdded;
|
||||
rv = bookmarks->GetItemDateAdded(aItemId, &dateAdded);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
node->mDateAdded = dateAdded;
|
||||
}
|
||||
else {
|
||||
node->mDateAdded = 0;
|
||||
}
|
||||
|
||||
nsNavHistoryResult* result = GetResult();
|
||||
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -3144,7 +3218,6 @@ nsNavHistoryFolderResultNode::OnItemChanged(PRInt64 aItemId,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsNavHistoryFolderResultNode::OnItemVisited (nsINavBookmarkObserver)
|
||||
//
|
||||
// Update visit count and last visit time and refresh.
|
||||
|
@ -3738,7 +3811,6 @@ nsNavHistoryResult::OnItemChanged(PRInt64 aItemId,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsNavHistoryResult::OnItemVisited (nsINavBookmarkObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -225,7 +225,12 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResult, NS_NAVHISTORYRESULT_IID)
|
|||
NS_IMETHOD GetBookmarkIndex(PRInt32* aIndex) \
|
||||
{ *aIndex = mBookmarkIndex; return NS_OK; } \
|
||||
NS_IMETHOD GetItemId(PRInt64* aId) \
|
||||
{ *aId= mItemId; return NS_OK; }
|
||||
{ *aId= mItemId; return NS_OK; } \
|
||||
NS_IMETHOD GetDateAdded(PRTime* aDateAdded) \
|
||||
{ *aDateAdded = mDateAdded; return NS_OK; } \
|
||||
NS_IMETHOD GetLastModified(PRTime* aLastModified) \
|
||||
{ *aLastModified = mLastModified; return NS_OK; }
|
||||
|
||||
|
||||
// This is used by the base classes instead of
|
||||
// NS_FORWARD_NSINAVHISTORYRESULTNODE(nsNavHistoryResultNode) because they
|
||||
|
@ -365,6 +370,8 @@ public:
|
|||
nsCString mFaviconURI;
|
||||
PRInt32 mBookmarkIndex;
|
||||
PRInt64 mItemId;
|
||||
PRTime mDateAdded;
|
||||
PRTime mLastModified;
|
||||
|
||||
// The indent level of this node. The root node will have a value of -1. The
|
||||
// root's children will have a value of 0, and so on.
|
||||
|
@ -578,6 +585,14 @@ public:
|
|||
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
|
||||
PR_STATIC_CALLBACK(int) SortComparison_AnnotationGreater(
|
||||
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
|
||||
PR_STATIC_CALLBACK(int) SortComparison_DateAddedLess(
|
||||
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
|
||||
PR_STATIC_CALLBACK(int) SortComparison_DateAddedGreater(
|
||||
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
|
||||
PR_STATIC_CALLBACK(int) SortComparison_LastModifiedLess(
|
||||
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
|
||||
PR_STATIC_CALLBACK(int) SortComparison_LastModifiedGreater(
|
||||
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
|
||||
|
||||
// finding children: THESE DO NOT ADDREF
|
||||
nsNavHistoryResultNode* FindChildURI(nsIURI* aURI, PRUint32* aNodeIndex)
|
||||
|
|
|
@ -136,18 +136,44 @@ function run_test() {
|
|||
do_check_eq(bmsvc.getItemType(testRoot), bmsvc.TYPE_FOLDER);
|
||||
|
||||
// insert a bookmark
|
||||
// the time before we insert, in microseconds
|
||||
var beforeInsert = Date.now() * 1000;
|
||||
do_check_true(beforeInsert > 0);
|
||||
|
||||
var newId = bmsvc.insertItem(testRoot, uri("http://google.com/"), bmsvc.DEFAULT_INDEX);
|
||||
do_check_eq(observer._itemAddedId, newId);
|
||||
do_check_eq(observer._itemAddedParent, testRoot);
|
||||
do_check_eq(observer._itemAddedIndex, testStartIndex);
|
||||
do_check_eq(bmsvc.getBookmarkURI(newId).spec, "http://google.com/");
|
||||
|
||||
var dateAdded = bmsvc.getItemDateAdded(newId);
|
||||
// dateAdded can equal beforeInsert
|
||||
do_check_true(dateAdded >= beforeInsert);
|
||||
|
||||
// after just inserting, modified should not be set
|
||||
var lastModified = bmsvc.getItemLastModified(newId);
|
||||
do_check_eq(lastModified, 0);
|
||||
|
||||
// the time before we set the title, in microseconds
|
||||
var beforeSetTitle = Date.now() * 1000;
|
||||
do_check_true(beforeSetTitle >= beforeInsert);
|
||||
|
||||
// set bookmark title
|
||||
bmsvc.setItemTitle(newId, "Google");
|
||||
do_check_eq(observer._itemChangedId, newId);
|
||||
do_check_eq(observer._itemChangedProperty, "title");
|
||||
do_check_eq(observer._itemChangedValue, "Google");
|
||||
|
||||
// check that dateAdded hasn't changed
|
||||
var dateAdded2 = bmsvc.getItemDateAdded(newId);
|
||||
do_check_eq(dateAdded2, dateAdded);
|
||||
|
||||
// check lastModified after we set the title
|
||||
var lastModified2 = bmsvc.getItemLastModified(newId);
|
||||
do_check_true(lastModified2 > lastModified);
|
||||
do_check_true(lastModified2 >= dateAdded);
|
||||
do_check_true(lastModified2 >= beforeSetTitle);
|
||||
|
||||
// get item title
|
||||
var title = bmsvc.getItemTitle(newId);
|
||||
do_check_eq(title, "Google");
|
||||
|
@ -298,14 +324,24 @@ function run_test() {
|
|||
var tmpFolder = bmsvc.createFolder(testRoot, "tmp", 2);
|
||||
do_check_eq(bmsvc.getItemIndex(tmpFolder), 2);
|
||||
|
||||
// test setKeywordForURI
|
||||
// test setKeywordForBookmark
|
||||
var kwTestItemId = bmsvc.insertItem(testRoot, uri("http://keywordtest.com"), bmsvc.DEFAULT_INDEX);
|
||||
try {
|
||||
var dateAdded = bmsvc.getItemDateAdded(kwTestItemId);
|
||||
// after just inserting, modified should not be set
|
||||
var lastModified = bmsvc.getItemLastModified(kwTestItemId);
|
||||
do_check_eq(lastModified, 0);
|
||||
|
||||
bmsvc.setKeywordForBookmark(kwTestItemId, "bar");
|
||||
|
||||
var lastModified2 = bmsvc.getItemLastModified(kwTestItemId);
|
||||
do_check_true(lastModified2 > lastModified);
|
||||
do_check_true(lastModified2 >= dateAdded);
|
||||
} catch(ex) {
|
||||
do_throw("setKeywordForBookmark: " + ex);
|
||||
}
|
||||
|
||||
var lastModified3 = bmsvc.getItemLastModified(kwTestItemId);
|
||||
// test getKeywordForBookmark
|
||||
var k = bmsvc.getKeywordForBookmark(kwTestItemId);
|
||||
do_check_eq("bar", k);
|
||||
|
@ -411,7 +447,18 @@ function run_test() {
|
|||
|
||||
// test change bookmark uri
|
||||
var newId10 = bmsvc.insertItem(testRoot, uri("http://foo10.com/"), bmsvc.DEFAULT_INDEX);
|
||||
var dateAdded = bmsvc.getItemDateAdded(newId10);
|
||||
// after just inserting, modified should not be set
|
||||
var lastModified = bmsvc.getItemLastModified(newId10);
|
||||
do_check_eq(lastModified, 0);
|
||||
|
||||
bmsvc.changeBookmarkURI(newId10, uri("http://foo11.com/"));
|
||||
|
||||
// check that lastModified is set after we change the bookmark uri
|
||||
var lastModified2 = bmsvc.getItemLastModified(newId10);
|
||||
do_check_true(lastModified2 > lastModified);
|
||||
do_check_true(lastModified2 >= dateAdded);
|
||||
|
||||
do_check_eq(observer._itemChangedId, newId10);
|
||||
do_check_eq(observer._itemChangedProperty, "uri");
|
||||
do_check_eq(observer._itemChangedValue, "http://foo11.com/");
|
||||
|
@ -486,6 +533,76 @@ function run_test() {
|
|||
do_throw("bookmarks query: " + ex);
|
||||
}
|
||||
|
||||
// test dateAdded and lastModified properties
|
||||
// for a search query
|
||||
try {
|
||||
var options = histsvc.getNewQueryOptions();
|
||||
options.excludeQueries = 1;
|
||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS;
|
||||
var query = histsvc.getNewQuery();
|
||||
query.onlyBookmarked = true;
|
||||
query.searchTerms = "ZZZXXXYYY";
|
||||
var result = histsvc.executeQuery(query, options);
|
||||
var rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
var cc = rootNode.childCount;
|
||||
do_check_eq(cc, 1);
|
||||
var node = rootNode.getChild(0);
|
||||
|
||||
do_check_eq(typeof node.dateAdded, "number");
|
||||
do_check_true(node.dateAdded > 0);
|
||||
|
||||
do_check_eq(typeof node.lastModified, "number");
|
||||
do_check_true(node.lastModified > 0);
|
||||
|
||||
rootNode.containerOpen = false;
|
||||
}
|
||||
catch(ex) {
|
||||
do_throw("bookmarks query: " + ex);
|
||||
}
|
||||
|
||||
// test dateAdded and lastModified properties
|
||||
// for a folder query
|
||||
try {
|
||||
var options = histsvc.getNewQueryOptions();
|
||||
options.setGroupingMode([Ci.nsINavHistoryQueryOptions.GROUP_BY_FOLDER], 1);
|
||||
var query = histsvc.getNewQuery();
|
||||
query.setFolders([testRoot], 1);
|
||||
var result = histsvc.executeQuery(query, options);
|
||||
var rootNode = result.root;
|
||||
rootNode.containerOpen = true;
|
||||
var cc = rootNode.childCount;
|
||||
for (var i = 0; i < cc; i++) {
|
||||
var node = rootNode.getChild(i);
|
||||
|
||||
if (node.type == node.RESULT_TYPE_URI) {
|
||||
do_check_eq(typeof node.dateAdded, "number");
|
||||
do_check_true(node.dateAdded > 0);
|
||||
|
||||
do_check_eq(typeof node.lastModified, "number");
|
||||
do_check_true(node.lastModified > 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
rootNode.containerOpen = false;
|
||||
}
|
||||
catch(ex) {
|
||||
do_throw("bookmarks query: " + ex);
|
||||
}
|
||||
|
||||
// check setItemLastModified() and setItemDateAdded()
|
||||
var newId14 = bmsvc.insertItem(testRoot, uri("http://bar.tld/"), bmsvc.DEFAULT_INDEX);
|
||||
var dateAdded = bmsvc.getItemDateAdded(newId14);
|
||||
var lastModified = bmsvc.getItemLastModified(newId14);
|
||||
do_check_eq(lastModified, 0);
|
||||
do_check_true(dateAdded > lastModified);
|
||||
bmsvc.setItemLastModified(newId14, 1234);
|
||||
var fakeLastModified = bmsvc.getItemLastModified(newId14);
|
||||
do_check_eq(fakeLastModified, 1234);
|
||||
bmsvc.setItemDateAdded(newId14, 4321);
|
||||
var fakeDateAdded = bmsvc.getItemDateAdded(newId14);
|
||||
do_check_eq(fakeDateAdded, 4321);
|
||||
|
||||
// ensure that removing an item removes its annotations
|
||||
do_check_true(annosvc.itemHasAnnotation(newId3, "test-annotation"));
|
||||
bmsvc.removeItem(newId3);
|
||||
|
@ -500,8 +617,30 @@ function run_test() {
|
|||
}
|
||||
|
||||
function testSimpleFolderResult() {
|
||||
// the time before we create a folder, in microseconds
|
||||
var beforeCreate = Date.now() * 1000;
|
||||
do_check_true(beforeCreate > 0);
|
||||
|
||||
// create a folder
|
||||
var parent = bmsvc.createFolder(root, "test", bmsvc.DEFAULT_INDEX);
|
||||
|
||||
var dateCreated = bmsvc.getItemDateAdded(parent);
|
||||
do_check_true(dateCreated > 0);
|
||||
// dateCreated can equal beforeCreate
|
||||
do_check_true(dateCreated >= beforeCreate);
|
||||
|
||||
// the time before we insert, in microseconds
|
||||
var beforeInsert = Date.now() * 1000;
|
||||
do_check_true(beforeInsert > 0);
|
||||
|
||||
// insert a separator
|
||||
var sep = bmsvc.insertSeparator(parent, bmsvc.DEFAULT_INDEX);
|
||||
|
||||
var dateAdded = bmsvc.getItemDateAdded(sep);
|
||||
do_check_true(dateAdded > 0);
|
||||
// dateAdded can equal beforeInsert
|
||||
do_check_true(dateAdded >= beforeInsert);
|
||||
|
||||
var item = bmsvc.insertItem(parent, uri("about:blank"), bmsvc.DEFAULT_INDEX);
|
||||
bmsvc.setItemTitle(item, "test bookmark");
|
||||
var folder = bmsvc.createFolder(parent, "test folder", bmsvc.DEFAULT_INDEX);
|
||||
|
|
|
@ -115,13 +115,28 @@ function run_test() {
|
|||
|
||||
// string item-annotation
|
||||
try {
|
||||
var lastModified = bmsvc.getItemLastModified(testItemId);
|
||||
// verify that lastModified is 0 before we set the annotation
|
||||
do_check_eq(lastModified, 0);
|
||||
annosvc.setItemAnnotationString(testItemId, testAnnoName, testAnnoVal, 0, 0);
|
||||
var lastModified2 = bmsvc.getItemLastModified(testItemId);
|
||||
// verify that setting the annotation updates the last modified time
|
||||
do_check_true(lastModified2 > lastModified);
|
||||
} catch(ex) {
|
||||
do_throw("unable to add item annotation");
|
||||
}
|
||||
do_check_eq(annoObserver.ITEM_lastSet_Id, testItemId);
|
||||
do_check_eq(annoObserver.ITEM_lastSet_AnnoName, testAnnoName);
|
||||
|
||||
try {
|
||||
var lastModified = bmsvc.getItemLastModified(testItemId);
|
||||
var annoVal = annosvc.getItemAnnotationString(testItemId, testAnnoName);
|
||||
// verify the anno value
|
||||
do_check_eq(testAnnoVal, annoVal);
|
||||
} catch(ex) {
|
||||
do_throw("unable to get item annotation");
|
||||
}
|
||||
|
||||
// test getPagesWithAnnotation
|
||||
var uri2 = uri("http://www.tests.tld");
|
||||
annosvc.setPageAnnotationString(uri2, testAnnoName, testAnnoVal, 0, 0);
|
||||
|
@ -318,7 +333,14 @@ function run_test() {
|
|||
|
||||
// test annotation removal
|
||||
annosvc.removePageAnnotation(testURI, int32Key);
|
||||
|
||||
annosvc.setItemAnnotationString(testItemId, testAnnoName, testAnnoVal, 0, 0);
|
||||
// verify that removing an annotation updates the last modified date
|
||||
var lastModified3 = bmsvc.getItemLastModified(testItemId);
|
||||
annosvc.removeItemAnnotation(testItemId, int32Key);
|
||||
var lastModified4 = bmsvc.getItemLastModified(testItemId);
|
||||
do_check_true(lastModified4 >= lastModified3);
|
||||
|
||||
do_check_eq(annoObserver.PAGE_lastRemoved_URI, testURI.spec);
|
||||
do_check_eq(annoObserver.PAGE_lastRemoved_AnnoName, int32Key);
|
||||
do_check_eq(annoObserver.ITEM_lastRemoved_Id, testItemId);
|
||||
|
|
|
@ -145,6 +145,9 @@ function run_test() {
|
|||
// id1 precedes id2 per title-descending fallback
|
||||
checkOrder(id3, id1, id2);
|
||||
|
||||
// XXXtodo: test dateAdded sort
|
||||
// XXXtodo: test lastModified sort
|
||||
|
||||
// test live update
|
||||
annosvc.setItemAnnotationString(id1, "testAnno", "c", 0, 0);
|
||||
checkOrder(id1, id3, id2);
|
||||
|
|
Загрузка…
Ссылка в новой задаче