mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
History-based bookmarks implementation for Places. Bug 314553, r=brettw.
This commit is contained in:
parent
9d6eceb84f
commit
d0295dcf29
@ -87,3 +87,9 @@
|
||||
|
||||
#define NS_NAVHISTORY_CONTRACTID \
|
||||
"@mozilla.org/browser/nav-history;1"
|
||||
|
||||
#define NS_NAVBOOKMARKSSERVICE_CID \
|
||||
{ 0x9de95a0c, 0x39a4, 0x4d64, {0x9a, 0x53, 0x17, 0x94, 0x0d, 0xd7, 0xca, 0xbb}}
|
||||
|
||||
#define NS_NAVBOOKMARKSSERVICE_CONTRACTID \
|
||||
"@mozilla.org/browser/nav-bookmarks-service;1"
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "nsForwardProxyDataSource.h"
|
||||
#ifdef MOZ_PLACES
|
||||
#include "nsNavHistory.h"
|
||||
#include "nsNavBookmarks.h"
|
||||
#endif
|
||||
#ifdef XP_WIN
|
||||
#include "nsWindowsShellService.h"
|
||||
@ -77,6 +78,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsBookmarksService, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsForwardProxyDataSource, Init)
|
||||
#ifdef MOZ_PLACES
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNavHistory, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNavBookmarks, Init)
|
||||
#endif
|
||||
#ifdef XP_WIN
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindowsShellService)
|
||||
@ -137,6 +139,11 @@ static const nsModuleComponentInfo components[] =
|
||||
NS_NAVHISTORY_CID,
|
||||
"@mozilla.org/autocomplete/search;1?name=history",
|
||||
nsNavHistoryConstructor },
|
||||
|
||||
{ "Browser Bookmarks Service",
|
||||
NS_NAVBOOKMARKSSERVICE_CID,
|
||||
NS_NAVBOOKMARKSSERVICE_CONTRACTID,
|
||||
nsNavBookmarksConstructor },
|
||||
#endif
|
||||
|
||||
{ "Bookmarks",
|
||||
|
@ -49,6 +49,7 @@ XPIDL_MODULE = places
|
||||
XPIDLSRCS = \
|
||||
nsIAnnotationService.idl \
|
||||
nsINavHistory.idl \
|
||||
nsINavBookmarksService.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
264
browser/components/places/public/nsINavBookmarksService.idl
Normal file
264
browser/components/places/public/nsINavBookmarksService.idl
Normal file
@ -0,0 +1,264 @@
|
||||
/* -*- 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):
|
||||
* Brian Ryner <bryner@brianryner.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 nsINavHistoryResult;
|
||||
|
||||
/**
|
||||
* Observer for bookmark changes.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(c4159523-bedb-4e3f-a163-087e6d89e8a6)]
|
||||
interface nsINavBookmarkObserver : nsISupports
|
||||
{
|
||||
/**
|
||||
* Notify this observer that a batch transaction has started.
|
||||
* Other notifications will be sent during the batch change,
|
||||
* but the observer is guaranteed that onEndUpdateBatch() will be called
|
||||
* at the completion of changes.
|
||||
*/
|
||||
void onBeginUpdateBatch();
|
||||
|
||||
/**
|
||||
* Notify this observer that a batch transaction has ended.
|
||||
*/
|
||||
void onEndUpdateBatch();
|
||||
|
||||
/**
|
||||
* True requests that you want to get called for all updates, false if you
|
||||
* don't necessarily care about which exact things changed during a batch
|
||||
* update. If false, this will sometimes not call you for things in between
|
||||
* onBeginUpdateBatch and onEndUpdateBatch. You'll still get the begin and
|
||||
* end, so you'll know something changed.
|
||||
*
|
||||
* Lots of observers don't care about what changes, only that something
|
||||
* changed so they can update their UI. This allows delete operations to
|
||||
* avoid iterating over every item, and just doing a single bulk SQL DELETE
|
||||
* command, which is much more efficient.
|
||||
*
|
||||
* Note that you still might get called if you say false in some situations.
|
||||
* This only skips certain time-consuming notifications if NO observers
|
||||
* want the information.
|
||||
*/
|
||||
readonly attribute boolean wantAllDetails;
|
||||
|
||||
/**
|
||||
* Notify this observer that the bookmark was added.
|
||||
* Called after the actual add took place.
|
||||
*
|
||||
* @param bookmark The bookmark item that was added.
|
||||
* @param folder The folder that the item was added to.
|
||||
* @param index The item's index in the folder.
|
||||
*/
|
||||
void onItemAdded(in nsIURI bookmark, in PRInt64 folder, in long index);
|
||||
|
||||
/**
|
||||
* Notify this observer that the bookmark was removed.
|
||||
* Called after the actual remove took place.
|
||||
*
|
||||
* @param bookmark The bookmark item will be removed.
|
||||
* @param folder The folder that the item was removed from.
|
||||
* @param index The bookmark's index in the folder.
|
||||
*/
|
||||
void onItemRemoved(in nsIURI bookmark, in PRInt64 container, in long index);
|
||||
|
||||
/**
|
||||
* Notify this observer that a bookmark's information has changed. This
|
||||
* will be called whenever any attributes like "title" are changed.
|
||||
*
|
||||
* @param bookmark The bookmark which changed.
|
||||
* @param property The property which changed.
|
||||
*/
|
||||
void onItemChanged(in nsIURI bookmark, in ACString property);
|
||||
|
||||
/**
|
||||
* Notify this observer that a bookmark folder has been added.
|
||||
* @param folder The id of the folder that was added.
|
||||
* @param parent The id of the folder's parent.
|
||||
* @param index The folder's index inside its parent.
|
||||
*/
|
||||
void onFolderAdded(in PRInt64 folder, in PRInt64 parent, in long index);
|
||||
|
||||
/**
|
||||
* Notify this observer that a bookmark folder has been removed.
|
||||
* @param folder The id of the folder that was removed.
|
||||
* @param parent The id of the folder's old parent.
|
||||
* @param index The folder's old index in its parent.
|
||||
*/
|
||||
void onFolderRemoved(in PRInt64 folder, in PRInt64 parent, in long index);
|
||||
|
||||
/**
|
||||
* Notify this observer that a bookmark folder has been moved.
|
||||
* @param folder The id of the folder that was moved.
|
||||
* @param newParent The id of the folder's new paremt.
|
||||
* @param index The folder's index inside newParent.
|
||||
*/
|
||||
void onFolderMoved(in PRInt64 folder, in PRInt64 newParent, in long index);
|
||||
|
||||
/**
|
||||
* Notify this observer that a bookmark folder's information has changed.
|
||||
* This will be called whenever any attributes like "title" are changed.
|
||||
* @param folder The id of the folder that was changed.
|
||||
* @param property The property that was changed.
|
||||
*/
|
||||
void onFolderChanged(in PRInt64 folder, in ACString property);
|
||||
};
|
||||
|
||||
/**
|
||||
* The BookmarksService interface provides methods for managing bookmarked
|
||||
* history items. Bookmarks consist of a set of user-customizable
|
||||
* folders. A URI in history can be contained in one or more such folders.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(5feca204-b735-40e8-921f-8b057eedffe2)]
|
||||
interface nsINavBookmarksService : nsISupports
|
||||
{
|
||||
/**
|
||||
* The folder ID of the bookmarks root.
|
||||
*/
|
||||
readonly attribute PRInt64 bookmarksRoot;
|
||||
|
||||
/**
|
||||
* A query result containing the bookmarks folder tree.
|
||||
*/
|
||||
readonly attribute nsINavHistoryResult bookmarks;
|
||||
|
||||
/**
|
||||
* Inserts a child item into the given folder.
|
||||
* @param folder The id of the parent folder
|
||||
* @param item The URI to insert
|
||||
* @param index The index to insert at, or -1 to append
|
||||
*/
|
||||
void insertItem(in PRInt64 folder, in nsIURI item, in PRInt32 index);
|
||||
|
||||
/**
|
||||
* Removes a child item from the given folder.
|
||||
* @param folder The folder to remove the child from
|
||||
* @param item The child item to remove
|
||||
*/
|
||||
void removeItem(in PRInt64 folder, in nsIURI child);
|
||||
|
||||
/**
|
||||
* Creates a new child folder and inserts it under the given parent.
|
||||
* @param parent The id of the parent folder
|
||||
* @param name The name of the new folder
|
||||
* @param index The index to insert at, or -1 to append
|
||||
* @returns the ID of the newly-inserted folder
|
||||
*/
|
||||
PRInt64 createFolder(in PRInt64 parent, in AString name, in PRInt32 index);
|
||||
|
||||
/**
|
||||
* Removes a folder from the bookmarks tree.
|
||||
* @param folder The id of the folder to remove.
|
||||
*/
|
||||
void removeFolder(in PRInt64 folder);
|
||||
|
||||
/**
|
||||
* Moves a folder to a different container, preserving its contents.
|
||||
* @param folder The folder to move
|
||||
* @param newParent The id of the folder's new parent
|
||||
* @param index The folder's index under newParent, or -1 to append
|
||||
*/
|
||||
void moveFolder(in PRInt64 folder, in PRInt64 newParent, in PRInt32 index);
|
||||
|
||||
/**
|
||||
* Set the history/bookmark title for a URI. The new title will be used
|
||||
* anywhere the URI is shown in bookmarks or history.
|
||||
* @param uri The URI whose name should be set
|
||||
* @param title The new title for the URI
|
||||
*/
|
||||
void setItemTitle(in nsIURI uri, in AString title);
|
||||
|
||||
/**
|
||||
* Get the history/bookmark title for the URI.
|
||||
* @param uri The URI whose title should be retrieved
|
||||
* @returns The title for the URI.
|
||||
*/
|
||||
AString getItemTitle(in nsIURI uri);
|
||||
|
||||
/**
|
||||
* Set the title for a bookmark folder.
|
||||
* @param folder The folder whose title should be set
|
||||
* @param title The new title for the folder
|
||||
*/
|
||||
void setFolderTitle(in PRInt64 folder, in AString title);
|
||||
|
||||
/**
|
||||
* Get the title for a bookmark folder.
|
||||
* @param folder The folder whose title should be retrieved
|
||||
* @returns The title for the folder
|
||||
*/
|
||||
AString getFolderTitle(in PRInt64 folder);
|
||||
|
||||
/**
|
||||
* Returns true if the given URI is in any bookmark folder.
|
||||
*/
|
||||
boolean isBookmarked(in nsIURI uri);
|
||||
|
||||
/**
|
||||
* Returns the list of folder ids that contain the given URI.
|
||||
*/
|
||||
void getBookmarkCategories(in nsIURI uri, out PRUint32 count,
|
||||
[array, retval, size_is(count)] out PRInt64 categories);
|
||||
|
||||
/**
|
||||
* Adds a bookmark observer. The bookmark service will keep an owning
|
||||
* reference to the observer.
|
||||
*/
|
||||
void addObserver(in nsINavBookmarkObserver aObserver);
|
||||
|
||||
/**
|
||||
* Removes a bookmark observer.
|
||||
*/
|
||||
void removeObserver(in nsINavBookmarkObserver aObserver);
|
||||
|
||||
/**
|
||||
* Causes observers to be notified of a beginUpdateBatch when a lot of things
|
||||
* are about to change. Calls can be nested, observers will only be
|
||||
* notified when all batches begin/end.
|
||||
*/
|
||||
void beginUpdateBatch();
|
||||
|
||||
/**
|
||||
* Causes observers to be notified of an endUpdateBatch when a batch is
|
||||
* done changing. Should match beginUpdateBatch or bad things will happen.
|
||||
*/
|
||||
void endUpdateBatch();
|
||||
};
|
@ -55,7 +55,8 @@ interface nsINavHistoryResultNode : nsISupports
|
||||
const PRUint32 RESULT_TYPE_VISIT = 1;
|
||||
const PRUint32 RESULT_TYPE_HOST = 2;
|
||||
const PRUint32 RESULT_TYPE_DAY = 3;
|
||||
readonly attribute PRUInt32 type;
|
||||
const PRUint32 RESULT_TYPE_FOLDER = 4;
|
||||
readonly attribute PRUint32 type;
|
||||
|
||||
/**
|
||||
* URL of the web page in question. Empty for all other types, including
|
||||
@ -305,6 +306,101 @@ interface nsINavHistoryQuery : nsISupports
|
||||
readonly attribute boolean hasDomain;
|
||||
};
|
||||
|
||||
/**
|
||||
* This object represents the global options for executing a query.
|
||||
*/
|
||||
[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 PRInt32 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,
|
||||
* "bugzilla.mozilla.org" and "www.mozilla.org" will be separate). The
|
||||
* children of these will correspond to the results for each host.
|
||||
*/
|
||||
const PRInt32 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 PRInt32 GROUP_BY_DOMAIN = 2;
|
||||
|
||||
/**
|
||||
* Group by bookmark folder.
|
||||
* This should only be used for queries which have onlyBookmarked set.
|
||||
*/
|
||||
const PRInt32 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
|
||||
* be self-explanatory.
|
||||
*
|
||||
* Note: re-sorting is slower, as is sorting by title or when you have a
|
||||
* host name.
|
||||
*/
|
||||
const PRInt32 SORT_BY_NONE = 0;
|
||||
const PRInt32 SORT_BY_TITLE_ASCENDING = 1;
|
||||
const PRInt32 SORT_BY_TITLE_DESCENDING = 2;
|
||||
const PRInt32 SORT_BY_DATE_ASCENDING = 3;
|
||||
const PRInt32 SORT_BY_DATE_DESCENDING = 4;
|
||||
const PRInt32 SORT_BY_URL_ASCENDING = 5;
|
||||
const PRInt32 SORT_BY_URL_DESCENDING = 6;
|
||||
const PRInt32 SORT_BY_VISITCOUNT_ASCENDING = 7;
|
||||
const PRInt32 SORT_BY_VISITCOUNT_DESCENDING = 8;
|
||||
|
||||
/**
|
||||
* "URL" results, one for each URL visited in the range.
|
||||
*/
|
||||
const PRInt32 RESULT_TYPE_URL = 0;
|
||||
|
||||
/**
|
||||
* "Visit" results, with one for each time a page was visited
|
||||
* (this will often give you multiple results for one URL).
|
||||
*/
|
||||
const PRInt32 RESULT_TYPE_VISIT = 1;
|
||||
|
||||
/**
|
||||
* Set 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.
|
||||
*/
|
||||
void setGroupingMode([const,array,size_is(groupCount)] in PRInt32 groupingMode,
|
||||
in PRUint32 groupCount);
|
||||
|
||||
/**
|
||||
* Set the sorting mode to be used for this query.
|
||||
* mode is one of SORT_BY_*
|
||||
*/
|
||||
void setSortingMode(in PRInt32 mode);
|
||||
|
||||
/**
|
||||
* Sets the result type. One of RESULT_TYPE_*.
|
||||
*/
|
||||
void setResultType(in PRInt32 type);
|
||||
|
||||
/**
|
||||
* When set, allows items with "place:" URIs to appear as containers,
|
||||
* with the container's contents filled in from the stored query.
|
||||
* If not set, these will appear as normal items.
|
||||
*/
|
||||
void setExpandPlaces(in boolean expand);
|
||||
};
|
||||
|
||||
[scriptable, uuid(C51F54CB-5E89-4B20-A37C-1343888935B7)]
|
||||
interface nsINavHistory : nsISupports
|
||||
{
|
||||
@ -325,74 +421,23 @@ interface nsINavHistory : nsISupports
|
||||
*/
|
||||
boolean canAddURI(in nsIURI aURI);
|
||||
|
||||
/**
|
||||
* 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,
|
||||
* "bugzilla.mozilla.org" and "www.mozilla.org" will be separate). The
|
||||
* children of these will correspond to the results for each host.
|
||||
*/
|
||||
const PRUint32 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 PRUint32 GROUP_BY_DOMAIN = 2;
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* be self-explanatory.
|
||||
*
|
||||
* Note: re-sorting is slower, as is sorting by title or when you have a
|
||||
* host name.
|
||||
*/
|
||||
const PRUint32 SORT_BY_NONE = 0;
|
||||
const PRUint32 SORT_BY_TITLE_ASCENDING = 1;
|
||||
const PRUint32 SORT_BY_TITLE_DESCENDING = 2;
|
||||
const PRUint32 SORT_BY_DATE_ASCENDING = 3;
|
||||
const PRUint32 SORT_BY_DATE_DESCENDING = 4;
|
||||
const PRUint32 SORT_BY_URL_ASCENDING = 5;
|
||||
const PRUint32 SORT_BY_URL_DESCENDING = 6;
|
||||
const PRUint32 SORT_BY_VISITCOUNT_ASCENDING = 7;
|
||||
const PRUint32 SORT_BY_VISITCOUNT_DESCENDING = 8;
|
||||
|
||||
/**
|
||||
* This returns a new query object that you can pass to executeQuer[y/ies].
|
||||
* It will be initialized to all empty (so using it will give you all history).
|
||||
*/
|
||||
nsINavHistoryQuery getNewQuery();
|
||||
|
||||
/**
|
||||
* This returns a new options object that you can pass to executeQuer[y/ies]
|
||||
* after setting the desired options.
|
||||
*/
|
||||
nsINavHistoryQueryOptions getNewQueryOptions();
|
||||
|
||||
/**
|
||||
* Executes a single query.
|
||||
*
|
||||
* sortingMode is one of SORT_BY_*
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* asVisits is what to return for the pages. If false, this will return "URL"
|
||||
* results, one for each URL visited in the range. If true, this will return
|
||||
* "visit" results, with one for each time a page was visited (this will
|
||||
* often give you multiple results for one URL).
|
||||
*/
|
||||
nsINavHistoryResult executeQuery(in nsINavHistoryQuery aQuery,
|
||||
[const,array,size_is(aGroupCount)] in PRInt32 aGroupingMode, in PRUint32 aGroupCount,
|
||||
in PRInt32 aSortingMode, in PRBool aAsVisits);
|
||||
in nsINavHistoryQueryOptions options);
|
||||
|
||||
/**
|
||||
* Executes an array of queries. All of the query objects are ORed
|
||||
@ -401,8 +446,7 @@ interface nsINavHistory : nsISupports
|
||||
*/
|
||||
nsINavHistoryResult executeQueries(
|
||||
[const,array,size_is(aQueryCount)] in nsINavHistoryQuery aQueries, in PRUint32 aQueryCount,
|
||||
[const,array,size_is(aGroupCount)] in PRInt32 aGroupingMode, in PRUint32 aGroupCount,
|
||||
in PRInt32 aSortingMode, in PRBool aAsVisits);
|
||||
in nsINavHistoryQueryOptions options);
|
||||
|
||||
/**
|
||||
* Adds a history observer. The history service will keep an owning
|
||||
|
@ -55,7 +55,8 @@ interface nsINavHistoryResultNode : nsISupports
|
||||
const PRUint32 RESULT_TYPE_VISIT = 1;
|
||||
const PRUint32 RESULT_TYPE_HOST = 2;
|
||||
const PRUint32 RESULT_TYPE_DAY = 3;
|
||||
readonly attribute PRUInt32 type;
|
||||
const PRUint32 RESULT_TYPE_FOLDER = 4;
|
||||
readonly attribute PRUint32 type;
|
||||
|
||||
/**
|
||||
* URL of the web page in question. Empty for all other types, including
|
||||
@ -305,6 +306,101 @@ interface nsINavHistoryQuery : nsISupports
|
||||
readonly attribute boolean hasDomain;
|
||||
};
|
||||
|
||||
/**
|
||||
* This object represents the global options for executing a query.
|
||||
*/
|
||||
[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 PRInt32 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,
|
||||
* "bugzilla.mozilla.org" and "www.mozilla.org" will be separate). The
|
||||
* children of these will correspond to the results for each host.
|
||||
*/
|
||||
const PRInt32 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 PRInt32 GROUP_BY_DOMAIN = 2;
|
||||
|
||||
/**
|
||||
* Group by bookmark folder.
|
||||
* This should only be used for queries which have onlyBookmarked set.
|
||||
*/
|
||||
const PRInt32 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
|
||||
* be self-explanatory.
|
||||
*
|
||||
* Note: re-sorting is slower, as is sorting by title or when you have a
|
||||
* host name.
|
||||
*/
|
||||
const PRInt32 SORT_BY_NONE = 0;
|
||||
const PRInt32 SORT_BY_TITLE_ASCENDING = 1;
|
||||
const PRInt32 SORT_BY_TITLE_DESCENDING = 2;
|
||||
const PRInt32 SORT_BY_DATE_ASCENDING = 3;
|
||||
const PRInt32 SORT_BY_DATE_DESCENDING = 4;
|
||||
const PRInt32 SORT_BY_URL_ASCENDING = 5;
|
||||
const PRInt32 SORT_BY_URL_DESCENDING = 6;
|
||||
const PRInt32 SORT_BY_VISITCOUNT_ASCENDING = 7;
|
||||
const PRInt32 SORT_BY_VISITCOUNT_DESCENDING = 8;
|
||||
|
||||
/**
|
||||
* "URL" results, one for each URL visited in the range.
|
||||
*/
|
||||
const PRInt32 RESULT_TYPE_URL = 0;
|
||||
|
||||
/**
|
||||
* "Visit" results, with one for each time a page was visited
|
||||
* (this will often give you multiple results for one URL).
|
||||
*/
|
||||
const PRInt32 RESULT_TYPE_VISIT = 1;
|
||||
|
||||
/**
|
||||
* Set 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.
|
||||
*/
|
||||
void setGroupingMode([const,array,size_is(groupCount)] in PRInt32 groupingMode,
|
||||
in PRUint32 groupCount);
|
||||
|
||||
/**
|
||||
* Set the sorting mode to be used for this query.
|
||||
* mode is one of SORT_BY_*
|
||||
*/
|
||||
void setSortingMode(in PRInt32 mode);
|
||||
|
||||
/**
|
||||
* Sets the result type. One of RESULT_TYPE_*.
|
||||
*/
|
||||
void setResultType(in PRInt32 type);
|
||||
|
||||
/**
|
||||
* When set, allows items with "place:" URIs to appear as containers,
|
||||
* with the container's contents filled in from the stored query.
|
||||
* If not set, these will appear as normal items.
|
||||
*/
|
||||
void setExpandPlaces(in boolean expand);
|
||||
};
|
||||
|
||||
[scriptable, uuid(C51F54CB-5E89-4B20-A37C-1343888935B7)]
|
||||
interface nsINavHistory : nsISupports
|
||||
{
|
||||
@ -325,74 +421,23 @@ interface nsINavHistory : nsISupports
|
||||
*/
|
||||
boolean canAddURI(in nsIURI aURI);
|
||||
|
||||
/**
|
||||
* 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,
|
||||
* "bugzilla.mozilla.org" and "www.mozilla.org" will be separate). The
|
||||
* children of these will correspond to the results for each host.
|
||||
*/
|
||||
const PRUint32 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 PRUint32 GROUP_BY_DOMAIN = 2;
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* be self-explanatory.
|
||||
*
|
||||
* Note: re-sorting is slower, as is sorting by title or when you have a
|
||||
* host name.
|
||||
*/
|
||||
const PRUint32 SORT_BY_NONE = 0;
|
||||
const PRUint32 SORT_BY_TITLE_ASCENDING = 1;
|
||||
const PRUint32 SORT_BY_TITLE_DESCENDING = 2;
|
||||
const PRUint32 SORT_BY_DATE_ASCENDING = 3;
|
||||
const PRUint32 SORT_BY_DATE_DESCENDING = 4;
|
||||
const PRUint32 SORT_BY_URL_ASCENDING = 5;
|
||||
const PRUint32 SORT_BY_URL_DESCENDING = 6;
|
||||
const PRUint32 SORT_BY_VISITCOUNT_ASCENDING = 7;
|
||||
const PRUint32 SORT_BY_VISITCOUNT_DESCENDING = 8;
|
||||
|
||||
/**
|
||||
* This returns a new query object that you can pass to executeQuer[y/ies].
|
||||
* It will be initialized to all empty (so using it will give you all history).
|
||||
*/
|
||||
nsINavHistoryQuery getNewQuery();
|
||||
|
||||
/**
|
||||
* This returns a new options object that you can pass to executeQuer[y/ies]
|
||||
* after setting the desired options.
|
||||
*/
|
||||
nsINavHistoryQueryOptions getNewQueryOptions();
|
||||
|
||||
/**
|
||||
* Executes a single query.
|
||||
*
|
||||
* sortingMode is one of SORT_BY_*
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* asVisits is what to return for the pages. If false, this will return "URL"
|
||||
* results, one for each URL visited in the range. If true, this will return
|
||||
* "visit" results, with one for each time a page was visited (this will
|
||||
* often give you multiple results for one URL).
|
||||
*/
|
||||
nsINavHistoryResult executeQuery(in nsINavHistoryQuery aQuery,
|
||||
[const,array,size_is(aGroupCount)] in PRInt32 aGroupingMode, in PRUint32 aGroupCount,
|
||||
in PRInt32 aSortingMode, in PRBool aAsVisits);
|
||||
in nsINavHistoryQueryOptions options);
|
||||
|
||||
/**
|
||||
* Executes an array of queries. All of the query objects are ORed
|
||||
@ -401,8 +446,7 @@ interface nsINavHistory : nsISupports
|
||||
*/
|
||||
nsINavHistoryResult executeQueries(
|
||||
[const,array,size_is(aQueryCount)] in nsINavHistoryQuery aQueries, in PRUint32 aQueryCount,
|
||||
[const,array,size_is(aGroupCount)] in PRInt32 aGroupingMode, in PRUint32 aGroupCount,
|
||||
in PRInt32 aSortingMode, in PRBool aAsVisits);
|
||||
in nsINavHistoryQueryOptions options);
|
||||
|
||||
/**
|
||||
* Adds a history observer. The history service will keep an owning
|
||||
|
@ -66,11 +66,12 @@ REQUIRES = xpcom \
|
||||
uconv \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = -I$(DEPTH)/toolkit/components/autocomplete/src
|
||||
LOCAL_INCLUDES = -I$(srcdir)/../../build
|
||||
|
||||
CPPSRCS = \
|
||||
nsAnnotationService.cpp \
|
||||
nsNavHistory.cpp \
|
||||
nsNavBookmarks.cpp \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
784
browser/components/places/src/nsNavBookmarks.cpp
Normal file
784
browser/components/places/src/nsNavBookmarks.cpp
Normal file
@ -0,0 +1,784 @@
|
||||
/* -*- Mode: C++; tab-width: 8; 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):
|
||||
* Brian Ryner <bryner@brianryner.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 "nsNavBookmarks.h"
|
||||
#include "nsNavHistory.h"
|
||||
#include "mozStorageHelper.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
const PRInt32 nsNavBookmarks::kFindBookmarksIndex_ItemChild = 0;
|
||||
const PRInt32 nsNavBookmarks::kFindBookmarksIndex_FolderChild = 1;
|
||||
const PRInt32 nsNavBookmarks::kFindBookmarksIndex_Parent = 2;
|
||||
const PRInt32 nsNavBookmarks::kFindBookmarksIndex_Position = 3;
|
||||
|
||||
const PRInt32 nsNavBookmarks::kGetFolderInfoIndex_FolderID = 0;
|
||||
const PRInt32 nsNavBookmarks::kGetFolderInfoIndex_Title = 1;
|
||||
|
||||
// These columns sit to the right of the kGetInfoIndex_* columns.
|
||||
const PRInt32 nsNavBookmarks::kGetChildrenIndex_Position = 6;
|
||||
const PRInt32 nsNavBookmarks::kGetChildrenIndex_ItemChild = 7;
|
||||
const PRInt32 nsNavBookmarks::kGetChildrenIndex_FolderChild = 8;
|
||||
const PRInt32 nsNavBookmarks::kGetChildrenIndex_FolderTitle = 9;
|
||||
|
||||
nsNavBookmarks* nsNavBookmarks::sInstance = nsnull;
|
||||
|
||||
nsNavBookmarks::nsNavBookmarks()
|
||||
{
|
||||
NS_ASSERTION(!sInstance, "Multiple nsNavBookmarks instances!");
|
||||
sInstance = this;
|
||||
}
|
||||
|
||||
nsNavBookmarks::~nsNavBookmarks()
|
||||
{
|
||||
NS_ASSERTION(sInstance == this, "Expected sInstance == this");
|
||||
sInstance = nsnull;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsNavBookmarks,
|
||||
nsINavBookmarksService, nsINavHistoryObserver)
|
||||
|
||||
nsresult
|
||||
nsNavBookmarks::Init()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsNavHistory *history = History();
|
||||
NS_ENSURE_TRUE(history, NS_ERROR_UNEXPECTED);
|
||||
history->AddObserver(this); // allows us to notify on title changes
|
||||
mozIStorageConnection *dbConn = DBConn();
|
||||
mozStorageTransaction transaction(dbConn, PR_FALSE);
|
||||
|
||||
PRBool exists = PR_FALSE;
|
||||
dbConn->TableExists(NS_LITERAL_CSTRING("moz_bookmarks_assoc"), &exists);
|
||||
if (!exists) {
|
||||
rv = dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("CREATE TABLE moz_bookmarks_assoc (item_child INTEGER, folder_child INTEGER, parent INTEGER, position INTEGER)"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
dbConn->TableExists(NS_LITERAL_CSTRING("moz_bookmarks_containers"), &exists);
|
||||
if (!exists) {
|
||||
rv = dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("CREATE TABLE moz_bookmarks_containers (id INTEGER PRIMARY KEY, name LONGVARCHAR)"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
mRoot = 0;
|
||||
{
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("SELECT folder_child FROM moz_bookmarks_assoc WHERE parent IS NULL"),
|
||||
getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool results;
|
||||
rv = statement->ExecuteStep(&results);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (results) {
|
||||
mRoot = statement->AsInt64(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mRoot) {
|
||||
// Create the root container
|
||||
rv = dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("INSERT INTO moz_bookmarks_containers (name) VALUES (NULL)"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = dbConn->GetLastInsertRowID(&mRoot);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCAutoString buffer;
|
||||
buffer.AssignLiteral("INSERT INTO moz_bookmarks_assoc (folder_child) VALUES(");
|
||||
buffer.AppendInt(mRoot);
|
||||
buffer.AppendLiteral(")");
|
||||
|
||||
rv = dbConn->ExecuteSimpleSQL(buffer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("SELECT a.* FROM moz_bookmarks_assoc a, moz_history h WHERE h.url = ?1 AND a.item_child = h.id"),
|
||||
getter_AddRefs(mDBFindURIBookmarks));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// This gigantic statement constructs a result where the first columns exactly match
|
||||
// those returned by mDBGetVisitPageInfo, and additionally contains columns for
|
||||
// position, item_child, and folder_child from moz_bookmarks_assoc, and name from
|
||||
// moz_bookmarks_containers. The end result is a list of all folder and item children
|
||||
// for a given folder id, sorted by position.
|
||||
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("SELECT h.id, h.url, h.title, h.visit_count, MAX(fullv.visit_date), h.rev_host, a.position, a.item_child, a.folder_child, null FROM moz_bookmarks_assoc a JOIN moz_history h ON a.item_child = h.id LEFT JOIN moz_historyvisit v ON h.id = v.page_id LEFT JOIN moz_historyvisit fullv ON h.id = fullv.page_id WHERE a.parent = ?1 GROUP BY h.id UNION ALL SELECT null, null, null, null, null, null, a.position, a.item_child, a.folder_child, c.name FROM moz_bookmarks_assoc a JOIN moz_bookmarks_containers c ON c.id = a.folder_child WHERE a.parent = ?1 ORDER BY a.position"),
|
||||
getter_AddRefs(mDBGetChildren));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("SELECT COUNT(*) FROM moz_bookmarks_assoc WHERE parent = ?1"),
|
||||
getter_AddRefs(mDBFolderCount));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return transaction.Commit();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNavBookmarks::AdjustIndices(PRInt64 aFolder,
|
||||
PRInt32 aStartIndex, PRInt32 aEndIndex,
|
||||
PRInt32 aDelta)
|
||||
{
|
||||
nsCAutoString buffer;
|
||||
buffer.AssignLiteral("UPDATE moz_bookmarks_assoc SET position = position + ");
|
||||
buffer.AppendInt(aDelta);
|
||||
buffer.AppendLiteral(" WHERE parent = ");
|
||||
buffer.AppendInt(aFolder);
|
||||
|
||||
if (aStartIndex != 0) {
|
||||
buffer.AppendLiteral(" AND position >= ");
|
||||
buffer.AppendInt(aStartIndex);
|
||||
}
|
||||
if (aEndIndex != -1) {
|
||||
buffer.AppendLiteral(" AND position <= ");
|
||||
buffer.AppendInt(aEndIndex);
|
||||
}
|
||||
|
||||
// TODO notify observers about renumbering?
|
||||
|
||||
return DBConn()->ExecuteSimpleSQL(buffer);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::GetBookmarksRoot(PRInt64 *aRoot)
|
||||
{
|
||||
*aRoot = mRoot;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::InsertItem(PRInt64 aFolder, nsIURI *aItem, PRInt32 aIndex)
|
||||
{
|
||||
mozIStorageConnection *dbConn = DBConn();
|
||||
mozStorageTransaction transaction(dbConn, PR_FALSE);
|
||||
|
||||
PRInt64 childID;
|
||||
nsresult rv = History()->GetUrlIdFor(aItem, &childID, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 index = (aIndex == -1) ? FolderCount(aFolder) : aIndex;
|
||||
|
||||
rv = AdjustIndices(aFolder, index, -1, 1);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCAutoString buffer;
|
||||
buffer.AssignLiteral("INSERT INTO moz_bookmarks_assoc (item_child, parent, position) VALUES (");
|
||||
buffer.AppendInt(childID);
|
||||
buffer.AppendLiteral(", ");
|
||||
buffer.AppendInt(aFolder);
|
||||
buffer.AppendLiteral(", ");
|
||||
buffer.AppendInt(index);
|
||||
buffer.AppendLiteral(")");
|
||||
|
||||
rv = dbConn->ExecuteSimpleSQL(buffer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); ++i) {
|
||||
mObservers[i]->OnItemAdded(aItem, aFolder, index);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::RemoveItem(PRInt64 aFolder, nsIURI *aItem)
|
||||
{
|
||||
mozIStorageConnection *dbConn = DBConn();
|
||||
mozStorageTransaction transaction(dbConn, PR_FALSE);
|
||||
|
||||
PRInt64 childID;
|
||||
nsresult rv = History()->GetUrlIdFor(aItem, &childID, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (childID == 0) {
|
||||
return NS_OK; // the item isn't in history at all
|
||||
}
|
||||
|
||||
PRInt32 childIndex;
|
||||
nsCAutoString buffer;
|
||||
{
|
||||
buffer.AssignLiteral("SELECT position FROM moz_bookmarks_assoc WHERE parent = ");
|
||||
buffer.AppendInt(aFolder);
|
||||
buffer.AppendLiteral(" AND item_child = ");
|
||||
buffer.AppendInt(childID);
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
rv = dbConn->CreateStatement(buffer, getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool results;
|
||||
rv = statement->ExecuteStep(&results);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We _should_ always have a result here, but maybe we don't if the table
|
||||
// has become corrupted. Just silently skip adjusting indices.
|
||||
childIndex = results ? statement->AsInt32(0) : -1;
|
||||
}
|
||||
|
||||
buffer.AssignLiteral("DELETE FROM moz_bookmarks_assoc WHERE parent = ");
|
||||
buffer.AppendInt(aFolder);
|
||||
buffer.AppendLiteral(" AND item_child = ");
|
||||
buffer.AppendInt(childID);
|
||||
|
||||
rv = dbConn->ExecuteSimpleSQL(buffer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (childIndex != -1) {
|
||||
rv = AdjustIndices(aFolder, childIndex + 1, -1, -1);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); ++i) {
|
||||
mObservers[i]->OnItemRemoved(aItem, aFolder, childIndex);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::CreateFolder(PRInt64 aParent, const nsAString &aName,
|
||||
PRInt32 aIndex, PRInt64 *aNewFolder)
|
||||
{
|
||||
mozIStorageConnection *dbConn = DBConn();
|
||||
mozStorageTransaction transaction(dbConn, PR_FALSE);
|
||||
|
||||
PRInt32 index = (aIndex == -1) ? FolderCount(aParent) : aIndex;
|
||||
|
||||
nsresult rv = AdjustIndices(aParent, index, -1, 1);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("INSERT INTO moz_bookmarks_containers (name) VALUES (") +
|
||||
NS_ConvertUTF16toUTF8(aName) +
|
||||
NS_LITERAL_CSTRING(")"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt64 child;
|
||||
rv = dbConn->GetLastInsertRowID(&child);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCAutoString buffer;
|
||||
buffer.AssignLiteral("INSERT INTO moz_bookmarks_assoc (folder_child, parent, position) VALUES (");
|
||||
buffer.AppendInt(child);
|
||||
buffer.AppendLiteral(", ");
|
||||
buffer.AppendInt(aParent);
|
||||
buffer.AppendLiteral(", ");
|
||||
buffer.AppendInt(index);
|
||||
buffer.AppendLiteral(")");
|
||||
rv = dbConn->ExecuteSimpleSQL(buffer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); ++i) {
|
||||
mObservers[i]->OnFolderAdded(child, aParent, index);
|
||||
}
|
||||
|
||||
*aNewFolder = child;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::RemoveFolder(PRInt64 aFolder)
|
||||
{
|
||||
mozIStorageConnection *dbConn = DBConn();
|
||||
mozStorageTransaction transaction(dbConn, PR_FALSE);
|
||||
|
||||
nsCAutoString buffer;
|
||||
buffer.AssignLiteral("SELECT parent, position FROM moz_bookmarks_assoc WHERE folder_child = ");
|
||||
buffer.AppendInt(aFolder);
|
||||
|
||||
nsresult rv;
|
||||
PRInt64 parent;
|
||||
PRInt32 index;
|
||||
{
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
rv = dbConn->CreateStatement(buffer, getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool results;
|
||||
rv = statement->ExecuteStep(&results);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!results) {
|
||||
return NS_ERROR_INVALID_ARG; // folder is not in the hierarchy
|
||||
}
|
||||
|
||||
parent = statement->AsInt64(0);
|
||||
index = statement->AsInt32(1);
|
||||
}
|
||||
|
||||
buffer.AssignLiteral("DELETE FROM moz_bookmarks_containers WHERE id = ");
|
||||
buffer.AppendInt(aFolder);
|
||||
rv = dbConn->ExecuteSimpleSQL(buffer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
buffer.AssignLiteral("DELETE FROM moz_bookmarks_assoc WHERE folder_child = ");
|
||||
buffer.AppendInt(aFolder);
|
||||
rv = dbConn->ExecuteSimpleSQL(buffer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = AdjustIndices(parent, index + 1, -1, -1);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); ++i) {
|
||||
mObservers[i]->OnFolderRemoved(aFolder, parent, index);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::MoveFolder(PRInt64 aFolder, PRInt64 aNewParent, PRInt32 aIndex)
|
||||
{
|
||||
mozIStorageConnection *dbConn = DBConn();
|
||||
mozStorageTransaction transaction(dbConn, PR_FALSE);
|
||||
|
||||
nsCAutoString buffer;
|
||||
buffer.AssignLiteral("SELECT parent, position FROM moz_bookmarks_assoc WHERE folder_child = ");
|
||||
buffer.AppendInt(aFolder);
|
||||
|
||||
nsresult rv;
|
||||
PRInt64 parent;
|
||||
PRInt32 index;
|
||||
|
||||
{
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
rv = dbConn->CreateStatement(buffer, getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool results;
|
||||
rv = statement->ExecuteStep(&results);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!results) {
|
||||
return NS_ERROR_INVALID_ARG; // folder is not in the hierarchy
|
||||
}
|
||||
|
||||
parent = statement->AsInt64(0);
|
||||
index = statement->AsInt32(1);
|
||||
}
|
||||
|
||||
if (aNewParent == parent && aIndex == index) {
|
||||
// Nothing to do!
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (parent == aNewParent) {
|
||||
// We can optimize the updates if moving within the same container
|
||||
if (index > aIndex) {
|
||||
rv = AdjustIndices(parent, aIndex, index - 1, 1);
|
||||
} else {
|
||||
rv = AdjustIndices(parent, index + 1, aIndex, -1);
|
||||
}
|
||||
} else {
|
||||
rv = AdjustIndices(parent, index + 1, -1, -1);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = AdjustIndices(aNewParent, aIndex, -1, 1);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
buffer.AssignLiteral("UPDATE moz_bookmarks_assoc SET parent = ");
|
||||
buffer.AppendInt(aNewParent);
|
||||
buffer.AppendLiteral(", position = ");
|
||||
buffer.AppendInt(aIndex);
|
||||
buffer.AppendLiteral(" WHERE id = ");
|
||||
buffer.AppendInt(aFolder);
|
||||
|
||||
rv = dbConn->ExecuteSimpleSQL(buffer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); ++i) {
|
||||
mObservers[i]->OnFolderMoved(aFolder, aNewParent, aIndex);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::SetItemTitle(nsIURI *aURI, const nsAString &aTitle)
|
||||
{
|
||||
return History()->SetPageTitle(aURI, aTitle);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::GetItemTitle(nsIURI *aURI, nsAString &aTitle)
|
||||
{
|
||||
mozIStorageStatement *statement = DBGetURLPageInfo();
|
||||
nsresult rv = BindStatementURI(statement, 0, aURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozStorageStatementScoper scope(statement);
|
||||
|
||||
PRBool results;
|
||||
rv = statement->ExecuteStep(&results);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!results) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return statement->GetString(nsNavHistory::kGetInfoIndex_Title, aTitle);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::SetFolderTitle(PRInt64 aFolder, const nsAString &aTitle)
|
||||
{
|
||||
nsCAutoString buffer;
|
||||
buffer.AssignLiteral("UPDATE moz_bookmarks_container SET title = ");
|
||||
AppendUTF16toUTF8(aTitle, buffer);
|
||||
buffer.AppendLiteral(" WHERE id = ");
|
||||
buffer.AppendInt(aFolder);
|
||||
|
||||
nsresult rv = DBConn()->ExecuteSimpleSQL(buffer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); ++i) {
|
||||
mObservers[i]->OnFolderChanged(aFolder, NS_LITERAL_CSTRING("title"));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::GetFolderTitle(PRInt64 aFolder, nsAString &aTitle)
|
||||
{
|
||||
mozStorageStatementScoper scope(mDBGetFolderInfo);
|
||||
nsresult rv = mDBGetFolderInfo->BindInt64Parameter(0, aFolder);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool results;
|
||||
rv = mDBGetFolderInfo->ExecuteStep(&results);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!results) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return mDBGetFolderInfo->GetString(kGetFolderInfoIndex_Title, aTitle);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavFolderResultNode::GetChildCount(PRInt32 *aChildCount)
|
||||
{
|
||||
if (!mQueriedChildren) {
|
||||
nsresult rv = nsNavBookmarks::sInstance->FillFolderChildren(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return nsNavHistoryResultNode::GetChildCount(aChildCount);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavFolderResultNode::GetChild(PRInt32 aIndex,
|
||||
nsINavHistoryResultNode **aChild)
|
||||
{
|
||||
if (!mQueriedChildren) {
|
||||
nsresult rv = nsNavBookmarks::sInstance->FillFolderChildren(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return nsNavHistoryResultNode::GetChild(aIndex, aChild);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNavBookmarks::ResultNodeForFolder(PRInt64 aID,
|
||||
const nsString &aTitle,
|
||||
nsNavHistoryResultNode **aNode)
|
||||
{
|
||||
nsNavFolderResultNode *node = new nsNavFolderResultNode();
|
||||
NS_ENSURE_TRUE(node, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
node->mID = aID;
|
||||
node->mType = nsINavHistoryResultNode::RESULT_TYPE_FOLDER;
|
||||
node->mTitle = aTitle;
|
||||
node->mAccessCount = 0;
|
||||
node->mTime = 0;
|
||||
|
||||
NS_ADDREF(*aNode = node);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::GetBookmarks(nsINavHistoryResult **aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
|
||||
nsNavHistory *history = History();
|
||||
nsRefPtr<nsNavHistoryResult> result(History()->NewHistoryResult());
|
||||
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsresult rv = result->Init();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Fill the result with a single result node for the bookmarks root.
|
||||
nsCOMPtr<nsNavHistoryResultNode> topNode;
|
||||
rv = ResultNodeForFolder(mRoot, EmptyString(), getter_AddRefs(topNode));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ENSURE_TRUE(result->GetTopLevel()->AppendObject(topNode),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
result->FilledAllResults();
|
||||
|
||||
NS_STATIC_CAST(nsRefPtr<nsINavHistoryResult>, result).swap(*aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNavBookmarks::FillFolderChildren(nsNavFolderResultNode *aNode)
|
||||
{
|
||||
NS_ASSERTION(!aNode->mQueriedChildren, "children already queried");
|
||||
NS_ASSERTION(aNode->mChildren.Count() == 0, "already have child nodes");
|
||||
|
||||
mozStorageStatementScoper scope(mDBGetChildren);
|
||||
mozStorageTransaction transaction(DBConn(), PR_FALSE);
|
||||
|
||||
nsresult rv = mDBGetChildren->BindInt64Parameter(0, aNode->mID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMArray<nsNavHistoryResultNode>* children = &aNode->mChildren;
|
||||
|
||||
PRBool results;
|
||||
while (NS_SUCCEEDED(mDBGetChildren->ExecuteStep(&results)) && results) {
|
||||
nsCOMPtr<nsNavHistoryResultNode> node;
|
||||
if (mDBGetChildren->IsNull(kGetChildrenIndex_FolderChild)) {
|
||||
rv = History()->RowToResult(mDBGetChildren, PR_FALSE, getter_AddRefs(node));
|
||||
} else {
|
||||
PRInt64 folder = mDBGetChildren->AsInt64(kGetChildrenIndex_FolderChild);
|
||||
nsAutoString title;
|
||||
mDBGetChildren->GetString(kGetChildrenIndex_FolderTitle, title);
|
||||
rv = ResultNodeForFolder(folder, title, getter_AddRefs(node));
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(children->AppendObject(node), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
aNode->mQueriedChildren = PR_TRUE;
|
||||
return transaction.Commit();
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsNavBookmarks::FolderCount(PRInt64 aFolder)
|
||||
{
|
||||
mozStorageStatementScoper scope(mDBFolderCount);
|
||||
|
||||
nsresult rv = mDBFolderCount->BindInt64Parameter(0, aFolder);
|
||||
NS_ENSURE_SUCCESS(rv, 0);
|
||||
|
||||
PRBool results;
|
||||
rv = mDBFolderCount->ExecuteStep(&results);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return mDBFolderCount->AsInt32(0);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::IsBookmarked(nsIURI *aURI, PRBool *aBookmarked)
|
||||
{
|
||||
*aBookmarked = PR_FALSE;
|
||||
|
||||
mozStorageStatementScoper scope(mDBFindURIBookmarks);
|
||||
|
||||
nsresult rv = BindStatementURI(mDBFindURIBookmarks, 0, aURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mDBFindURIBookmarks->ExecuteStep(aBookmarked);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::GetBookmarkCategories(nsIURI *aURI, PRUint32 *aCount,
|
||||
PRInt64 **aCategories)
|
||||
{
|
||||
*aCount = 0;
|
||||
*aCategories = nsnull;
|
||||
|
||||
mozStorageStatementScoper scope(mDBFindURIBookmarks);
|
||||
mozStorageTransaction transaction(DBConn(), PR_FALSE);
|
||||
|
||||
nsresult rv = BindStatementURI(mDBFindURIBookmarks, 0, aURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 arraySize = 8;
|
||||
PRInt64 *categories = NS_STATIC_CAST(PRInt64*,
|
||||
nsMemory::Alloc(arraySize * sizeof(PRInt64)));
|
||||
NS_ENSURE_TRUE(categories, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
PRUint32 count = 0;
|
||||
PRBool more;
|
||||
|
||||
while (NS_SUCCEEDED((rv = mDBFindURIBookmarks->ExecuteStep(&more))) && more) {
|
||||
if (count >= arraySize) {
|
||||
arraySize <<= 1;
|
||||
PRInt64 *res = NS_STATIC_CAST(PRInt64*, nsMemory::Realloc(categories,
|
||||
arraySize * sizeof(PRInt64)));
|
||||
if (!res) {
|
||||
delete categories;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
categories = res;
|
||||
}
|
||||
categories[count++] =
|
||||
mDBFindURIBookmarks->AsInt64(kFindBookmarksIndex_Parent);
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aCount = count;
|
||||
*aCategories = categories;
|
||||
|
||||
return transaction.Commit();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::BeginUpdateBatch()
|
||||
{
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); ++i) {
|
||||
mObservers[i]->OnBeginUpdateBatch();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::EndUpdateBatch()
|
||||
{
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); ++i) {
|
||||
mObservers[i]->OnEndUpdateBatch();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::AddObserver(nsINavBookmarkObserver *aObserver)
|
||||
{
|
||||
NS_ENSURE_TRUE(mObservers.AppendObject(aObserver), NS_ERROR_OUT_OF_MEMORY);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::RemoveObserver(nsINavBookmarkObserver *aObserver)
|
||||
{
|
||||
mObservers.RemoveObject(aObserver);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsNavBookmarks::nsINavHistoryObserver
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::OnBeginUpdateBatch()
|
||||
{
|
||||
// These aren't passed through to bookmark observers currently.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::OnEndUpdateBatch()
|
||||
{
|
||||
// These aren't passed through to bookmark observers currently.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::GetWantAllDetails(PRBool *aWant)
|
||||
{
|
||||
*aWant = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::OnAddURI(nsIURI *aURI, PRTime aTime)
|
||||
{
|
||||
// A new URI won't yet be bookmarked, so don't notify.
|
||||
#ifdef DEBUG
|
||||
PRBool bookmarked;
|
||||
IsBookmarked(aURI, &bookmarked);
|
||||
NS_ASSERTION(!bookmarked, "New URI shouldn't be bookmarked!");
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::OnDeleteURI(nsIURI *aURI)
|
||||
{
|
||||
// A deleted URI shouldn't be bookmarked.
|
||||
#ifdef DEBUG
|
||||
PRBool bookmarked;
|
||||
IsBookmarked(aURI, &bookmarked);
|
||||
NS_ASSERTION(!bookmarked, "Deleted URI shouldn't be bookmarked!");
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::OnClearHistory()
|
||||
{
|
||||
// Nothing being cleared should be bookmarked.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::OnPageChanged(nsIURI *aURI, PRUint32 aWhat,
|
||||
const nsAString &aValue)
|
||||
{
|
||||
if (aWhat == ATTRIBUTE_TITLE) {
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); ++i) {
|
||||
mObservers[i]->OnItemChanged(aURI, NS_LITERAL_CSTRING("title"));
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
123
browser/components/places/src/nsNavBookmarks.h
Normal file
123
browser/components/places/src/nsNavBookmarks.h
Normal file
@ -0,0 +1,123 @@
|
||||
/* -*- Mode: C++; tab-width: 8; 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):
|
||||
* Brian Ryner <bryner@brianryner.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 "nsINavBookmarksService.h"
|
||||
#include "nsNavHistory.h"
|
||||
#include "nsBrowserCompsCID.h"
|
||||
|
||||
class nsNavBookmarks;
|
||||
|
||||
class nsNavFolderResultNode : public nsNavHistoryResultNode
|
||||
{
|
||||
public:
|
||||
nsNavFolderResultNode() :
|
||||
nsNavHistoryResultNode(), mQueriedChildren(PR_FALSE) { }
|
||||
|
||||
NS_IMETHOD GetChildCount(PRInt32 *aChildCount);
|
||||
NS_IMETHOD GetChild(PRInt32 aIndex, nsINavHistoryResultNode **aChild);
|
||||
|
||||
private:
|
||||
friend class nsNavBookmarks;
|
||||
PRBool mQueriedChildren;
|
||||
};
|
||||
|
||||
class nsNavBookmarks : public nsINavBookmarksService,
|
||||
public nsINavHistoryObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSINAVBOOKMARKSSERVICE
|
||||
NS_DECL_NSINAVHISTORYOBSERVER
|
||||
|
||||
nsNavBookmarks();
|
||||
nsresult Init();
|
||||
|
||||
static nsNavBookmarks* GetBookmarksService() {
|
||||
if (!sInstance) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINavBookmarksService> serv(do_GetService(NS_NAVBOOKMARKSSERVICE_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
NS_ASSERTION(sInstance, "Should have static instance pointer now");
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private:
|
||||
static nsNavBookmarks *sInstance;
|
||||
|
||||
~nsNavBookmarks();
|
||||
|
||||
nsresult AdjustIndices(PRInt64 aFolder,
|
||||
PRInt32 aStartIndex, PRInt32 aEndIndex,
|
||||
PRInt32 aDelta);
|
||||
nsresult ResultNodeForFolder(PRInt64 aFolder, const nsString &aTitle,
|
||||
nsNavHistoryResultNode **aNode);
|
||||
nsresult FillFolderChildren(nsNavFolderResultNode *aNode);
|
||||
PRInt32 FolderCount(PRInt64 aFolder);
|
||||
|
||||
nsNavHistory* History() { return nsNavHistory::GetHistoryService(); }
|
||||
|
||||
mozIStorageStatement* DBGetURLPageInfo()
|
||||
{ return History()->DBGetURLPageInfo(); }
|
||||
|
||||
mozIStorageConnection* DBConn() { return History()->GetStorageConnection(); }
|
||||
|
||||
nsCOMArray<nsINavBookmarkObserver> mObservers;
|
||||
PRInt64 mRoot;
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> mDBGetFolderInfo; // kGetFolderInfoIndex_* results
|
||||
static const PRInt32 kGetFolderInfoIndex_FolderID;
|
||||
static const PRInt32 kGetFolderInfoIndex_Title;
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> mDBGetChildren; // kGetInfoIndex_* results + kGetChildrenIndex_* results
|
||||
|
||||
static const PRInt32 kGetChildrenIndex_Position;
|
||||
static const PRInt32 kGetChildrenIndex_ItemChild;
|
||||
static const PRInt32 kGetChildrenIndex_FolderChild;
|
||||
static const PRInt32 kGetChildrenIndex_FolderTitle;
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> mDBFindURIBookmarks; // kFindBookmarksIndex_* results
|
||||
static const PRInt32 kFindBookmarksIndex_ItemChild;
|
||||
static const PRInt32 kFindBookmarksIndex_FolderChild;
|
||||
static const PRInt32 kFindBookmarksIndex_Parent;
|
||||
static const PRInt32 kFindBookmarksIndex_Position;
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> mDBFolderCount;
|
||||
|
||||
friend class nsNavFolderResultNode;
|
||||
};
|
@ -72,6 +72,7 @@ Extra:
|
||||
|
||||
#include <stdio.h>
|
||||
#include "nsNavHistory.h"
|
||||
#include "nsNavBookmarks.h"
|
||||
|
||||
#include "nsArray.h"
|
||||
#include "nsDebug.h"
|
||||
@ -235,7 +236,9 @@ nsNavHistory::nsNavHistory() : mNowValid(PR_FALSE),
|
||||
|
||||
nsNavHistory::~nsNavHistory()
|
||||
{
|
||||
gObserverService->RemoveObserver(this, gQuitApplicationMessage);
|
||||
if (gObserverService) {
|
||||
gObserverService->RemoveObserver(this, gQuitApplicationMessage);
|
||||
}
|
||||
|
||||
// remove the static reference to the service. Check to make sure its us
|
||||
// in case somebody creates an extra instance of the service.
|
||||
@ -514,7 +517,7 @@ nsNavHistory::SaveCollapseItem(const nsAString& aTitle)
|
||||
// added to the history.
|
||||
|
||||
nsresult
|
||||
nsNavHistory::InternalAdd(nsIURI* aURI, PRUint32 aSessionID,
|
||||
nsNavHistory::InternalAdd(nsIURI* aURI, PRInt64 aSessionID,
|
||||
PRUint32 aTransitionType, const PRUnichar* aTitle,
|
||||
PRTime aVisitDate, PRBool aRedirect,
|
||||
PRBool aToplevel, PRInt64* aPageID)
|
||||
@ -749,7 +752,7 @@ nsresult nsNavHistory::AddVisit(PRInt64 aFromStep, PRInt64 aPageID,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = dbInsertStatement->BindInt32Parameter(3, aTransitionType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = dbInsertStatement->BindInt32Parameter(4, aSessionID);
|
||||
rv = dbInsertStatement->BindInt64Parameter(4, aSessionID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = dbInsertStatement->Execute(); // should reset the statement
|
||||
@ -1007,23 +1010,27 @@ NS_IMETHODIMP nsNavHistory::GetNewQuery(nsINavHistoryQuery **_retval)
|
||||
*_retval = new nsNavHistoryQuery();
|
||||
if (! *_retval)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
(*_retval)->AddRef();
|
||||
NS_ADDREF(*_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsNavHistory::GetNewQueryOptions(nsINavHistoryQueryOptions **_retval)
|
||||
{
|
||||
*_retval = new nsNavHistoryQueryOptions();
|
||||
NS_ENSURE_TRUE(*_retval, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ADDREF(*_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsNavHistory::ExecuteQuery
|
||||
//
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavHistory::ExecuteQuery(nsINavHistoryQuery *aQuery,
|
||||
const PRInt32 *aGroupingMode, PRUint32 aGroupCount,
|
||||
PRInt32 aSortingMode, PRBool aAsVisits,
|
||||
nsNavHistory::ExecuteQuery(nsINavHistoryQuery *aQuery, nsINavHistoryQueryOptions *aOptions,
|
||||
nsINavHistoryResult** _retval)
|
||||
{
|
||||
return ExecuteQueries(NS_CONST_CAST(const nsINavHistoryQuery**, &aQuery), 1,
|
||||
aGroupingMode, aGroupCount,
|
||||
aSortingMode, aAsVisits, _retval);
|
||||
aOptions, _retval);
|
||||
}
|
||||
|
||||
|
||||
@ -1033,15 +1040,22 @@ nsNavHistory::ExecuteQuery(nsINavHistoryQuery *aQuery,
|
||||
// it ANDed with the all the rest of the queries.
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavHistory::ExecuteQueries(const nsINavHistoryQuery** aQueries,
|
||||
PRUint32 aQueryCount,
|
||||
const PRInt32 *aGroupingMode, PRUint32 aGroupCount,
|
||||
PRInt32 aSortingMode, PRBool aAsVisits,
|
||||
nsNavHistory::ExecuteQueries(const nsINavHistoryQuery** aQueries, PRUint32 aQueryCount,
|
||||
nsINavHistoryQueryOptions *aOptions,
|
||||
nsINavHistoryResult** _retval)
|
||||
{
|
||||
nsresult rv;
|
||||
if (aSortingMode < 0 || aSortingMode > SORT_BY_VISITCOUNT_DESCENDING)
|
||||
|
||||
nsCOMPtr<nsNavHistoryQueryOptions> options = do_QueryInterface(aOptions);
|
||||
NS_ENSURE_TRUE(options, NS_ERROR_INVALID_ARG);
|
||||
|
||||
PRInt32 sortingMode = options->SortingMode();
|
||||
if (sortingMode < 0 ||
|
||||
sortingMode > nsINavHistoryQueryOptions::SORT_BY_VISITCOUNT_DESCENDING) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
PRBool asVisits = options->ResultType() == nsINavHistoryQueryOptions::RESULT_TYPE_VISIT;
|
||||
|
||||
// conditions we want on all history queries, this just selects history
|
||||
// entries that are "active"
|
||||
@ -1052,7 +1066,7 @@ nsNavHistory::ExecuteQueries(const nsINavHistoryQuery** aQueries,
|
||||
// Query string: Output parameters should be in order of kGetInfoIndex_*
|
||||
nsCAutoString queryString;
|
||||
nsCAutoString groupBy;
|
||||
if (aAsVisits) {
|
||||
if (asVisits) {
|
||||
// if we want visits, this is easy, just combine all possible matches
|
||||
// between the history and visits table and do our query.
|
||||
queryString = NS_LITERAL_CSTRING("SELECT h.id, h.url, h.title, h.visit_count, v.visit_date, h.rev_host"
|
||||
@ -1094,30 +1108,30 @@ nsNavHistory::ExecuteQueries(const nsINavHistoryQuery** aQueries,
|
||||
// Sort clause: we will sort later, but if it comes out of the DB sorted,
|
||||
// our later sort will be basically free. The DB can sort these for free
|
||||
// most of the time anyway, because it has indices over these items.
|
||||
switch(aSortingMode) {
|
||||
case SORT_BY_NONE:
|
||||
switch(sortingMode) {
|
||||
case nsINavHistoryQueryOptions::SORT_BY_NONE:
|
||||
break;
|
||||
case SORT_BY_TITLE_ASCENDING:
|
||||
case SORT_BY_TITLE_DESCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_TITLE_ASCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_TITLE_DESCENDING:
|
||||
// the DB doesn't have indices on titles, and we need to do special
|
||||
// sorting for locales. This type of sorting is done only at the end.
|
||||
break;
|
||||
case SORT_BY_DATE_ASCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_DATE_ASCENDING:
|
||||
queryString += NS_LITERAL_CSTRING(" ORDER BY v.visit_date ASC");
|
||||
break;
|
||||
case SORT_BY_DATE_DESCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_DATE_DESCENDING:
|
||||
queryString += NS_LITERAL_CSTRING(" ORDER BY v.visit_date DESC");
|
||||
break;
|
||||
case SORT_BY_URL_ASCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_URL_ASCENDING:
|
||||
queryString += NS_LITERAL_CSTRING(" ORDER BY h.url ASC");
|
||||
break;
|
||||
case SORT_BY_URL_DESCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_URL_DESCENDING:
|
||||
queryString += NS_LITERAL_CSTRING(" ORDER BY h.url DESC");
|
||||
break;
|
||||
case SORT_BY_VISITCOUNT_ASCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_VISITCOUNT_ASCENDING:
|
||||
queryString += NS_LITERAL_CSTRING(" ORDER BY h.visit_count ASC");
|
||||
break;
|
||||
case SORT_BY_VISITCOUNT_DESCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_VISITCOUNT_DESCENDING:
|
||||
queryString += NS_LITERAL_CSTRING(" ORDER BY h.visit_count DESC");
|
||||
break;
|
||||
default:
|
||||
@ -1158,15 +1172,18 @@ nsNavHistory::ExecuteQueries(const nsINavHistoryQuery** aQueries,
|
||||
aQueries[0])->GetHasSearchTerms(&hasSearchTerms);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aGroupCount == 0 && ! hasSearchTerms) {
|
||||
PRUint32 groupCount;
|
||||
const PRInt32 *groupings = options->GroupingMode(&groupCount);
|
||||
|
||||
if (groupCount == 0 && ! hasSearchTerms) {
|
||||
// optimize the case where we just want a list with no grouping: this
|
||||
// directly fills in the results and we avoid a copy of the whole list
|
||||
rv = ResultsAsList(statement, aAsVisits, result->GetTopLevel());
|
||||
rv = ResultsAsList(statement, asVisits, result->GetTopLevel());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
// generate the toplevel results
|
||||
nsCOMArray<nsNavHistoryResultNode> toplevel;
|
||||
rv = ResultsAsList(statement, aAsVisits, &toplevel);
|
||||
rv = ResultsAsList(statement, asVisits, &toplevel);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (hasSearchTerms) {
|
||||
@ -1174,25 +1191,25 @@ nsNavHistory::ExecuteQueries(const nsINavHistoryQuery** aQueries,
|
||||
nsAutoString searchTerms;
|
||||
NS_CONST_CAST(nsINavHistoryQuery*, aQueries[0])
|
||||
->GetSearchTerms(searchTerms);
|
||||
if (aGroupCount == 0) {
|
||||
if (groupCount == 0) {
|
||||
FilterResultSet(toplevel, result->GetTopLevel(), searchTerms);
|
||||
} else {
|
||||
nsCOMArray<nsNavHistoryResultNode> filteredResults;
|
||||
FilterResultSet(toplevel, &filteredResults, searchTerms);
|
||||
rv = RecursiveGroup(filteredResults, aGroupingMode, aGroupCount,
|
||||
rv = RecursiveGroup(filteredResults, groupings, groupCount,
|
||||
result->GetTopLevel());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
} else {
|
||||
// group unfiltered results
|
||||
rv = RecursiveGroup(toplevel, aGroupingMode, aGroupCount,
|
||||
rv = RecursiveGroup(toplevel, groupings, groupCount,
|
||||
result->GetTopLevel());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
if (aSortingMode != SORT_BY_NONE)
|
||||
result->RecursiveSort(aSortingMode);
|
||||
if (sortingMode != nsINavHistoryQueryOptions::SORT_BY_NONE)
|
||||
result->RecursiveSort(sortingMode);
|
||||
|
||||
// automatically expand things that were expanded before
|
||||
if (gExpandedItems.Count() > 0)
|
||||
@ -1201,7 +1218,7 @@ nsNavHistory::ExecuteQueries(const nsINavHistoryQuery** aQueries,
|
||||
result->FilledAllResults();
|
||||
|
||||
*_retval = result;
|
||||
(*_retval)->AddRef();
|
||||
NS_ADDREF(*_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1363,14 +1380,20 @@ nsNavHistory::RemovePage(nsIURI *aURI)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// history entries
|
||||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"DELETE FROM moz_history WHERE url = ?1"),
|
||||
getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = BindStatementURI(statement, 0, aURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsNavBookmarks *bookmarks = nsNavBookmarks::GetBookmarksService();
|
||||
NS_ENSURE_TRUE(bookmarks, NS_ERROR_UNEXPECTED);
|
||||
PRBool bookmarked;
|
||||
bookmarks->IsBookmarked(aURI, &bookmarked);
|
||||
if (!bookmarked) {
|
||||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"DELETE FROM moz_history WHERE url = ?1"),
|
||||
getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = BindStatementURI(statement, 0, aURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Observers: Be sure to finish transaction before calling observers. Note also
|
||||
// that we always call the observers even though we aren't sure something
|
||||
@ -2302,7 +2325,12 @@ nsNavHistory::QueryToSelectClause(nsINavHistoryQuery* aQuery, // const
|
||||
|
||||
// search terms FIXME
|
||||
|
||||
// onlyBookmarked FIXME
|
||||
if (NS_SUCCEEDED(aQuery->GetOnlyBookmarked(&hasIt)) && hasIt) {
|
||||
if (! aClause->IsEmpty())
|
||||
*aClause += NS_LITERAL_CSTRING(" AND ");
|
||||
|
||||
*aClause += NS_LITERAL_CSTRING("EXISTS (SELECT b.item_child FROM moz_bookmarks_assoc b WHERE b.item_child = id)");
|
||||
}
|
||||
|
||||
// domain
|
||||
if (NS_SUCCEEDED(aQuery->GetHasDomain(&hasIt)) && hasIt) {
|
||||
@ -2365,7 +2393,7 @@ nsNavHistory::BindQueryClauseParameters(mozIStorageStatement* statement,
|
||||
|
||||
// search terms FIXME
|
||||
|
||||
// onlyBookmarked FIXME
|
||||
// onlyBookmarked: nothing to bind
|
||||
|
||||
// domain (see GetReversedHostname for more info on reversed host names)
|
||||
if (NS_SUCCEEDED(aQuery->GetHasDomain(&hasIt)) && hasIt) {
|
||||
@ -2436,13 +2464,13 @@ nsNavHistory::RecursiveGroup(const nsCOMArray<nsNavHistoryResultNode>& aSource,
|
||||
|
||||
nsresult rv;
|
||||
switch (aGroupingMode[0]) {
|
||||
case GROUP_BY_DAY:
|
||||
case nsINavHistoryQueryOptions::GROUP_BY_DAY:
|
||||
rv = GroupByDay(aSource, aDest);
|
||||
break;
|
||||
case GROUP_BY_HOST:
|
||||
case nsINavHistoryQueryOptions::GROUP_BY_HOST:
|
||||
rv = GroupByHost(aSource, aDest);
|
||||
break;
|
||||
case GROUP_BY_DOMAIN:
|
||||
case nsINavHistoryQueryOptions::GROUP_BY_DOMAIN:
|
||||
rv = GroupByDomain(aSource, aDest);
|
||||
break;
|
||||
default:
|
||||
@ -3042,7 +3070,7 @@ GetReversedHostname(const nsString& aForward, nsAString& aRevHost)
|
||||
void
|
||||
GetUnreversedHostname(const nsString& aBackward, nsAString& aForward)
|
||||
{
|
||||
NS_ASSERTION(! aBackward.IsEmpty() > 0 && aBackward[aBackward.Length()-1] == '.',
|
||||
NS_ASSERTION(! aBackward.IsEmpty() && aBackward[aBackward.Length()-1] == '.',
|
||||
"Malformed reversed hostname with no trailing dot");
|
||||
|
||||
aForward.Truncate(0);
|
||||
@ -3076,7 +3104,7 @@ PRBool IsNumericHostName(const nsString& aHost)
|
||||
char cur = aHost[i];
|
||||
if (cur == '.')
|
||||
periodCount ++;
|
||||
else if (cur < '0' || cur > '9')
|
||||
else if (cur < PRUnichar('0') || cur > PRUnichar('9'))
|
||||
return PR_FALSE;
|
||||
}
|
||||
return (periodCount == 3);
|
||||
@ -3259,15 +3287,15 @@ nsresult BindStatementURI(mozIStorageStatement* statement, PRInt32 index,
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsNavHistoryResultNode, nsINavHistoryResultNode)
|
||||
|
||||
nsNavHistoryResultNode::nsNavHistoryResultNode() : mID(0), mExpanded(PR_FALSE)
|
||||
nsNavHistoryResultNode::nsNavHistoryResultNode() : mID(0), mExpanded(PR_FALSE),
|
||||
mQueriedChildren(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
/* attribute nsINavHistoryResultNode parent */
|
||||
NS_IMETHODIMP nsNavHistoryResultNode::GetParent(nsINavHistoryResultNode** parent)
|
||||
{
|
||||
*parent = mParent;
|
||||
(*parent)->AddRef();
|
||||
NS_IF_ADDREF(*parent = mParent);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3326,8 +3354,7 @@ NS_IMETHODIMP nsNavHistoryResultNode::GetChild(PRInt32 aIndex,
|
||||
{
|
||||
if (aIndex < 0 || aIndex >= mChildren.Count())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
*_retval = mChildren[aIndex];
|
||||
(*_retval)->AddRef();
|
||||
NS_ADDREF(*_retval = mChildren[aIndex]);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3465,7 +3492,7 @@ nsNavHistoryResult::nsNavHistoryResult(nsNavHistory* aHistoryService,
|
||||
nsIStringBundle* aHistoryBundle)
|
||||
: mBundle(aHistoryBundle), mHistoryService(aHistoryService),
|
||||
mCollapseDuplicates(PR_TRUE),
|
||||
mTimesIncludeDates(PR_TRUE), mCurrentSort(nsNavHistory::SORT_BY_NONE)
|
||||
mTimesIncludeDates(PR_TRUE), mCurrentSort(nsINavHistoryQueryOptions::SORT_BY_NONE)
|
||||
{
|
||||
}
|
||||
|
||||
@ -3560,7 +3587,7 @@ nsNavHistoryResult::GetTopLevel(nsIArray** aTopLevel)
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResult::RecursiveSort(PRUint32 aSortingMode)
|
||||
{
|
||||
if (aSortingMode > nsNavHistory::SORT_BY_VISITCOUNT_DESCENDING)
|
||||
if (aSortingMode > nsINavHistoryQueryOptions::SORT_BY_VISITCOUNT_DESCENDING)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
mCurrentSort = aSortingMode;
|
||||
@ -3624,30 +3651,30 @@ nsNavHistoryResult::RecursiveSortArray(
|
||||
{
|
||||
switch (aSortingMode)
|
||||
{
|
||||
case nsNavHistory::SORT_BY_NONE:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_NONE:
|
||||
break;
|
||||
case nsNavHistory::SORT_BY_TITLE_ASCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_TITLE_ASCENDING:
|
||||
aSources.Sort(SortComparison_TitleLess, NS_STATIC_CAST(void*, this));
|
||||
break;
|
||||
case nsNavHistory::SORT_BY_TITLE_DESCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_TITLE_DESCENDING:
|
||||
aSources.Sort(SortComparison_TitleGreater, NS_STATIC_CAST(void*, this));
|
||||
break;
|
||||
case nsNavHistory::SORT_BY_DATE_ASCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_DATE_ASCENDING:
|
||||
aSources.Sort(SortComparison_DateLess, NS_STATIC_CAST(void*, this));
|
||||
break;
|
||||
case nsNavHistory::SORT_BY_DATE_DESCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_DATE_DESCENDING:
|
||||
aSources.Sort(SortComparison_DateGreater, NS_STATIC_CAST(void*, this));
|
||||
break;
|
||||
case nsNavHistory::SORT_BY_URL_ASCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_URL_ASCENDING:
|
||||
aSources.Sort(SortComparison_URLLess, NS_STATIC_CAST(void*, this));
|
||||
break;
|
||||
case nsNavHistory::SORT_BY_URL_DESCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_URL_DESCENDING:
|
||||
aSources.Sort(SortComparison_URLGreater, NS_STATIC_CAST(void*, this));
|
||||
break;
|
||||
case nsNavHistory::SORT_BY_VISITCOUNT_ASCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_VISITCOUNT_ASCENDING:
|
||||
aSources.Sort(SortComparison_VisitCountLess, NS_STATIC_CAST(void*, this));
|
||||
break;
|
||||
case nsNavHistory::SORT_BY_VISITCOUNT_DESCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_VISITCOUNT_DESCENDING:
|
||||
aSources.Sort(SortComparison_VisitCountGreater, NS_STATIC_CAST(void*, this));
|
||||
break;
|
||||
default:
|
||||
@ -3749,8 +3776,7 @@ nsNavHistoryResult::NodeForTreeIndex(PRUint32 index,
|
||||
{
|
||||
if (index >= (PRUint32)mVisibleElements.Count())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
*aResult = VisibleElementAt(index);
|
||||
(*aResult)->AddRef();
|
||||
NS_ADDREF(*aResult = VisibleElementAt(index));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3783,7 +3809,7 @@ nsNavHistoryResult::SetTreeSortingIndicator()
|
||||
}
|
||||
|
||||
// set new sorting indicator by looking through all columns for ours
|
||||
if (mCurrentSort == nsNavHistory::SORT_BY_NONE)
|
||||
if (mCurrentSort == nsINavHistoryQueryOptions::SORT_BY_NONE)
|
||||
return;
|
||||
PRBool desiredIsDescending;
|
||||
ColumnType desiredColumn = SortTypeToColumnType(mCurrentSort,
|
||||
@ -4129,8 +4155,7 @@ NS_IMETHODIMP nsNavHistoryResult::GetSelection(nsITreeSelection** aSelection)
|
||||
*aSelection = nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
*aSelection = mSelection;
|
||||
(*aSelection)->AddRef();
|
||||
NS_ADDREF(*aSelection = mSelection);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsNavHistoryResult::SetSelection(nsITreeSelection* aSelection)
|
||||
@ -4164,7 +4189,10 @@ NS_IMETHODIMP nsNavHistoryResult::IsContainer(PRInt32 index, PRBool *_retval)
|
||||
{
|
||||
if (index < 0 || index >= mVisibleElements.Count())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
*_retval = (VisibleElementAt(index)->mChildren.Count() > 0);
|
||||
|
||||
nsNavHistoryResultNode *node = VisibleElementAt(index);
|
||||
*_retval = (node->mChildren.Count() > 0 ||
|
||||
node->mType == nsINavHistoryResultNode::RESULT_TYPE_FOLDER);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -4430,29 +4458,29 @@ NS_IMETHODIMP nsNavHistoryResult::CycleHeader(nsITreeColumn *col)
|
||||
PRInt32 newSort;
|
||||
switch (GetColumnType(col)) {
|
||||
case Column_Title:
|
||||
if (mCurrentSort == nsNavHistory::SORT_BY_TITLE_ASCENDING)
|
||||
newSort = nsNavHistory::SORT_BY_TITLE_DESCENDING;
|
||||
if (mCurrentSort == nsINavHistoryQueryOptions::SORT_BY_TITLE_ASCENDING)
|
||||
newSort = nsINavHistoryQueryOptions::SORT_BY_TITLE_DESCENDING;
|
||||
else
|
||||
newSort = nsNavHistory::SORT_BY_TITLE_ASCENDING;
|
||||
newSort = nsINavHistoryQueryOptions::SORT_BY_TITLE_ASCENDING;
|
||||
break;
|
||||
case Column_URL:
|
||||
if (mCurrentSort == nsNavHistory::SORT_BY_URL_ASCENDING)
|
||||
newSort = nsNavHistory::SORT_BY_URL_DESCENDING;
|
||||
if (mCurrentSort == nsINavHistoryQueryOptions::SORT_BY_URL_ASCENDING)
|
||||
newSort = nsINavHistoryQueryOptions::SORT_BY_URL_DESCENDING;
|
||||
else
|
||||
newSort = nsNavHistory::SORT_BY_URL_ASCENDING;
|
||||
newSort = nsINavHistoryQueryOptions::SORT_BY_URL_ASCENDING;
|
||||
break;
|
||||
case Column_Date:
|
||||
if (mCurrentSort == nsNavHistory::SORT_BY_DATE_ASCENDING)
|
||||
newSort = nsNavHistory::SORT_BY_DATE_DESCENDING;
|
||||
if (mCurrentSort == nsINavHistoryQueryOptions::SORT_BY_DATE_ASCENDING)
|
||||
newSort = nsINavHistoryQueryOptions::SORT_BY_DATE_DESCENDING;
|
||||
else
|
||||
newSort = nsNavHistory::SORT_BY_DATE_ASCENDING;
|
||||
newSort = nsINavHistoryQueryOptions::SORT_BY_DATE_ASCENDING;
|
||||
break;
|
||||
case Column_VisitCount:
|
||||
// visit count default is unusual because it is descending
|
||||
if (mCurrentSort == nsNavHistory::SORT_BY_VISITCOUNT_DESCENDING)
|
||||
newSort = nsNavHistory::SORT_BY_VISITCOUNT_ASCENDING;
|
||||
if (mCurrentSort == nsINavHistoryQueryOptions::SORT_BY_VISITCOUNT_DESCENDING)
|
||||
newSort = nsINavHistoryQueryOptions::SORT_BY_VISITCOUNT_ASCENDING;
|
||||
else
|
||||
newSort = nsNavHistory::SORT_BY_VISITCOUNT_DESCENDING;
|
||||
newSort = nsINavHistoryQueryOptions::SORT_BY_VISITCOUNT_DESCENDING;
|
||||
break;
|
||||
default:
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
@ -4542,31 +4570,73 @@ nsNavHistoryResult::SortTypeToColumnType(PRUint32 aSortType,
|
||||
PRBool* aDescending)
|
||||
{
|
||||
switch(aSortType) {
|
||||
case nsINavHistory::SORT_BY_TITLE_ASCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_TITLE_ASCENDING:
|
||||
*aDescending = PR_FALSE;
|
||||
return Column_Title;
|
||||
case nsINavHistory::SORT_BY_TITLE_DESCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_TITLE_DESCENDING:
|
||||
*aDescending = PR_TRUE;
|
||||
return Column_Title;
|
||||
case nsINavHistory::SORT_BY_DATE_ASCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_DATE_ASCENDING:
|
||||
*aDescending = PR_FALSE;
|
||||
return Column_Date;
|
||||
case nsINavHistory::SORT_BY_DATE_DESCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_DATE_DESCENDING:
|
||||
*aDescending = PR_TRUE;
|
||||
return Column_Date;
|
||||
case nsINavHistory::SORT_BY_URL_ASCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_URL_ASCENDING:
|
||||
*aDescending = PR_FALSE;
|
||||
return Column_URL;
|
||||
case nsINavHistory::SORT_BY_URL_DESCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_URL_DESCENDING:
|
||||
*aDescending = PR_TRUE;
|
||||
return Column_URL;
|
||||
case nsINavHistory::SORT_BY_VISITCOUNT_ASCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_VISITCOUNT_ASCENDING:
|
||||
*aDescending = PR_FALSE;
|
||||
return Column_VisitCount;
|
||||
case nsINavHistory::SORT_BY_VISITCOUNT_DESCENDING:
|
||||
case nsINavHistoryQueryOptions::SORT_BY_VISITCOUNT_DESCENDING:
|
||||
*aDescending = PR_TRUE;
|
||||
return Column_VisitCount;
|
||||
default:
|
||||
return Column_Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
// nsNavHistoryQueryOptions
|
||||
NS_IMPL_ISUPPORTS2(nsNavHistoryQueryOptions, nsNavHistoryQueryOptions, nsINavHistoryQueryOptions)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryOptions::SetGroupingMode(const PRInt32 *aGroupingMode,
|
||||
PRUint32 aGroupCount)
|
||||
{
|
||||
delete[] mGroupings;
|
||||
mGroupCount = 0;
|
||||
|
||||
mGroupings = new PRInt32[aGroupCount];
|
||||
NS_ENSURE_TRUE(mGroupings, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
for (PRUint32 i = 0; i < aGroupCount; ++i) {
|
||||
mGroupings[i] = aGroupingMode[i];
|
||||
}
|
||||
|
||||
mGroupCount = aGroupCount;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryOptions::SetSortingMode(PRInt32 aMode)
|
||||
{
|
||||
mSort = aMode;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryOptions::SetResultType(PRInt32 aType)
|
||||
{
|
||||
mResultType = aType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryOptions::SetExpandPlaces(PRBool aExpand)
|
||||
{
|
||||
mExpandPlaces = aExpand;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -36,10 +36,13 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsNavHistory_h_
|
||||
#define nsNavHistory_h_
|
||||
|
||||
#include "mozIStorageService.h"
|
||||
#include "mozIStorageConnection.h"
|
||||
#include "mozIStorageValueArray.h"
|
||||
#include "mozIStorageStatement.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
@ -71,7 +74,7 @@
|
||||
#define AUTOCOMPLETE_NONPAGE_VISIT_COUNT_BOOST 5
|
||||
|
||||
class mozIAnnotationService;
|
||||
|
||||
class nsNavHistory;
|
||||
|
||||
// nsNavHistoryQuery
|
||||
//
|
||||
@ -100,6 +103,7 @@ protected:
|
||||
PRInt32 mGroupingMode;
|
||||
PRInt32 mSortingMode;
|
||||
PRBool mAsVisits;
|
||||
PRBool mExpandPlaces;
|
||||
};
|
||||
|
||||
|
||||
@ -114,7 +118,7 @@ public:
|
||||
NS_DECL_NSINAVHISTORYRESULTNODE
|
||||
|
||||
private:
|
||||
~nsNavHistoryResultNode() {}
|
||||
virtual ~nsNavHistoryResultNode() {}
|
||||
|
||||
protected:
|
||||
// parent of this element, NULL if no parent. Filled in by FillAllElements
|
||||
@ -150,12 +154,14 @@ protected:
|
||||
// this is set to the default in the constructor
|
||||
PRBool mExpanded;
|
||||
|
||||
// for bookmark folders, stores whether we've queried for the child list yet
|
||||
PRBool mQueriedChildren;
|
||||
|
||||
friend class nsNavHistory;
|
||||
friend class nsNavHistoryResult;
|
||||
};
|
||||
|
||||
class nsIDateTimeFormat;
|
||||
class nsNavHistory;
|
||||
|
||||
// nsNavHistoryResult
|
||||
//
|
||||
@ -271,9 +277,41 @@ protected:
|
||||
|
||||
class AutoCompleteIntermediateResultSet;
|
||||
|
||||
#define NS_NAVHISTORYQUERYOPTIONS_IID \
|
||||
{0x95f8ba3b, 0xd681, 0x4d89, {0xab, 0xd1, 0xfd, 0xae, 0xf2, 0xa3, 0xde, 0x18}}
|
||||
|
||||
class nsNavHistoryQueryOptions : public nsINavHistoryQueryOptions
|
||||
{
|
||||
public:
|
||||
nsNavHistoryQueryOptions() : mSort(0), mResultType(0),
|
||||
mGroupCount(0), mGroupings(nsnull), mExpandPlaces(PR_FALSE)
|
||||
{ }
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_INAVHISTORYQUERYOPTIONS_IID)
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSINAVHISTORYQUERYOPTIONS
|
||||
|
||||
PRInt32 SortingMode() const { return mSort; }
|
||||
PRInt32 ResultType() const { return mResultType; }
|
||||
const PRInt32* GroupingMode(PRUint32 *count) const {
|
||||
*count = mGroupCount; return mGroupings;
|
||||
}
|
||||
PRBool ExpandPlaces() const { return mExpandPlaces; }
|
||||
|
||||
private:
|
||||
~nsNavHistoryQueryOptions() { delete[] mGroupings; }
|
||||
|
||||
PRInt32 mSort;
|
||||
PRInt32 mResultType;
|
||||
PRUint32 mGroupCount;
|
||||
PRInt32 *mGroupings;
|
||||
PRBool mExpandPlaces;
|
||||
};
|
||||
|
||||
// nsNavHistory
|
||||
|
||||
class nsNavHistory : nsSupportsWeakReference,
|
||||
class nsNavHistory : public nsSupportsWeakReference,
|
||||
public nsINavHistory,
|
||||
public nsIObserver,
|
||||
public nsIBrowserHistory,
|
||||
@ -301,9 +339,9 @@ public:
|
||||
static nsNavHistory* GetHistoryService()
|
||||
{
|
||||
if (! gHistoryService) {
|
||||
// don't want the return value, since that's the interface. We want the
|
||||
// pointer to the implementation.
|
||||
do_GetService("@mozilla.org/browser/nav-history;1");
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINavHistory> serv(do_GetService("@mozilla.org/browser/nav-history;1", &rv));
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
// our constructor should have set the static variable. If it didn't,
|
||||
// something is wrong.
|
||||
@ -333,6 +371,26 @@ public:
|
||||
void SaveExpandItem(const nsAString& aTitle);
|
||||
void SaveCollapseItem(const nsAString& aTitle);
|
||||
|
||||
// get the statement for selecting a history row by id
|
||||
mozIStorageStatement* DBGetURLPageInfo() { return mDBGetURLPageInfo; }
|
||||
|
||||
// Constants for the columns returned by the above statement.
|
||||
static const PRInt32 kGetInfoIndex_PageID;
|
||||
static const PRInt32 kGetInfoIndex_URL;
|
||||
static const PRInt32 kGetInfoIndex_Title;
|
||||
static const PRInt32 kGetInfoIndex_VisitCount;
|
||||
static const PRInt32 kGetInfoIndex_VisitDate;
|
||||
static const PRInt32 kGetInfoIndex_RevHost;
|
||||
|
||||
// Take a result returned from DBGetURLPageInfo and construct a
|
||||
// ResultNode.
|
||||
nsresult RowToResult(mozIStorageValueArray* aRow, PRBool aAsVisits,
|
||||
nsNavHistoryResultNode** aResult);
|
||||
|
||||
// Construct a new HistoryResult object.
|
||||
nsNavHistoryResult* NewHistoryResult()
|
||||
{ return new nsNavHistoryResult(this, mBundle); }
|
||||
|
||||
private:
|
||||
~nsNavHistory();
|
||||
|
||||
@ -358,12 +416,6 @@ protected:
|
||||
nsCOMPtr<mozIStorageStatement> mDBGetVisitPageInfo; // kGetInfoIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBGetURLPageInfo; // kGetInfoIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBFullAutoComplete; // kAutoCompleteIndex_* results, 1 arg (max # results)
|
||||
static const PRInt32 kGetInfoIndex_PageID;
|
||||
static const PRInt32 kGetInfoIndex_URL;
|
||||
static const PRInt32 kGetInfoIndex_Title;
|
||||
static const PRInt32 kGetInfoIndex_VisitCount;
|
||||
static const PRInt32 kGetInfoIndex_VisitDate;
|
||||
static const PRInt32 kGetInfoIndex_RevHost;
|
||||
static const PRInt32 kAutoCompleteIndex_URL;
|
||||
static const PRInt32 kAutoCompleteIndex_Title;
|
||||
static const PRInt32 kAutoCompleteIndex_VisitCount;
|
||||
@ -378,7 +430,7 @@ protected:
|
||||
|
||||
nsresult InitMemDB();
|
||||
|
||||
nsresult InternalAdd(nsIURI* aURI, PRUint32 aSessionID,
|
||||
nsresult InternalAdd(nsIURI* aURI, PRInt64 aSessionID,
|
||||
PRUint32 aTransitionType, const PRUnichar* aTitle,
|
||||
PRTime aVisitDate, PRBool aRedirect,
|
||||
PRBool aToplevel, PRInt64* aPageID);
|
||||
@ -410,8 +462,6 @@ protected:
|
||||
nsresult ResultsAsList(mozIStorageStatement* statement, PRBool aAsVisits,
|
||||
nsCOMArray<nsNavHistoryResultNode>* aResults);
|
||||
|
||||
nsresult RowToResult(mozIStorageValueArray* aRow, PRBool aAsVisits,
|
||||
nsNavHistoryResultNode** aResult);
|
||||
void TitleForDomain(const nsString& domain, nsAString& aTitle);
|
||||
|
||||
nsresult RecursiveGroup(const nsCOMArray<nsNavHistoryResultNode>& aSource,
|
||||
@ -486,3 +536,5 @@ protected:
|
||||
*/
|
||||
nsresult BindStatementURI(mozIStorageStatement* statement, PRInt32 index,
|
||||
nsIURI* aURI);
|
||||
|
||||
#endif // nsNavHistory_h_
|
||||
|
188
browser/components/places/tests/testbookmarks.js
Executable file
188
browser/components/places/tests/testbookmarks.js
Executable file
@ -0,0 +1,188 @@
|
||||
/* -*- Mode: C++; 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):
|
||||
* Brian Ryner <bryner@brianryner.com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
/**
|
||||
* Unit test for the bookmarks service. Invoke the test like this:
|
||||
* xpcshell -f testbookmarks.js
|
||||
*/
|
||||
|
||||
const NS_STORAGE_FILE = "UStor";
|
||||
const nsIFile = Components.interfaces.nsIFile;
|
||||
|
||||
// If there's no location registered for the storage file, register one now.
|
||||
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
|
||||
var storageFile = null;
|
||||
try {
|
||||
storageFile = dirSvc.get(NS_STORAGE_FILE, nsIFile);
|
||||
} catch (e) {}
|
||||
if (!storageFile) {
|
||||
// Register our own provider for the storage file. It will create the file
|
||||
// "storage.sdb" in the current directory.
|
||||
var provider = {
|
||||
getFile: function(prop, persistent) {
|
||||
persistent.value = true;
|
||||
if (prop == NS_STORAGE_FILE) {
|
||||
var file = dirSvc.get("CurProcD", nsIFile);
|
||||
file.append("storage.sdb");
|
||||
return file;
|
||||
}
|
||||
throw Components.results.NS_ERROR_FAILURE;
|
||||
},
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(Components.interfaces.nsIDirectoryServiceProvider) ||
|
||||
iid.equals(Components.interfaces.nsISupports)) {
|
||||
return this;
|
||||
}
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
};
|
||||
dirSvc.QueryInterface(Components.interfaces.nsIDirectoryService).registerProvider(provider);
|
||||
}
|
||||
|
||||
var iosvc = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
|
||||
|
||||
function uri(spec) {
|
||||
return iosvc.newURI(spec, null, null);
|
||||
}
|
||||
|
||||
dump("starting tests\n");
|
||||
|
||||
var bmsvc = Components.classes["@mozilla.org/browser/nav-bookmarks-service;1"].getService(Components.interfaces.nsINavBookmarksService);
|
||||
|
||||
var observer = {
|
||||
onBeginUpdateBatch: function() {
|
||||
this._beginUpdateBatch = true;
|
||||
},
|
||||
onEndUpdateBatch: function() {
|
||||
this._endUpdateBatch = true;
|
||||
},
|
||||
get wantAllDetails() { return this._wantAllDetails; },
|
||||
onItemAdded: function(uri, folder, index) {
|
||||
this._itemAdded = uri;
|
||||
this._itemAddedFolder = folder;
|
||||
this._itemAddedIndex = index;
|
||||
},
|
||||
onItemRemoved: function(uri, folder, index) {
|
||||
this._itemRemoved = uri;
|
||||
this._itemRemovedFolder = folder;
|
||||
this._itemRemovedIndex = index;
|
||||
},
|
||||
onItemChanged: function(uri, property) {
|
||||
this._itemChanged = uri;
|
||||
this._itemChangedProperty = property;
|
||||
},
|
||||
onFolderAdded: function(folder, parent, index) {
|
||||
this._folderAdded = folder;
|
||||
this._folderAddedParent = parent;
|
||||
this._folderAddedIndex = index;
|
||||
},
|
||||
onFolderRemoved: function(folder, parent, index) {
|
||||
this._folderRemoved = folder;
|
||||
this._folderRemovedParent = parent;
|
||||
this._folderRemovedIndex = index;
|
||||
},
|
||||
onFolderMoved: function(folder, parent, index) {
|
||||
this._folderMoved = folder;
|
||||
this._folderMovedParent = parent;
|
||||
this._folderMovedIndex = index;
|
||||
},
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(Components.interfaces.nsINavBookmarkObserver) ||
|
||||
iid.equals(Components.interfaces.nsISupports)) {
|
||||
return this;
|
||||
}
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
_wantAllDetails: true
|
||||
};
|
||||
|
||||
bmsvc.addObserver(observer);
|
||||
|
||||
var root = bmsvc.bookmarksRoot;
|
||||
|
||||
// add some bookmarks and folders
|
||||
|
||||
bmsvc.insertItem(root, uri("http://www.mozilla.org/"), 0);
|
||||
if (observer._itemAdded.spec != "http://www.mozilla.org/" ||
|
||||
observer._itemAddedFolder != root || observer._itemAddedIndex != 0) {
|
||||
dump("insertItem notification FAILED\n");
|
||||
}
|
||||
bmsvc.setItemTitle(uri("http://www.mozilla.org/"), "Mozilla.org");
|
||||
if (observer._itemChanged.spec != "http://www.mozilla.org/" ||
|
||||
observer._itemChangedProperty != "title") {
|
||||
dump("setItemTitle notification FAILED\n");
|
||||
}
|
||||
bmsvc.insertItem(root, uri("http://google.com/"), -1);
|
||||
if (observer._itemAdded.spec != "http://google.com/" ||
|
||||
observer._itemAddedFolder != root || observer._itemAddedIndex != 1) {
|
||||
dump("insertItem notification FAILED\n");
|
||||
}
|
||||
bmsvc.setItemTitle(uri("http://google.com/"), "Google");
|
||||
if (observer._itemChanged.spec != "http://google.com/" ||
|
||||
observer._itemChangedProperty != "title") {
|
||||
dump("setItemTitle notification FAILED\n");
|
||||
}
|
||||
bmsvc.removeItem(root, uri("http://www.mozilla.org/"));
|
||||
if (observer._itemRemoved.spec != "http://www.mozilla.org/" ||
|
||||
observer._itemRemovedFolder != root || observer._itemRemovedIndex != 0) {
|
||||
dump("removeItem notification FAILED\n");
|
||||
}
|
||||
bmsvc.insertItem(root, uri("http://www.mozilla.org/"), -1);
|
||||
if (observer._itemAdded.spec != "http://www.mozilla.org/" ||
|
||||
observer._itemAddedFolder != root || observer._itemAddedIndex != 1) {
|
||||
dump("insertItem notification FAILED\n");
|
||||
}
|
||||
|
||||
/// EXPECTED TABLE RESULTS
|
||||
/// moz_bookmarks_assoc:
|
||||
/// item_child folder_child parent position
|
||||
/// ---------- ------------ ------ --------
|
||||
/// 1
|
||||
/// 2 1 0
|
||||
/// 1 1 1
|
||||
///
|
||||
/// moz_history:
|
||||
/// id url
|
||||
/// -- ------------------------
|
||||
/// 1 http://www.mozilla.org/
|
||||
/// 2 http://google.com/
|
||||
///
|
||||
/// moz_bookmarks_containers:
|
||||
/// id
|
||||
/// --
|
||||
// 1
|
Loading…
Reference in New Issue
Block a user