Bug 324553, r=bryner. Finish remote container API plus manay misc fixes and cleanup.

This commit is contained in:
brettw%gmail.com 2006-01-26 20:24:25 +00:00
parent 702907f622
commit 03e599bde3
16 changed files with 883 additions and 475 deletions

View File

@ -39,9 +39,6 @@ const PREF_PLACES_GROUPING_GENERIC = "browser.places.grouping.generic";
const PREF_PLACES_GROUPING_BOOKMARK = "browser.places.grouping.bookmark";
// Default Search Queries
const QUERY_MONTH_HISTORY = "place:&group=2&sort=1&type=1";
const QUERY_DAY_HISTORY = "place:&beginTimeRef=1&endTimeRef=2&sort=4&type=1";
const QUERY_BOOKMARKS_MENU = "place:&folders=3&group=3";
const INDEX_HISTORY = 0;
const INDEX_BOOKMARKS = 1;

View File

@ -51,8 +51,8 @@ XPIDLSRCS = \
nsIFaviconService.idl \
nsINavHistoryService.idl \
nsINavBookmarksService.idl \
nsIBookmarksContainer.idl \
nsILivemarkService.idl \
nsIRemoteContainer.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -1,101 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Places.
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Annie Sullivan <annie.sullivan@gmail.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIURI;
/**
* The Bookmarks Container interface provides a base class
* for services that want to provide containers for bookmarks.
* Some examples of possible services are the livemarks service and
* the filesystem. Containers are implemented as bookmarked folders.
*/
[scriptable, uuid(45bf2020-9683-498c-9638-f08130c4151d)]
interface nsIBookmarksContainer : nsISupports
{
/**
* Called when the given container is about to be shown,
* so that the service can populate the container if necessary.
* @returns true if the data for the node has changed, false otherwise.
* @param container The folderId of the bookmark folder
* representing the container.
*/
boolean onContainerOpening(in PRInt64 container);
/**
* Called when the given container has just been hidden,
* so that the service can do any necessary cleanup.
* @param container The folderId of the bookmark folder
* representing the container.
*/
void onContainerClosed(in PRInt64 container);
/**
* Called when the given container is about to be deleted, so
* that the service can do any necessary cleanup.
* Called BEFORE the container is deleted, so that the service
* can still reference it.
* @param container The folderId of the bookmark folder
* representing the container to be deleted.
*/
void onContainerRemoving(in PRInt64 container);
/**
* Called when the given container has just been moved, in case
* the service needs to do any bookkeeping.
* Called AFTER the container has been moved, so the service can
* get the new URI.
* @param container The folderId of the bookmark folder
* representing the container to be moved.
* @param newFolder The folderId of the new parent folder
* for the container.
* @param newIndex The index the container will be inserted at,
* or -1 for append.
*/
void onContainerMoved(in PRInt64 container,
in PRInt64 newFolder, in PRInt32 newIndex);
/**
* Returns true if containers of this type should not expose UI for
* inserting, moving, or deleting children.
*/
readonly attribute boolean childrenReadOnly;
};

View File

@ -37,12 +37,12 @@
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "nsIBookmarksContainer.idl"
#include "nsIRemoteContainer.idl"
interface nsIURI;
[scriptable, uuid(b1257934-86cf-4143-8386-734ac352b6ba)]
interface nsILivemarkService : nsIBookmarksContainer
interface nsILivemarkService : nsIRemoteContainer
{
/**
* Creates a new livemark

View File

@ -42,6 +42,8 @@
interface nsIFile;
interface nsINavHistoryContainerResultNode;
interface nsINavHistoryQueryResultNode;
interface nsINavHistoryFolderResultNode;
interface nsINavHistoryQuery;
interface nsINavHistoryQueryOptions;
interface nsITransactionManager;
@ -58,15 +60,20 @@ interface nsINavHistoryResultNode : nsISupports
readonly attribute nsINavHistoryContainerResultNode parent;
/**
* Identifies the type of this node.
* Identifies the type of this node. This node can then be QI-ed to the
* corresponding specialized result node interface. The remote_container one
* is a little weird, it is a temportary folder generated by the remote
* container API. Note that bookmark folders can also be filled by the
* remote container API (these are the entrypoints for the API) and may
* have a remote container type as well.
*/
const PRUint32 RESULT_TYPE_URI = 0;
const PRUint32 RESULT_TYPE_VISIT = 1;
const PRUint32 RESULT_TYPE_FULL_VISIT = 2;
const PRUint32 RESULT_TYPE_HOST = 3;
const PRUint32 RESULT_TYPE_DAY = 4;
const PRUint32 RESULT_TYPE_QUERY = 5;
const PRUint32 RESULT_TYPE_FOLDER = 6;
const PRUint32 RESULT_TYPE_URI = 0; // nsINavHistoryURIResultNode
const PRUint32 RESULT_TYPE_VISIT = 1; // nsINavHistoryVisitResultNode
const PRUint32 RESULT_TYPE_FULL_VISIT = 2; // nsINavHistoryFullVisitResultNode
const PRUint32 RESULT_TYPE_HOST = 3; // nsINavHistoryContainerResultNode
const PRUint32 RESULT_TYPE_REMOTE_CONTAINER = 4; // nsINavHistoryContainerResultNode
const PRUint32 RESULT_TYPE_QUERY = 5; // nsINavHistoryQueryResultNode
const PRUint32 RESULT_TYPE_FOLDER = 6; // nsINavHistoryFolderResultNode
readonly attribute PRUint32 type;
/**
@ -233,6 +240,97 @@ interface nsINavHistoryContainerResultNode : nsINavHistoryResultNode
* been called to override it, and true for non-folder nodes.
*/
readonly attribute boolean childrenReadOnly;
// --------------------------------------------------------------------------
// Remote container
/**
* This is a string representing the remote container API service that is
* responsible for this container. It is empty if there is none. This can
* be set for bookmark folders which have been registered, and also for
* RESULT_TYPE_REMOTE_CONTAINER nodes which have been dynamically generated
* by the remote container API.
*/
readonly attribute AUTF8String remoteContainerType;
/**
* Appends a full visit node to this container and returns it. For the remote
* container API. TO BE CALLED FROM nsIRemoteContainer::OnContainerOpening()
* ONLY, and only for non-bookmark-folder containers.
*
* @see nsINavHistoryURIResultNode for parameters.
*/
nsINavHistoryURIResultNode appendURINode(
in AUTF8String aTitle, in PRUint32 aAccessCount, in PRTime aTime,
in AUTF8String aIconURI, in AUTF8String aURI);
/**
* Appends a full visit node to this container and returns it. For the remote
* container API. TO BE CALLED FROM nsIRemoteContainer::OnContainerOpening()
* ONLY, and only for non-bookmark-folder containers.
*
* @see nsINavHistoryVisitResultNode for parameters.
*/
nsINavHistoryVisitResultNode appendVisitNode(
in AUTF8String aTitle, in PRUint32 aAccessCount, in PRTime aTime,
in AUTF8String aIconURI, in AUTF8String aURI, in PRInt64 aSession);
/**
* Appends a full visit node to this container and returns it. For the remote
* container API. TO BE CALLED FROM nsIRemoteContainer::OnContainerOpening()
* ONLY, and only for non-bookmark-folder containers.
*
* @see nsINavHistoryFullVisitResultNode for parameters.
*/
nsINavHistoryFullVisitResultNode appendFullVisitNode(
in AUTF8String aTitle, in PRUint32 aAccessCount, in PRTime aTime,
in AUTF8String aIconURI, in AUTF8String aURI, in PRInt64 aSession,
in PRInt64 aVisitId, in PRInt64 aReferringVisitId,
in PRInt32 aTransitionType);
/**
* Appends a container node to this container and returns it. For the remote
* container API. TO BE CALLED FROM nsIRemoteContainer::OnContainerOpening()
* ONLY, and only for non-bookmark-folder containers.
*
* aContainerType should be either RESULT_TYPE_HOST or
* RESULT_TYPE_REMOTE_CONTAINER. When type is remote container you must
* specify a remote container type, otherwise, the remote container type must
* be null. Use appendQueryNode and appendFolderNode for the other container
* types.
*/
nsINavHistoryContainerResultNode appendContainerNode(
in AUTF8String aTitle, in AUTF8String aIconURI, in PRUint32 aContainerType,
in AUTF8String aRemoteContainerType);
/**
* Appends a query node to this container and returns it. For the remote
* container API. TO BE CALLED FROM nsIRemoteContainer::OnContainerOpening()
* ONLY, and only for non-bookmark-folder containers.
*
* Normally you should supply an empty string for IconURI and it will take
* the default query icon for the current theme.
*/
nsINavHistoryQueryResultNode appendQueryNode(
in AUTF8String aTitle, in AUTF8String aIconURI, in AUTF8String aQueryString);
/**
* Appends a bookmark folder node to this container and returns it. For the
* remote container API. TO BE CALLED FROM nsIRemoteContainer::OnContainerOpening()
* ONLY, and only for non-bookmark-folder containers.
*
* All container attributes will come from the boomkarks service for this
* folder.
*/
nsINavHistoryFolderResultNode appendFolderNode(in PRInt64 aFolderId);
/**
* Clears all children of this container. For the remote container API.
* TO BE CALLED FROM nsIRemoteContainer::OnContainerOpening and
* nsIRemoteContainer::OnContainerClosed ONLY, and valid only for
* non-bookmark-folder containers.
*/
void clearContents();
};
@ -635,13 +733,6 @@ interface nsINavHistoryQuery : nsISupports
[scriptable, uuid(25fd4de4-33b0-475e-a63d-2bcb1d123e0d)]
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 PRUint32 GROUP_BY_DAY = 0;
/**
* Groping by exact host. The results will be an array of nsINavHistoryResults
* with type = RESULT_TYPE_HOST, one for each unique host (for example,
@ -709,12 +800,9 @@ interface nsINavHistoryQueryOptions : nsISupports
/**
* 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 a tree,
* you can specify an empty array.
* Grouping mode is an array of GROUP_BY_* values that specifies the
* structure of the tree you want. If you don't want grouping, you can
* specify an empty array.
*/
void getGroupingMode(out PRUint32 groupCount,
[retval,array,size_is(groupCount)] out PRUint32 groupingMode);

View File

@ -0,0 +1,141 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Places.
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Annie Sullivan <annie.sullivan@gmail.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIURI;
interface nsINavHistoryContainerResultNode;
interface nsINavHistoryQueryOptions;
/**
* The Remote Container interface provides a base class for services that want
* to provide containers for bookmarks. Some examples of possible services are
* the livemarks service and the filesystem.
*
* There are two primary modes of operation: container services might create
* actual bookmarks, or they might fill containers on the fly as needed. The
* livemarks service, for example, queries the feed from time to time and
* creates actual bookmarks in the folder corresponding to the feed. This way
* the items are persistent even if the user is offline, and can be searched.
* In this mode, the service just looks for moves and deletes to update the
* corresponding bookkeeping information. It can use the normal population
* method provided by the bookmark service and need not do any work for the
* onContainerOpen message.
*
* Such a bookmark-based container service might listen for onContainerOpening
* notifications messages to see whether
*
* Persistent bookmarks are not appropriate for more short-lived data, such as
* the filesystem interface. In this case, the service can fill result nodes
* directly into the container when it is being opened. It can use the property
* bag on every result node to store data associated with each item, such as
* full path on disk. It would create additional containers for each folder,
* resgistered to its service. These dynamic containers are not bookmark
* folders in contrast to the initial item.
*/
[scriptable, uuid(45bf2020-9683-498c-9638-f08130c4151d)]
interface nsIRemoteContainer : nsISupports
{
/**
* Called when the given container is about to be populated so that the
* service can populate the container if necessary.
*
* @param container The container node for the container being opened.
* If the node type is a bookmarks container, you can
* QI it to nsINavHistoryFolderResultNode and access the
* folder ID, etc. Note that all result nodes implement
* a property bag if you need to store state.
* @param options The options used to generate this query. Containers
* should follow these when possible, for example,
* whether to expand queries, etc. Implementations should
* use this when possible if adding query and folder nodes
* to the container. DO NOT MODIFY THIS VALUE.
*/
void onContainerOpening(in nsINavHistoryContainerResultNode container,
in nsINavHistoryQueryOptions options);
/**
* Called when the given container has just been hidden so that the service
* can do any necessary cleanup. This is NOT guaranteed to get called. In
* particular, if the query just goes away (like the user switched views on
* the places page) you will not get this call. This only happens when the
* container itself goes from the open state to the closed state. A serviced
* with large numbers of dynamically populated items might use this to do
* some cleanup so those items don't hang around
*
* @param container The container node of the container being closed. The
* service need not worry about removing any created nodes,
* they will be automatically removed when this call
* completes.
*/
void onContainerClosed(in nsINavHistoryContainerResultNode container);
/**
* Called when the given container is about to be deleted, so
* that the service can do any necessary cleanup.
* Called BEFORE the container is deleted, so that the service
* can still reference it.
* @param container The folderId of the bookmark folder
* representing the container to be deleted.
*/
void onContainerRemoving(in PRInt64 container);
/**
* Called when the given container has just been moved, in case
* the service needs to do any bookkeeping.
* Called AFTER the container has been moved, so the service can
* get the new URI.
* @param container The folderId of the bookmark folder
* representing the container to be moved.
* @param newFolder The folderId of the new parent folder
* for the container.
* @param newIndex The index the container will be inserted at,
* or -1 for append.
*/
void onContainerMoved(in PRInt64 container,
in PRInt64 newFolder, in PRInt32 newIndex);
/**
* Returns true if containers of this type should not expose UI for
* inserting, moving, or deleting children.
*/
readonly attribute boolean childrenReadOnly;
};

View File

@ -39,6 +39,7 @@
#include "nsLivemarkService.h"
#include "nsIServiceManager.h"
#include "nsNavBookmarks.h"
#include "nsNavHistoryResult.h"
#include "nsIAnnotationService.h"
#include "nsNetUtil.h"
#include "rdf.h"
@ -95,7 +96,7 @@ nsLivemarkService::~nsLivemarkService()
mTimer = nsnull;
}
// Cancel any pending loads
for (PRInt32 i = 0; i < mLivemarks.Length(); ++i) {
for (PRUint32 i = 0; i < mLivemarks.Length(); ++i) {
LivemarkInfo *li = mLivemarks[i];
if (li->loadGroup) {
li->loadGroup->Cancel(NS_BINDING_ABORTED);
@ -105,7 +106,7 @@ nsLivemarkService::~nsLivemarkService()
NS_IMPL_ISUPPORTS2(nsLivemarkService,
nsILivemarkService,
nsIBookmarksContainer)
nsIRemoteContainer)
nsresult
nsLivemarkService::Init()
@ -186,7 +187,7 @@ nsLivemarkService::Init()
&pLivemarks);
NS_ENSURE_SUCCESS(rv, rv);
for (PRInt32 i = 0; i < numLivemarks; ++i) {
for (PRUint32 i = 0; i < numLivemarks; ++i) {
// Get the feed URI from the annotation.
nsAutoString feedURIString;
@ -198,26 +199,24 @@ nsLivemarkService::Init()
rv = NS_NewURI(getter_AddRefs(feedURI), NS_ConvertUTF16toUTF8(feedURIString));
NS_ENSURE_SUCCESS(rv, rv);
// Use QueryStringToQueries() to get the folderId from the place:uri.
// (It ends up in folders[0])
// Use QueryStringToQueryArray() to get the folderId from the place:uri.
// (It ends up in folders[0] since we know that this place: uri was
// generated by the bookmark service to uniquely identify the folder)
nsCAutoString folderQueryString;
rv = pLivemarks[i]->GetSpec(folderQueryString);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 resultCount;
nsINavHistoryQuery** queries = nsnull;
nsCOMPtr<nsINavHistoryQueryOptions> options;
rv = History()->QueryStringToQueries(folderQueryString,
&queries,
&resultCount,
getter_AddRefs(options));
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 folderCount;
PRInt64 *folders = nsnull;
rv = queries[0]->GetFolders(&folderCount, &folders);
nsCOMArray<nsNavHistoryQuery> queries;
nsCOMPtr<nsNavHistoryQueryOptions> options;
rv = History()->QueryStringToQueryArray(folderQueryString, &queries,
getter_AddRefs(options));
NS_ENSURE_SUCCESS(rv, rv);
if (queries.Count() != 1 || queries[0]->Folders().Length() != 1)
continue; // invalid folder URI (should identify exactly one folder)
// Create the livemark and add it to the list.
LivemarkInfo *li = new LivemarkInfo(folders[0], pLivemarks[i], feedURI);
LivemarkInfo *li = new LivemarkInfo(queries[0]->Folders()[0],
pLivemarks[i], feedURI);
NS_ENSURE_TRUE(li, NS_ERROR_OUT_OF_MEMORY);
NS_ENSURE_TRUE(mLivemarks.AppendElement(li), NS_ERROR_OUT_OF_MEMORY);
}
@ -283,17 +282,18 @@ nsLivemarkService::CreateLivemark(PRInt64 aFolder,
NS_IMETHODIMP
nsLivemarkService::OnContainerOpening(PRInt64 aContainer, PRBool * _result)
nsLivemarkService::OnContainerOpening(
nsINavHistoryContainerResultNode* container,
nsINavHistoryQueryOptions* options)
{
// Nothing to do here since the containers are filled in
// as the livemarks are loaded through FireTimer().
*_result = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsLivemarkService::OnContainerClosed(PRInt64 aContainer)
nsLivemarkService::OnContainerClosed(nsINavHistoryContainerResultNode* container)
{
// Nothing to clean up
return NS_OK;
@ -308,7 +308,7 @@ nsLivemarkService::OnContainerRemoving(PRInt64 aContainer)
// Find the livemark id in the list of livemarks.
PRInt32 lmIndex = -1;
PRInt32 i;
for (i = 0; i < mLivemarks.Length(); i++) {
for (i = 0; i < PRInt32(mLivemarks.Length()); i++) {
if (mLivemarks[i]->folderId == aContainer) {
lmIndex = i;
break;
@ -332,7 +332,7 @@ nsLivemarkService::OnContainerRemoving(PRInt64 aContainer)
// If not, remove the annotations for the feed.
PRBool stillInUse = PR_FALSE;
PRBool urisEqual = PR_FALSE;
for (i = 0; i < mLivemarks.Length(); i++) {
for (i = 0; i < PRInt32(mLivemarks.Length()); i++) {
if (i != lmIndex &&
(NS_OK == mLivemarks[i]->feedURI->Equals(removedItem->feedURI, &urisEqual)) &&
urisEqual) {
@ -369,7 +369,7 @@ nsLivemarkService::OnContainerMoved(PRInt64 aContainer,
// Find the livemark in the list.
PRInt32 index = -1;
for (PRInt32 i = 0; i < mLivemarks.Length(); i++) {
for (PRInt32 i = 0; i < PRInt32(mLivemarks.Length()); i++) {
if (mLivemarks[i]->folderId == aContainer) {
index = i;
break;
@ -436,7 +436,7 @@ nsLivemarkService::FireTimer(nsITimer* aTimer, void* aClosure)
if (!lmks) return;
// Go through all of the livemarks, and check if each needs to be updated.
for (PRInt32 i = 0; i < lmks->mLivemarks.Length(); i++) {
for (PRUint32 i = 0; i < lmks->mLivemarks.Length(); i++) {
lmks->UpdateLivemarkChildren(i);
}
}

View File

@ -52,7 +52,7 @@ class nsLivemarkService : public nsILivemarkService
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIBOOKMARKSCONTAINER
NS_DECL_NSIREMOTECONTAINER
NS_DECL_NSILIVEMARKSERVICE
nsLivemarkService();

View File

@ -43,7 +43,7 @@
#include "nsIServiceManager.h"
#include "nsNetUtil.h"
#include "nsIAnnotationService.h"
#include "nsIBookmarksContainer.h"
#include "nsIRemoteContainer.h"
const PRInt32 nsNavBookmarks::kFindBookmarksIndex_ItemChild = 0;
const PRInt32 nsNavBookmarks::kFindBookmarksIndex_FolderChild = 1;
@ -719,12 +719,12 @@ nsNavBookmarks::RemoveFolder(PRInt64 aFolder)
{
// If this is a container bookmark, try to notify its service.
nsresult rv;
nsAutoString folderType;
nsCAutoString folderType;
rv = GetFolderType(aFolder, folderType);
NS_ENSURE_SUCCESS(rv, rv);
if (folderType.Length() > 0) {
// There is a type associated with this folder; it's a livemark.
nsCOMPtr<nsIBookmarksContainer> bmcServ = do_GetService(NS_ConvertUTF16toUTF8(folderType).get());
nsCOMPtr<nsIRemoteContainer> bmcServ = do_GetService(folderType.get());
if (bmcServ) {
rv = bmcServ->OnContainerRemoving(aFolder);
if (NS_FAILED(rv))
@ -796,16 +796,16 @@ nsNavBookmarks::RemoveFolderChildren(PRInt64 aFolder)
nsTArray<PRInt64> folderChildren;
{
mozStorageStatementScoper scope(mDBGetFolderChildren);
rv = mDBGetChildren->BindInt64Parameter(0, aFolder);
rv = mDBGetFolderChildren->BindInt64Parameter(0, aFolder);
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBGetChildren->BindInt32Parameter(1, 0);
rv = mDBGetFolderChildren->BindInt32Parameter(1, 0);
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBGetChildren->BindInt32Parameter(2, PR_INT32_MAX);
rv = mDBGetFolderChildren->BindInt32Parameter(2, PR_INT32_MAX);
NS_ENSURE_SUCCESS(rv, rv);
PRBool more;
while (NS_SUCCEEDED(rv = mDBGetChildren->ExecuteStep(&more)) && more) {
folderChildren.AppendElement(mDBGetChildren->AsInt64(kGetChildrenIndex_FolderChild));
while (NS_SUCCEEDED(rv = mDBGetFolderChildren->ExecuteStep(&more)) && more) {
folderChildren.AppendElement(mDBGetFolderChildren->AsInt64(kGetChildrenIndex_FolderChild));
}
}
@ -944,10 +944,23 @@ nsNavBookmarks::MoveFolder(PRInt64 aFolder, PRInt64 aNewParent, PRInt32 aIndex)
rv = transaction.Commit();
NS_ENSURE_SUCCESS(rv, rv);
// notify bookmark observers
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
OnFolderMoved(aFolder, parent, oldIndex,
aNewParent, newIndex))
// notify remote container provider if there is one
nsCAutoString type;
rv = GetFolderType(aFolder, type);
NS_ENSURE_SUCCESS(rv, rv);
if (! type.IsEmpty()) {
nsCOMPtr<nsIRemoteContainer> container =
do_GetService(type.get(), &rv);
if (NS_SUCCEEDED(rv)) {
rv = container->OnContainerMoved(aFolder, aNewParent, newIndex);
NS_ENSURE_SUCCESS(rv, rv);
}
}
return NS_OK;
}
@ -1051,7 +1064,7 @@ nsNavBookmarks::GetFolderTitle(PRInt64 aFolder, nsAString &aTitle)
nsresult
nsNavBookmarks::GetFolderType(PRInt64 aFolder, nsAString &aType)
nsNavBookmarks::GetFolderType(PRInt64 aFolder, nsACString &aType)
{
mozStorageStatementScoper scope(mDBGetFolderInfo);
nsresult rv = mDBGetFolderInfo->BindInt64Parameter(0, aFolder);
@ -1065,7 +1078,7 @@ nsNavBookmarks::GetFolderType(PRInt64 aFolder, nsAString &aType)
return NS_ERROR_INVALID_ARG;
}
return mDBGetFolderInfo->GetString(kGetFolderInfoIndex_Type, aType);
return mDBGetFolderInfo->GetUTF8String(kGetFolderInfoIndex_Type, aType);
}
nsresult
@ -1090,19 +1103,10 @@ nsNavBookmarks::ResultNodeForFolder(PRInt64 aID,
nsCAutoString title;
rv = mDBGetFolderInfo->GetUTF8String(kGetFolderInfoIndex_Title, title);
if (folderType.IsEmpty()) {
*aNode = new nsNavHistoryFolderResultNode(title, 0, 0, aOptions, aID);
if (! *aNode)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aNode);
} else {
// a container API thing
// FIXME(brettw)
//NS_NOTREACHED("FIXME: Not implemented");
*aNode = nsnull;
return NS_ERROR_NOT_IMPLEMENTED;
}
*aNode = new nsNavHistoryFolderResultNode(title, aOptions, aID, folderType);
if (! *aNode)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aNode);
return NS_OK;
}
@ -1118,7 +1122,7 @@ nsNavBookmarks::GetFolderURI(PRInt64 aFolder, nsIURI **aURI)
// correct string here.
//
// If you change this, change IsSimpleFolderURI which detects this string.
nsCAutoString spec("place:folders=");
nsCAutoString spec("place:folder=");
spec.AppendInt(aFolder);
spec.AppendLiteral("&group=3"); // GROUP_BY_FOLDER
return NS_NewURI(aURI, spec);
@ -1127,15 +1131,15 @@ nsNavBookmarks::GetFolderURI(PRInt64 aFolder, nsIURI **aURI)
NS_IMETHODIMP
nsNavBookmarks::GetFolderReadonly(PRInt64 aFolder, PRBool *aResult)
{
// Ask the folder's nsIBookmarksContainer for the readonly property.
// Ask the folder's nsIRemoteContainer for the readonly property.
*aResult = PR_FALSE;
nsAutoString type;
nsCAutoString type;
nsresult rv = GetFolderType(aFolder, type);
NS_ENSURE_SUCCESS(rv, rv);
if (!type.IsEmpty()) {
nsCOMPtr<nsIBookmarksContainer> container =
do_GetService(NS_ConvertUTF16toUTF8(type).get(), &rv);
nsCOMPtr<nsIRemoteContainer> container =
do_GetService(type.get(), &rv);
if (NS_SUCCEEDED(rv)) {
rv = container->GetChildrenReadOnly(aResult);
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -96,7 +96,7 @@ private:
PRInt32 aStartIndex, PRInt32 aEndIndex,
PRInt32 aDelta);
PRInt32 FolderCount(PRInt64 aFolder);
nsresult GetFolderType(PRInt64 aFolder, nsAString &aType);
nsresult GetFolderType(PRInt64 aFolder, nsACString &aType);
// remove me when there is better query initialization
nsNavHistory* History() { return nsNavHistory::GetHistoryService(); }

View File

@ -120,8 +120,8 @@ static PRInt32 GetTLDType(const nsCString& aHostTail);
static void GetUnreversedHostname(const nsString& aBackward,
nsAString& aForward);
static PRBool IsNumericHostName(const nsCString& aHost);
static PRInt64 GetSimpleBookmarksQueryFolder(nsINavHistoryQuery** aQueries,
PRUint32 aQueryCount);
static PRInt64 GetSimpleBookmarksQueryFolder(
const nsCOMArray<nsNavHistoryQuery>& aQueries);
static void ParseSearchQuery(const nsString& aQuery, nsStringArray* aTerms);
inline void ReverseString(const nsString& aInput, nsAString& aReversed)
@ -1192,16 +1192,16 @@ nsNavHistory::NormalizeTime(PRUint32 aRelative, PRTime aOffset)
// change operations as simple instead of complex.
PRUint32
nsNavHistory::GetUpdateRequirements(nsCOMArray<nsINavHistoryQuery>* aQueries,
nsNavHistory::GetUpdateRequirements(const nsCOMArray<nsNavHistoryQuery>& aQueries,
nsNavHistoryQueryOptions* aOptions,
PRBool* aHasSearchTerms)
{
NS_ASSERTION(aQueries->Count() > 0, "Must have at least one query");
NS_ASSERTION(aQueries.Count() > 0, "Must have at least one query");
// first check if there are search terms
*aHasSearchTerms = PR_FALSE;
for (PRInt32 i = 0; i < aQueries->Count(); i ++) {
(*aQueries)[i]->GetHasSearchTerms(aHasSearchTerms);
for (PRInt32 i = 0; i < aQueries.Count(); i ++) {
aQueries[i]->GetHasSearchTerms(aHasSearchTerms);
if (*aHasSearchTerms)
break;
}
@ -1213,13 +1213,8 @@ nsNavHistory::GetUpdateRequirements(nsCOMArray<nsINavHistoryQuery>* aQueries,
return QUERYUPDATE_COMPLEX;
PRBool nonTimeBasedItems = PR_FALSE;
for (PRInt32 i = 0; i < aQueries->Count(); i ++) {
nsresult rv;
nsCOMPtr<nsNavHistoryQuery> query = do_QueryInterface((*aQueries)[i], &rv);
if (NS_FAILED(rv)) {
NS_NOTREACHED("Query is not one of our query objects!");
return QUERYUPDATE_COMPLEX;
}
for (PRInt32 i = 0; i < aQueries.Count(); i ++) {
nsNavHistoryQuery* query = aQueries[i];
if (query->Folders().Length() > 0 || query->OnlyBookmarked()) {
return QUERYUPDATE_COMPLEX_WITH_BOOKMARKS;
@ -1232,7 +1227,7 @@ nsNavHistory::GetUpdateRequirements(nsCOMArray<nsINavHistoryQuery>* aQueries,
nonTimeBasedItems = PR_TRUE;
}
if (aQueries->Count() == 1 && ! nonTimeBasedItems)
if (aQueries.Count() == 1 && ! nonTimeBasedItems)
return QUERYUPDATE_TIME;
return QUERYUPDATE_SIMPLE;
}
@ -1253,21 +1248,16 @@ nsNavHistory::GetUpdateRequirements(nsCOMArray<nsINavHistoryQuery>* aQueries,
// Returns true if node matches the query, false if not.
PRBool
nsNavHistory::EvaluateQueryForNode(nsCOMArray<nsINavHistoryQuery>* aQueries,
nsNavHistory::EvaluateQueryForNode(const nsCOMArray<nsNavHistoryQuery>& aQueries,
nsNavHistoryQueryOptions* aOptions,
nsNavHistoryURIResultNode* aNode)
{
// lazily created from the node's string when we need to match URIs
nsCOMPtr<nsIURI> nodeUri;
nsresult rv;
for (PRInt32 i = 0; i < aQueries->Count(); i ++) {
for (PRInt32 i = 0; i < aQueries.Count(); i ++) {
PRBool hasIt;
nsCOMPtr<nsNavHistoryQuery> query = do_QueryInterface((*aQueries)[i], &rv);
if (NS_FAILED(rv)) {
NS_NOTREACHED("Query is not one of ours.");
return PR_FALSE;
}
nsCOMPtr<nsNavHistoryQuery> query = aQueries[i];
// --- begin time ---
query->GetHasBeginTime(&hasIt);
@ -1294,7 +1284,7 @@ nsNavHistory::EvaluateQueryForNode(nsCOMArray<nsINavHistoryQuery>* aQueries,
nsCOMArray<nsNavHistoryResultNode> inputSet;
inputSet.AppendObject(aNode);
nsCOMArray<nsNavHistoryResultNode> filteredSet;
rv = FilterResultSet(inputSet, &filteredSet, query->SearchTerms());
nsresult rv = FilterResultSet(inputSet, &filteredSet, query->SearchTerms());
if (NS_FAILED(rv))
continue;
if (! filteredSet.Count())
@ -1336,7 +1326,7 @@ nsNavHistory::EvaluateQueryForNode(nsCOMArray<nsINavHistoryQuery>* aQueries,
if (! query->UriIsPrefix()) {
// easy case: the URI is an exact match
PRBool equals;
rv = query->Uri()->Equals(nodeUri, &equals);
nsresult rv = query->Uri()->Equals(nodeUri, &equals);
NS_ENSURE_SUCCESS(rv, rv);
if (! equals)
continue;
@ -1640,21 +1630,33 @@ nsNavHistory::ExecuteQueries(nsINavHistoryQuery** aQueries, PRUint32 aQueryCount
nsCOMPtr<nsNavHistoryQueryOptions> options = do_QueryInterface(aOptions);
NS_ENSURE_TRUE(options, NS_ERROR_INVALID_ARG);
// concrete queries array
nsCOMArray<nsNavHistoryQuery> queries;
for (PRUint32 i = 0; i < aQueryCount; i ++) {
nsCOMPtr<nsNavHistoryQuery> query = do_QueryInterface(aQueries[i], &rv);
NS_ENSURE_SUCCESS(rv, rv);
queries.AppendObject(query);
}
// root node
nsRefPtr<nsNavHistoryContainerResultNode> rootNode;
PRInt64 folderId = GetSimpleBookmarksQueryFolder(aQueries, aQueryCount);
PRInt64 folderId = GetSimpleBookmarksQueryFolder(queries);
if (folderId) {
// In the simple case where we're just querying children of a single bookmark
// folder, we can more efficiently generate results.
rootNode = new nsNavHistoryFolderResultNode(EmptyCString(), 0, 0,
options, folderId);
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsNavHistoryResultNode> tempRootNode;
rv = bookmarks->ResultNodeForFolder(folderId, options,
getter_AddRefs(tempRootNode));
NS_ENSURE_SUCCESS(rv, rv);
rootNode = tempRootNode->GetAsContainer();
} else {
// complex query
rootNode = new nsNavHistoryQueryResultNode(options,
EmptyCString(), 0, 0, EmptyCString(),
aQueries, aQueryCount, options);
rootNode = new nsNavHistoryQueryResultNode(EmptyCString(), EmptyCString(),
queries, options);
NS_ENSURE_TRUE(rootNode, NS_ERROR_OUT_OF_MEMORY);
}
NS_ENSURE_TRUE(rootNode, NS_ERROR_OUT_OF_MEMORY);
// result object
nsRefPtr<nsNavHistoryResult> result;
@ -1688,7 +1690,7 @@ nsNavHistory::ExecuteQueries(nsINavHistoryQuery** aQueries, PRUint32 aQueryCount
// it ANDed with the all the rest of the queries.
nsresult
nsNavHistory::GetQueryResults(const nsCOMArray<nsINavHistoryQuery>& aQueries,
nsNavHistory::GetQueryResults(const nsCOMArray<nsNavHistoryQuery>& aQueries,
nsNavHistoryQueryOptions *aOptions,
nsCOMArray<nsNavHistoryResultNode>* aResults)
{
@ -1843,15 +1845,13 @@ nsNavHistory::GetQueryResults(const nsCOMArray<nsINavHistoryQuery>& aQueries,
for (i = 0; i < aQueries.Count(); i ++) {
PRInt32 clauseParameters = 0;
rv = BindQueryClauseParameters(statement, numParameters,
NS_CONST_CAST(nsINavHistoryQuery*, aQueries[i]),
&clauseParameters);
aQueries[i], &clauseParameters);
NS_ENSURE_SUCCESS(rv, rv);
numParameters += clauseParameters;
}
PRBool hasSearchTerms;
rv = NS_CONST_CAST(nsINavHistoryQuery*,
aQueries[0])->GetHasSearchTerms(&hasSearchTerms);
rv = aQueries[0]->GetHasSearchTerms(&hasSearchTerms);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 groupCount;
@ -1868,37 +1868,26 @@ nsNavHistory::GetQueryResults(const nsCOMArray<nsINavHistoryQuery>& aQueries,
rv = ResultsAsList(statement, aOptions, &toplevel);
NS_ENSURE_SUCCESS(rv, rv);
/* FIXME(brettw)
if (hasSearchTerms) {
// keyword search
nsAutoString searchTerms;
NS_CONST_CAST(nsINavHistoryQuery*, aQueries[0])
->GetSearchTerms(searchTerms);
if (groupCount == 0) {
FilterResultSet(toplevel, result->GetTopLevel(), searchTerms);
// keyword search with no grouping: can filter directly into the result
FilterResultSet(toplevel, aResults, aQueries[0]->SearchTerms());
} else {
// keyword searching with grouping: need intermediate filtered results
nsCOMArray<nsNavHistoryResultNode> filteredResults;
FilterResultSet(toplevel, &filteredResults, searchTerms);
FilterResultSet(toplevel, &filteredResults, aQueries[0]->SearchTerms());
rv = RecursiveGroup(filteredResults, groupings, groupCount,
result->GetTopLevel());
aResults);
NS_ENSURE_SUCCESS(rv, rv);
}
} else */{
} else {
// group unfiltered results
rv = RecursiveGroup(toplevel, groupings, groupCount, aResults);
NS_ENSURE_SUCCESS(rv, rv);
}
}
/*
nsNavHistoryContainerResultNode::SortComparator comparator =
nsNavHistoryContainerResultNode::GetSortingComparator(
sortingMode);
if (sortingMode)
nsNavHistoryContainerResultNode::RecursiveSortArray(
aResults, mCollation, comparator);
*/
// automatically expand things that were expanded before
// FIXME(brettw)
//if (gExpandedItems.Count() > 0)
@ -2526,7 +2515,7 @@ nsNavHistory::Observe(nsISupports *aSubject, const char *aTopic,
// no way for those to fail.
nsresult
nsNavHistory::QueryToSelectClause(nsINavHistoryQuery* aQuery, // const
nsNavHistory::QueryToSelectClause(nsNavHistoryQuery* aQuery, // const
PRInt32 aStartParameter,
nsCString* aClause,
PRInt32* aParamCount,
@ -2559,7 +2548,7 @@ nsNavHistory::QueryToSelectClause(nsINavHistoryQuery* aQuery, // const
// search terms FIXME
// only bookmarked
if (NS_SUCCEEDED(aQuery->GetOnlyBookmarked(&hasIt)) && hasIt) {
if (aQuery->OnlyBookmarked()) {
if (! aClause->IsEmpty())
*aClause += NS_LITERAL_CSTRING(" AND ");
@ -2602,15 +2591,12 @@ nsNavHistory::QueryToSelectClause(nsINavHistoryQuery* aQuery, // const
if (! aClause->IsEmpty())
*aClause += NS_LITERAL_CSTRING(" AND ");
PRBool uriIsPrefix;
aQuery->GetUriIsPrefix(&uriIsPrefix);
nsCAutoString paramString;
parameterString(aStartParameter + *aParamCount, paramString);
(*aParamCount) ++;
nsCAutoString match;
if (uriIsPrefix) {
if (aQuery->UriIsPrefix()) {
// Prefix: want something of the form SUBSTR(h.url, 0, length(?1)) = ?1
*aClause += NS_LITERAL_CSTRING("SUBSTR(h.url, 0, LENGTH(") +
paramString + NS_LITERAL_CSTRING(")) = ") + paramString;
@ -2625,14 +2611,11 @@ nsNavHistory::QueryToSelectClause(nsINavHistoryQuery* aQuery, // const
if (! aClause->IsEmpty())
*aClause += NS_LITERAL_CSTRING(" AND ");
if (hasIt) {
PRBool notAnnotation;
aQuery->GetAnnotationIsNot(&notAnnotation);
nsCAutoString paramString;
parameterString(aStartParameter + *aParamCount, paramString);
(*aParamCount) ++;
if (notAnnotation)
if (aQuery->AnnotationIsNot())
aClause->AppendLiteral("NOT ");
aClause->AppendLiteral("EXISTS (SELECT anno_id FROM moz_anno anno WHERE anno.page = h.id AND anno.name = ");
aClause->Append(paramString);
@ -2655,7 +2638,7 @@ nsNavHistory::QueryToSelectClause(nsINavHistoryQuery* aQuery, // const
nsresult
nsNavHistory::BindQueryClauseParameters(mozIStorageStatement* statement,
PRInt32 aStartParameter,
nsINavHistoryQuery* aQuery, // const
nsNavHistoryQuery* aQuery, // const
PRInt32* aParamCount)
{
nsresult rv;
@ -2665,11 +2648,8 @@ nsNavHistory::BindQueryClauseParameters(mozIStorageStatement* statement,
// begin time
if (NS_SUCCEEDED(aQuery->GetHasBeginTime(&hasIt)) && hasIt) {
PRTime time;
aQuery->GetBeginTime(&time);
PRUint32 timeReference;
aQuery->GetBeginTimeReference(&timeReference);
time = NormalizeTime(timeReference, time);
PRTime time = NormalizeTime(aQuery->BeginTimeReference(),
aQuery->BeginTime());
rv = statement->BindInt64Parameter(aStartParameter + *aParamCount, time);
NS_ENSURE_SUCCESS(rv, rv);
(*aParamCount) ++;
@ -2677,11 +2657,8 @@ nsNavHistory::BindQueryClauseParameters(mozIStorageStatement* statement,
// end time
if (NS_SUCCEEDED(aQuery->GetHasEndTime(&hasIt)) && hasIt) {
PRTime time;
aQuery->GetEndTime(&time);
PRUint32 timeReference;
aQuery->GetEndTimeReference(&timeReference);
time = NormalizeTime(timeReference, time);
PRTime time = NormalizeTime(aQuery->EndTimeReference(),
aQuery->EndTime());
rv = statement->BindInt64Parameter(aStartParameter + *aParamCount, time);
NS_ENSURE_SUCCESS(rv, rv);
(*aParamCount) ++;
@ -2693,14 +2670,10 @@ nsNavHistory::BindQueryClauseParameters(mozIStorageStatement* statement,
// domain (see GetReversedHostname for more info on reversed host names)
if (NS_SUCCEEDED(aQuery->GetHasDomain(&hasIt)) && hasIt) {
nsCAutoString domain;
aQuery->GetDomain(domain);
nsString revDomain;
GetReversedHostname(NS_ConvertUTF8toUTF16(domain), revDomain);
GetReversedHostname(NS_ConvertUTF8toUTF16(aQuery->Domain()), revDomain);
PRBool domainIsHost = PR_FALSE;
aQuery->GetDomainIsHost(&domainIsHost);
if (domainIsHost) {
if (aQuery->DomainIsHost()) {
rv = statement->BindStringParameter(aStartParameter + *aParamCount, revDomain);
NS_ENSURE_SUCCESS(rv, rv);
(*aParamCount) ++;
@ -2722,21 +2695,15 @@ nsNavHistory::BindQueryClauseParameters(mozIStorageStatement* statement,
// URI
if (NS_SUCCEEDED(aQuery->GetHasUri(&hasIt)) && hasIt) {
nsCOMPtr<nsIURI> uri;
rv = aQuery->GetUri(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE); // if (hasUri) then it should be valid
BindStatementURI(statement, aStartParameter + *aParamCount, uri);
BindStatementURI(statement, aStartParameter + *aParamCount, aQuery->Uri());
(*aParamCount) ++;
}
// annotation
aQuery->GetHasAnnotation(&hasIt);
if (hasIt) {
nsCAutoString annotationName;
aQuery->GetAnnotation(annotationName);
rv = statement->BindUTF8StringParameter(aStartParameter + *aParamCount,
annotationName);
aQuery->Annotation());
NS_ENSURE_SUCCESS(rv, rv);
}
@ -2791,9 +2758,6 @@ nsNavHistory::RecursiveGroup(const nsCOMArray<nsNavHistoryResultNode>& aSource,
nsresult rv;
switch (aGroupingMode[0]) {
case nsINavHistoryQueryOptions::GROUP_BY_DAY:
rv = GroupByDay(aSource, aDest);
break;
case nsINavHistoryQueryOptions::GROUP_BY_HOST:
rv = GroupByHost(aSource, aDest, PR_FALSE);
break;
@ -2825,18 +2789,6 @@ nsNavHistory::RecursiveGroup(const nsCOMArray<nsNavHistoryResultNode>& aSource,
}
// nsNavHistory::GroupByDay
//
// FIXME TODO IMPLEMENT ME (or maybe we don't care about this?)
nsresult
nsNavHistory::GroupByDay(const nsCOMArray<nsNavHistoryResultNode>& aSource,
nsCOMArray<nsNavHistoryResultNode>* aDest)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
// nsNavHistory::GroupByHost
//
// OPTIMIZATION: This parses the URI of each node that is coming in. This
@ -2892,7 +2844,7 @@ nsNavHistory::GroupByHost(const nsCOMArray<nsNavHistoryResultNode>& aSource,
TitleForDomain(curHostName, title);
curTopGroup = new nsNavHistoryContainerResultNode(title, EmptyCString(),
nsNavHistoryResultNode::RESULT_TYPE_HOST);
nsNavHistoryResultNode::RESULT_TYPE_HOST, PR_TRUE, EmptyCString());
if (! curTopGroup)
return NS_ERROR_OUT_OF_MEMORY;
@ -2955,29 +2907,28 @@ nsNavHistory::FilterResultSet(const nsCOMArray<nsNavHistoryResultNode>& aSet,
}
*/
/* FIXME(brettw)
for (PRInt32 termIndex = 0; termIndex < terms.Count(); termIndex ++) {
PRBool termFound = PR_FALSE;
// title and URL
if (CaseInsensitiveFindInReadable(*terms[termIndex],
NS_ConvertUTF8toUTF16(aSet[nodeIndex]->mTitle)) ||
CaseInsensitiveFindInReadable(*terms[termIndex],
NS_ConvertUTF8toUTF16(aSet[nodeIndex]->mUrl)))
(aSet[nodeIndex]->IsURI() &&
CaseInsensitiveFindInReadable(*terms[termIndex],
NS_ConvertUTF8toUTF16(aSet[nodeIndex]->GetAsURI()->mURI))))
termFound = PR_TRUE;
// searchable annotations
if (! termFound) {
/*if (! termFound) {
for (PRInt32 annotIndex = 0; annotIndex < curAnnotations.Count(); annotIndex ++) {
if (CaseInsensitiveFindInReadable(*terms[termIndex],
*curAnnotations[annotIndex]))
termFound = PR_TRUE;
}
}
}*/
if (! termFound) {
allTermsFound = PR_FALSE;
break;
}
}
*/
if (allTermsFound)
aFiltered->AppendObject(aSet[nodeIndex]);
}
@ -3077,41 +3028,8 @@ nsNavHistory::RowToResult(mozIStorageValueArray* aRow,
NS_ENSURE_SUCCESS(rv, rv);
if (IsQueryURI(url)) {
nsINavHistoryQuery** queries;
PRUint32 queryCount;
nsCOMPtr<nsINavHistoryQueryOptions> subIOptions;
rv = QueryStringToQueries(url, &queries, &queryCount,
getter_AddRefs(subIOptions));
if (NS_FAILED(rv)) {
// This was a query that did not parse, what do we do? We don't want to
// return failure since that will kill the whole query process. Instead
// make a query node with the query as a string. This way we have a valid
// node for the user to manipulate, but it will never populate since the
// query string is invalid.
*aResult = new nsNavHistoryQueryResultNode(aOptions, title, accessCount,
time, favicon, url);
} else {
nsCOMPtr<nsNavHistoryQueryOptions> subOptions =
do_QueryInterface(subIOptions, &rv);
NS_ASSERTION(NS_SUCCEEDED(rv), "Options must be our concrete ones");
PRInt64 folderId = GetSimpleBookmarksQueryFolder(queries, queryCount);
if (folderId) {
// simple bookmarks folder, magically generate a bookmarks folder node
*aResult = new nsNavHistoryFolderResultNode(title, 0, 0,
subOptions, folderId);
} else {
// regular query
*aResult = new nsNavHistoryQueryResultNode(subOptions, title, 0,
0, EmptyCString(),
queries, queryCount,
subOptions);
}
nsMemory::Free(queries);
}
if (! *aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
// special case "place:" URIs: turn them into containers
return QueryRowToResult(url, title, accessCount, time, favicon, aResult);
} else if (aOptions->ResultType() == nsNavHistoryQueryOptions::RESULTS_AS_URI) {
*aResult = new nsNavHistoryURIResultNode(title, accessCount, time,
favicon, url);
@ -3164,6 +3082,54 @@ nsNavHistory::RowToResult(mozIStorageValueArray* aRow,
}
// nsNavHistory::QueryRowToResult
//
// Called by RowToResult when the URI is a place: URI to generate the proper
// folder or query node.
nsresult
nsNavHistory::QueryRowToResult(const nsACString& aURI, const nsACString& aTitle,
PRUint32 aAccessCount, PRTime aTime,
const nsACString& aFavicon,
nsNavHistoryResultNode** aNode)
{
nsCOMArray<nsNavHistoryQuery> queries;
nsCOMPtr<nsNavHistoryQueryOptions> options;
nsresult rv = QueryStringToQueryArray(aURI, &queries,
getter_AddRefs(options));
if (NS_FAILED(rv)) {
// This was a query that did not parse, what do we do? We don't want to
// return failure since that will kill the whole query process. Instead
// make a query node with the query as a string. This way we have a valid
// node for the user to manipulate that will look like a query, but it will
// never populate since the query string is invalid.
*aNode = new nsNavHistoryQueryResultNode(aTitle, aFavicon, aURI);
if (! *aNode)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aNode);
} else {
PRInt64 folderId = GetSimpleBookmarksQueryFolder(queries);
if (folderId) {
// simple bookmarks folder, magically generate a bookmarks folder node
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY);
// this addrefs for us
rv = bookmarks->ResultNodeForFolder(folderId, options, aNode);
NS_ENSURE_SUCCESS(rv, rv);
} else {
// regular query
*aNode = new nsNavHistoryQueryResultNode(aTitle, EmptyCString(),
queries, options);
if (! *aNode)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aNode);
}
}
return NS_OK;
}
// nsNavHistory::VisitIdToResultNode
//
// Used by the query results to create new nodes on the fly when
@ -3473,13 +3439,12 @@ PRBool IsNumericHostName(const nsCString& aHost)
// Returns the folder ID if it is a simple folder query, 0 if not.
static PRInt64
GetSimpleBookmarksQueryFolder(nsINavHistoryQuery** aQueries, PRUint32 aQueryCount)
GetSimpleBookmarksQueryFolder(const nsCOMArray<nsNavHistoryQuery>& aQueries)
{
if (aQueryCount != 1)
if (aQueries.Count() != 1)
return 0;
nsresult rv;
nsCOMPtr<nsNavHistoryQuery> query = do_QueryInterface(aQueries[0], &rv);
nsNavHistoryQuery* query = aQueries[0];
if (query->Folders().Length() != 1)
return 0;

View File

@ -200,7 +200,7 @@ public:
// this actually executes a query and gives you results, it is used by
// nsNavHistoryQueryResultNode
nsresult GetQueryResults(const nsCOMArray<nsINavHistoryQuery>& aQueries,
nsresult GetQueryResults(const nsCOMArray<nsNavHistoryQuery>& aQueries,
nsNavHistoryQueryOptions *aOptions,
nsCOMArray<nsNavHistoryResultNode>* aResults);
@ -209,6 +209,10 @@ public:
nsresult RowToResult(mozIStorageValueArray* aRow,
nsNavHistoryQueryOptions* aOptions,
nsNavHistoryResultNode** aResult);
nsresult QueryRowToResult(const nsACString& aURI, const nsACString& aTitle,
PRUint32 aAccessCount, PRTime aTime,
const nsACString& aFavicon,
nsNavHistoryResultNode** aNode);
nsresult VisitIdToResultNode(PRInt64 visitId,
nsNavHistoryQueryOptions* aOptions,
@ -233,10 +237,10 @@ public:
static const char kAnnotationPreviousEncoding[];
// used by query result nodes to update: see comment on body of CanLiveUpdateQuery
static PRUint32 GetUpdateRequirements(nsCOMArray<nsINavHistoryQuery>* aQueries,
static PRUint32 GetUpdateRequirements(const nsCOMArray<nsNavHistoryQuery>& aQueries,
nsNavHistoryQueryOptions* aOptions,
PRBool* aHasSearchTerms);
PRBool EvaluateQueryForNode(nsCOMArray<nsINavHistoryQuery>* aQueries,
PRBool EvaluateQueryForNode(const nsCOMArray<nsNavHistoryQuery>& aQueries,
nsNavHistoryQueryOptions* aOptions,
nsNavHistoryURIResultNode* aNode);
@ -249,6 +253,11 @@ public:
const PRUint32* aGroupingMode, PRUint32 aGroupCount,
nsCOMArray<nsNavHistoryResultNode>* aDest);
// better alternative to QueryStringToQueries (in nsNavHistoryQuery.cpp)
nsresult QueryStringToQueryArray(const nsACString& aQueryString,
nsCOMArray<nsNavHistoryQuery>* aQueries,
nsNavHistoryQueryOptions** aOptions);
private:
~nsNavHistory();
@ -319,14 +328,14 @@ protected:
nsCOMPtr<nsITimer> mExpireNowTimer;
static void expireNowTimerCallback(nsITimer* aTimer, void* aClosure);
nsresult QueryToSelectClause(nsINavHistoryQuery* aQuery,
nsresult QueryToSelectClause(nsNavHistoryQuery* aQuery,
PRInt32 aStartParameter,
nsCString* aClause,
PRInt32* aParamCount,
const nsACString& aCommonConditions);
nsresult BindQueryClauseParameters(mozIStorageStatement* statement,
PRInt32 aStartParameter,
nsINavHistoryQuery* aQuery,
nsNavHistoryQuery* aQuery,
PRInt32* aParamCount);
nsresult ResultsAsList(mozIStorageStatement* statement,
@ -337,8 +346,6 @@ protected:
nsresult SetPageTitleInternal(nsIURI* aURI, PRBool aIsUserTitle,
const nsAString& aTitle);
nsresult GroupByDay(const nsCOMArray<nsNavHistoryResultNode>& aSource,
nsCOMArray<nsNavHistoryResultNode>* aDest);
nsresult GroupByHost(const nsCOMArray<nsNavHistoryResultNode>& aSource,
nsCOMArray<nsNavHistoryResultNode>* aDest,
PRBool aIsDomain);
@ -413,7 +420,7 @@ protected:
// in nsNavHistoryQuery.cpp
nsresult TokensToQueries(const nsTArray<QueryKeyValuePair>& aTokens,
nsCOMArray<nsINavHistoryQuery>* aQueries,
nsCOMArray<nsNavHistoryQuery>* aQueries,
nsNavHistoryQueryOptions* aOptions);
// Transaction Manager

View File

@ -141,7 +141,7 @@ static void SetOptionsKeyUint32(const nsCString& aValue,
#define QUERYKEY_ONLY_BOOKMARKED "onlyBookmarked"
#define QUERYKEY_DOMAIN_IS_HOST "domainIsHost"
#define QUERYKEY_DOMAIN "domain"
#define QUERYKEY_FOLDERS "folders"
#define QUERYKEY_FOLDER "folder"
#define QUERYKEY_NOTANNOTATION "!annotation"
#define QUERYKEY_ANNOTATION "annotation"
#define QUERYKEY_URI "uri"
@ -175,7 +175,11 @@ inline void AppendInt64(nsACString& str, PRInt64 i)
str.Append(tmp);
}
// nsNavHistory::QueryStringToQueries
//
// From C++ places code, you should use QueryStringToQueryArray, this is
// the harder-to-use XPCOM version.
NS_IMETHODIMP
nsNavHistory::QueryStringToQueries(const nsACString& aQueryString,
@ -183,9 +187,42 @@ nsNavHistory::QueryStringToQueries(const nsACString& aQueryString,
PRUint32* aResultCount,
nsINavHistoryQueryOptions** aOptions)
{
nsresult rv;
*aQueries = nsnull;
*aResultCount = 0;
nsCOMPtr<nsNavHistoryQueryOptions> options;
nsCOMArray<nsNavHistoryQuery> queries;
nsresult rv = QueryStringToQueryArray(aQueryString, &queries,
getter_AddRefs(options));
NS_ENSURE_SUCCESS(rv, rv);
*aResultCount = queries.Count();
if (queries.Count() > 0) {
// convert COM array to raw
*aQueries = NS_STATIC_CAST(nsINavHistoryQuery**,
nsMemory::Alloc(sizeof(nsINavHistoryQuery*) * queries.Count()));
NS_ENSURE_TRUE(*aQueries, NS_ERROR_OUT_OF_MEMORY);
for (PRInt32 i = 0; i < queries.Count(); i ++) {
(*aQueries)[i] = queries[i];
NS_ADDREF((*aQueries)[i]);
}
}
NS_ADDREF(*aOptions = options);
return NS_OK;
}
// nsNavHistory::QueryStringToQueryArray
//
// An internal version of QueryStringToQueries that fills a COM array for
// ease-of-use.
nsresult
nsNavHistory::QueryStringToQueryArray(const nsACString& aQueryString,
nsCOMArray<nsNavHistoryQuery>* aQueries,
nsNavHistoryQueryOptions** aOptions)
{
nsresult rv;
aQueries->Clear();
*aOptions = nsnull;
nsRefPtr<nsNavHistoryQueryOptions> options(new nsNavHistoryQueryOptions());
@ -196,30 +233,14 @@ nsNavHistory::QueryStringToQueries(const nsACString& aQueryString,
rv = TokenizeQueryString(aQueryString, &tokens);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMArray<nsINavHistoryQuery> queries;
rv = TokensToQueries(tokens, &queries, options);
rv = TokensToQueries(tokens, aQueries, options);
if (NS_FAILED(rv)) {
NS_WARNING("Unable to parse the query string: ");
NS_WARNING(PromiseFlatCString(aQueryString).get());
}
NS_ENSURE_SUCCESS(rv, rv);
NS_STATIC_CAST(nsRefPtr<nsINavHistoryQueryOptions>, options).swap(*aOptions);
*aResultCount = queries.Count();
if (queries.Count() == 0) {
// need to special-case 0 queries since we don't allocate an array
*aQueries = nsnull;
return NS_OK;
}
// convert COM array to raw
*aQueries = NS_STATIC_CAST(nsINavHistoryQuery**,
nsMemory::Alloc(sizeof(nsINavHistoryQuery*) * queries.Count()));
if (! *aQueries)
return NS_ERROR_OUT_OF_MEMORY;
for (PRInt32 i = 0; i < queries.Count(); i ++) {
(*aQueries)[i] = queries[i];
NS_ADDREF((*aQueries)[i]);
}
NS_ADDREF(*aOptions = options);
return NS_OK;
}
@ -352,7 +373,7 @@ nsNavHistory::QueriesToQueryString(nsINavHistoryQuery **aQueries,
query->GetFolders(&folderCount, &folders);
for (PRUint32 i = 0; i < folderCount; ++i) {
AppendAmpersandIfNonempty(aQueryString);
aQueryString += NS_LITERAL_CSTRING(QUERYKEY_FOLDERS "=");
aQueryString += NS_LITERAL_CSTRING(QUERYKEY_FOLDER "=");
AppendInt64(aQueryString, folders[0]);
}
}
@ -465,7 +486,7 @@ TokenizeQueryString(const nsACString& aQuery,
nsresult
nsNavHistory::TokensToQueries(const nsTArray<QueryKeyValuePair>& aTokens,
nsCOMArray<nsINavHistoryQuery>* aQueries,
nsCOMArray<nsNavHistoryQuery>* aQueries,
nsNavHistoryQueryOptions* aOptions)
{
nsresult rv;
@ -475,7 +496,7 @@ nsNavHistory::TokensToQueries(const nsTArray<QueryKeyValuePair>& aTokens,
nsTArray<PRUint32> groups;
nsTArray<PRInt64> folders;
nsCOMPtr<nsINavHistoryQuery> query(new nsNavHistoryQuery());
nsCOMPtr<nsNavHistoryQuery> query(new nsNavHistoryQuery());
if (! query)
return NS_ERROR_OUT_OF_MEMORY;
if (! aQueries->AppendObject(query))
@ -522,7 +543,7 @@ nsNavHistory::TokensToQueries(const nsTArray<QueryKeyValuePair>& aTokens,
NS_ENSURE_SUCCESS(rv, rv);
// folders: FIXME use folder name???
} else if (kvp.key.EqualsLiteral(QUERYKEY_FOLDERS)) {
} else if (kvp.key.EqualsLiteral(QUERYKEY_FOLDER)) {
PRInt64 folder;
if (PR_sscanf(kvp.value.get(), "%lld", &folder) == 1) {
NS_ENSURE_TRUE(folders.AppendElement(folder), NS_ERROR_OUT_OF_MEMORY);

View File

@ -77,6 +77,8 @@ public:
const nsCString& Domain() { return mDomain; }
PRBool UriIsPrefix() { return mUriIsPrefix; }
nsIURI* Uri() { return mUri; } // NOT AddRef-ed!
PRBool AnnotationIsNot() { return mAnnotationIsNot; }
const nsCString& Annotation() { return mAnnotation; }
const nsTArray<PRInt64>& Folders() const { return mFolders; }
private:

View File

@ -52,6 +52,7 @@
#include "nsILocale.h"
#include "nsILocaleService.h"
#include "nsILocalFile.h"
#include "nsIRemoteContainer.h"
#include "nsIServiceManager.h"
#include "nsISupportsPrimitives.h"
#include "nsITreeColumns.h"
@ -162,6 +163,45 @@ nsNavHistoryResultNode::GetResult()
}
// nsNavHistoryResultNode::GetGeneratingOptions
//
// Searches up the tree for the closest node that has an options structure.
// This will tell us the options that were used to generate this node.
//
// Be careful, this function walks up the tree, so it can not be used when
// result nodes are created because they have no parent. Only call this
// function after the tree has been built.
nsNavHistoryQueryOptions*
nsNavHistoryResultNode::GetGeneratingOptions()
{
if (! mParent) {
// When we have no parent, it either means we haven't built the tree yet,
// in which case calling this function is a bug, or this node is the root
// of the tree. When we are the root of the tree, our own options are the
// generating options, and we know we are either a query of a folder node.
if (IsFolder())
return GetAsFolder()->mOptions;
else if (IsQuery())
return GetAsQuery()->mOptions;
NS_NOTREACHED("Can't find a generating node for this container, perhaps FillStats has not been called on this tree yet?");
return nsnull;
}
nsNavHistoryContainerResultNode* cur = mParent;
while (cur) {
if (cur->IsFolder())
return cur->GetAsFolder()->mOptions;
else if (cur->IsQuery())
return cur->GetAsQuery()->mOptions;
cur = cur->mParent;
}
// we should always find a folder or query node as an ancestor
NS_NOTREACHED("Can't find a generating node for this container, the tree seemes corrupted.");
return nsnull;
}
// nsNavHistoryURIResultNode ***************************************************
NS_IMPL_ISUPPORTS_INHERITED1(nsNavHistoryURIResultNode,
@ -216,32 +256,17 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsNavHistoryContainerResultNode,
nsNavHistoryResultNode,
nsINavHistoryContainerResultNode)
nsNavHistoryContainerResultNode::nsNavHistoryContainerResultNode(
const nsACString& aTitle, PRUint32 aAccessCount, PRTime aTime,
const nsACString& aIconURI, PRUint32 aContainerType, PRBool aReadOnly) :
nsNavHistoryResultNode(aTitle, aAccessCount, aTime, aIconURI),
mResult(nsnull),
mContainerType(aContainerType),
mExpanded(PR_FALSE),
mChildrenReadOnly(aReadOnly)
{
}
nsNavHistoryContainerResultNode::nsNavHistoryContainerResultNode(
const nsACString& aTitle, const nsACString& aIconURI,
PRUint32 aContainerType) :
PRUint32 aContainerType, PRBool aReadOnly,
const nsACString& aRemoteContainerType) :
nsNavHistoryResultNode(aTitle, 0, 0, aIconURI),
mResult(nsnull),
mContainerType(aContainerType),
mExpanded(PR_FALSE),
mChildrenReadOnly(PR_TRUE)
mChildrenReadOnly(aReadOnly),
mRemoteContainerType(aRemoteContainerType)
{
// The container type must be a host or day. This constructor is used when
// we are grouping and want to create host or day containers. Therefore, you
// can't use it with folder or query containers.
NS_ASSERTION(aContainerType == nsINavHistoryResultNode::RESULT_TYPE_HOST ||
aContainerType == nsINavHistoryResultNode::RESULT_TYPE_DAY,
"You are passing in a container type that isn't valid");
}
@ -312,6 +337,9 @@ nsNavHistoryContainerResultNode::SetContainerOpen(PRBool aContainerOpen)
// nsNavHistoryContainerResultNode::OpenContainer
//
// This handles the generic container case. Other container types should
// override this to do their own handling.
nsresult
nsNavHistoryContainerResultNode::OpenContainer()
@ -320,6 +348,20 @@ nsNavHistoryContainerResultNode::OpenContainer()
NS_ASSERTION(! mExpanded, "Container must be expanded to close it");
mExpanded = PR_TRUE;
if (! mRemoteContainerType.IsEmpty()) {
// remote container API may want to fill us
nsCOMPtr<nsIRemoteContainer> remote = do_GetService(mRemoteContainerType.get(), &rv);
if (NS_SUCCEEDED(rv)) {
remote->OnContainerOpening(this, GetGeneratingOptions());
} else {
NS_WARNING("Unable to get remote container for ");
NS_WARNING(mRemoteContainerType.get());
}
PRInt32 oldAccessCount = mAccessCount;
FillStats();
ReverseUpdateStats(mAccessCount - oldAccessCount);
}
nsNavHistoryResult* result = GetResult();
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
rv = result->RefreshVisibleSection(this);
@ -336,9 +378,17 @@ nsNavHistoryContainerResultNode::CloseContainer()
NS_ASSERTION(mExpanded, "Container must be expanded to close it");
mExpanded = PR_FALSE;
nsresult rv;
if (! mRemoteContainerType.IsEmpty()) {
// notify remote containers that we are closing
nsCOMPtr<nsIRemoteContainer> remote = do_GetService(mRemoteContainerType.get(), &rv);
if (NS_SUCCEEDED(rv))
remote->OnContainerClosed(this);
}
nsNavHistoryResult* result = GetResult();
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
nsresult rv = result->RefreshVisibleSection(this);
rv = result->RefreshVisibleSection(this);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
@ -691,9 +741,6 @@ PRInt32 PR_CALLBACK nsNavHistoryContainerResultNode::SortComparison_URILess(
nsNavHistoryURIResultNode* aURI = a->GetAsURI();
nsNavHistoryURIResultNode* bURI = b->GetAsURI();
value = aURI->mURI.Compare(bURI->mURI.get());
} else if (aType == nsINavHistoryResultNode::RESULT_TYPE_DAY) {
// date nodes use date (skip conflict resolution because it uses date too)
return ComparePRTime(a->mTime, b->mTime);
} else {
// for everything else, use title (= host name)
nsICollation* collation = NS_STATIC_CAST(nsICollation*, closure);
@ -1079,6 +1126,20 @@ nsNavHistoryContainerResultNode::RemoveChildAt(PRInt32 aIndex,
}
// nsNavHistoryContainerResultNode::CanRemoteContainersChange
//
// Returns true if remote containers can manipulate the contents of this
// container. This is false for folders and queries, true for everything
// else.
PRBool
nsNavHistoryContainerResultNode::CanRemoteContainersChange()
{
return (mContainerType != nsINavHistoryResultNode::RESULT_TYPE_FOLDER &&
mContainerType != nsINavHistoryResultNode::RESULT_TYPE_QUERY);
}
// nsNavHistoryContainerResultNode::GetHasChildren
//
// Complex containers (folders and queries) will override this. Here, we
@ -1131,27 +1192,233 @@ nsNavHistoryContainerResultNode::GetChildrenReadOnly(PRBool *aChildrenReadOnly)
return NS_OK;
}
// nsNavHistoryContainerResultNode::GetRemoteContainerType
NS_IMETHODIMP
nsNavHistoryContainerResultNode::GetRemoteContainerType(
nsACString& aRemoteContainerType)
{
aRemoteContainerType = mRemoteContainerType;
return NS_OK;
}
// nsNavHistoryContainerResultNode::AppendURINode
NS_IMETHODIMP
nsNavHistoryContainerResultNode::AppendURINode(
const nsACString& aTitle, PRUint32 aAccessCount, PRTime aTime,
const nsACString& aIconURI, const nsACString& aURI,
nsINavHistoryURIResultNode** _retval)
{
*_retval = nsnull;
if (mRemoteContainerType.IsEmpty() || ! CanRemoteContainersChange())
return NS_ERROR_INVALID_ARG; // we must be a remote container
nsRefPtr<nsNavHistoryURIResultNode> result =
new nsNavHistoryURIResultNode(aTitle, aAccessCount, aTime, aIconURI, aURI);
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
// append to our list
if (! mChildren.AppendObject(result))
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*_retval = result);
return NS_OK;
}
// nsNavHistoryContainerResultNode::AppendVisitNode
NS_IMETHODIMP
nsNavHistoryContainerResultNode::AppendVisitNode(
const nsACString& aTitle, PRUint32 aAccessCount, PRTime aTime,
const nsACString& aIconURI, const nsACString& aURI, PRInt64 aSession,
nsINavHistoryVisitResultNode** _retval)
{
*_retval = nsnull;
if (mRemoteContainerType.IsEmpty() || ! CanRemoteContainersChange())
return NS_ERROR_INVALID_ARG; // we must be a remote container
nsRefPtr<nsNavHistoryVisitResultNode> result =
new nsNavHistoryVisitResultNode(aTitle, aAccessCount, aTime,
aIconURI, aURI, aSession);
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
// append to our list
if (! mChildren.AppendObject(result))
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*_retval = result);
return NS_OK;
}
// nsNavHistoryContainerResultNode::AppendFullVisitNode
NS_IMETHODIMP
nsNavHistoryContainerResultNode::AppendFullVisitNode(
const nsACString& aTitle, PRUint32 aAccessCount, PRTime aTime,
const nsACString& aIconURI, const nsACString& aURI, PRInt64 aSession,
PRInt64 aVisitId, PRInt64 aReferringVisitId, PRInt32 aTransitionType,
nsINavHistoryFullVisitResultNode** _retval)
{
*_retval = nsnull;
if (mRemoteContainerType.IsEmpty() || ! CanRemoteContainersChange())
return NS_ERROR_INVALID_ARG; // we must be a remote container
nsRefPtr<nsNavHistoryFullVisitResultNode> result =
new nsNavHistoryFullVisitResultNode(aTitle, aAccessCount, aTime,
aIconURI, aURI, aSession,
aVisitId, aReferringVisitId,
aTransitionType);
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
// append to our list
if (! mChildren.AppendObject(result))
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*_retval = result);
return NS_OK;
}
// nsNavHistoryContainerResultNode::AppendContainerNode
NS_IMETHODIMP
nsNavHistoryContainerResultNode::AppendContainerNode(
const nsACString& aTitle, const nsACString& aIconURI,
PRUint32 aContainerType, const nsACString& aRemoteContainerType,
nsINavHistoryContainerResultNode** _retval)
{
*_retval = nsnull;
if (mRemoteContainerType.IsEmpty() || ! CanRemoteContainersChange())
return NS_ERROR_INVALID_ARG; // we must be a remote container
if (! IsTypeContainer(aContainerType) || IsTypeFolder(aContainerType) ||
IsTypeQuery(aContainerType))
return NS_ERROR_INVALID_ARG; // not proper container type
if (aContainerType == nsINavHistoryResultNode::RESULT_TYPE_REMOTE_CONTAINER &&
aRemoteContainerType.IsEmpty())
return NS_ERROR_INVALID_ARG; // remote containers must have r.c. type
if (aContainerType != nsINavHistoryResultNode::RESULT_TYPE_REMOTE_CONTAINER &&
! aRemoteContainerType.IsEmpty())
return NS_ERROR_INVALID_ARG; // non-remote containers must NOT have r.c. type
nsRefPtr<nsNavHistoryContainerResultNode> result =
new nsNavHistoryContainerResultNode(aTitle, aIconURI, aContainerType,
PR_TRUE, aRemoteContainerType);
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
// append to our list
if (! mChildren.AppendObject(result))
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*_retval = result);
return NS_OK;
}
// nsNavHistoryContainerResultNode::AppendQueryNode
NS_IMETHODIMP
nsNavHistoryContainerResultNode::AppendQueryNode(
const nsACString& aTitle, const nsACString& aIconURI,
const nsACString& aQueryString, nsINavHistoryQueryResultNode** _retval)
{
*_retval = nsnull;
if (mRemoteContainerType.IsEmpty() || ! CanRemoteContainersChange())
return NS_ERROR_INVALID_ARG; // we must be a remote container
nsRefPtr<nsNavHistoryQueryResultNode> result =
new nsNavHistoryQueryResultNode(aTitle, aIconURI, aQueryString);
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
// append to our list
if (! mChildren.AppendObject(result))
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*_retval = result);
return NS_OK;
}
// nsNavHistoryContainerResultNode::AppendFolderNode
NS_IMETHODIMP
nsNavHistoryContainerResultNode::AppendFolderNode(
PRInt64 aFolderId, nsINavHistoryFolderResultNode** _retval)
{
*_retval = nsnull;
if (mRemoteContainerType.IsEmpty() || ! CanRemoteContainersChange())
return NS_ERROR_INVALID_ARG; // we must be a remote container
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY);
// create the node, it will be addrefed for us
nsRefPtr<nsNavHistoryResultNode> result;
nsresult rv = bookmarks->ResultNodeForFolder(aFolderId,
GetGeneratingOptions(),
getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
// append to our list
if (! mChildren.AppendObject(result))
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*_retval = result->GetAsFolder());
return NS_OK;
}
// nsNavHistoryContainerResultNode::ClearContents
//
// Used by the remote container API to clear this container
NS_IMETHODIMP
nsNavHistoryContainerResultNode::ClearContents()
{
if (mRemoteContainerType.IsEmpty() || ! CanRemoteContainersChange())
return NS_ERROR_INVALID_ARG; // we must be a remote container
// we know if CanRemoteContainersChange() then we are a regular container
// and not a query or folder, so clearing doesn't need anything else to
// happen (like unregistering observers). Also, since this should only
// happen when the container is closed, we don't need to redraw the screen.
mChildren.Clear();
PRUint32 oldAccessCount = mAccessCount;
mAccessCount = 0;
mTime = 0;
ReverseUpdateStats(-oldAccessCount);
return NS_OK;
}
// nsNavHistoryQueryResultNode *************************************************
//
// HOW QUERY UPDATING WORKS
//
// Queries are different than bookmark folders in that we can not always
// do dynamic updates (easily) and updates are more expensive.
// do dynamic updates (easily) and updates are more expensive. Therefore,
// we do NOT query if we are not open and want to see if we have any children
// (for drawing a twisty) and always assume we will.
//
//
// When the container is opened, we execute the query and register the
// listeners. Like bookmark folders, we stay registered even when closed,
// and clear ourselves as soon as a message comes in. This lets us respond
// quickly if the user closes and reopens the container.
//
// We try to handle the most common notifications for the most common query
// types dynamically, that is, figuring out what should happen in response
// to a message without doing a requery. For complex changes or complex
// queries, we give up and requery.
NS_IMPL_ISUPPORTS_INHERITED1(nsNavHistoryQueryResultNode,
nsNavHistoryContainerResultNode,
nsINavHistoryQueryResultNode)
nsNavHistoryQueryResultNode::nsNavHistoryQueryResultNode(
nsNavHistoryQueryOptions* aGeneratingOptions,
const nsACString& aTitle, PRUint32 aAccessCount, PRTime aTime,
const nsACString& aIconURI, const nsACString& aQueryURI) :
nsNavHistoryContainerResultNode(aTitle, aAccessCount, aTime, aIconURI,
const nsACString& aTitle, const nsACString& aIconURI,
const nsACString& aQueryURI) :
nsNavHistoryContainerResultNode(aTitle, aIconURI,
nsINavHistoryResultNode::RESULT_TYPE_QUERY,
PR_TRUE),
mGeneratingOptions(aGeneratingOptions),
PR_TRUE, EmptyCString()),
mQueryURI(aQueryURI),
mHasSearchTerms(PR_FALSE),
mContentsValid(PR_FALSE),
@ -1163,26 +1430,27 @@ nsNavHistoryQueryResultNode::nsNavHistoryQueryResultNode(
}
nsNavHistoryQueryResultNode::nsNavHistoryQueryResultNode(
nsNavHistoryQueryOptions* aGeneratingOptions,
const nsACString& aTitle, PRUint32 aAccessCount, PRTime aTime,
const nsACString& aIconURI, nsINavHistoryQuery** aQueries,
PRUint32 aQueryCount, nsNavHistoryQueryOptions* aOptions) :
nsNavHistoryContainerResultNode(aTitle, aAccessCount, aTime, aIconURI,
const nsACString& aTitle, const nsACString& aIconURI,
const nsCOMArray<nsNavHistoryQuery>& aQueries,
nsNavHistoryQueryOptions* aOptions) :
nsNavHistoryContainerResultNode(aTitle, aIconURI,
nsINavHistoryResultNode::RESULT_TYPE_QUERY,
PR_TRUE),
mGeneratingOptions(aGeneratingOptions),
PR_TRUE, EmptyCString()),
mQueries(aQueries),
mOptions(aOptions),
mContentsValid(PR_FALSE),
mBatchInProgress(PR_FALSE)
{
NS_ASSERTION(aQueryCount > 0, "Must have at least one query");
NS_ASSERTION(aQueries.Count() > 0, "Must have at least one query");
/*
for (PRUint32 i = 0; i < aQueryCount; i ++)
mQueries.AppendObject(aQueries[i]);
aOptions->Clone(getter_AddRefs(mOptions));
*/
nsNavHistory* history = nsNavHistory::GetHistoryService();
NS_ASSERTION(history, "History service missing");
mLiveUpdate = history->GetUpdateRequirements(&mQueries, mOptions,
mLiveUpdate = history->GetUpdateRequirements(mQueries, mOptions,
&mHasSearchTerms);
// queries have special icons if not otherwise set
@ -1200,7 +1468,8 @@ nsNavHistoryQueryResultNode::nsNavHistoryQueryResultNode(
PRBool
nsNavHistoryQueryResultNode::CanExpand()
{
if (mGeneratingOptions->ExpandQueries())
nsNavHistoryQueryOptions* options = GetGeneratingOptions();
if (options && options->ExpandQueries())
return PR_TRUE;
if (mResult && mResult->mRootNode == this)
return PR_TRUE;
@ -1233,13 +1502,18 @@ nsNavHistoryQueryResultNode::OnRemoving()
nsresult
nsNavHistoryQueryResultNode::OpenContainer()
{
NS_ASSERTION(! mExpanded, "Container must be expanded to close it");
if (! CanExpand())
return NS_OK;
if (! mContentsValid) {
nsresult rv = FillChildren();
NS_ENSURE_SUCCESS(rv, rv);
}
return nsNavHistoryContainerResultNode::OpenContainer();
mExpanded = PR_TRUE;
nsNavHistoryResult* result = GetResult();
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
return result->RefreshVisibleSection(this);
}
@ -1329,31 +1603,11 @@ nsNavHistoryQueryResultNode::VerifyQueriesParsed()
nsNavHistory* history = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
nsINavHistoryQuery** queries;
PRUint32 queryCount;
nsCOMPtr<nsINavHistoryQueryOptions> options;
nsresult rv = history->QueryStringToQueries(mQueryURI, &queries, &queryCount,
getter_AddRefs(options));
nsresult rv = history->QueryStringToQueryArray(mQueryURI, &mQueries,
getter_AddRefs(mOptions));
NS_ENSURE_SUCCESS(rv, rv);
mOptions = do_QueryInterface(options, &rv); // need concrete pointer
if (NS_FAILED(rv)) {
nsMemory::Free(queries);
return rv;
}
// Copy the individual queries into our array. At the same time, note if
// we have any bookmark components so we know whether to pay attention to
// bookmark notifications.
for (PRUint32 i = 0; i < queryCount; i ++) {
if (! mQueries.AppendObject(queries[i])) {
nsMemory::Free(queries);
mQueries.Clear();
return NS_ERROR_OUT_OF_MEMORY;
}
}
nsMemory::Free(queries);
mLiveUpdate = history->GetUpdateRequirements(&mQueries, mOptions,
mLiveUpdate = history->GetUpdateRequirements(mQueries, mOptions,
&mHasSearchTerms);
return NS_OK;
}
@ -1726,7 +1980,7 @@ nsNavHistoryQueryResultNode::OnVisit(nsIURI* aURI, PRInt64 aVisitId,
rv = history->VisitIdToResultNode(aVisitId, mOptions,
getter_AddRefs(addition));
NS_ENSURE_SUCCESS(rv, rv);
if (! history->EvaluateQueryForNode(&mQueries, mOptions,
if (! history->EvaluateQueryForNode(mQueries, mOptions,
addition->GetAsURI()))
return NS_OK; // don't need to include in our query
break;
@ -2051,11 +2305,11 @@ NS_IMPL_ISUPPORTS_INHERITED2(nsNavHistoryFolderResultNode,
nsINavHistoryFolderResultNode)
nsNavHistoryFolderResultNode::nsNavHistoryFolderResultNode(
const nsACString& aTitle, PRUint32 aAccessCount, PRTime aTime,
nsNavHistoryQueryOptions* aOptions, PRInt64 aFolderId) :
nsNavHistoryContainerResultNode(aTitle, aAccessCount, aTime, EmptyCString(),
const nsACString& aTitle, nsNavHistoryQueryOptions* aOptions,
PRInt64 aFolderId, const nsACString& aRemoteContainerType) :
nsNavHistoryContainerResultNode(aTitle, EmptyCString(),
nsINavHistoryResultNode::RESULT_TYPE_FOLDER,
PR_FALSE),
PR_FALSE, aRemoteContainerType),
mContentsValid(PR_FALSE),
mOptions(aOptions),
mFolderId(aFolderId)
@ -2104,11 +2358,28 @@ nsNavHistoryFolderResultNode::OnRemoving()
nsresult
nsNavHistoryFolderResultNode::OpenContainer()
{
NS_ASSERTION(! mExpanded, "Container must be expanded to close it");
nsresult rv;
if (! mRemoteContainerType.IsEmpty()) {
// remote container API may want to change the bookmarks for this folder.
nsCOMPtr<nsIRemoteContainer> remote = do_GetService(mRemoteContainerType.get(), &rv);
if (NS_SUCCEEDED(rv)) {
remote->OnContainerOpening(NS_STATIC_CAST(nsINavHistoryFolderResultNode*, this),
mOptions);
} else {
NS_WARNING("Unable to get remote container for ");
NS_WARNING(mRemoteContainerType.get());
}
}
if (! mContentsValid) {
nsresult rv = FillChildren();
rv = FillChildren();
NS_ENSURE_SUCCESS(rv, rv);
}
return nsNavHistoryContainerResultNode::OpenContainer();
mExpanded = PR_TRUE;
nsNavHistoryResult* result = GetResult();
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
return result->RefreshVisibleSection(this);
}
@ -2734,11 +3005,9 @@ nsNavHistoryResult::ComputeShowSessions()
return; // not date sorting
PRUint32 groupCount;
const PRUint32* groups = mOptions->GroupingMode(&groupCount);
for (PRUint32 i = 0; i < groupCount; i ++) {
if (groups[i] != nsINavHistoryQueryOptions::GROUP_BY_DAY)
return; // non-time-based grouping
}
mOptions->GroupingMode(&groupCount);
if (groupCount > 0)
return;
mShowSessions = PR_TRUE;
}

View File

@ -53,6 +53,7 @@ class nsNavHistory;
class nsNavHistoryResult;
class nsIDateTimeFormat;
class nsIWritablePropertyBag;
class nsNavHistoryQuery;
class nsNavHistoryQueryOptions;
class nsNavHistoryContainerResultNode;
@ -167,13 +168,14 @@ public:
public:
nsNavHistoryResult* GetResult();
nsNavHistoryQueryOptions* GetGeneratingOptions();
// These functions test the type. We don't use a virtual function since that
// 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_DAY ||
type == nsINavHistoryResultNode::RESULT_TYPE_REMOTE_CONTAINER ||
type == nsINavHistoryResultNode::RESULT_TYPE_QUERY ||
type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER);
}
@ -184,10 +186,10 @@ public:
}
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 include host
// and day containers, but doesn't include other queries and folders.
return (type == nsINavHistoryResultNode::RESULT_TYPE_HOST ||
type == nsINavHistoryResultNode::RESULT_TYPE_DAY);
// 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);
}
PRBool IsQuerySubcontainer() {
PRUint32 type;
@ -371,17 +373,31 @@ public:
NS_IMETHOD GetChild(PRUint32 index, nsINavHistoryResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::GetChild(index, _retval); } \
NS_IMETHOD GetChildrenReadOnly(PRBool *aChildrenReadOnly) \
{ return nsNavHistoryContainerResultNode::GetChildrenReadOnly(aChildrenReadOnly); }
{ return nsNavHistoryContainerResultNode::GetChildrenReadOnly(aChildrenReadOnly); } \
NS_IMETHOD GetRemoteContainerType(nsACString& aRemoteContainerType) \
{ return nsNavHistoryContainerResultNode::GetRemoteContainerType(aRemoteContainerType); } \
NS_IMETHOD AppendURINode(const nsACString& aTitle, PRUint32 aAccessCount, PRTime aTime, const nsACString& aIconURI, const nsACString & aURI, nsINavHistoryURIResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::AppendURINode(aTitle, aAccessCount, aTime, aIconURI, aURI, _retval); } \
NS_IMETHOD AppendVisitNode(const nsACString & aTitle, PRUint32 aAccessCount, PRTime aTime, const nsACString & aIconURI, const nsACString & aURI, PRInt64 aSession, nsINavHistoryVisitResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::AppendVisitNode(aTitle, aAccessCount, aTime, aIconURI, aURI, aSession, _retval); } \
NS_IMETHOD AppendFullVisitNode(const nsACString & aTitle, PRUint32 aAccessCount, PRTime aTime, const nsACString & aIconURI, const nsACString & aURI, PRInt64 aSession, PRInt64 aVisitId, PRInt64 aReferringVisitId, PRInt32 aTransitionType, nsINavHistoryFullVisitResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::AppendFullVisitNode(aTitle, aAccessCount, aTime, aIconURI, aURI, aSession, aVisitId, aReferringVisitId, aTransitionType, _retval); } \
NS_IMETHOD AppendContainerNode(const nsACString & aTitle, const nsACString & aIconURI, PRUint32 aContainerType, const nsACString & aRemoteContainerType, nsINavHistoryContainerResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::AppendContainerNode(aTitle, aIconURI, aContainerType, aRemoteContainerType, _retval); } \
NS_IMETHOD AppendQueryNode(const nsACString & aTitle, const nsACString & aIconURI, const nsACString & aQueryString, nsINavHistoryQueryResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::AppendQueryNode(aTitle, aIconURI, aQueryString, _retval); } \
NS_IMETHOD AppendFolderNode(PRInt64 aFolderId, nsINavHistoryFolderResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::AppendFolderNode(aFolderId, _retval); } \
NS_IMETHOD ClearContents() \
{ return nsNavHistoryContainerResultNode::ClearContents(); }
class nsNavHistoryContainerResultNode : public nsNavHistoryResultNode,
public nsINavHistoryContainerResultNode
{
public:
nsNavHistoryContainerResultNode(const nsACString& aTitle, PRUint32 aAccessCount,
PRTime aTime, const nsACString& aIconURI, PRUint32 aContainerType,
PRBool aReadOnly);
nsNavHistoryContainerResultNode(const nsACString& aTitle,
const nsACString& aIconURI, PRUint32 aContainerType);
const nsACString& aIconURI, PRUint32 aContainerType,
PRBool aReadOnly, const nsACString& aRemoteContainerType);
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_RESULTNODE_TO_BASE_EXCEPT_GETTYPE
@ -397,7 +413,7 @@ public:
// overridded by descendents to populate
virtual nsresult OpenContainer();
virtual nsresult CloseContainer();
nsresult CloseContainer();
// this points to the result that owns this container. All containers have
// their result pointer set so we can quickly get to the result without having
@ -405,8 +421,8 @@ public:
// for every leaf node to the result.
nsNavHistoryResult* mResult;
// for example, RESULT_TYPE_HOST or RESULT_TYPE_DAY. Query and Folder results
// override GetType so this is not used, but is still kept in sync.
// for example, RESULT_TYPE_HOST. Query and Folder results override GetType
// so this is not used, but is still kept in sync.
PRUint32 mContainerType;
// when there are children, this stores the open state in the tree
@ -418,6 +434,11 @@ public:
PRBool mChildrenReadOnly;
// ID of a remote container interface that we can use GetService to get.
// This is empty to indicate there is no remote container service for this
// container (the common case).
nsCString mRemoteContainerType;
void FillStats();
void ReverseUpdateStats(PRInt32 aAccessCountChange);
@ -472,6 +493,8 @@ public:
nsresult ReplaceChildURIAt(PRUint32 aIndex,
nsNavHistoryURIResultNode* aNode);
nsresult RemoveChildAt(PRInt32 aIndex, PRBool aIsTemporary = PR_FALSE);
PRBool CanRemoteContainersChange();
};
@ -485,14 +508,12 @@ class nsNavHistoryQueryResultNode : public nsNavHistoryContainerResultNode,
public nsINavHistoryQueryResultNode
{
public:
nsNavHistoryQueryResultNode(nsNavHistoryQueryOptions* aGeneratingOptions,
const nsACString& aTitle, PRUint32 aAccessCount,
PRTime aTime, const nsACString& aIconURI,
nsNavHistoryQueryResultNode(const nsACString& aTitle,
const nsACString& aIconURI,
const nsACString& aQueryURI);
nsNavHistoryQueryResultNode(nsNavHistoryQueryOptions* aGeneratingOptions,
const nsACString& aTitle, PRUint32 aAccessCount,
PRTime aTime, const nsACString& aIconURI,
nsINavHistoryQuery** aQueries, PRUint32 aQueryCount,
nsNavHistoryQueryResultNode(const nsACString& aTitle,
const nsACString& aIconURI,
const nsCOMArray<nsNavHistoryQuery>& aQueries,
nsNavHistoryQueryOptions* aOptions);
NS_DECL_ISUPPORTS_INHERITED
@ -511,13 +532,6 @@ public:
virtual void OnRemoving();
public:
// These are the options that caused this node to be generated. For just
// running queries directly, this node will be the root of the result and
// mGeneratingOptions will be the same as mOptions. When queries are in
// bookmark folders, this it the options structure used to generate the
// bookmarks tree. It tells us, for example, if we should expand ourselves.
nsCOMPtr<nsNavHistoryQueryOptions> mGeneratingOptions;
// this may be constructedlazily from mQueries and mOptions, call VerifyQueriesSerialized
// either this or mQueries/mOptions should be valid
nsCString mQueryURI;
@ -525,7 +539,7 @@ public:
// these may be constructed lazily from mQueryURI, call VerifyQueriesParsed
// either this or mQueryURI should be valid
nsCOMArray<nsINavHistoryQuery> mQueries;
nsCOMArray<nsNavHistoryQuery> mQueries;
nsCOMPtr<nsNavHistoryQueryOptions> mOptions;
PRUint32 mLiveUpdate; // one of QUERYUPDATE_* in nsNavHistory.h
PRBool mHasSearchTerms;
@ -561,9 +575,10 @@ class nsNavHistoryFolderResultNode : public nsNavHistoryContainerResultNode,
public nsINavHistoryFolderResultNode
{
public:
nsNavHistoryFolderResultNode(const nsACString& aTitle, PRUint32 aAccessCount,
PRTime aTime, nsNavHistoryQueryOptions* options,
PRInt64 aFolderId);
nsNavHistoryFolderResultNode(const nsACString& aTitle,
nsNavHistoryQueryOptions* options,
PRInt64 aFolderId,
const nsACString& aRemoteContainerType);
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_RESULTNODE_TO_BASE_EXCEPT_GETTYPE