Bug 385245 ? history sidebar very slow (way slower than fx2) (for ondrej@allpeers.com, r=dietrich)

This commit is contained in:
dietrich%mozilla.com 2008-02-27 04:48:53 +00:00
Родитель bec44c8676
Коммит d084f217e0
22 изменённых файлов: 1072 добавлений и 1163 удалений

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

@ -639,6 +639,10 @@ pref("browser.places.createdSmartBookmarks", false);
// XXX to be removed after beta 2 (bug 391419)
pref("browser.places.migratePostDataAnnotations", true);
// If true, will update the Smart Bookmarks uri for
// recent tags (bug 385245). Useful just for FX3 beta users.
pref("browser.places.updateRecentTagsUri", true);
// the (maximum) number of the recent visits to sample
// when calculating frecency
pref("places.frecency.numVisits", 10);

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

@ -1024,7 +1024,7 @@ function placesMigrationTasks() {
// XXX - REMOVE ME FOR BETA 3 (bug 391419)
if (gPrefService.getBoolPref("browser.places.migratePostDataAnnotations")) {
const annosvc = PlacesUtils.annotations;
const bmsvc = PlacesUtils.bookmarks;
var bmsvc = PlacesUtils.bookmarks;
const oldPostDataAnno = "URIProperties/POSTData";
var pages = annosvc.getPagesWithAnnotation(oldPostDataAnno, {});
for (let i = 0; i < pages.length; i++) {
@ -1048,4 +1048,30 @@ function placesMigrationTasks() {
}
gPrefService.setBoolPref("browser.places.migratePostDataAnnotations", false);
}
if (gPrefService.getBoolPref("browser.places.updateRecentTagsUri")) {
var bmsvc = PlacesUtils.bookmarks;
var tagsFolder = bmsvc.tagsFolder;
var oldUriSpec = "place:folder=" + tagsFolder + "&group=3&queryType=1"+
"&applyOptionsToContainers=1&sort=12&maxResults=10";
var maxResults = 10;
var newUriSpec = "place:type=" +
Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY +
"&sort=" +
Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
"&maxResults=" + maxResults;
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
var oldUri = ios.newURI(oldUriSpec, null, null);
var newUri = ios.newURI(newUriSpec, null, null);
let bookmarks = bmsvc.getBookmarkIdsForURI( oldUri, {});
for (let i = 0; i < bookmarks.length; i++) {
bmsvc.changeBookmarkURI( bookmarks[i], newUri);
}
gPrefService.setBoolPref("browser.places.updateRecentTagsUri", false);
}
}

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

@ -539,7 +539,6 @@ BrowserGlue.prototype = {
var bookmarksMenuFolder = bmsvc.bookmarksMenuFolder;
var unfiledBookmarksFolder = bmsvc.unfiledBookmarksFolder;
var toolbarFolder = bmsvc.toolbarFolder;
var tagsFolder = bmsvc.tagsFolder;
var defaultIndex = bmsvc.DEFAULT_INDEX;
// index = 0, make it the first folder
@ -574,14 +573,11 @@ BrowserGlue.prototype = {
var sep = bmsvc.insertSeparator(placesFolder, defaultIndex);
var recentTagsItem = bmsvc.insertBookmark(placesFolder,
this._uri("place:folder=" + tagsFolder +
"&group=" + Ci.nsINavHistoryQueryOptions.GROUP_BY_FOLDER +
"&queryType=" + Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
"&applyOptionsToContainers=1" +
"&sort=" +
Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
this._uri("place:"+
"type=" + Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY +
"&sort=" + Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
"&maxResults=" + maxResults),
defaultIndex, recentTagsTitle);
defaultIndex, recentTagsTitle);
}
};

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

@ -413,6 +413,17 @@ PlacesController.prototype = {
switch(nodeType) {
case Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY:
nodeData["query"] = true;
if (node.parent) {
switch (asQuery(node.parent).queryOptions.resultType) {
case Ci.nsINavHistoryQueryOptions.RESULTS_AS_SITE_QUERY:
nodeData["host"] = true;
break;
case Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_SITE_QUERY:
case Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_QUERY:
nodeData["day"] = true;
break;
}
}
break;
case Ci.nsINavHistoryResultNode.RESULT_TYPE_DYNAMIC_CONTAINER:
nodeData["dynamiccontainer"] = true;
@ -421,9 +432,6 @@ PlacesController.prototype = {
case Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT:
nodeData["folder"] = true;
break;
case Ci.nsINavHistoryResultNode.RESULT_TYPE_HOST:
nodeData["host"] = true;
break;
case Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR:
nodeData["separator"] = true;
break;
@ -442,8 +450,6 @@ PlacesController.prototype = {
nodeData["livemarkChild"] = true;
}
break;
case Ci.nsINavHistoryResultNode.RESULT_TYPE_DAY:
nodeData["day"] = true;
}
// Mutability is whether or not a container can have selected items
@ -903,14 +909,16 @@ PlacesController.prototype = {
// day nodes have time property set to the last day in the interval
var endDate = node.time;
// if this is not the last day container, then beginDate
// is the time property of the next day container
for (var j = 0; j < root.childCount-1 && !beginDate; ++j) {
if (root.getChild(j) != node)
continue;
var nextNode = root.getChild(j+1);
beginDate = nextNode.time
}
var nodeIdx = 0;
var cc = root.childCount;
// Find index of current day node
while (nodeIdx < cc && root.getChild(nodeIdx) != node)
++nodeIdx;
// We have an older day
if (nodeIdx+1 < cc)
beginDate = root.getChild(nodeIdx+1).time;
// we want to exclude beginDate from the removal
bhist.removePagesByTimeframe(beginDate+1, endDate);

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

@ -114,7 +114,6 @@ function searchHistory(aInput)
const NHQO = Ci.nsINavHistoryQueryOptions;
var sortingMode;
var groups = [];
var resultType;
if (aInput) {
@ -132,22 +131,20 @@ function searchHistory(aInput)
resultType = NHQO.RESULTS_AS_URI;
sortingMode = NHQO.SORT_BY_DATE_DESCENDING;
break;
case "dayandsite": // fall through
groups.push(NHQO.GROUP_BY_DAY);
case "dayandsite":
resultType = NHQO.RESULTS_AS_DATE_SITE_QUERY;
break;
case "site":
groups.push(NHQO.GROUP_BY_HOST);
resultType = NHQO.RESULTS_AS_VISIT;
resultType = NHQO.RESULTS_AS_SITE_QUERY;
sortingMode = NHQO.SORT_BY_TITLE_ASCENDING;
break;
case "day":
default:
resultType = NHQO.RESULTS_AS_VISIT;
groups.push(NHQO.GROUP_BY_DAY);
sortingMode = NHQO.SORT_BY_TITLE_ASCENDING;
resultType = NHQO.RESULTS_AS_DATE_QUERY;
break;
}
}
options.setGroupingMode(groups, groups.length);
options.sortingMode = sortingMode;
options.resultType = resultType;

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

@ -97,15 +97,6 @@
var query = PlacesUtils.history.getNewQuery();
query.searchTerms = filterString;
// Remove "group by folder" from the options list, because
// nsNavHistory::RecursiveGroup doesn't support it.
function isFolderGrouping(grouping, index, ary) {
return grouping != Ci.nsINavHistoryQueryOptions.GROUP_BY_FOLDER;
}
var groupings = options.getGroupingMode({});
var folderGroupings = groupings.filter(isFolderGrouping);
options.setGroupingMode(folderGroupings, folderGroupings.length);
if (folderRestrict) {
query.setFolders(folderRestrict, folderRestrict.length);
options.queryType = options.QUERY_TYPE_BOOKMARKS;

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

@ -85,6 +85,13 @@ PlacesTreeView.prototype = {
if (this._tree && this._result)
this.sortingChanged(this._result.sortingMode);
var qoInt = Ci.nsINavHistoryQueryOptions;
var options = asQuery(this._result.root).queryOptions;
this._showQueryAsFolder = (options &&
(options.resultType == qoInt.RESULTS_AS_DATE_QUERY ||
options.resultType == qoInt.RESULTS_AS_SITE_QUERY ||
options.resultType == qoInt.RESULTS_AS_DATE_SITE_QUERY));
// if there is no tree, BuildVisibleList will clear everything for us
this._buildVisibleList();
},
@ -109,14 +116,6 @@ PlacesTreeView.prototype = {
sortType != nsINavHistoryQueryOptions::SORT_BY_DATE_DESCENDING)
return; // not date sorting
// showing sessions only makes sense if we are grouping by date
// any other grouping (or recursive grouping) doesn't make sense
var groupings = options.getGroupingMode({});
for (var i=0; i < groupings.length; i++) {
if (groupings[i] != Ci.nsINavHistoryQueryOptions.GROUP_BY_DAY)
return; // non-time-based grouping
}
this._showSessions = true;
},
@ -200,26 +199,6 @@ PlacesTreeView.prototype = {
var curChild = aContainer.getChild(i);
var curChildType = curChild.type;
// collapse all duplicates starting from here
if (this._collapseDuplicates) {
var showThis = { value: false };
while (i < cc - 1 &&
this._canCollapseDuplicates(curChild, aContainer.getChild(i+1),
showThis)) {
if (showThis.value) {
// collapse the first and use the second
curChild.viewIndex = -1;
curChild = aContainer.getChild(i+1);
curChildType = curChild.type;
}
else {
// collapse the second and use the first
aContainer.getChild(i+1).viewIndex = -1;
}
i++;
}
}
// don't display separators when sorted
if (curChildType == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR) {
if (this._result.sortingMode !=
@ -418,30 +397,6 @@ PlacesTreeView.prototype = {
}
},
/**
* This returns true if the two results can be collapsed as duplicates.
* aShowThisOne will be either 0 or 1, indicating which of the
* duplicates should be shown.
*/
_canCollapseDuplicates:
function PTV__canCollapseDuplicate(aTop, aNext, aShowThisOne) {
if (!this._collapseDuplicates)
return false;
if (!PlacesUtils.nodeIsVisit(aTop) ||
!PlacesUtils.nodeIsVisit(aNext))
return false; // only collapse two visits
asVisit(aTop);
asVisit(aNext);
if (aTop.uri != aNext.uri)
return false; // don't collapse nonmatching URIs
// now we know we want to collapse, show the one with the more recent time
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);
@ -600,44 +555,6 @@ PlacesTreeView.prototype = {
}
}
// Try collapsing with the previous node. Note that we do not have to try
// to redraw the surrounding rows (which we normally would because session
// boundaries may have changed) because when an item is merged, it will
// always be in the same session.
var showThis = { value: true };
if (newViewIndex > 0 &&
this._canCollapseDuplicates
(this._visibleElements[newViewIndex - 1], aItem, showThis)) {
if (!showThis.value) {
// new node is invisible, collapsed with previous one
aItem.viewIndex = -1;
}
else {
// new node replaces the previous
this.itemReplaced(aParent, this._visibleElements[newViewIndex - 1],
aItem, 0);
}
return;
}
// try collapsing with the next node (which is currently at the same
// index we are trying to insert at)
if (newViewIndex < this._visibleElements.length &&
this._canCollapseDuplicates(aItem, this._visibleElements[newViewIndex],
showThis)) {
if (!showThis.value) {
// new node replaces the next node
this.itemReplaced(aParent, this._visibleElements[newViewIndex], aItem,
0);
}
else {
// new node is invisible, replaced by next one
aItem.viewIndex = -1;
}
return;
}
// no collapsing, insert new item
aItem.viewIndex = newViewIndex;
this._visibleElements.splice(newViewIndex, 0, aItem);
for (var i = newViewIndex + 1;
@ -668,40 +585,14 @@ PlacesTreeView.prototype = {
// this may have been a container, in which case it has a lot of rows
var count = this._countVisibleRowsForItem(aItem);
// We really want tail recursion here, since we sometimes do another
// remove after this when duplicates are being collapsed. This loop
// emulates that.
while (true) {
if (oldViewIndex > this._visibleElements.length)
throw("Trying to remove an item with an invalid viewIndex");
if (oldViewIndex > this._visibleElements.length)
throw("Trying to remove an item with an invalid viewIndex");
this._visibleElements.splice(oldViewIndex, count);
for (var i = oldViewIndex; i < this._visibleElements.length; i++)
this._visibleElements[i].viewIndex = i;
this._visibleElements.splice(oldViewIndex, count);
for (var i = oldViewIndex; i < this._visibleElements.length; i++)
this._visibleElements[i].viewIndex = i;
this._tree.rowCountChanged(oldViewIndex, -count);
// the removal might have put two things together that should be collapsed
if (oldViewIndex > 0 &&
oldViewIndex < this._visibleElements.length) {
var showThisOne = { value: true };
if (this._canCollapseDuplicates
(this._visibleElements[oldViewIndex - 1],
this._visibleElements[oldViewIndex], showThisOne))
{
// Fake-tail-recurse to the beginning of this function to
// remove the collapsed row. Note that we need to set the
// visible index to -1 before looping because we can never
// touch the row we're removing (callers may have already
// destroyed it).
oldViewIndex = oldViewIndex - 1 + (showThisOne.value ? 1 : 0);
this._visibleElements[oldViewIndex].viewIndex = -1;
count = 1; // next time remove one row
continue;
}
}
break; // normal path: just remove once
}
this._tree.rowCountChanged(oldViewIndex, -count);
// redraw parent because twisty may have changed
if (!aParent.hasChildren)
@ -917,22 +808,6 @@ PlacesTreeView.prototype = {
return val;
},
// nsINavHistoryResultTreeViewer
get collapseDuplicates() {
return this._collapseDuplicates;
},
set collapseDuplicates(val) {
if (this._collapseDuplicates == val)
return val; // no change;
this._collapseDuplicates = val;
if (this._tree && this._result)
this.invalidateAll();
return val;
},
nodeForTreeIndex: function PTV_nodeForTreeIndex(aIndex) {
if (aIndex > this._visibleElements.length)
throw Cr.NS_ERROR_INVALID_ARG;
@ -1007,10 +882,12 @@ PlacesTreeView.prototype = {
var nodeType = node.type;
if (PlacesUtils.containerTypes.indexOf(nodeType) != -1) {
if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY)
if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY) {
aProperties.AppendElement(this._getAtomFor("query"));
else if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER ||
nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT) {
if (this._showQueryAsFolder)
aProperties.AppendElement(this._getAtomFor("folder"));
} else if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER ||
nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT) {
if (PlacesUtils.annotations.itemHasAnnotation(node.itemId,
LMANNO_FEEDURI))
aProperties.AppendElement(this._getAtomFor("livemark"));
@ -1467,7 +1344,6 @@ function PlacesTreeView(aShowRoot, aFlatList, aOnOpenFlatContainer) {
this._tree = null;
this._result = null;
this._collapseDuplicates = true;
this._showSessions = false;
this._selection = null;
this._visibleElements = [];

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

@ -349,7 +349,10 @@ var PlacesUtils = {
*/
nodeIsHost: function PU_nodeIsHost(aNode) {
NS_ASSERT(aNode, "null node");
return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_HOST;
return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY &&
aNode.parent &&
asQuery(aNode.parent).queryOptions.resultType ==
Ci.nsINavHistoryQueryOptions.RESULTS_AS_SITE_QUERY;
},
/**
@ -359,7 +362,13 @@ var PlacesUtils = {
* @returns true if the node is a day container, false otherwise
*/
nodeIsDay: function PU_nodeIsDay(aNode) {
return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_DAY;
NS_ASSERT(aNode, "null node");
var resultType;
return aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY &&
aNode.parent &&
((resultType = asQuery(aNode.parent).queryOptions.resultType) ==
Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_QUERY ||
resultType == Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_SITE_QUERY);
},
/**
@ -371,8 +380,6 @@ var PlacesUtils = {
containerTypes: [Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER,
Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT,
Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY,
Ci.nsINavHistoryResultNode.RESULT_TYPE_HOST,
Ci.nsINavHistoryResultNode.RESULT_TYPE_DAY,
Ci.nsINavHistoryResultNode.RESULT_TYPE_DYNAMIC_CONTAINER],
nodeIsContainer: function PU_nodeIsContainer(aNode) {
NS_ASSERT(aNode, "null node");
@ -1666,11 +1673,8 @@ var PlacesUtils = {
// Include visible url nodes only
let child = aNode.getChild(i);
if (this.nodeIsURI(child)) {
// If the node contents is visible, add the uri only if its node is
// visible. Otherwise follow viewer's collapseDuplicates property,
// default to true
// If the node contents is visible, add the uri
if ((wasOpen && oldViewer && child.viewIndex != -1) ||
(oldViewer && !oldViewer.collapseDuplicates) ||
urls.indexOf(child.uri) == -1) {
urls.push({ uri: child.uri,
isBookmark: this.nodeIsBookmark(child) });

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

@ -50,6 +50,12 @@ treechildren::-moz-tree-image(title, query) {
-moz-image-region: auto;
}
/* We want some queries to look like ordinary folders. This must come
after the (title, query) selector, or it would get overridden. */
treechildren::-moz-tree-image(title, query, folder) {
list-style-image: url("moz-icon://stock/gtk-directory?size=menu");
}
treechildren::-moz-tree-row(session-start) {
border-top:1px dotted ThreeDShadow;
font-weight: bold;

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

@ -135,6 +135,14 @@ treechildren::-moz-tree-image(query) {
list-style-image: url("chrome://browser/skin/places/query.png");
}
/* We want some queries to look like ordinary folders. This must come
after the (title, query) selector, or it would get overridden. */
treechildren::-moz-tree-image(title, query, folder),
treechildren::-moz-tree-image(title, query, folder, open) {
list-style-image: url("chrome://global/skin/tree/folder.png");
-moz-image-region: rect(0, 16px, 16px, 0);
}
/* FIXME this should make the date field invisible, but only does it for
unselected items and maybe won't work for different color schemes. */
treechildren::-moz-tree-cell-text(date, session-continue) {

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

@ -58,6 +58,17 @@ treechildren::-moz-tree-image(title, query) {
-moz-image-region: auto;
}
/* We want some queries to look like ordinary folders. This must come
after the (title, query) selector, or it would get overridden. */
treechildren::-moz-tree-image(title, query, folder) {
list-style-image: url("chrome://global/skin/icons/folder-item.png");
-moz-image-region: rect(0px, 32px, 16px, 16px);
}
treechildren::-moz-tree-image(title, query, folder, open) {
-moz-image-region: rect(16px, 32px, 32px, 16px);
}
treechildren::-moz-tree-row(session-start) {
border-top:1px dotted ThreeDShadow;
font-weight: bold;

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

@ -79,17 +79,15 @@ interface nsINavHistoryResultNode : nsISupports
const unsigned long RESULT_TYPE_URI = 0; // nsINavHistoryResultNode
const unsigned long RESULT_TYPE_VISIT = 1; // nsINavHistoryVisitResultNode
const unsigned long RESULT_TYPE_FULL_VISIT = 2; // nsINavHistoryFullVisitResultNode
const unsigned long RESULT_TYPE_HOST = 3; // nsINavHistoryContainerResultNode
const unsigned long RESULT_TYPE_DYNAMIC_CONTAINER = 4; // nsINavHistoryContainerResultNode
const unsigned long RESULT_TYPE_QUERY = 5; // nsINavHistoryQueryResultNode
const unsigned long RESULT_TYPE_FOLDER = 6; // nsINavHistoryQueryResultNode
const unsigned long RESULT_TYPE_SEPARATOR = 7; // nsINavHistoryResultNode
const unsigned long RESULT_TYPE_DAY = 8; // nsINavHistoryContainerResultNode
const unsigned long RESULT_TYPE_FOLDER_SHORTCUT = 9; // nsINavHistoryQueryResultNode
readonly attribute unsigned long type;
/**
* Title of the web page, or of the node's grouping (day, host, folder, etc)
* Title of the web page, or of the node's query (day, host, folder, etc)
*/
readonly attribute AUTF8String title;
@ -113,8 +111,8 @@ interface nsINavHistoryResultNode : nsISupports
* For hosts, or other node types with children, this is the most recent
* access time for any of the children.
*
* For days, this is midnight on the morning of the day in question in
* UTC time.
* For days queries this is the respective endTime - a maximum possible
* visit time to fit in the day range.
*/
readonly attribute PRTime time;
@ -340,8 +338,8 @@ interface nsINavHistoryContainerResultNode : nsINavHistoryResultNode
* container API. TO BE CALLED FROM nsIDynamicContainer::OnContainerOpening()
* ONLY, and only for non-bookmark-folder containers.
*
* aContainerType should be either RESULT_TYPE_HOST or
* RESULT_TYPE_DYNAMIC_CONTAINER. When type is dynamic container you must
* aContainerType should be RESULT_TYPE_DYNAMIC_CONTAINER.
* When type is dynamic container you must
* specify a dynamic container type, otherwise, the dynamic container type must
* be null. Use appendQueryNode and appendFolderNode for the other container
* types.
@ -500,8 +498,7 @@ interface nsINavHistoryResultViewer : nsISupports
/**
* Called when something significant is changing that requires everything
* to be recomputed. For example, changing sorting or changing collapse
* duplicates can affect every row.
* to be recomputed. For example, changing sorting can affect every row.
*/
void invalidateAll();
@ -537,24 +534,9 @@ interface nsINavHistoryResultViewer : nsISupports
* object, attach it to a result, never attach it to a tree, and forget about
* it, it will leak!
*/
[scriptable, uuid(e0ce87df-8b77-407b-a52b-7510eab14fb5)]
[scriptable, uuid(fa77e4e9-9fc8-45d2-9507-0fe4f0602505)]
interface nsINavHistoryResultTreeViewer : nsINavHistoryResultViewer
{
/**
* Controls whether duplicate adjacent elements are collapsed into a single
* item in the tree. This prevents you from seeing multiple entries for
* things when you have selected to get visits. When you sort by date, the
* multiple entries will then appear because they will be separated (unless
* you clicked reload a bunch of times in a row). If you know you'll only
* ever want one entry per site, you should ask for URIs back instead of
* visits so it will be more efficient.
* Default = true
*
* Changing this value is somewhat heavyweight since it will force a tree
* refresh.
*/
attribute boolean collapseDuplicates;
/**
* This allows you to get at the real node for a given row index. This is
* only valid when a tree is attached.
@ -637,7 +619,7 @@ interface nsINavHistoryResult : nsISupports
* DANGER! If you are in the middle of a batch transaction, there may be a
* database transaction active. You can still access the DB, but be careful.
*/
[scriptable, uuid(849e2184-3dee-416f-91cd-6a619ca49d1c)]
[scriptable, uuid(eacb76eb-3eeb-419b-a963-9b3a9d65f356)]
interface nsINavHistoryObserver : nsISupports
{
/**
@ -666,10 +648,14 @@ interface nsINavHistoryObserver : nsISupports
* @param aSessionID The ID of one connected sequence of visits.
* @param aReferringID The ID of the visit the user came from. 0 if empty.
* @param aTransitionType One of nsINavHistory.TRANSITION_*
* @param aAdded Incremented by query nodes when the visited uri
* belongs to them. If no such query exists, the
* history result creates a new query node dynamically.
* It is used in places views only and can be ignored.
*/
void onVisit(in nsIURI aURI, in long long aVisitID, in PRTime aTime,
in long long aSessionID, in long long aReferringID,
in unsigned long aTransitionType);
in unsigned long aTransitionType, out unsigned long aAdded);
/**
* Called whenever either the "real" title or the custom title of the page
@ -868,41 +854,9 @@ interface nsINavHistoryQuery : nsISupports
/**
* This object represents the global options for executing a query.
*/
[scriptable, uuid(ff73bf85-2755-4c1a-a48d-8c91ccca770e)]
[scriptable, uuid(a46c132e-35f3-4e1e-bb3d-4e3043657248)]
interface nsINavHistoryQueryOptions : nsISupports
{
/**
* Grouping by day. The results will be an array of nsINavHistoryResults with
* type = RESULT_TYPE_DAY, one for each day where there are results. These
* will have children of corresponding to the search results of that day.
*/
const unsigned short GROUP_BY_DAY = 0;
/**
* Grouping by exact host. The results will be an array of nsINavHistoryResults
* with type = RESULT_TYPE_HOST, one for each unique host (for example,
* "bugzilla.mozilla.org" and "www.mozilla.org" will be separate). The
* children of these will correspond to the results for each host.
*/
const unsigned short GROUP_BY_HOST = 1;
/**
* Grouping by toplevel domain. Similar to GROUP_BY_HOST, but there will be
* one result for each toplevel domain (mozilla.org will be one entry, and
* will contain results including, for example, "bugzilla.mozilla.org" and
* "www.mozilla.org").
*/
const unsigned short GROUP_BY_DOMAIN = 2;
/**
* Group by bookmark folders. Results from the query are grouped in folders
* containers. This option requires there to be at least one parent folder specified
* via nsINavHistoryQuery::setFolders. Note, since the folder containers are built
* from the items that match the results that we are grouping, you will not get any
* folders (when grouping by folder) with zero items.
*/
const unsigned short GROUP_BY_FOLDER = 3;
/**
* You can ask for the results to be pre-sorted. Since the DB has indices
* of many items, it can produce sorted results almost for free. These should
@ -928,8 +882,6 @@ interface nsINavHistoryQueryOptions : nsISupports
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_COUNT_ASCENDING = 15;
const unsigned short SORT_BY_COUNT_DESCENDING = 16;
const unsigned short SORT_BY_TAGS_ASCENDING = 17;
const unsigned short SORT_BY_TAGS_DESCENDING = 18;
const unsigned short SORT_BY_ANNOTATION_ASCENDING = 19;
@ -958,18 +910,32 @@ interface nsINavHistoryQueryOptions : nsISupports
const unsigned short RESULTS_AS_FULL_VISIT = 2;
/**
* The grouping mode to be used for this query.
* Grouping mode is an array of GROUP_BY_* values that specifies the
* structure of the tree you want. For example, an array consisting of
* [GROUP_BY_DAY, GROUP_BY_DOMAIN] will give you a tree whose first level is
* a list of days, and whose second level is a list of domains, and whose
* third level is a list of pages in those domains.
* If you don't want grouping, you can specify an empty array.
* This returns query nodes for each predefined date range where we
* had visits. The node contains information how to load its content:
* - visits for the given date range will be loaded.
*/
void getGroupingMode(out unsigned long groupCount,
[retval,array,size_is(groupCount)] out unsigned short groupingMode);
void setGroupingMode([const,array,size_is(groupCount)] in unsigned short groupingMode,
in unsigned long groupCount);
const unsigned short RESULTS_AS_DATE_QUERY = 3;
/**
* This returns nsINavHistoryQueryResultNode nodes for each site where we
* have visits. The node contains information how to load its content:
* - last visit for each url in the given host will be loaded.
*/
const unsigned short RESULTS_AS_SITE_QUERY = 4;
/**
* This returns nsINavHistoryQueryResultNode nodes for each day where we
* have visits. The node contains information how to load its content:
* - list of hosts visited in the given period will be loaded.
*/
const unsigned short RESULTS_AS_DATE_SITE_QUERY = 5;
/**
* This returns nsINavHistoryQueryResultNode nodes for each tag.
* The node contains information how to load its content:
* - list of bookmarks with the given tag will be loaded.
*/
const unsigned short RESULTS_AS_TAG_QUERY = 6;
/**
* The sorting mode to be used for this query.
@ -1063,11 +1029,6 @@ interface nsINavHistoryQueryOptions : nsISupports
*/
attribute unsigned long maxResults;
/**
* only apply our query options to the containers
*/
attribute boolean applyOptionsToContainers;
const unsigned short QUERY_TYPE_HISTORY = 0;
const unsigned short QUERY_TYPE_BOOKMARKS = 1;
const unsigned short QUERY_TYPE_UNIFIED = 2;

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

@ -2608,7 +2608,7 @@ nsNavBookmarks::OnEndUpdateBatch()
NS_IMETHODIMP
nsNavBookmarks::OnVisit(nsIURI *aURI, PRInt64 aVisitID, PRTime aTime,
PRInt64 aSessionID, PRInt64 aReferringID,
PRUint32 aTransitionType)
PRUint32 aTransitionType, PRUint32* aAdded)
{
// If the page is bookmarked, we need to notify observers
PRBool bookmarked = PR_FALSE;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -94,6 +94,7 @@
#define QUERYUPDATE_SIMPLE 1
#define QUERYUPDATE_COMPLEX 2
#define QUERYUPDATE_COMPLEX_WITH_BOOKMARKS 3
#define QUERYUPDATE_HOST 4
// this is a work-around for a problem with the optimizer of sqlite
// A sub-select on MAX(visit_date) is slower than this query with our indexes
@ -110,6 +111,7 @@ class nsNavBookmarks;
class QueryKeyValuePair;
class nsIEffectiveTLDService;
class nsIIDNService;
class PlacesSQLQueryBuilder;
// nsNavHistory
@ -126,6 +128,8 @@ class nsNavHistory : public nsSupportsWeakReference,
{
friend class AutoCompleteIntermediateResultSet;
friend class AutoCompleteResultComparator;
friend class PlacesSQLQueryBuilder;
public:
nsNavHistory();
@ -237,6 +241,7 @@ public:
{ return mCollation; }
nsIDateTimeFormat* GetDateFormatter()
{ return mDateFormatter; }
void GetStringFromName(const PRUnichar* aName, nsACString& aResult);
// returns true if history has been disabled
PRBool IsHistoryDisabled() { return mExpireDaysMax == 0; }
@ -319,10 +324,6 @@ public:
void DomainNameFromURI(nsIURI* aURI,
nsACString& aDomainName);
static PRTime NormalizeTime(PRUint32 aRelative, PRTime aOffset);
nsresult RecursiveGroup(nsNavHistoryQueryResultNode *aResultNode,
const nsCOMArray<nsNavHistoryResultNode>& aSource,
const PRUint16* aGroupingMode, PRUint32 aGroupCount,
nsCOMArray<nsNavHistoryResultNode>* aDest);
// Don't use these directly, inside nsNavHistory use UpdateBatchScoper,
// else use nsINavHistoryService::RunInBatchMode
@ -455,6 +456,7 @@ protected:
* The database was migrated to a new version.
*/
nsresult InitDB(PRInt16 *aMadeChanges);
nsresult InitFunctions();
nsresult InitStatements();
nsresult ForceMigrateBookmarksDB(mozIStorageConnection *aDBConn);
nsresult MigrateV3Up(mozIStorageConnection *aDBConn);
@ -564,14 +566,14 @@ protected:
nsresult ConstructQueryString(const nsCOMArray<nsNavHistoryQuery>& aQueries,
nsNavHistoryQueryOptions *aOptions,
nsCString &queryString);
nsCString& queryString,
PRBool& aParamsPresent);
nsresult QueryToSelectClause(nsNavHistoryQuery* aQuery,
nsNavHistoryQueryOptions* aOptions,
PRInt32 aStartParameter,
nsCString* aClause,
PRInt32* aParamCount,
const nsACString& aCommonConditions);
PRInt32* aParamCount);
nsresult BindQueryClauseParameters(mozIStorageStatement* statement,
PRInt32 aStartParameter,
nsNavHistoryQuery* aQuery,
@ -585,25 +587,10 @@ protected:
void GetAgeInDaysString(PRInt32 aInt, const PRUnichar *aName,
nsACString& aResult);
void GetStringFromName(const PRUnichar *aName, nsACString& aResult);
void TitleForDomain(const nsCString& domain, nsACString& aTitle);
nsresult SetPageTitleInternal(nsIURI* aURI, const nsAString& aTitle);
nsresult GroupByDay(nsNavHistoryQueryResultNode *aResultNode,
const nsCOMArray<nsNavHistoryResultNode>& aSource,
nsCOMArray<nsNavHistoryResultNode>* aDest);
nsresult GroupByHost(nsNavHistoryQueryResultNode *aResultNode,
const nsCOMArray<nsNavHistoryResultNode>& aSource,
nsCOMArray<nsNavHistoryResultNode>* aDest,
PRBool aIsDomain);
nsresult GroupByFolder(nsNavHistoryQueryResultNode *aResultNode,
const nsCOMArray<nsNavHistoryResultNode>& aSource,
nsCOMArray<nsNavHistoryResultNode>* aDest);
PRBool URIHasTag(const nsACString& aURISpec, const nsAString& aTag);
PRBool URIHasAnyTagFromTerms(const nsACString& aURISpec, const nsStringArray& aTerms);
void CreateTermsFromTokens(const nsStringArray& aTagTokens, nsStringArray& aTerms);

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

@ -167,7 +167,6 @@ static void SetOptionsKeyUint32(const nsCString& aValue,
#define QUERYKEY_FORCE_ORIGINAL_TITLE "originalTitle"
#define QUERYKEY_INCLUDE_HIDDEN "includeHidden"
#define QUERYKEY_SHOW_SESSIONS "showSessions"
#define QUERYKEY_APPLY_OPTIONS_TO_CONTAINERS "applyOptionsToContainers"
#define QUERYKEY_MAX_RESULTS "maxResults"
#define QUERYKEY_QUERY_TYPE "queryType"
@ -417,15 +416,6 @@ nsNavHistory::QueriesToQueryString(nsINavHistoryQuery **aQueries,
nsMemory::Free(folders);
}
// grouping
PRUint32 groupCount;
const PRUint16* groups = options->GroupingMode(&groupCount);
for (PRUint32 i = 0; i < groupCount; i ++) {
AppendAmpersandIfNonempty(queryString);
queryString += NS_LITERAL_CSTRING(QUERYKEY_GROUP "=");
AppendInt16(queryString, groups[i]);
}
// sorting
if (options->SortingMode() != nsINavHistoryQueryOptions::SORT_BY_NONE) {
AppendAmpersandIfNonempty(queryString);
@ -501,12 +491,6 @@ nsNavHistory::QueriesToQueryString(nsINavHistoryQuery **aQueries,
queryString += NS_LITERAL_CSTRING(QUERYKEY_SHOW_SESSIONS "=1");
}
// apply options to containers
if (options->ApplyOptionsToContainers()) {
AppendAmpersandIfNonempty(queryString);
queryString += NS_LITERAL_CSTRING(QUERYKEY_APPLY_OPTIONS_TO_CONTAINERS "=1");
}
// max results
if (options->MaxResults()) {
AppendAmpersandIfNonempty(queryString);
@ -577,7 +561,6 @@ nsNavHistory::TokensToQueries(const nsTArray<QueryKeyValuePair>& aTokens,
if (aTokens.Length() == 0)
return NS_OK; // nothing to do
nsTArray<PRUint16> groups;
nsTArray<PRInt64> folders;
nsCOMPtr<nsNavHistoryQuery> query(new nsNavHistoryQuery());
@ -695,15 +678,6 @@ nsNavHistory::TokensToQueries(const nsTArray<QueryKeyValuePair>& aTokens,
if (! aQueries->AppendObject(query))
return NS_ERROR_OUT_OF_MEMORY;
// grouping
} else if (kvp.key.EqualsLiteral(QUERYKEY_GROUP)) {
PRUint32 grouping = kvp.value.ToInteger((PRInt32*)&rv);
if (NS_SUCCEEDED(rv)) {
groups.AppendElement(grouping);
} else {
NS_WARNING("Bad number for grouping in query");
}
// sorting mode
} else if (kvp.key.EqualsLiteral(QUERYKEY_SORT)) {
SetOptionsKeyUint16(kvp.value, aOptions,
@ -754,10 +728,6 @@ nsNavHistory::TokensToQueries(const nsTArray<QueryKeyValuePair>& aTokens,
} else if (kvp.key.EqualsLiteral(QUERYKEY_SHOW_SESSIONS)) {
SetOptionsKeyBool(kvp.value, aOptions,
&nsINavHistoryQueryOptions::SetShowSessions);
// apply options to containers
} else if (kvp.key.EqualsLiteral(QUERYKEY_APPLY_OPTIONS_TO_CONTAINERS)) {
SetOptionsKeyBool(kvp.value, aOptions,
&nsINavHistoryQueryOptions::SetApplyOptionsToContainers);
// max results
} else if (kvp.key.EqualsLiteral(QUERYKEY_MAX_RESULTS)) {
SetOptionsKeyUint32(kvp.value, aOptions,
@ -775,7 +745,6 @@ nsNavHistory::TokensToQueries(const nsTArray<QueryKeyValuePair>& aTokens,
if (folders.Length() != 0)
query->SetFolders(folders.Elements(), folders.Length());
aOptions->SetGroupingMode(groups.Elements(), groups.Length());
return NS_OK;
}
@ -1097,54 +1066,6 @@ NS_IMETHODIMP nsNavHistoryQuery::Clone(nsINavHistoryQuery** _retval)
// nsNavHistoryQueryOptions
NS_IMPL_ISUPPORTS2(nsNavHistoryQueryOptions, nsNavHistoryQueryOptions, nsINavHistoryQueryOptions)
NS_IMETHODIMP
nsNavHistoryQueryOptions::GetGroupingMode(PRUint32 *aGroupCount,
PRUint16** aGroupingMode)
{
if (mGroupCount == 0) {
*aGroupCount = 0;
*aGroupingMode = nsnull;
return NS_OK;
}
*aGroupingMode = static_cast<PRUint16*>
(nsMemory::Alloc(sizeof(PRUint16) * mGroupCount));
if (! *aGroupingMode)
return NS_ERROR_OUT_OF_MEMORY;
for(PRUint32 i = 0; i < mGroupCount; i ++)
(*aGroupingMode)[i] = mGroupings[i];
*aGroupCount = mGroupCount;
return NS_OK;
}
NS_IMETHODIMP
nsNavHistoryQueryOptions::SetGroupingMode(const PRUint16 *aGroupingMode,
PRUint32 aGroupCount)
{
// check input
PRUint32 i;
for (i = 0; i < aGroupCount; i ++) {
if (aGroupingMode[i] > GROUP_BY_FOLDER)
return NS_ERROR_INVALID_ARG;
}
if (mGroupings) {
delete[] mGroupings;
mGroupings = nsnull;
mGroupCount = 0;
}
if (! aGroupCount)
return NS_OK;
mGroupings = new PRUint16[aGroupCount];
NS_ENSURE_TRUE(mGroupings, NS_ERROR_OUT_OF_MEMORY);
for (i = 0; i < aGroupCount; ++i) {
mGroupings[i] = aGroupingMode[i];
}
mGroupCount = aGroupCount;
return NS_OK;
}
// sortingMode
NS_IMETHODIMP
nsNavHistoryQueryOptions::GetSortingMode(PRUint16* aMode)
@ -1184,7 +1105,7 @@ nsNavHistoryQueryOptions::GetResultType(PRUint16* aType)
NS_IMETHODIMP
nsNavHistoryQueryOptions::SetResultType(PRUint16 aType)
{
if (aType > RESULTS_AS_FULL_VISIT)
if (aType > RESULTS_AS_TAG_QUERY)
return NS_ERROR_INVALID_ARG;
mResultType = aType;
return NS_OK;
@ -1287,20 +1208,6 @@ nsNavHistoryQueryOptions::SetShowSessions(PRBool aShowSessions)
return NS_OK;
}
// applyOptionsToContainers
NS_IMETHODIMP
nsNavHistoryQueryOptions::GetApplyOptionsToContainers(PRBool* aApplyOptionsToContainers)
{
*aApplyOptionsToContainers = mApplyOptionsToContainers;
return NS_OK;
}
NS_IMETHODIMP
nsNavHistoryQueryOptions::SetApplyOptionsToContainers(PRBool aApplyOptionsToContainers)
{
mApplyOptionsToContainers = aApplyOptionsToContainers;
return NS_OK;
}
// maxResults
NS_IMETHODIMP
nsNavHistoryQueryOptions::GetMaxResults(PRUint32* aMaxResults)
@ -1349,21 +1256,9 @@ nsNavHistoryQueryOptions::Clone(nsNavHistoryQueryOptions **aResult)
nsRefPtr<nsNavHistoryQueryOptions> resultHolder(result);
result->mSort = mSort;
result->mResultType = mResultType;
result->mGroupCount = mGroupCount;
if (mGroupCount) {
result->mGroupings = new PRUint16[mGroupCount];
if (! result->mGroupings) {
return NS_ERROR_OUT_OF_MEMORY;
}
for (PRUint32 i = 0; i < mGroupCount; i ++)
result->mGroupings[i] = mGroupings[i];
} else {
result->mGroupCount = nsnull;
}
result->mExcludeItems = mExcludeItems;
result->mExcludeQueries = mExcludeQueries;
result->mShowSessions = mShowSessions;
result->mApplyOptionsToContainers = mApplyOptionsToContainers;
result->mExpandQueries = mExpandQueries;
result->mMaxResults = mMaxResults;
result->mQueryType = mQueryType;

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

@ -118,14 +118,12 @@ class nsNavHistoryQueryOptions : public nsINavHistoryQueryOptions
{
public:
nsNavHistoryQueryOptions() : mSort(0), mResultType(0),
mGroupCount(0), mGroupings(nsnull),
mExcludeItems(PR_FALSE),
mExcludeQueries(PR_FALSE),
mExcludeReadOnlyFolders(PR_FALSE),
mExpandQueries(PR_TRUE),
mIncludeHidden(PR_FALSE),
mShowSessions(PR_FALSE),
mApplyOptionsToContainers(PR_FALSE),
mMaxResults(0),
mQueryType(nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY)
{ }
@ -141,16 +139,12 @@ public:
PRUint16 SortingMode() const { return mSort; }
PRUint16 ResultType() const { return mResultType; }
const PRUint16* GroupingMode(PRUint32 *count) const {
*count = mGroupCount; return mGroupings;
}
PRBool ExcludeItems() const { return mExcludeItems; }
PRBool ExcludeQueries() const { return mExcludeQueries; }
PRBool ExcludeReadOnlyFolders() const { return mExcludeReadOnlyFolders; }
PRBool ExpandQueries() const { return mExpandQueries; }
PRBool IncludeHidden() const { return mIncludeHidden; }
PRBool ShowSessions() const { return mShowSessions; }
PRBool ApplyOptionsToContainers() const { return mApplyOptionsToContainers; }
PRUint32 MaxResults() const { return mMaxResults; }
PRUint16 QueryType() const { return mQueryType; }
@ -159,8 +153,6 @@ public:
private:
nsNavHistoryQueryOptions(const nsNavHistoryQueryOptions& other) {} // no copy
~nsNavHistoryQueryOptions() { delete[] mGroupings; }
// IF YOU ADD MORE ITEMS:
// * Add a new getter for C++ above if it makes sense
// * Add to the serialization code (see nsNavHistory::QueriesToQueryString())
@ -171,15 +163,12 @@ private:
nsCString mSortingAnnotation;
nsCString mParentAnnotationToExclude;
PRUint16 mResultType;
PRUint32 mGroupCount;
PRUint16 *mGroupings;
PRPackedBool mExcludeItems;
PRPackedBool mExcludeQueries;
PRPackedBool mExcludeReadOnlyFolders;
PRPackedBool mExpandQueries;
PRPackedBool mIncludeHidden;
PRPackedBool mShowSessions;
PRPackedBool mApplyOptionsToContainers;
PRUint32 mMaxResults;
PRUint16 mQueryType;
};

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

@ -373,6 +373,21 @@ nsNavHistoryContainerResultNode::nsNavHistoryContainerResultNode(
{
}
nsNavHistoryContainerResultNode::nsNavHistoryContainerResultNode(
const nsACString& aURI, const nsACString& aTitle,
PRTime aTime,
const nsACString& aIconURI, PRUint32 aContainerType, PRBool aReadOnly,
const nsACString& aDynamicContainerType,
nsNavHistoryQueryOptions* aOptions) :
nsNavHistoryResultNode(aURI, aTitle, 0, aTime, aIconURI),
mResult(nsnull),
mContainerType(aContainerType),
mExpanded(PR_FALSE),
mChildrenReadOnly(aReadOnly),
mDynamicContainerType(aDynamicContainerType),
mOptions(aOptions)
{
}
// nsNavHistoryContainerResultNode::OnRemoving
//
@ -526,8 +541,9 @@ nsNavHistoryContainerResultNode::CloseContainer(PRBool aUpdateView)
void
nsNavHistoryContainerResultNode::FillStats()
{
mAccessCount = 0;
mTime = 0;
PRUint32 accessCount = 0;
PRTime newTime = 0;
for (PRInt32 i = 0; i < mChildren.Count(); i ++) {
nsNavHistoryResultNode* node = mChildren[i];
node->mParent = this;
@ -537,12 +553,17 @@ nsNavHistoryContainerResultNode::FillStats()
container->mResult = mResult;
container->FillStats();
}
mAccessCount += node->mAccessCount;
accessCount += node->mAccessCount;
// this is how container nodes get sorted by date
// (of type nsINavHistoryResultNode::RESULT_TYPE_DAY, for example)
// The container gets the most recent time of the child nodes.
if (node->mTime > mTime)
mTime = node->mTime;
if (node->mTime > newTime)
newTime = node->mTime;
}
if (mExpanded) {
mAccessCount = accessCount;
if (!IsQuery() || newTime > mTime)
mTime = newTime;
}
}
@ -676,10 +697,6 @@ nsNavHistoryContainerResultNode::GetSortingComparator(PRUint16 aSortType)
return &SortComparison_LastModifiedLess;
case nsINavHistoryQueryOptions::SORT_BY_LASTMODIFIED_DESCENDING:
return &SortComparison_LastModifiedGreater;
case nsINavHistoryQueryOptions::SORT_BY_COUNT_ASCENDING:
return &SortComparison_CountLess;
case nsINavHistoryQueryOptions::SORT_BY_COUNT_DESCENDING:
return &SortComparison_CountGreater;
case nsINavHistoryQueryOptions::SORT_BY_TAGS_ASCENDING:
return &SortComparison_TagsLess;
case nsINavHistoryQueryOptions::SORT_BY_TAGS_DESCENDING:
@ -721,8 +738,11 @@ nsNavHistoryContainerResultNode::RecursiveSort(
PRUint32
nsNavHistoryContainerResultNode::FindInsertionPoint(
nsNavHistoryResultNode* aNode, SortComparator aComparator,
const char* aData)
const char* aData, PRBool* aItemExists)
{
if (aItemExists)
(*aItemExists) = PR_FALSE;
if (mChildren.Count() == 0)
return 0;
@ -730,10 +750,19 @@ nsNavHistoryContainerResultNode::FindInsertionPoint(
// The common case is the beginning or the end because this is used to insert
// new items that are added to history, which is usually sorted by date.
if (aComparator(aNode, mChildren[0], data) <= 0)
PRInt32 res;
res = aComparator(aNode, mChildren[0], data);
if (res <= 0) {
if (aItemExists && res == 0)
(*aItemExists) = PR_TRUE;
return 0;
if (aComparator(aNode, mChildren[mChildren.Count() - 1], data) >= 0)
}
res = aComparator(aNode, mChildren[mChildren.Count() - 1], data);
if (res >= 0) {
if (aItemExists && res == 0)
(*aItemExists) = PR_TRUE;
return mChildren.Count();
}
PRUint32 beginRange = 0; // inclusive
PRUint32 endRange = mChildren.Count(); // exclusive
@ -741,10 +770,15 @@ nsNavHistoryContainerResultNode::FindInsertionPoint(
if (beginRange == endRange)
return endRange;
PRUint32 center = beginRange + (endRange - beginRange) / 2;
if (aComparator(aNode, mChildren[center], data) <= 0)
PRInt32 res = aComparator(aNode, mChildren[center], data);
if (res <= 0) {
endRange = center; // left side
else
if (aItemExists && res == 0)
(*aItemExists) = PR_TRUE;
}
else {
beginRange = center + 1; // right site
}
}
}
@ -787,7 +821,7 @@ PRInt32 nsNavHistoryContainerResultNode::SortComparison_StringLess(
nsNavHistory* history = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(history, 0);
nsICollation* collation = history->GetCollation();
NS_ENSURE_TRUE(history, 0);
NS_ENSURE_TRUE(collation, 0);
PRInt32 res = 0;
collation->CompareString(nsICollation::kCollationCaseInSensitive, a, b, &res);
@ -821,18 +855,6 @@ PRInt32 PR_CALLBACK nsNavHistoryContainerResultNode::SortComparison_TitleLess(
PRUint32 aType;
a->GetType(&aType);
if (aType == nsINavHistoryResultNode::RESULT_TYPE_DAY) {
// for the history sidebar, when we do "View | By Date" or
// "View | By Date and Site" we sort by SORT_BY_TITLE_ASCENDING.
//
// so to make the day container show up in the desired order
// we need to compare by time, instead of by title.
//
// hard coding this isn't ideal, but we can't currently have
// one sort per grouping. see bug #359332 on that issue.
return -ComparePRTime(a->mTime, b->mTime);
}
PRInt32 value = SortComparison_StringLess(NS_ConvertUTF8toUTF16(a->mTitle),
NS_ConvertUTF8toUTF16(b->mTitle));
if (value == 0) {
@ -921,70 +943,6 @@ PRInt32 PR_CALLBACK nsNavHistoryContainerResultNode::SortComparison_LastModified
return -nsNavHistoryContainerResultNode::SortComparison_LastModifiedLess(a, b, closure);
}
// nsNavHistoryContainerResultNode::SortComparison_Count*
//
PRInt32 PR_CALLBACK nsNavHistoryContainerResultNode::SortComparison_CountLess(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure)
{
PRUint32 count1 = 0;
PRUint32 count2 = 0;
nsresult rv;
if (a->IsContainer()) {
nsNavHistoryResult* result = a->GetResult();
nsCOMPtr<nsINavHistoryResultViewer> viewer;
if (result) {
rv = result->GetViewer(getter_AddRefs(viewer));
if (NS_SUCCEEDED(rv))
result->SetViewer(nsnull);
}
rv = a->GetAsContainer()->SetContainerOpen(PR_TRUE);
if (NS_SUCCEEDED(rv))
rv = a->GetAsContainer()->GetChildCount(&count1);
if (NS_FAILED(rv))
count1 = 0;
(void)a->GetAsContainer()->SetContainerOpen(PR_FALSE);
if (result && viewer)
result->SetViewer(viewer);
}
if (b->IsContainer()) {
nsNavHistoryResult* result = a->GetResult();
nsCOMPtr<nsINavHistoryResultViewer> viewer;
if (result) {
rv = result->GetViewer(getter_AddRefs(viewer));
if (NS_SUCCEEDED(rv))
result->SetViewer(nsnull);
}
rv = b->GetAsContainer()->SetContainerOpen(PR_TRUE);
if (NS_SUCCEEDED(rv))
rv = b->GetAsContainer()->GetChildCount(&count2);
if (NS_FAILED(rv))
count2 = 0;
(void)b->GetAsContainer()->SetContainerOpen(PR_FALSE);
if (result && viewer)
result->SetViewer(viewer);
}
PRInt32 value = CompareIntegers(count1, count2);
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_CountGreater(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure)
{
return -nsNavHistoryContainerResultNode::SortComparison_CountLess(a, b, closure);
}
// nsNavHistoryContainerResultNode::SortComparison_URI*
//
// Certain types of parent nodes are treated specially because URIs are not
@ -1372,7 +1330,8 @@ nsNavHistoryContainerResultNode::InsertChildAt(nsNavHistoryResultNode* aNode,
nsresult
nsNavHistoryContainerResultNode::InsertSortedChild(
nsNavHistoryResultNode* aNode, PRBool aIsTemporary)
nsNavHistoryResultNode* aNode,
PRBool aIsTemporary, PRBool aIgnoreDuplicates)
{
if (mChildren.Count() == 0)
@ -1395,8 +1354,14 @@ nsNavHistoryContainerResultNode::InsertSortedChild(
nsCAutoString sortingAnnotation;
GetSortingAnnotation(sortingAnnotation);
return InsertChildAt(aNode, FindInsertionPoint(aNode, comparator, sortingAnnotation.get()),
aIsTemporary);
PRBool itemExists;
PRUint32 position = FindInsertionPoint(aNode, comparator,
sortingAnnotation.get(),
&itemExists);
if (aIgnoreDuplicates && itemExists)
return NS_OK;
return InsertChildAt(aNode, position, aIsTemporary);
}
return InsertChildAt(aNode, mChildren.Count(), aIsTemporary);
}
@ -1426,7 +1391,8 @@ nsNavHistoryContainerResultNode::EnsureItemPosition(PRUint32 aIndex) {
nsRefPtr<nsNavHistoryResultNode> node(mChildren[aIndex]);
mChildren.RemoveObjectAt(aIndex);
PRUint32 newIndex = FindInsertionPoint(node, comparator,sortAnno.get());
PRUint32 newIndex = FindInsertionPoint(
node, comparator,sortAnno.get(), nsnull);
mChildren.InsertObjectAt(node.get(), newIndex);
nsNavHistoryResult* result = GetResult();
@ -1440,9 +1406,8 @@ nsNavHistoryContainerResultNode::EnsureItemPosition(PRUint32 aIndex) {
// nsNavHistoryContainerResultNode::MergeResults
//
// This takes a fully grouped list of nodes and merges them into the
// current result set. Any containers that are added must already be
// sorted.
// This takes a list of nodes and merges them into the current result set.
// Any containers that are added must already be sorted.
//
// This assumes that the items in 'aAddition' are new visits or
// replacement URIs. We do not update visits.
@ -1628,12 +1593,6 @@ nsNavHistoryContainerResultNode::RecursiveFindURIs(PRBool aOnlyOne,
if (aOnlyOne)
return;
}
} else if (nsNavHistoryResultNode::IsTypeQuerySubcontainer(type)) {
// search into sub-containers
RecursiveFindURIs(aOnlyOne, aContainer->mChildren[child]->GetAsContainer(),
aSpec, aMatches);
if (aOnlyOne && aMatches->Count() > 0)
return;
}
}
}
@ -2078,6 +2037,26 @@ nsNavHistoryQueryResultNode::nsNavHistoryQueryResultNode(
&mHasSearchTerms);
}
nsNavHistoryQueryResultNode::nsNavHistoryQueryResultNode(
const nsACString& aTitle, const nsACString& aIconURI,
PRTime aTime,
const nsCOMArray<nsNavHistoryQuery>& aQueries,
nsNavHistoryQueryOptions* aOptions) :
nsNavHistoryContainerResultNode(EmptyCString(), aTitle, aTime, aIconURI,
nsNavHistoryResultNode::RESULT_TYPE_QUERY,
PR_TRUE, EmptyCString(), aOptions),
mQueries(aQueries),
mContentsValid(PR_FALSE),
mBatchInProgress(PR_FALSE)
{
NS_ASSERTION(aQueries.Count() > 0, "Must have at least one query");
nsNavHistory* history = nsNavHistory::GetHistoryService();
NS_ASSERTION(history, "History service missing");
mLiveUpdate = history->GetUpdateRequirements(mQueries, mOptions,
&mHasSearchTerms);
}
// nsNavHistoryQueryResultNode::CanExpand
//
@ -2311,19 +2290,26 @@ nsNavHistoryQueryResultNode::FillChildren()
// nodes and the result node pointers on the containers
FillStats();
// once we've computed all tree stats, we can sort, because containers will
// then have proper visit counts and dates
SortComparator comparator = GetSortingComparator(GetSortType());
if (comparator) {
nsCAutoString sortingAnnotation;
GetSortingAnnotation(sortingAnnotation);
RecursiveSort(sortingAnnotation.get(), comparator);
PRUint16 sortType = GetSortType();
// The default SORT_BY_NONE sorts by the bookmark index (position),
// which we do not have for history queries
if (mOptions->QueryType() != nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY ||
sortType != nsINavHistoryQueryOptions::SORT_BY_NONE) {
// once we've computed all tree stats, we can sort, because containers will
// then have proper visit counts and dates
SortComparator comparator = GetSortingComparator(GetSortType());
if (comparator) {
nsCAutoString sortingAnnotation;
GetSortingAnnotation(sortingAnnotation);
RecursiveSort(sortingAnnotation.get(), comparator);
}
}
// if our options apply to containers and we are limiting our results
// remove items from the end of the mChildren array after sorting.
// if we are limiting our results remove items from the end of the
// mChildren array after sorting. This is done for root node only.
// note, if count < max results, we won't do anything.
if (mOptions->ApplyOptionsToContainers() && mOptions->MaxResults()) {
if (!mParent && mOptions->MaxResults()) {
while (mChildren.Count() > mOptions->MaxResults())
mChildren.RemoveObjectAt(mChildren.Count() - 1);
}
@ -2517,7 +2503,8 @@ NS_IMETHODIMP
nsNavHistoryQueryResultNode::OnVisit(nsIURI* aURI, PRInt64 aVisitId,
PRTime aTime, PRInt64 aSessionId,
PRInt64 aReferringId,
PRUint32 aTransitionType)
PRUint32 aTransitionType,
PRUint32* aAdded)
{
// ignore everything during batches
if (mBatchInProgress)
@ -2529,11 +2516,37 @@ nsNavHistoryQueryResultNode::OnVisit(nsIURI* aURI, PRInt64 aVisitId,
nsresult rv;
nsRefPtr<nsNavHistoryResultNode> addition;
switch(mLiveUpdate) {
case QUERYUPDATE_HOST: {
// For these simple yet common cases we can check the host ourselves
// before doing the overhead of creating a new result node.
NS_ASSERTION(mQueries.Count() == 1,
"Host updated queries can have only one object");
nsCOMPtr<nsNavHistoryQuery> queryHost =
do_QueryInterface(mQueries[0], &rv);
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasDomain;
queryHost->GetHasDomain(&hasDomain);
if (!hasDomain || !queryHost->DomainIsHost())
return NS_OK;
nsCAutoString host;
if (NS_FAILED(aURI->GetAsciiHost(host)))
return NS_OK;
if (!queryHost->Domain().Equals(host))
return NS_OK;
} // Let it fall through - we want to check the time too,
// if the time is not present it will match too.
case QUERYUPDATE_TIME: {
// For these simple yet common cases we can check the time ourselves
// before doing the overhead of creating a new result node.
NS_ASSERTION(mQueries.Count() == 1, "Time updated queries can have only one object");
nsCOMPtr<nsNavHistoryQuery> query = do_QueryInterface(mQueries[0], &rv);
NS_ASSERTION(mQueries.Count() == 1,
"Time updated queries can have only one object");
nsCOMPtr<nsNavHistoryQuery> query =
do_QueryInterface(mQueries[0], &rv);
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasIt;
@ -2555,6 +2568,11 @@ nsNavHistoryQueryResultNode::OnVisit(nsIURI* aURI, PRInt64 aVisitId,
rv = history->VisitIdToResultNode(aVisitId, mOptions,
getter_AddRefs(addition));
NS_ENSURE_SUCCESS(rv, rv);
// We do not want to add this result to this node
if (!addition)
return NS_OK;
break;
}
case QUERYUPDATE_SIMPLE: {
@ -2588,23 +2606,16 @@ nsNavHistoryQueryResultNode::OnVisit(nsIURI* aURI, PRInt64 aVisitId,
// When more queries are possible (show pages I've visited less than 5 times)
// this will be important to add.
PRUint32 groupCount;
const PRUint16* groupings = mOptions->GroupingMode(&groupCount);
nsCOMArray<nsNavHistoryResultNode> grouped;
if (groupCount > 0) {
// feed this one node into the results grouper for this query to see where
// it should go in the results
nsCOMArray<nsNavHistoryResultNode> itemSource;
if (! itemSource.AppendObject(addition))
return NS_ERROR_OUT_OF_MEMORY;
history->RecursiveGroup(this, itemSource, groupings, groupCount, &grouped);
} else {
// no grouping
if (! grouped.AppendObject(addition))
return NS_ERROR_OUT_OF_MEMORY;
}
nsCOMArray<nsNavHistoryResultNode> mergerNode;
if (!mergerNode.AppendObject(addition))
return NS_ERROR_OUT_OF_MEMORY;
MergeResults(&mergerNode);
if (aAdded)
(*aAdded)++;
MergeResults(&grouped);
return NS_OK;
}
@ -2680,7 +2691,7 @@ nsNavHistoryQueryResultNode::OnDeleteURI(nsIURI *aURI)
NS_ASSERTION(childIndex >= 0, "Child not found in parent");
parent->RemoveChildAt(childIndex);
if (parent->mChildren.Count() == 0 && parent->IsQuerySubcontainer()) {
if (parent->mChildren.Count() == 0 && parent->IsQuery()) {
// when query subcontainers (like hosts) get empty we should remove them
// as well. Just append this to our list and it will get evaluated later
// in the loop.
@ -3088,6 +3099,14 @@ nsNavHistoryFolderResultNode::FillChildren()
RecursiveSort(sortingAnnotation.get(), comparator);
}
// if we are limiting our results remove items from the end of the
// mChildren array after sorting. This is done for root node only.
// note, if count < max results, we won't do anything.
if (!mParent && mOptions->MaxResults()) {
while (mChildren.Count() > mOptions->MaxResults())
mChildren.RemoveObjectAt(mChildren.Count() - 1);
}
// register with the result for updates
nsNavHistoryResult* result = GetResult();
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
@ -4107,10 +4126,117 @@ nsNavHistoryResult::OnItemMoved(PRInt64 aItemId,
NS_IMETHODIMP
nsNavHistoryResult::OnVisit(nsIURI* aURI, PRInt64 aVisitId, PRTime aTime,
PRInt64 aSessionId, PRInt64 aReferringId,
PRUint32 aTransitionType)
PRUint32 aTransitionType, PRUint32* aAdded)
{
PRUint32 added = 0;
ENUMERATE_HISTORY_OBSERVERS(OnVisit(aURI, aVisitId, aTime, aSessionId,
aReferringId, aTransitionType));
aReferringId, aTransitionType, &added));
if (!added && mRootNode->mExpanded) {
nsresult rv;
// None of registered query observers has accepted our URI, this means,
// that a matching query either was not expanded or it does not exist.
// If it just was not expanded, we can ignore it, but if it did not
// exist, we have to add the query to the right place.
PRUint32 resultType = mRootNode->mOptions->ResultType();
nsNavHistoryResultNode * siteRoot = mRootNode;
nsCAutoString dateRange;
// For day based queries we just check whether the first item is Today,
if (resultType == nsINavHistoryQueryOptions::RESULTS_AS_DATE_QUERY ||
resultType == nsINavHistoryQueryOptions::RESULTS_AS_DATE_SITE_QUERY) {
nsNavHistory* history = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(history, 0);
// code borrowed from xpfe/components/history/src/nsGlobalHistory.cpp
// pass in a pre-normalized now and a date, and we'll find
// the difference since midnight on each of the days.
//
// USECS_PER_DAY == PR_USEC_PER_SEC * 60 * 60 * 24;
static const PRInt64 USECS_PER_DAY = LL_INIT(20, 500654080);
dateRange = nsPrintfCString(255,
"&beginTime=%lld&endTime=%lld",
history->NormalizeTime(
nsINavHistoryQuery::TIME_RELATIVE_TODAY, 0),
history->NormalizeTime(
nsINavHistoryQuery::TIME_RELATIVE_TODAY, USECS_PER_DAY));
PRBool todayIsMissing = PR_FALSE;
PRUint32 childCount;
rv = mRootNode->GetChildCount(&childCount);
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString todayLabel;
history->GetStringFromName(
NS_LITERAL_STRING("finduri-AgeInDays-is-0").get(), todayLabel);
if (!childCount) {
todayIsMissing = PR_TRUE;
} else {
nsCOMPtr<nsINavHistoryResultNode> firstChild;
rv = mRootNode->GetChild(0, getter_AddRefs(firstChild));
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString title;
rv = firstChild->GetTitle( title);
NS_ENSURE_SUCCESS(rv, rv);
if (todayLabel.Equals(title)) {
siteRoot = static_cast<nsNavHistoryResultNode *>(firstChild.get());
} else {
todayIsMissing = PR_TRUE;
}
}
if (todayIsMissing) { // Add "Today"
nsCAutoString queryUri;
queryUri = nsPrintfCString(255,
"place:type=%ld&sort=%ld%s",
resultType == nsINavHistoryQueryOptions::RESULTS_AS_DATE_QUERY
?nsINavHistoryQueryOptions::RESULTS_AS_URI
:nsINavHistoryQueryOptions::RESULTS_AS_SITE_QUERY,
nsINavHistoryQueryOptions::SORT_BY_TITLE_ASCENDING,
dateRange.get());
nsRefPtr<nsNavHistoryQueryResultNode> todayNode;
todayNode = new nsNavHistoryQueryResultNode(todayLabel,
EmptyCString(), queryUri);
rv = mRootNode->InsertChildAt( todayNode, 0);
NS_ENSURE_SUCCESS(rv, rv);
}
// "Today" was missing or we had day query
if (resultType == nsINavHistoryQueryOptions::RESULTS_AS_DATE_QUERY ||
todayIsMissing)
return NS_OK; // No more processing necessary
}
if (siteRoot->IsQuery() && siteRoot->GetAsQuery()->mContentsValid &&
(resultType == nsINavHistoryQueryOptions::RESULTS_AS_DATE_SITE_QUERY ||
resultType == nsINavHistoryQueryOptions::RESULTS_AS_SITE_QUERY)) {
nsCAutoString host;
rv = aURI->GetAsciiHost(host);
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString queryUri;
queryUri = nsPrintfCString(255,
"place:type=%ld&sort=%ld&domain=%s&domainIsHost=true%s",
nsINavHistoryQueryOptions::RESULTS_AS_URI,
nsINavHistoryQueryOptions::SORT_BY_TITLE_ASCENDING,
host.get(),
dateRange.get());
nsRefPtr<nsNavHistoryQueryResultNode> siteNode;
siteNode = new nsNavHistoryQueryResultNode(host, EmptyCString(), queryUri);
rv = siteRoot->GetAsContainer()->InsertSortedChild(
siteNode, PR_FALSE, PR_TRUE/*Ignore duplicates*/);
NS_ENSURE_SUCCESS(rv, rv);
}
}
return NS_OK;
}

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

@ -98,7 +98,7 @@ private:
NS_DECL_NSINAVBOOKMARKOBSERVER \
NS_IMETHOD OnVisit(nsIURI* aURI, PRInt64 aVisitId, PRTime aTime, \
PRInt64 aSessionId, PRInt64 aReferringId, \
PRUint32 aTransitionType); \
PRUint32 aTransitionType, PRUint32* aAdded); \
NS_IMETHOD OnTitleChanged(nsIURI* aURI, const nsAString& aPageTitle); \
NS_IMETHOD OnDeleteURI(nsIURI *aURI); \
NS_IMETHOD OnClearHistory(); \
@ -310,12 +310,10 @@ public:
// would take a vtable slot for every one of (potentially very many) nodes.
// Note that GetType() already has a vtable slot because its on the iface.
PRBool IsTypeContainer(PRUint32 type) {
return (type == nsINavHistoryResultNode::RESULT_TYPE_HOST ||
type == nsINavHistoryResultNode::RESULT_TYPE_DYNAMIC_CONTAINER ||
return (type == nsINavHistoryResultNode::RESULT_TYPE_DYNAMIC_CONTAINER ||
type == nsINavHistoryResultNode::RESULT_TYPE_QUERY ||
type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER ||
type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT ||
type == nsINavHistoryResultNode::RESULT_TYPE_DAY);
type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT);
}
PRBool IsContainer() {
PRUint32 type;
@ -327,19 +325,6 @@ public:
GetType(&type);
return (type == nsINavHistoryResultNode::RESULT_TYPE_DYNAMIC_CONTAINER);
}
static PRBool IsTypeQuerySubcontainer(PRUint32 type) {
// Tests containers that are inside queries that really belong to the query
// itself, and is used when recursively updating a query. This currently
// includes only host containers, but may be extended to support things
// like days or other criteria. It doesn't include other queries and folders.
return (type == nsINavHistoryResultNode::RESULT_TYPE_HOST ||
type == nsINavHistoryResultNode::RESULT_TYPE_DAY);
}
PRBool IsQuerySubcontainer() {
PRUint32 type;
GetType(&type);
return IsTypeQuerySubcontainer(type);
}
static PRBool IsTypeURI(PRUint32 type) {
return (type == nsINavHistoryResultNode::RESULT_TYPE_URI ||
type == nsINavHistoryResultNode::RESULT_TYPE_VISIT ||
@ -534,6 +519,12 @@ public:
const nsACString& aIconURI, PRUint32 aContainerType,
PRBool aReadOnly, const nsACString& aDynamicContainerType,
nsNavHistoryQueryOptions* aOptions);
nsNavHistoryContainerResultNode(
const nsACString& aURI, const nsACString& aTitle,
PRTime aTime,
const nsACString& aIconURI, PRUint32 aContainerType,
PRBool aReadOnly, const nsACString& aDynamicContainerType,
nsNavHistoryQueryOptions* aOptions);
NS_DECLARE_STATIC_IID_ACCESSOR(NS_NAVHISTORYCONTAINERRESULTNODE_IID)
@ -562,7 +553,7 @@ public:
// for every leaf node to the result.
nsRefPtr<nsNavHistoryResult> mResult;
// for example, RESULT_TYPE_HOST. Query and Folder results override GetType
// for example, RESULT_TYPE_QUERY. Query and Folder results override GetType
// so this is not used, but is still kept in sync.
PRUint32 mContainerType;
@ -592,7 +583,7 @@ public:
virtual void RecursiveSort(const char* aData,
SortComparator aComparator);
PRUint32 FindInsertionPoint(nsNavHistoryResultNode* aNode, SortComparator aComparator,
const char* aData);
const char* aData, PRBool* aItemExists);
PRBool DoesChildNeedResorting(PRUint32 aIndex, SortComparator aComparator,
const char* aData);
@ -632,10 +623,6 @@ public:
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_LastModifiedGreater(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_CountLess(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_CountGreater(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_TagsLess(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_TagsGreater(
@ -662,7 +649,8 @@ public:
nsresult InsertChildAt(nsNavHistoryResultNode* aNode, PRInt32 aIndex,
PRBool aIsTemporary = PR_FALSE);
nsresult InsertSortedChild(nsNavHistoryResultNode* aNode,
PRBool aIsTemporary = PR_FALSE);
PRBool aIsTemporary = PR_FALSE,
PRBool aIgnoreDuplicates = PR_FALSE);
PRBool EnsureItemPosition(PRUint32 aIndex);
void MergeResults(nsCOMArray<nsNavHistoryResultNode>* aNodes);
nsresult ReplaceChildURIAt(PRUint32 aIndex, nsNavHistoryResultNode* aNode);
@ -700,6 +688,11 @@ public:
const nsACString& aIconURI,
const nsCOMArray<nsNavHistoryQuery>& aQueries,
nsNavHistoryQueryOptions* aOptions);
nsNavHistoryQueryResultNode(const nsACString& aTitle,
const nsACString& aIconURI,
PRTime aTime,
const nsCOMArray<nsNavHistoryQuery>& aQueries,
nsNavHistoryQueryOptions* aOptions);
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_COMMON_RESULTNODE_TO_BASE

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

@ -283,8 +283,9 @@ function run_test() {
do_check_eq(observer._itemChangedProperty, "title");
// insert query item
var newId6 = bmsvc.insertBookmark(testRoot, uri("place:domain=google.com&group=1"),
bmsvc.DEFAULT_INDEX, "");
var uri6 = uri("place:domain=google.com&type="+
Ci.nsINavHistoryQueryOptions.RESULTS_AS_SITE_QUERY);
var newId6 = bmsvc.insertBookmark(testRoot, uri6, bmsvc.DEFAULT_INDEX, "");
do_check_eq(observer._itemAddedParent, testRoot);
do_check_eq(observer._itemAddedIndex, 3);

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

@ -72,7 +72,7 @@ function run_test() {
bmsvc.DEFAULT_INDEX, "3 title");
// bookmark query that should result in the "hierarchical" result
// because there is one query, no grouping, one folder,
// because there is one query, one folder,
// no begin time, no end time, no domain, no uri, no search term
// and no max results. See GetSimpleBookmarksQueryFolder()
// for more details.
@ -122,43 +122,4 @@ function run_test() {
// multiple folders, a begin time, an end time, a domain, a uri
// or a search term, that we get the (correct) flat list results
// (like we do when specified maxResults)
// bookmark query that should result in results grouped by folder
// because we specified GROUP_BY_FOLDER
var options = histsvc.getNewQueryOptions();
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS;
options.setGroupingMode([Ci.nsINavHistoryQueryOptions.GROUP_BY_FOLDER], 1);
var query = histsvc.getNewQuery();
query.setFolders([folder], 1);
var result = histsvc.executeQuery(query, options);
var root = result.root;
root.containerOpen = true;
do_check_eq(root.childCount, 3);
// note these containers are nsNavHistoryContainerResultNodes,
// created in GroupByFolder() and not nsNavHistoryFolderResultNodes,
do_check_eq(root.getChild(0).title, "test folder");
do_check_eq(root.getChild(1).title, "subfolder 1");
do_check_eq(root.getChild(2).title, "subfolder 2");
// check the contents of the "test folder" container
var rfNode = root.getChild(0);
rfNode = rfNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
rfNode.containerOpen = true;
do_check_eq(rfNode.childCount, 1);
do_check_eq(rfNode.getChild(0).itemId, b1);
// check the contents of the "subfolder 1" container
var sf1Node = root.getChild(1);
sf1Node = sf1Node.QueryInterface(Ci.nsINavHistoryContainerResultNode);
sf1Node.containerOpen = true;
do_check_eq(sf1Node.childCount, 1);
do_check_eq(sf1Node.getChild(0).itemId, b2);
// check the contents of the "subfolder 1" container
var sf2Node = root.getChild(2);
sf2Node = sf2Node.QueryInterface(Ci.nsINavHistoryContainerResultNode);
sf2Node.containerOpen = true;
do_check_eq(sf2Node.childCount, 1);
do_check_eq(sf2Node.getChild(0).itemId, b3);
}

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

@ -91,7 +91,8 @@ var observer = {
},
onEndUpdateBatch: function() {
},
onVisit: function(aURI, aVisitID, aTime, aSessionID, aReferringID, aTransitionType) {
onVisit: function(aURI, aVisitID, aTime, aSessionID,
aReferringID, aTransitionType, aAdded) {
do_check_eq(aURI.spec, gVisits[this._visitCount].url);
do_check_eq(aTransitionType, gVisits[this._visitCount].transition);
this._visitCount++;
@ -110,7 +111,7 @@ var observer = {
onPageExpired: function(aURI, aVisitTime, aWholeEntry) {
},
QueryInterface: function(iid) {
if (iid.equals(Ci.nsINavBookmarkObserver) ||
if (iid.equals(Ci.nsINavHistoryObserver) ||
iid.equals(Ci.nsISupports)) {
return this;
}