Bug 382877 - dynamic containers implementation, part 1. r=dietrich.

This commit is contained in:
mozilla.mano%sent.com 2007-08-02 20:19:45 +00:00
Родитель 494a5292e6
Коммит 23788fbf9c
17 изменённых файлов: 620 добавлений и 377 удалений

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

@ -230,7 +230,7 @@ var PlacesUtils = {
/**
* Determines whether or not a ResultNode is a Bookmark folder or not.
* @param aNode
* A NavHistoryResultNode
* A result node
* @returns true if the node is a Bookmark folder, false otherwise
*/
nodeIsFolder: function PU_nodeIsFolder(aNode) {
@ -241,7 +241,7 @@ var PlacesUtils = {
/**
* Determines whether or not a ResultNode represents a bookmarked URI.
* @param aNode
* A NavHistoryResultNode
* A result node
* @returns true if the node represents a bookmarked URI, false otherwise
*/
nodeIsBookmark: function PU_nodeIsBookmark(aNode) {
@ -253,7 +253,7 @@ var PlacesUtils = {
/**
* Determines whether or not a ResultNode is a Bookmark separator.
* @param aNode
* A NavHistoryResultNode
* A result node
* @returns true if the node is a Bookmark separator, false otherwise
*/
nodeIsSeparator: function PU_nodeIsSeparator(aNode) {
@ -265,7 +265,7 @@ var PlacesUtils = {
/**
* Determines whether or not a ResultNode is a visit item or not
* @param aNode
* A NavHistoryResultNode
* A result node
* @returns true if the node is a visit item, false otherwise
*/
nodeIsVisit: function PU_nodeIsVisit(aNode) {
@ -280,7 +280,7 @@ var PlacesUtils = {
/**
* Determines whether or not a ResultNode is a URL item or not
* @param aNode
* A NavHistoryResultNode
* A result node
* @returns true if the node is a URL item, false otherwise
*/
nodeIsURI: function PU_nodeIsURI(aNode) {
@ -296,7 +296,7 @@ var PlacesUtils = {
/**
* Determines whether or not a ResultNode is a Query item or not
* @param aNode
* A NavHistoryResultNode
* A result node
* @returns true if the node is a Query item, false otherwise
*/
nodeIsQuery: function PU_nodeIsQuery(aNode) {
@ -309,7 +309,7 @@ var PlacesUtils = {
* Determines if a node is read only (children cannot be inserted, sometimes
* they cannot be removed depending on the circumstance)
* @param aNode
* A NavHistoryResultNode
* A result node
* @returns true if the node is readonly, false otherwise
*/
nodeIsReadOnly: function PU_nodeIsReadOnly(aNode) {
@ -325,7 +325,7 @@ var PlacesUtils = {
/**
* Determines whether or not a ResultNode is a host folder or not
* @param aNode
* A NavHistoryResultNode
* A result node
* @returns true if the node is a host item, false otherwise
*/
nodeIsHost: function PU_nodeIsHost(aNode) {
@ -337,7 +337,7 @@ var PlacesUtils = {
/**
* Determines whether or not a ResultNode is a container item or not
* @param aNode
* A NavHistoryResultNode
* A result node
* @returns true if the node is a container item, false otherwise
*/
nodeIsContainer: function PU_nodeIsContainer(aNode) {
@ -349,31 +349,22 @@ var PlacesUtils = {
type == NHRN.RESULT_TYPE_QUERY ||
type == NHRN.RESULT_TYPE_FOLDER ||
type == NHRN.RESULT_TYPE_DAY ||
type == NHRN.RESULT_TYPE_REMOTE_CONTAINER;
type == NHRN.RESULT_TYPE_DYNAMIC_CONTAINER;
},
/**
* Determines whether or not a ResultNode is a remotecontainer item.
* ResultNote may be either a remote container result type or a bookmark folder
* with a nonempty remoteContainerType. The remote container result node
* type is for dynamically created remote containers (i.e., for the file
* browser service where you get your folders in bookmark menus). Bookmark
* folders are marked as remote containers when some other component is
* registered as interested in them and providing some operations, in which
* case their remoteContainerType indicates which component is thus registered.
* For exmaple, the livemark service uses this mechanism.
* Determines whether or not a result-node is a dynamic-container item.
* The dynamic container result node type is for dynamically created
* containers (e.g. for the file browser service where you get your folders
* in bookmark menus).
* @param aNode
* A NavHistoryResultNode
* @returns true if the node is a container item, false otherwise
* A result node
* @returns true if the node is a dynamic container item, false otherwise
*/
nodeIsRemoteContainer: function PU_nodeIsRemoteContainer(aNode) {
nodeIsDynamicContainer: function PU_nodeIsDynamicContainer(aNode) {
NS_ASSERT(aNode, "null node");
const NHRN = Ci.nsINavHistoryResultNode;
if (aNode.type == NHRN.RESULT_TYPE_REMOTE_CONTAINER)
if (aNode.type == NHRN.RESULT_TYPE_DYNAMIC_CONTAINER)
return true;
if (this.nodeIsFolder(aNode))
return asContainer(aNode).remoteContainerType != "";
return false;
},
@ -385,9 +376,8 @@ var PlacesUtils = {
* @returns true if the node is a livemark container item
*/
nodeIsLivemarkContainer: function PU_nodeIsLivemarkContainer(aNode) {
return (this.nodeIsRemoteContainer(aNode) &&
asContainer(aNode).remoteContainerType ==
"@mozilla.org/browser/livemark-service;2");
return this.nodeIsFolder(aNode) &&
this.annotations.itemHasAnnotation(aNode.itemId, "livemark/feedURI");
},
/**

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

@ -2399,7 +2399,7 @@ nsPlacesImportExportService::ExportHTMLToFile(nsILocalFile* aBookmarksFile)
NS_ENSURE_SUCCESS(rv, rv);
// get root (folder) node
nsCOMPtr<nsINavHistoryQueryResultNode> rootNode;
nsCOMPtr<nsINavHistoryContainerResultNode> rootNode;
rv = result->GetRoot(getter_AddRefs(rootNode));
NS_ENSURE_SUCCESS(rv, rv);

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

@ -53,7 +53,7 @@ XPIDLSRCS = \
nsINavHistoryService.idl \
nsINavBookmarksService.idl \
nsILivemarkService.idl \
nsIRemoteContainer.idl \
nsIDynamicContainer.idl \
nsITaggingService.idl \
$(NULL)

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

@ -0,0 +1,114 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Places.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Annie Sullivan <annie.sullivan@gmail.com> (original author)
* Asaf Romano <mano@mozilla.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 ***** */
#include "nsISupports.idl"
interface nsIURI;
interface nsINavHistoryContainerResultNode;
interface nsINavHistoryQueryOptions;
/**
* The dynamic container interface provides a base class for services that want
* to provide containers for temporary contents.
*
* The service can fill result nodes directly into the container when it is
* being opened. It can use the property bag on every result node to store data
* associated with each item, such as full path on disk. It would create
* additional containers for each container, registered to its service.
*
* See also createDynamicContainer in nsINavBookmarksService.
*/
[scriptable, uuid(7e85d97b-4109-4ea7-afd8-bc2cd3840d70)]
interface nsIDynamicContainer : nsISupports
{
/**
* Called when the given container node is about to be populated so that the
* service can populate the container if necessary.
*
* @param aContainer
* The container node for the container being opened. Note that all
* result nodes implement a property bag if you need to store state.
* @param aOptions
* The options used to generate this query. Containers should follow
* these when possible, for example, whether to expand queries, etc.
* Implementations should use this when possible if adding query and
* folder nodes to the container. DO NOT MODIFY THIS VALUE.
*/
void onContainerNodeOpening(in nsINavHistoryContainerResultNode aContainer,
in nsINavHistoryQueryOptions aOptions);
/**
* Called when the given container has just been collapsed so that the
* service can do any necessary cleanup. This is NOT guaranteed to get
* called. In particular, if the query just goes away, you will not get this
* call. This only happens when the container itself goes from the open state
* to the closed state. A service with large numbers of dynamically populated
* items might use this to do some cleanup so those items don't hang around
*
* @param aContainer
* The container node of the container being closed. The service need
* not worry about removing any created nodes, they will be
* automatically removed when this call completes.
*/
void onContainerNodeClosed(in nsINavHistoryContainerResultNode aContainer);
/**
* Called when the given container is about to be deleted from the bookmarks
* table, so that the service can do any necessary cleanup.
* Called BEFORE the container is deleted, so that the service
* can still reference it.
* @param aItemId
* The item-id of the container item.
*/
void onContainerRemoving(in long long aItemId);
/**
* Called when the given container has just been moved, in case
* the service needs to do any bookkeeping.
* Called AFTER the container has been moved.
* @param aItemId
* The item-id of the container item.
* @param aNewParent
* The item of the new parent folder for the container.
* @param aNewIndex
* The index the container will be inserted at, or -1 for append.
*/
void onContainerMoved(in long long aItemId,
in long long aNewParent, in long aNewIndex);
};

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

@ -38,13 +38,12 @@
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "nsIRemoteContainer.idl"
interface nsIURI;
interface nsINavBookmarksService;
[scriptable, uuid(86f0be08-7b7f-4ec6-97ff-ecace917b852)]
interface nsILivemarkService : nsIRemoteContainer
[scriptable, uuid(602e3a71-2d10-4d8f-80c2-6db302b5c89d)]
interface nsILivemarkService : nsISupports
{
/**
* Creates a new livemark

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

@ -22,6 +22,8 @@
* Contributor(s):
* Brian Ryner <bryner@brianryner.com> (original author)
* Joe Hughes <joe@retrovirus.com>
* Dietrich Ayala <dietrich@mozilla.com>
* Asaf Romano <mano@mozilla.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
@ -161,7 +163,7 @@ interface nsINavBookmarkObserver : nsISupports
* folders. A URI in history can be contained in one or more such folders.
*/
[scriptable, uuid(630dcd21-402c-44cd-8336-78bff3efc5f3)]
[scriptable, uuid(117e4d4c-8c10-4c50-b588-848942b55b6e)]
interface nsINavBookmarksService : nsISupports
{
/**
@ -197,6 +199,7 @@ interface nsINavBookmarksService : nsISupports
const unsigned short TYPE_BOOKMARK = 1;
const unsigned short TYPE_FOLDER = 2;
const unsigned short TYPE_SEPARATOR = 3;
const unsigned short TYPE_DYNAMIC_CONTAINER = 4;
/**
* Inserts a child bookmark into the given folder. If this item already exists in
@ -235,22 +238,22 @@ interface nsINavBookmarksService : nsISupports
in long index);
/**
* Wrapper for container services. Creates a folder under the given
* parent and sets the container type. Containers are wrappers around
* read-only folders, with a specific type.
* Creates a dynamic container under the given parent folder.
*
* @param aParentFolder
* The id of the parent folder
* @param aName
* The name of the new folder
* @param aType
* The type of container to insert
* @param aContractId
* The contract id of the service which is to manipulate this
* container.
* @param aIndex
* The index to insert at, or -1 to append
*
* @returns the ID of the newly-inserted folder
*/
long long createContainer(in long long aParentFolder, in AString aName,
in AString aType, in long aIndex);
long long createDynamicContainer(in long long aParentFolder, in AString aName,
in AString aContractId, in long aIndex);
/**
* Removes a folder from the bookmarks tree.
@ -434,13 +437,23 @@ interface nsINavBookmarksService : nsISupports
unsigned short getItemType(in long long aItemId);
/**
* Checks whether a folder has read-only children. This property is
* defined by the nsIBookmarsContainer for the folder, if one exists.
* Checks whether a folder is marked as read-only.
* If this is set to true, UI should not allow the user to add, remove,
* or reorder children in this folder. The default for all folders is false.
* or reorder children in this folder. The default for all folders is false.
* @param aFolder
* the item-id of the folder.
*/
boolean getFolderReadonly(in long long aFolder);
/**
* Sets or unsets the readonly flag from a folder
* @param aFolder
* the item-id of the folder.
* @param aReadOnly
* the read-only state (boolean).
*/
void setFolderReadonly(in long long aFolder, in boolean aReadOnly);
/**
* Returns true if the given URI is in any bookmark folder. If you want the
* results to be redirect-aware, use getBookmarkedURIFor()
@ -537,4 +550,3 @@ interface nsINavBookmarksService : nsISupports
void runInBatchMode(in nsINavHistoryBatchCallback aCallback,
in nsISupports aUserData);
};

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

@ -69,21 +69,17 @@ interface nsINavHistoryResultNode : nsISupports
/**
* Identifies the type of this node. This node can then be QI-ed to the
* corresponding specialized result node interface. The remote_container one
* is a little weird, it is a temporary folder generated by the remote
* container API. Note that bookmark folders can also be filled by the
* remote container API (these are the entrypoints for the API) and may
* have a remote container type as well.
* corresponding specialized result node interface.
*/
const unsigned long RESULT_TYPE_URI = 0; // nsINavHistoryResultNode
const unsigned long RESULT_TYPE_VISIT = 1; // nsINavHistoryVisitResultNode
const unsigned long RESULT_TYPE_FULL_VISIT = 2; // nsINavHistoryFullVisitResultNode
const unsigned long RESULT_TYPE_HOST = 3; // nsINavHistoryContainerResultNode
const unsigned long RESULT_TYPE_REMOTE_CONTAINER = 4; // nsINavHistoryContainerResultNode
const unsigned long RESULT_TYPE_QUERY = 5; // nsINavHistoryQueryResultNode
const unsigned long RESULT_TYPE_FOLDER = 6; // nsINavHistoryQueryResultNode
const unsigned long RESULT_TYPE_SEPARATOR = 7; // nsINavHistoryResultNode
const unsigned long RESULT_TYPE_DAY = 8; // nsINavHistoryContainerResultNode
const unsigned long RESULT_TYPE_URI = 0; // nsINavHistoryResultNode
const unsigned long RESULT_TYPE_VISIT = 1; // nsINavHistoryVisitResultNode
const unsigned long RESULT_TYPE_FULL_VISIT = 2; // nsINavHistoryFullVisitResultNode
const unsigned long RESULT_TYPE_HOST = 3; // nsINavHistoryContainerResultNode
const unsigned long RESULT_TYPE_DYNAMIC_CONTAINER = 4; // nsINavHistoryContainerResultNode
const unsigned long RESULT_TYPE_QUERY = 5; // nsINavHistoryQueryResultNode
const unsigned long RESULT_TYPE_FOLDER = 6; // nsINavHistoryQueryResultNode
const unsigned long RESULT_TYPE_SEPARATOR = 7; // nsINavHistoryResultNode
const unsigned long RESULT_TYPE_DAY = 8; // nsINavHistoryContainerResultNode
readonly attribute unsigned long type;
/**
@ -227,7 +223,7 @@ interface nsINavHistoryFullVisitResultNode : nsINavHistoryVisitResultNode
* Bookmark folders and places queries will be QueryResultNodes which extends
* these items.
*/
[scriptable, uuid(957065fd-76e7-4c24-9284-c31b5decbaaa)]
[scriptable, uuid(f9c8e1c1-e701-44ad-893c-8504c3956929)]
interface nsINavHistoryContainerResultNode : nsINavHistoryResultNode
{
@ -269,41 +265,34 @@ interface nsINavHistoryContainerResultNode : nsINavHistoryResultNode
* (adding or removing children, or reordering children), or true if
* the UI should not allow the list of children to be modified.
* This is false for bookmark folder nodes unless setFolderReadOnly() has
* been called to override it, and true for non-folder nodes. If this
* container is a remote container this flag may be redefined by the
* remote container provider.
* been called to override it, and true for non-folder nodes.
*/
readonly attribute boolean childrenReadOnly;
// --------------------------------------------------------------------------
// Remote container
// Dynamic container
/**
* This is a string representing the remote container API service that is
* responsible for this container. It is empty if there is none. The
* container may be a RESULT_TYPE_REMOTE_CONTAINER node that has been
* dynamically generated by the remote container API. It may also be a
* bookmark folder (RESULT_TYPE_FOLDER) for which some service (such as
* livemarks) has registered to provide certain operations.
* This is a string representing the dynamic container API service that is
* responsible for this container. This throws if if the node is not a dynamic
* container.
*/
readonly attribute AUTF8String remoteContainerType;
readonly attribute AUTF8String dynamicContainerType;
/**
* Appends a full visit node to this container and returns it. For the remote
* container API. TO BE CALLED FROM nsIRemoteContainer::OnContainerOpening()
* Appends a full visit node to this container and returns it. For the dynamic
* container API. TO BE CALLED FROM nsIDynamicContainer::OnContainerOpening()
* ONLY, and only for non-bookmark-folder containers.
*
* @see nsINavHistoryURIResultNode for parameters.
*
* UNTESTED: Container API functions are commented out until we can test
*/
/*nsINavHistoryResultNode appendURINode(
nsINavHistoryResultNode appendURINode(
in AUTF8String aURI, in AUTF8String aTitle, in PRUint32 aAccessCount,
in PRTime aTime, in AUTF8String aIconURI);*/
in PRTime aTime, in AUTF8String aIconURI);
/**
* Appends a full visit node to this container and returns it. For the remote
* container API. TO BE CALLED FROM nsIRemoteContainer::OnContainerOpening()
* Appends a full visit node to this container and returns it. For the dynamic
* container API. TO BE CALLED FROM nsIDynamicContainer::OnContainerOpening()
* ONLY, and only for non-bookmark-folder containers.
*
* @see nsINavHistoryVisitResultNode for parameters.
@ -315,8 +304,8 @@ interface nsINavHistoryContainerResultNode : nsINavHistoryResultNode
in PRTime aTime, in AUTF8String aIconURI, in PRInt64 aSession);*/
/**
* Appends a full visit node to this container and returns it. For the remote
* container API. TO BE CALLED FROM nsIRemoteContainer::OnContainerOpening()
* Appends a full visit node to this container and returns it. For the dynamic
* container API. TO BE CALLED FROM nsIDynamicContainer::OnContainerOpening()
* ONLY, and only for non-bookmark-folder containers.
*
* @see nsINavHistoryFullVisitResultNode for parameters.
@ -330,13 +319,13 @@ interface nsINavHistoryContainerResultNode : nsINavHistoryResultNode
in PRInt32 aTransitionType);*/
/**
* Appends a container node to this container and returns it. For the remote
* container API. TO BE CALLED FROM nsIRemoteContainer::OnContainerOpening()
* Appends a container node to this container and returns it. For the dynamic
* container API. TO BE CALLED FROM nsIDynamicContainer::OnContainerOpening()
* ONLY, and only for non-bookmark-folder containers.
*
* aContainerType should be either RESULT_TYPE_HOST or
* RESULT_TYPE_REMOTE_CONTAINER. When type is remote container you must
* specify a remote container type, otherwise, the remote container type must
* RESULT_TYPE_DYNAMIC_CONTAINER. When type is dynamic container you must
* specify a dynamic container type, otherwise, the dynamic container type must
* be null. Use appendQueryNode and appendFolderNode for the other container
* types.
*
@ -344,11 +333,11 @@ interface nsINavHistoryContainerResultNode : nsINavHistoryResultNode
*/
/*nsINavHistoryContainerResultNode appendContainerNode(
in AUTF8String aTitle, in AUTF8String aIconURI, in PRUint32 aContainerType,
in AUTF8String aRemoteContainerType);*/
in AUTF8String aDynamicContainerType);*/
/**
* Appends a query node to this container and returns it. For the remote
* container API. TO BE CALLED FROM nsIRemoteContainer::OnContainerOpening()
* Appends a query node to this container and returns it. For the dynamic
* container API. TO BE CALLED FROM nsIDynamicContainer::OnContainerOpening()
* ONLY, and only for non-bookmark-folder containers.
*
* Normally you should supply an empty string for IconURI and it will take
@ -361,20 +350,18 @@ interface nsINavHistoryContainerResultNode : nsINavHistoryResultNode
/**
* Appends a bookmark folder node to this container and returns it. For the
* remote container API. TO BE CALLED FROM nsIRemoteContainer::OnContainerOpening()
* dynamic container API. TO BE CALLED FROM nsIDynamicContainer::OnContainerOpening()
* ONLY, and only for non-bookmark-folder containers.
*
* All container attributes will come from the boomkarks service for this
* folder.
*
* UNTESTED: Container API functions are commented out until we can test
*/
/*nsINavHistoryFolderResultNode appendFolderNode(in PRInt64 aFolderId);*/
nsINavHistoryContainerResultNode appendFolderNode(in PRInt64 aFolderId);
/**
* Clears all children of this container. For the remote container API.
* TO BE CALLED FROM nsIRemoteContainer::OnContainerOpening and
* nsIRemoteContainer::OnContainerClosed ONLY, and valid only for
* Clears all children of this container. For the dynamic container API.
* TO BE CALLED FROM nsIDynamicContainer::OnContainerOpening and
* nsIDynamicContainer::OnContainerClosed ONLY, and valid only for
* non-bookmark-folder containers.
*
* UNTESTED: Container API functions are commented out until we can test
@ -669,7 +656,7 @@ interface nsINavHistoryResultTreeViewer : nsINavHistoryResultViewer
* through the nsINavHistoryResultViewObserver interface.
*/
[scriptable, uuid(6cfcb46f-9b70-4efa-b02a-c2ce85d75e00)]
[scriptable, uuid(d1562f6f-8d5a-4042-8524-72f747a51b18)]
interface nsINavHistoryResult : nsISupports
{
/**
@ -699,7 +686,7 @@ interface nsINavHistoryResult : nsISupports
* This is the root of the results. Remember that you need to open all
* containers for their contents to be valid.
*/
readonly attribute nsINavHistoryQueryResultNode root;
readonly attribute nsINavHistoryContainerResultNode root;
};

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

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

@ -144,6 +144,8 @@ function LivemarkService() {
);
this._pushLivemark(livemarks[i], feedURI);
}
this._bms.addObserver(this, false);
}
LivemarkService.prototype = {
@ -277,7 +279,8 @@ LivemarkService.prototype = {
_createFolder:
function LS__createFolder(bms, folder, name, siteURI, feedURI, index) {
var livemarkID = bms.createContainer(folder, name, LS_CONTRACTID, index);
var livemarkID = bms.createFolder(folder, name, index);
this._bms.setFolderReadonly(livemarkID, true);
// Add an annotation to map the folder URI to the livemark feed URI
this._ans.setItemAnnotation(livemarkID, LMANNO_FEEDURI, feedURI.spec, 0,
@ -380,9 +383,22 @@ LivemarkService.prototype = {
this._updateLivemarkChildren(livemarkIndex, true);
},
// nsIRemoteContainer
onContainerRemoving: function LS_onContainerRemoving(container) {
var livemarkIndex = this._getLivemarkIndex(container);
// nsINavBookmarkObserver
onBeginUpdateBatch: function() { },
onEndUpdateBatch: function() { },
onItemAdded: function() { },
onItemChanged: function() { },
onItemVisited: function() { },
onItemMoved: function() { },
onItemRemoved: function(aItemId, aParentFolder, aIndex) {
try {
var livemarkIndex = this._getLivemarkIndex(aItemId);
}
catch(ex) {
// not a livemark
return;
}
var livemark = this._livemarks[livemarkIndex];
var stillInUse = false;
@ -398,14 +414,8 @@ LivemarkService.prototype = {
if (livemark.loadGroup)
livemark.loadGroup.cancel(Cr.NS_BINDING_ABORTED);
this._livemarks.splice(livemarkIndex, 1);
this.deleteLivemarkChildren(container);
},
onContainerMoved:
function LS_onContainerMoved(container, newFolder, newIndex) { },
childrenReadOnly: true,
createInstance: function LS_createInstance(outer, iid) {
if (outer != null)
throw Cr.NS_ERROR_NO_AGGREGATION;
@ -414,12 +424,12 @@ LivemarkService.prototype = {
QueryInterface: function LS_QueryInterface(iid) {
if (iid.equals(Ci.nsILivemarkService) ||
iid.equals(Ci.nsIRemoteContainer) ||
iid.equals(Ci.nsIFactory) ||
iid.equals(Ci.nsINavBookmarkObserver) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
}
};
function LivemarkLoadListener(livemark) {

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

@ -42,7 +42,7 @@
#include "mozStorageHelper.h"
#include "nsIServiceManager.h"
#include "nsNetUtil.h"
#include "nsIRemoteContainer.h"
#include "nsIDynamicContainer.h"
#include "nsUnicharUtils.h"
#include "nsFaviconService.h"
#include "nsAnnotationService.h"
@ -71,7 +71,7 @@ const PRInt32 nsNavBookmarks::kGetItemPropertiesIndex_Position = 3;
const PRInt32 nsNavBookmarks::kGetItemPropertiesIndex_PlaceID = 4;
const PRInt32 nsNavBookmarks::kGetItemPropertiesIndex_Parent = 5;
const PRInt32 nsNavBookmarks::kGetItemPropertiesIndex_Type = 6;
const PRInt32 nsNavBookmarks::kGetItemPropertiesIndex_FolderType = 7;
const PRInt32 nsNavBookmarks::kGetItemPropertiesIndex_ServiceContractId = 7;
const PRInt32 nsNavBookmarks::kGetItemPropertiesIndex_DateAdded = 8;
const PRInt32 nsNavBookmarks::kGetItemPropertiesIndex_LastModified = 9;
@ -80,6 +80,7 @@ nsNavBookmarks* nsNavBookmarks::sInstance = nsnull;
#define BOOKMARKS_ANNO_PREFIX "bookmarks/"
#define BOOKMARKS_TOOLBAR_FOLDER_ANNO NS_LITERAL_CSTRING(BOOKMARKS_ANNO_PREFIX "toolbarFolder")
#define GUID_ANNO NS_LITERAL_CSTRING("placesInternal/GUID")
#define READ_ONLY_ANNO NS_LITERAL_CSTRING("placesInternal/READ_ONLY")
nsNavBookmarks::nsNavBookmarks()
: mRoot(0), mBookmarksRoot(0), mTagRoot(0), mToolbarFolder(0), mBatchLevel(0),
@ -1065,27 +1066,63 @@ NS_IMETHODIMP
nsNavBookmarks::CreateFolder(PRInt64 aParent, const nsAString &aName,
PRInt32 aIndex, PRInt64 *aNewFolder)
{
// CreateFolderWithID returns the index of the new folder, but that's not
// CreateContainerWithID returns the index of the new folder, but that's not
// used here. To avoid any risk of corrupting data should this function
// be changed, we'll use a local variable to hold it. The PR_TRUE argument
// will cause notifications to be sent to bookmark observers.
PRInt32 localIndex = aIndex;
return CreateFolderWithID(-1, aParent, aName, PR_TRUE, &localIndex, aNewFolder);
return CreateContainerWithID(-1, aParent, aName, EmptyString(), PR_TRUE,
&localIndex, aNewFolder);
}
NS_IMETHODIMP
nsNavBookmarks::CreateContainer(PRInt64 aParent, const nsAString &aName,
const nsAString &aType, PRInt32 aIndex,
PRInt64 *aNewFolder)
nsNavBookmarks::CreateDynamicContainer(PRInt64 aParent, const nsAString &aName,
const nsAString &aContractId,
PRInt32 aIndex,
PRInt64 *aNewFolder)
{
return CreateContainerWithID(-1, aParent, aName, aType, aIndex, aNewFolder);
if (aContractId.IsEmpty())
return NS_ERROR_INVALID_ARG;
PRInt32 index = aIndex;
return CreateContainerWithID(-1, aParent, aName, aContractId, PR_FALSE,
&aIndex, aNewFolder);
}
NS_IMETHODIMP
nsNavBookmarks::GetFolderReadonly(PRInt64 aFolder, PRBool *aResult)
{
nsAnnotationService* annosvc = nsAnnotationService::GetAnnotationService();
NS_ENSURE_TRUE(annosvc, NS_ERROR_OUT_OF_MEMORY);
return annosvc->ItemHasAnnotation(aFolder, READ_ONLY_ANNO, aResult);
}
NS_IMETHODIMP
nsNavBookmarks::SetFolderReadonly(PRInt64 aFolder, PRBool aReadOnly)
{
nsAnnotationService* annosvc = nsAnnotationService::GetAnnotationService();
NS_ENSURE_TRUE(annosvc, NS_ERROR_OUT_OF_MEMORY);
if (aReadOnly) {
return annosvc->SetItemAnnotationInt32(aFolder, READ_ONLY_ANNO, 1,
0,
nsAnnotationService::EXPIRE_NEVER);
}
else {
PRBool hasAnno;
nsresult rv = annosvc->ItemHasAnnotation(aFolder, READ_ONLY_ANNO, &hasAnno);
NS_ENSURE_SUCCESS(rv, rv);
if (hasAnno)
return annosvc->RemoveItemAnnotation(aFolder, READ_ONLY_ANNO);
}
return NS_OK;
}
nsresult
nsNavBookmarks::CreateFolderWithID(PRInt64 aFolder, PRInt64 aParent,
const nsAString& aName,
PRBool aSendNotifications,
PRInt32* aIndex, PRInt64* aNewFolder)
nsNavBookmarks::CreateContainerWithID(PRInt64 aItemId, PRInt64 aParent,
const nsAString& aName,
const nsAString& aContractId,
PRBool aIsBookmarkFolder,
PRInt32* aIndex, PRInt64* aNewFolder)
{
// You can pass -1 to indicate append, but no other negative number is allowed
if (*aIndex < -1)
@ -1100,29 +1137,35 @@ nsNavBookmarks::CreateFolderWithID(PRInt64 aFolder, PRInt64 aParent,
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<mozIStorageStatement> statement;
if (aFolder == -1) {
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("INSERT INTO moz_bookmarks (title, type, parent, position, folder_type, dateAdded) VALUES (?1, ?2, ?3, ?4, null, ?5)"),
if (aItemId == -1) {
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("INSERT INTO moz_bookmarks (title, type, parent, position, folder_type, dateAdded) VALUES (?1, ?2, ?3, ?4, ?5, ?6)"),
getter_AddRefs(statement));
NS_ENSURE_SUCCESS(rv, rv);
}
else {
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("INSERT INTO moz_bookmarks (id, title, type, parent, position, folder_type, dateAdded) VALUES (?6, ?1, ?2, ?3, ?4, null, ?5)"),
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("INSERT INTO moz_bookmarks (id, title, type, parent, position, folder_type, dateAdded) VALUES (?7, ?1, ?2, ?3, ?4, ?5, ?6)"),
getter_AddRefs(statement));
NS_ENSURE_SUCCESS(rv, rv);
rv = statement->BindInt64Parameter(5, aFolder);
rv = statement->BindInt64Parameter(6, aItemId);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = statement->BindStringParameter(0, aName);
NS_ENSURE_SUCCESS(rv, rv);
rv = statement->BindInt32Parameter(1, TYPE_FOLDER);
PRInt32 containerType =
aIsBookmarkFolder ? TYPE_FOLDER : TYPE_DYNAMIC_CONTAINER;
rv = statement->BindInt32Parameter(1, containerType);
NS_ENSURE_SUCCESS(rv, rv);
rv = statement->BindInt64Parameter(2, aParent);
NS_ENSURE_SUCCESS(rv, rv);
rv = statement->BindInt32Parameter(3, index);
NS_ENSURE_SUCCESS(rv, rv);
rv = statement->BindInt64Parameter(4, PR_Now());
rv = statement->BindStringParameter(4, aContractId);
NS_ENSURE_SUCCESS(rv, rv);
rv = statement->BindInt64Parameter(5, PR_Now());
NS_ENSURE_SUCCESS(rv, rv);
rv = statement->Execute();
@ -1138,54 +1181,14 @@ nsNavBookmarks::CreateFolderWithID(PRInt64 aFolder, PRInt64 aParent,
rv = transaction.Commit();
NS_ENSURE_SUCCESS(rv, rv);
// When creating a livemark container, we need to delay sending notifications
// until the container type has been set. In that case, they'll be sent by
// CreateContainerWithID rather than here.
if (aSendNotifications) {
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
OnItemAdded(id, aParent, index))
}
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
OnItemAdded(id, aParent, index))
*aIndex = index;
*aNewFolder = id;
return NS_OK;
}
nsresult
nsNavBookmarks::CreateContainerWithID(PRInt64 aFolder, PRInt64 aParent,
const nsAString &aName, const nsAString &aType,
PRInt32 aIndex, PRInt64 *aNewFolder)
{
// Containers are wrappers around read-only folders, with a specific type.
// CreateFolderWithID will return the index of the newly created folder,
// which we will need later on in order to send notifications. The PR_FALSE
// argument disables sending notifications, since we need to defer that until
// the folder type has been set.
PRInt32 localIndex = aIndex;
nsresult rv = CreateFolderWithID(aFolder, aParent, aName, PR_FALSE, &localIndex, aNewFolder);
NS_ENSURE_SUCCESS(rv, rv);
// Set the type.
nsCOMPtr<mozIStorageStatement> statement;
rv = DBConn()->CreateStatement(NS_LITERAL_CSTRING("UPDATE moz_bookmarks SET folder_type = ?2 WHERE id = ?1"),
getter_AddRefs(statement));
NS_ENSURE_SUCCESS(rv, rv);
rv = statement->BindInt64Parameter(0, *aNewFolder);
NS_ENSURE_SUCCESS(rv, rv);
rv = statement->BindStringParameter(1, aType);
NS_ENSURE_SUCCESS(rv, rv);
rv = statement->Execute();
NS_ENSURE_SUCCESS(rv, rv);
// Send notifications after folder type has been set.
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
OnItemAdded(*aNewFolder, aParent, localIndex))
return NS_OK;
}
NS_IMETHODIMP
nsNavBookmarks::InsertSeparator(PRInt64 aParent, PRInt32 aIndex,
PRInt64* aNewItemId)
@ -1334,14 +1337,14 @@ nsNavBookmarks::RemoveFolder(PRInt64 aFolder)
parent = mDBGetItemProperties->AsInt64(kGetItemPropertiesIndex_Parent);
index = mDBGetItemProperties->AsInt32(kGetItemPropertiesIndex_Position);
rv = mDBGetItemProperties->GetUTF8String(kGetItemPropertiesIndex_FolderType, folderType);
rv = mDBGetItemProperties->GetUTF8String(kGetItemPropertiesIndex_ServiceContractId, folderType);
NS_ENSURE_SUCCESS(rv, rv);
}
// If this is a container bookmark, try to notify its service.
if (folderType.Length() > 0) {
// There is a type associated with this folder; it's a livemark.
nsCOMPtr<nsIRemoteContainer> bmcServ = do_GetService(folderType.get());
nsCOMPtr<nsIDynamicContainer> bmcServ = do_GetService(folderType.get());
if (bmcServ) {
rv = bmcServ->OnContainerRemoving(aFolder);
if (NS_FAILED(rv))
@ -1403,7 +1406,7 @@ nsNavBookmarks::GetRemoveFolderTransaction(PRInt64 aFolder, nsITransaction** aRe
NS_ENSURE_SUCCESS(rv, rv);
RemoveFolderTransaction* rft =
new RemoveFolderTransaction(aFolder, parent, title, index, type);
new RemoveFolderTransaction(aFolder, parent, title, index, NS_ConvertUTF8toUTF16(type));
if (!rft)
return NS_ERROR_OUT_OF_MEMORY;
@ -1496,7 +1499,7 @@ nsNavBookmarks::MoveItem(PRInt64 aItemId, PRInt64 aNewParent, PRInt32 aIndex)
oldIndex = mDBGetItemProperties->AsInt32(kGetItemPropertiesIndex_Position);
itemType = mDBGetItemProperties->AsInt32(kGetItemPropertiesIndex_Type);
if (itemType == TYPE_FOLDER) {
rv = mDBGetItemProperties->GetUTF8String(kGetItemPropertiesIndex_FolderType,
rv = mDBGetItemProperties->GetUTF8String(kGetItemPropertiesIndex_ServiceContractId,
folderType);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -1608,9 +1611,9 @@ nsNavBookmarks::MoveItem(PRInt64 aItemId, PRInt64 aNewParent, PRInt32 aIndex)
OnItemMoved(aItemId, oldParent, oldIndex, aNewParent,
newIndex))
// notify remote container provider if there is one
// notify dynamic container provider if there is one
if (!folderType.IsEmpty()) {
nsCOMPtr<nsIRemoteContainer> container =
nsCOMPtr<nsIDynamicContainer> container =
do_GetService(folderType.get(), &rv);
if (NS_SUCCEEDED(rv)) {
rv = container->OnContainerMoved(aItemId, aNewParent, newIndex);
@ -1910,13 +1913,13 @@ nsNavBookmarks::GetFolderType(PRInt64 aFolder, nsACString &aType)
return NS_ERROR_INVALID_ARG;
}
return mDBGetItemProperties->GetUTF8String(kGetItemPropertiesIndex_FolderType, aType);
return mDBGetItemProperties->GetUTF8String(kGetItemPropertiesIndex_ServiceContractId, aType);
}
nsresult
nsNavBookmarks::ResultNodeForFolder(PRInt64 aID,
nsNavHistoryQueryOptions *aOptions,
nsNavHistoryResultNode **aNode)
nsNavBookmarks::ResultNodeForContainer(PRInt64 aID,
nsNavHistoryQueryOptions *aOptions,
nsNavHistoryResultNode **aNode)
{
mozStorageStatementScoper scope(mDBGetItemProperties);
mDBGetItemProperties->BindInt64Parameter(0, aID);
@ -1924,18 +1927,29 @@ nsNavBookmarks::ResultNodeForFolder(PRInt64 aID,
PRBool results;
nsresult rv = mDBGetItemProperties->ExecuteStep(&results);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(results, "ResultNodeForFolder expects a valid folder id");
NS_ASSERTION(results, "ResultNodeForContainer expects a valid item id");
// type
nsCAutoString folderType;
rv = mDBGetItemProperties->GetUTF8String(kGetItemPropertiesIndex_FolderType, folderType);
// contract id
nsCAutoString contractId;
rv = mDBGetItemProperties->GetUTF8String(kGetItemPropertiesIndex_ServiceContractId,
contractId);
NS_ENSURE_SUCCESS(rv, rv);
// title
nsCAutoString title;
rv = mDBGetItemProperties->GetUTF8String(kGetItemPropertiesIndex_Title, title);
*aNode = new nsNavHistoryFolderResultNode(title, aOptions, aID, folderType);
PRInt32 itemType = mDBGetItemProperties->AsInt32(kGetItemPropertiesIndex_Type);
if (itemType == TYPE_DYNAMIC_CONTAINER) {
*aNode = new nsNavHistoryContainerResultNode(EmptyCString(), title, EmptyCString(),
nsINavHistoryResultNode::RESULT_TYPE_DYNAMIC_CONTAINER,
PR_TRUE,
contractId,
aOptions);
(*aNode)->mItemId = aID;
} else { // TYPE_FOLDER
*aNode = new nsNavHistoryFolderResultNode(title, aOptions, aID, contractId);
}
if (!*aNode)
return NS_ERROR_OUT_OF_MEMORY;
@ -1966,27 +1980,6 @@ nsNavBookmarks::GetFolderURI(PRInt64 aFolder, nsIURI **aURI)
return NS_NewURI(aURI, spec);
}
NS_IMETHODIMP
nsNavBookmarks::GetFolderReadonly(PRInt64 aFolder, PRBool *aResult)
{
// Ask the folder's nsIRemoteContainer for the readonly property.
*aResult = PR_FALSE;
nsCAutoString type;
nsresult rv = GetFolderType(aFolder, type);
NS_ENSURE_SUCCESS(rv, rv);
if (!type.IsEmpty()) {
nsCOMPtr<nsIRemoteContainer> container =
do_GetService(type.get(), &rv);
if (NS_SUCCEEDED(rv)) {
rv = container->GetChildrenReadOnly(aResult);
NS_ENSURE_SUCCESS(rv, rv);
}
}
return NS_OK;
}
nsresult
nsNavBookmarks::QueryFolderChildren(PRInt64 aFolderId,
nsNavHistoryQueryOptions *aOptions,
@ -2015,12 +2008,12 @@ nsNavBookmarks::QueryFolderChildren(PRInt64 aFolderId,
// it will start counting at 0 the first time through the loop.
index ++;
PRBool isFolder = mDBGetChildren->AsInt32(kGetChildrenIndex_Type) == TYPE_FOLDER;
PRInt32 itemType = mDBGetChildren->AsInt32(kGetChildrenIndex_Type);
PRInt64 id = mDBGetChildren->AsInt64(nsNavHistory::kGetInfoIndex_ItemId);
nsCOMPtr<nsNavHistoryResultNode> node;
if (isFolder) {
if (options->ExcludeReadOnlyFolders()) {
if (itemType == TYPE_FOLDER || itemType == TYPE_DYNAMIC_CONTAINER) {
if (itemType == TYPE_DYNAMIC_CONTAINER ||
(itemType == TYPE_FOLDER && options->ExcludeReadOnlyFolders())) {
// see if it's read only and skip it
PRBool readOnly = PR_FALSE;
GetFolderReadonly(id, &readOnly);
@ -2028,7 +2021,7 @@ nsNavBookmarks::QueryFolderChildren(PRInt64 aFolderId,
continue; // skip
}
rv = ResultNodeForFolder(id, aOptions, getter_AddRefs(node));
rv = ResultNodeForContainer(id, aOptions, getter_AddRefs(node));
if (NS_FAILED(rv))
continue;
} else if (mDBGetChildren->AsInt32(kGetChildrenIndex_Type) == TYPE_SEPARATOR) {

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

@ -77,8 +77,8 @@ public:
nsresult AddBookmarkToHash(PRInt64 aBookmarkId, PRTime aMinTime);
nsresult ResultNodeForFolder(PRInt64 aID, nsNavHistoryQueryOptions *aOptions,
nsNavHistoryResultNode **aNode);
nsresult ResultNodeForContainer(PRInt64 aID, nsNavHistoryQueryOptions *aOptions,
nsNavHistoryResultNode **aNode);
// Find all the children of a folder, using the given query and options.
// For each child, a ResultNode is created and added to |children|.
@ -89,20 +89,13 @@ public:
// If aFolder is -1, uses the autoincrement id for folder index. Returns
// the index of the new folder in aIndex, whether it was passed in or
// generated by autoincrement. If aSendNotifications is true, sends
// OnFolderAdded notifications to bookmark observers.
nsresult CreateFolderWithID(PRInt64 aFolder, PRInt64 aParent,
const nsAString& title,
PRBool aSendNotifications,
PRInt32 *aIndex, PRInt64* aNewFolder);
// Creates a new container of the given type. If aFolder is -1, uses the
// autoincrement id for folder index. Sends OnFolderAdded notifications
// to all observers after the folder has been created and its type has
// been set.
nsresult CreateContainerWithID(PRInt64 aFolder, PRInt64 aParent,
const nsAString& title, const nsAString& type,
PRInt32 aIndex, PRInt64* aNewFolder);
// generated by autoincrement.
nsresult CreateContainerWithID(PRInt64 aId, PRInt64 aParent,
const nsAString& aName,
const nsAString& aContractId,
PRBool aIsBookmarkFolder,
PRInt32* aIndex,
PRInt64* aNewFolder);
// Called by History service when quitting.
nsresult OnQuit();
@ -200,7 +193,7 @@ private:
static const PRInt32 kGetItemPropertiesIndex_PlaceID;
static const PRInt32 kGetItemPropertiesIndex_Parent;
static const PRInt32 kGetItemPropertiesIndex_Type;
static const PRInt32 kGetItemPropertiesIndex_FolderType;
static const PRInt32 kGetItemPropertiesIndex_ServiceContractId;
static const PRInt32 kGetItemPropertiesIndex_DateAdded;
static const PRInt32 kGetItemPropertiesIndex_LastModified;
@ -219,7 +212,7 @@ private:
public:
RemoveFolderTransaction(PRInt64 aID, PRInt64 aParent,
const nsAString& aTitle, PRInt32 aIndex,
const nsACString& aType)
const nsAString& aType)
: mID(aID),
mParent(aParent),
mIndex(aIndex){
@ -237,12 +230,8 @@ private:
NS_IMETHOD UndoTransaction() {
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
PRInt64 newFolder;
// If the transaction has no specific type, default to a folder, and send notifications
// to all bookmark observers (controlled by the PR_TRUE argument to CreateFolderWithID).
if (mType.IsEmpty())
return bookmarks->CreateFolderWithID(mID, mParent, mTitle, PR_TRUE, &mIndex, &newFolder);
nsAutoString type; type.AssignWithConversion(mType);
return bookmarks->CreateContainerWithID(mID, mParent, mTitle, type, mIndex, &newFolder);
return bookmarks->CreateContainerWithID(mID, mParent, mTitle, mType, PR_TRUE,
&mIndex, &newFolder);
}
NS_IMETHOD RedoTransaction() {
@ -263,7 +252,7 @@ private:
PRInt64 mID;
PRInt64 mParent;
nsString mTitle;
nsCString mType;
nsString mType;
PRInt32 mIndex;
};
};

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

@ -2012,8 +2012,8 @@ nsNavHistory::ExecuteQueries(nsINavHistoryQuery** aQueries, PRUint32 aQueryCount
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsNavHistoryResultNode> tempRootNode;
rv = bookmarks->ResultNodeForFolder(folderId, options,
getter_AddRefs(tempRootNode));
rv = bookmarks->ResultNodeForContainer(folderId, options,
getter_AddRefs(tempRootNode));
NS_ENSURE_SUCCESS(rv, rv);
rootNode = tempRootNode->GetAsContainer();
} else {
@ -3911,7 +3911,8 @@ nsNavHistory::GroupByDay(nsNavHistoryQueryResultNode *aResultNode,
EmptyCString(),
nsNavHistoryResultNode::RESULT_TYPE_DAY,
PR_TRUE,
EmptyCString());
EmptyCString(),
nsnull);
if (!dates[ageInDays])
return NS_ERROR_OUT_OF_MEMORY;
@ -3989,7 +3990,7 @@ nsNavHistory::GroupByHost(nsNavHistoryQueryResultNode *aResultNode,
curTopGroup = new nsNavHistoryContainerResultNode(urn, title,
EmptyCString(), nsNavHistoryResultNode::RESULT_TYPE_HOST, PR_TRUE,
EmptyCString());
EmptyCString(), nsnull);
if (! curTopGroup)
return NS_ERROR_OUT_OF_MEMORY;
@ -4326,7 +4327,7 @@ nsNavHistory::QueryRowToResult(const nsACString& aURI, const nsACString& aTitle,
NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY);
// this addrefs for us
rv = bookmarks->ResultNodeForFolder(folderId, options, aNode);
rv = bookmarks->ResultNodeForContainer(folderId, options, aNode);
NS_ENSURE_SUCCESS(rv, rv);
} else {
// regular query

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

@ -54,7 +54,7 @@
#include "nsILocale.h"
#include "nsILocaleService.h"
#include "nsILocalFile.h"
#include "nsIRemoteContainer.h"
#include "nsIDynamicContainer.h"
#include "nsIServiceManager.h"
#include "nsISupportsPrimitives.h"
#include "nsITreeColumns.h"
@ -203,11 +203,9 @@ nsNavHistoryResultNode::GetGeneratingOptions()
// When we have no parent, it either means we haven't built the tree yet,
// in which case calling this function is a bug, or this node is the root
// of the tree. When we are the root of the tree, our own options are the
// generating options, and we know we are either a query of a folder node.
if (IsFolder())
return GetAsFolder()->mOptions;
else if (IsQuery())
return GetAsQuery()->mOptions;
// generating options.
if (IsContainer())
return GetAsContainer()->mOptions;
NS_NOTREACHED("Can't find a generating node for this container, perhaps FillStats has not been called on this tree yet?");
return nsnull;
}
@ -272,13 +270,14 @@ NS_INTERFACE_MAP_END_INHERITING(nsNavHistoryResultNode)
nsNavHistoryContainerResultNode::nsNavHistoryContainerResultNode(
const nsACString& aURI, const nsACString& aTitle,
const nsACString& aIconURI, PRUint32 aContainerType, PRBool aReadOnly,
const nsACString& aRemoteContainerType) :
const nsACString& aDynamicContainerType, nsNavHistoryQueryOptions* aOptions) :
nsNavHistoryResultNode(aURI, aTitle, 0, 0, aIconURI),
mResult(nsnull),
mContainerType(aContainerType),
mExpanded(PR_FALSE),
mChildrenReadOnly(aReadOnly),
mRemoteContainerType(aRemoteContainerType)
mDynamicContainerType(aDynamicContainerType),
mOptions(aOptions)
{
}
@ -360,22 +359,20 @@ nsNavHistoryContainerResultNode::OpenContainer()
NS_ASSERTION(! mExpanded, "Container must be expanded to close it");
mExpanded = PR_TRUE;
/* Untested container API functions
if (! mRemoteContainerType.IsEmpty()) {
// remote container API may want to fill us
if (IsDynamicContainer()) {
// dynamic container API may want to fill us
nsresult rv;
nsCOMPtr<nsIRemoteContainer> remote = do_GetService(mRemoteContainerType.get(), &rv);
nsCOMPtr<nsIDynamicContainer> svc = do_GetService(mDynamicContainerType.get(), &rv);
if (NS_SUCCEEDED(rv)) {
remote->OnContainerOpening(this, GetGeneratingOptions());
svc->OnContainerNodeOpening(this, GetGeneratingOptions());
} else {
NS_WARNING("Unable to get remote container for ");
NS_WARNING(mRemoteContainerType.get());
NS_WARNING("Unable to get dynamic container for ");
NS_WARNING(mDynamicContainerType.get());
}
PRInt32 oldAccessCount = mAccessCount;
FillStats();
ReverseUpdateStats(mAccessCount - oldAccessCount);
}
*/
nsNavHistoryResult* result = GetResult();
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
@ -405,15 +402,13 @@ nsNavHistoryContainerResultNode::CloseContainer(PRBool aUpdateView)
mExpanded = PR_FALSE;
/* Untested remote container functions
nsresult rv;
if (! mRemoteContainerType.IsEmpty()) {
// notify remote containers that we are closing
nsCOMPtr<nsIRemoteContainer> remote = do_GetService(mRemoteContainerType.get(), &rv);
if (IsDynamicContainer()) {
// notify dynamic containers that we are closing
nsCOMPtr<nsIDynamicContainer> svc = do_GetService(mDynamicContainerType.get(), &rv);
if (NS_SUCCEEDED(rv))
remote->OnContainerClosed(this);
svc->OnContainerNodeClosed(this);
}
*/
if (aUpdateView) {
nsNavHistoryResult* result = GetResult();
@ -1378,20 +1373,6 @@ nsNavHistoryContainerResultNode::RemoveChildAt(PRInt32 aIndex,
}
// nsNavHistoryContainerResultNode::CanRemoteContainersChange
//
// Returns true if remote containers can manipulate the contents of this
// container. This is false for folders and queries, true for everything
// else.
PRBool
nsNavHistoryContainerResultNode::CanRemoteContainersChange()
{
return (mContainerType != nsNavHistoryResultNode::RESULT_TYPE_FOLDER &&
mContainerType != nsNavHistoryResultNode::RESULT_TYPE_QUERY);
}
// nsNavHistoryContainerResultNode::RecursiveFindURIs
//
// This function searches for matches for the given URI.
@ -1621,40 +1602,39 @@ nsNavHistoryContainerResultNode::GetChildrenReadOnly(PRBool *aChildrenReadOnly)
}
// nsNavHistoryContainerResultNode::GetRemoteContainerType
// nsNavHistoryContainerResultNode::GetDynamicContainerType
NS_IMETHODIMP
nsNavHistoryContainerResultNode::GetRemoteContainerType(
nsACString& aRemoteContainerType)
nsNavHistoryContainerResultNode::GetDynamicContainerType(
nsACString& aDynamicContainerType)
{
aRemoteContainerType = mRemoteContainerType;
aDynamicContainerType = mDynamicContainerType;
return NS_OK;
}
// nsNavHistoryContainerResultNode::AppendURINode
#if 0 // UNTESTED, commented out until it can be tested
NS_IMETHODIMP
nsNavHistoryContainerResultNode::AppendURINode(
const nsACString& aURI, const nsACString& aTitle, PRUint32 aAccessCount,
PRTime aTime, const nsACString& aIconURI, nsINavHistoryResultNode** _retval)
{
*_retval = nsnull;
if (mRemoteContainerType.IsEmpty() || ! CanRemoteContainersChange())
return NS_ERROR_INVALID_ARG; // we must be a remote container
if (!IsDynamicContainer())
return NS_ERROR_INVALID_ARG; // we must be a dynamic container
nsRefPtr<nsNavHistoryResultNode> result =
new nsNavHistoryResultNode(aURI, aTitle, aAccessCount, aTime, aIconURI);
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
// append to our list
if (! mChildren.AppendObject(result))
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = InsertChildAt(result, mChildren.Count());
NS_ENSURE_SUCCESS(rv, rv);
NS_ADDREF(*_retval = result);
return NS_OK;
}
#endif
// nsNavHistoryContainerResultNode::AppendVisitNode
@ -1667,8 +1647,8 @@ nsNavHistoryContainerResultNode::AppendVisitNode(
nsINavHistoryVisitResultNode** _retval)
{
*_retval = nsnull;
if (mRemoteContainerType.IsEmpty() || ! CanRemoteContainersChange())
return NS_ERROR_INVALID_ARG; // we must be a remote container
if (!IsDynamicContainer())
return NS_ERROR_INVALID_ARG; // we must be a dynamic container
nsRefPtr<nsNavHistoryVisitResultNode> result =
new nsNavHistoryVisitResultNode(aURI, aTitle, aAccessCount, aTime,
@ -1681,12 +1661,10 @@ nsNavHistoryContainerResultNode::AppendVisitNode(
NS_ADDREF(*_retval = result);
return NS_OK;
}
#endif
// nsNavHistoryContainerResultNode::AppendFullVisitNode
#if 0 // UNTESTED, commented out until it can be tested
NS_IMETHODIMP
nsNavHistoryContainerResultNode::AppendFullVisitNode(
const nsACString& aURI, const nsACString& aTitle, PRUint32 aAccessCount,
@ -1695,8 +1673,8 @@ nsNavHistoryContainerResultNode::AppendFullVisitNode(
nsINavHistoryFullVisitResultNode** _retval)
{
*_retval = nsnull;
if (mRemoteContainerType.IsEmpty() || ! CanRemoteContainersChange())
return NS_ERROR_INVALID_ARG; // we must be a remote container
if (!IsDynamicContainer())
return NS_ERROR_INVALID_ARG; // we must be a dynamic container
nsRefPtr<nsNavHistoryFullVisitResultNode> result =
new nsNavHistoryFullVisitResultNode(aURI, aTitle, aAccessCount, aTime,
@ -1710,35 +1688,33 @@ nsNavHistoryContainerResultNode::AppendFullVisitNode(
NS_ADDREF(*_retval = result);
return NS_OK;
}
#endif
// nsNavHistoryContainerResultNode::AppendContainerNode
#if 0 // UNTESTED, commented out until it can be tested
NS_IMETHODIMP
nsNavHistoryContainerResultNode::AppendContainerNode(
const nsACString& aTitle, const nsACString& aIconURI,
PRUint32 aContainerType, const nsACString& aRemoteContainerType,
PRUint32 aContainerType, const nsACString& aDynamicContainerType,
nsINavHistoryContainerResultNode** _retval)
{
*_retval = nsnull;
if (mRemoteContainerType.IsEmpty() || ! CanRemoteContainersChange())
return NS_ERROR_INVALID_ARG; // we must be a remote container
if (!IsDynamicContainer())
return NS_ERROR_INVALID_ARG; // we must be a dynamic container
if (! IsTypeContainer(aContainerType) || IsTypeFolder(aContainerType) ||
IsTypeQuery(aContainerType))
return NS_ERROR_INVALID_ARG; // not proper container type
if (aContainerType == nsNavHistoryResultNode::RESULT_TYPE_REMOTE_CONTAINER &&
if (aContainerType == nsNavHistoryResultNode::RESULT_TYPE_DYNAMIC_CONTAINER &&
aRemoteContainerType.IsEmpty())
return NS_ERROR_INVALID_ARG; // remote containers must have r.c. type
if (aContainerType != nsNavHistoryResultNode::RESULT_TYPE_REMOTE_CONTAINER &&
! aRemoteContainerType.IsEmpty())
return NS_ERROR_INVALID_ARG; // non-remote containers must NOT have r.c. type
return NS_ERROR_INVALID_ARG; // dynamic containers must have d.c. type
if (aContainerType != nsNavHistoryResultNode::RESULT_TYPE_DYNAMIC_CONTAINER &&
! aDynamicContainerType.IsEmpty())
return NS_ERROR_INVALID_ARG; // non-dynamic containers must NOT have d.c. type
nsRefPtr<nsNavHistoryContainerResultNode> result =
new nsNavHistoryContainerResultNode(EmptyCString(), aTitle, aIconURI,
aContainerType, PR_TRUE,
aRemoteContainerType);
aDynamicContainerType);
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
// append to our list
@ -1757,8 +1733,8 @@ nsNavHistoryContainerResultNode::AppendQueryNode(
const nsACString& aIconURI, nsINavHistoryQueryResultNode** _retval)
{
*_retval = nsnull;
if (mRemoteContainerType.IsEmpty() || ! CanRemoteContainersChange())
return NS_ERROR_INVALID_ARG; // we must be a remote container
if (!IsDynamicContainer())
return NS_ERROR_INVALID_ARG; // we must be a dynamic container
nsRefPtr<nsNavHistoryQueryResultNode> result =
new nsNavHistoryQueryResultNode(aQueryURI, aTitle, aIconURI);
@ -1772,47 +1748,45 @@ nsNavHistoryContainerResultNode::AppendQueryNode(
}
#endif
// nsNavHistoryContainerResultNode::AppendFolderNode
#if 0 // UNTESTED, commented out until it can be tested
NS_IMETHODIMP
nsNavHistoryContainerResultNode::AppendFolderNode(
PRInt64 aFolderId, nsINavHistoryFolderResultNode** _retval)
PRInt64 aFolderId, nsINavHistoryContainerResultNode** _retval)
{
*_retval = nsnull;
if (mRemoteContainerType.IsEmpty() || ! CanRemoteContainersChange())
return NS_ERROR_INVALID_ARG; // we must be a remote container
if (!IsDynamicContainer())
return NS_ERROR_INVALID_ARG; // we must be a dynamic container
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY);
// create the node, it will be addrefed for us
nsRefPtr<nsNavHistoryResultNode> result;
nsresult rv = bookmarks->ResultNodeForFolder(aFolderId,
GetGeneratingOptions(),
getter_AddRefs(result));
nsresult rv = bookmarks->ResultNodeForContainer(aFolderId,
GetGeneratingOptions(),
getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
// append to our list
if (! mChildren.AppendObject(result))
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*_retval = result->GetAsFolder());
rv = InsertChildAt(result, mChildren.Count());
NS_ENSURE_SUCCESS(rv, rv);
NS_ADDREF(*_retval = result->GetAsContainer());
return NS_OK;
}
#endif
// nsNavHistoryContainerResultNode::ClearContents
//
// Used by the remote container API to clear this container
// Used by the dynamic container API to clear this container
#if 0 // UNTESTED, commented out until it can be tested
NS_IMETHODIMP
nsNavHistoryContainerResultNode::ClearContents()
{
if (mRemoteContainerType.IsEmpty() || ! CanRemoteContainersChange())
return NS_ERROR_INVALID_ARG; // we must be a remote container
if (!IsDynamicContainer())
return NS_ERROR_INVALID_ARG; // we must be a dynamic container
// we know if CanRemoteContainersChange() then we are a regular container
// and not a query or folder, so clearing doesn't need anything else to
@ -1828,7 +1802,6 @@ nsNavHistoryContainerResultNode::ClearContents()
}
#endif
// nsNavHistoryQueryResultNode *************************************************
//
// HOW QUERY UPDATING WORKS
@ -1857,7 +1830,7 @@ nsNavHistoryQueryResultNode::nsNavHistoryQueryResultNode(
const nsACString& aQueryURI) :
nsNavHistoryContainerResultNode(aQueryURI, aTitle, aIconURI,
nsNavHistoryResultNode::RESULT_TYPE_QUERY,
PR_TRUE, EmptyCString()),
PR_TRUE, EmptyCString(), nsnull),
mHasSearchTerms(PR_FALSE),
mContentsValid(PR_FALSE),
mBatchInProgress(PR_FALSE)
@ -1873,9 +1846,8 @@ nsNavHistoryQueryResultNode::nsNavHistoryQueryResultNode(
nsNavHistoryQueryOptions* aOptions) :
nsNavHistoryContainerResultNode(EmptyCString(), aTitle, aIconURI,
nsNavHistoryResultNode::RESULT_TYPE_QUERY,
PR_TRUE, EmptyCString()),
PR_TRUE, EmptyCString(), aOptions),
mQueries(aQueries),
mOptions(aOptions),
mContentsValid(PR_FALSE),
mBatchInProgress(PR_FALSE)
{
@ -2649,12 +2621,11 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsNavHistoryFolderResultNode,
nsNavHistoryFolderResultNode::nsNavHistoryFolderResultNode(
const nsACString& aTitle, nsNavHistoryQueryOptions* aOptions,
PRInt64 aFolderId, const nsACString& aRemoteContainerType) :
PRInt64 aFolderId, const nsACString& aDynamicContainerType) :
nsNavHistoryContainerResultNode(EmptyCString(), aTitle, EmptyCString(),
nsNavHistoryResultNode::RESULT_TYPE_FOLDER,
PR_FALSE, aRemoteContainerType),
mContentsValid(PR_FALSE),
mOptions(aOptions)
PR_FALSE, aDynamicContainerType, aOptions),
mContentsValid(PR_FALSE)
{
mItemId = aFolderId;
@ -2714,25 +2685,23 @@ nsNavHistoryFolderResultNode::OpenContainer()
NS_ASSERTION(! mExpanded, "Container must be expanded to close it");
nsresult rv;
/* Untested container API functions
if (! mRemoteContainerType.IsEmpty()) {
// remote container API may want to change the bookmarks for this folder.
nsCOMPtr<nsIRemoteContainer> remote = do_GetService(mRemoteContainerType.get(), &rv);
if (NS_SUCCEEDED(rv)) {
remote->OnContainerOpening(static_cast<nsINavHistoryFolderResultNode*>(this),
mOptions);
} else {
NS_WARNING("Unable to get remote container for ");
NS_WARNING(mRemoteContainerType.get());
}
}
*/
if (! mContentsValid) {
rv = FillChildren();
NS_ENSURE_SUCCESS(rv, rv);
if (IsDynamicContainer()) {
// dynamic container API may want to change the bookmarks for this folder.
nsCOMPtr<nsIDynamicContainer> svc = do_GetService(mDynamicContainerType.get(), &rv);
if (NS_SUCCEEDED(rv)) {
svc->OnContainerNodeOpening(
static_cast<nsNavHistoryContainerResultNode*>(this), mOptions);
} else {
NS_WARNING("Unable to get dynamic container for ");
NS_WARNING(mDynamicContainerType.get());
}
}
}
mExpanded = PR_TRUE;
nsNavHistoryResult* result = GetResult();
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
if (result->GetView())
@ -3093,7 +3062,7 @@ nsNavHistoryFolderResultNode::OnItemAdded(PRInt64 aItemId,
NS_ENSURE_SUCCESS(rv, rv);
}
else if (itemType == nsINavBookmarksService::TYPE_FOLDER) {
rv = bookmarks->ResultNodeForFolder(aItemId, mOptions, &node);
rv = bookmarks->ResultNodeForContainer(aItemId, mOptions, &node);
NS_ENSURE_SUCCESS(rv, rv);
}
else if (itemType == nsINavBookmarksService::TYPE_SEPARATOR) {
@ -3690,19 +3659,15 @@ nsNavHistoryResult::SetViewer(nsINavHistoryResultViewer* aViewer)
// nsNavHistoryResult::GetRoot (nsINavHistoryResult)
//
// We have a pointer to a container, but it will either be a folder or
// query node, both of which QI to QueryResultNode (even though folder
// does not inherit from a concrete query).
NS_IMETHODIMP
nsNavHistoryResult::GetRoot(nsINavHistoryQueryResultNode** aRoot)
nsNavHistoryResult::GetRoot(nsINavHistoryContainerResultNode** aRoot)
{
if (! mRootNode) {
NS_NOTREACHED("Root is null");
*aRoot = nsnull;
return NS_ERROR_FAILURE;
}
return mRootNode->QueryInterface(NS_GET_IID(nsINavHistoryQueryResultNode),
return mRootNode->QueryInterface(NS_GET_IID(nsINavHistoryContainerResultNode),
reinterpret_cast<void**>(aRoot));
}

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

@ -292,7 +292,7 @@ public:
// Note that GetType() already has a vtable slot because its on the iface.
PRBool IsTypeContainer(PRUint32 type) {
return (type == nsINavHistoryResultNode::RESULT_TYPE_HOST ||
type == nsINavHistoryResultNode::RESULT_TYPE_REMOTE_CONTAINER ||
type == nsINavHistoryResultNode::RESULT_TYPE_DYNAMIC_CONTAINER ||
type == nsINavHistoryResultNode::RESULT_TYPE_QUERY ||
type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER ||
type == nsINavHistoryResultNode::RESULT_TYPE_DAY);
@ -302,6 +302,11 @@ public:
GetType(&type);
return IsTypeContainer(type);
}
PRBool IsDynamicContainer() {
PRUint32 type;
GetType(&type);
return (type == nsINavHistoryResultNode::RESULT_TYPE_DYNAMIC_CONTAINER);
}
static PRBool IsTypeQuerySubcontainer(PRUint32 type) {
// Tests containers that are inside queries that really belong to the query
// itself, and is used when recursively updating a query. This currently
@ -476,11 +481,13 @@ public:
{ return nsNavHistoryContainerResultNode::GetChildCount(aChildCount); } \
NS_IMETHOD GetChild(PRUint32 index, nsINavHistoryResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::GetChild(index, _retval); } \
NS_IMETHOD GetRemoteContainerType(nsACString& aRemoteContainerType) \
{ return nsNavHistoryContainerResultNode::GetRemoteContainerType(aRemoteContainerType); }
/* Untested container API functions
NS_IMETHOD GetDynamicContainerType(nsACString& aDynamicContainerType) \
{ return nsNavHistoryContainerResultNode::GetDynamicContainerType(aDynamicContainerType); } \
NS_IMETHOD AppendURINode(const nsACString& aURI, const nsACString& aTitle, PRUint32 aAccessCount, PRTime aTime, const nsACString& aIconURI, nsINavHistoryResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::AppendURINode(aURI, aTitle, aAccessCount, aTime, aIconURI, _retval); } \
NS_IMETHOD AppendFolderNode(PRInt64 aFolderId, nsINavHistoryContainerResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::AppendFolderNode(aFolderId, _retval); }
/* Untested container API functions
NS_IMETHOD AppendVisitNode(const nsACString& aURI, const nsACString & aTitle, PRUint32 aAccessCount, PRTime aTime, const nsACString & aIconURI, PRInt64 aSession, nsINavHistoryVisitResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::AppendVisitNode(aURI, aTitle, aAccessCount, aTime, aIconURI, aSession, _retval); } \
NS_IMETHOD AppendFullVisitNode(const nsACString& aURI, const nsACString & aTitle, PRUint32 aAccessCount, PRTime aTime, const nsACString & aIconURI, PRInt64 aSession, PRInt64 aVisitId, PRInt64 aReferringVisitId, PRInt32 aTransitionType, nsINavHistoryFullVisitResultNode **_retval) \
@ -489,8 +496,6 @@ public:
{ return nsNavHistoryContainerResultNode::AppendContainerNode(aTitle, aIconURI, aContainerType, aRemoteContainerType, _retval); } \
NS_IMETHOD AppendQueryNode(const nsACString& aQueryURI, const nsACString & aTitle, const nsACString & aIconURI, nsINavHistoryQueryResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::AppendQueryNode(aQueryURI, aTitle, aIconURI, _retval); } \
NS_IMETHOD AppendFolderNode(PRInt64 aFolderId, nsINavHistoryFolderResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::AppendFolderNode(aFolderId, _retval); } \
NS_IMETHOD ClearContents() \
{ return nsNavHistoryContainerResultNode::ClearContents(); }
*/
@ -505,7 +510,8 @@ public:
nsNavHistoryContainerResultNode(
const nsACString& aURI, const nsACString& aTitle,
const nsACString& aIconURI, PRUint32 aContainerType,
PRBool aReadOnly, const nsACString& aRemoteContainerType);
PRBool aReadOnly, const nsACString& aDynamicContainerType,
nsNavHistoryQueryOptions* aOptions);
NS_DECLARE_STATIC_IID_ACCESSOR(NS_NAVHISTORYCONTAINERRESULTNODE_IID)
@ -546,10 +552,10 @@ public:
PRBool mChildrenReadOnly;
// ID of a remote container interface that we can use GetService to get.
// This is empty to indicate there is no remote container service for this
// container (the common case).
nsCString mRemoteContainerType;
nsCOMPtr<nsNavHistoryQueryOptions> mOptions;
// ID of a dynamic container interface that we can use GetService to get.
nsCString mDynamicContainerType;
void FillStats();
void ReverseUpdateStats(PRInt32 aAccessCountChange);
@ -630,8 +636,6 @@ public:
nsresult ReplaceChildURIAt(PRUint32 aIndex, nsNavHistoryResultNode* aNode);
nsresult RemoveChildAt(PRInt32 aIndex, PRBool aIsTemporary = PR_FALSE);
PRBool CanRemoteContainersChange();
void RecursiveFindURIs(PRBool aOnlyOne,
nsNavHistoryContainerResultNode* aContainer,
const nsCString& aSpec,
@ -691,7 +695,6 @@ public:
// these may be constructed lazily from mURI, call VerifyQueriesParsed
// either this or mURI should be valid
nsCOMArray<nsNavHistoryQuery> mQueries;
nsCOMPtr<nsNavHistoryQueryOptions> mOptions;
PRUint32 mLiveUpdate; // one of QUERYUPDATE_* in nsNavHistory.h
PRBool mHasSearchTerms;
nsresult VerifyQueriesParsed();
@ -723,7 +726,7 @@ public:
nsNavHistoryFolderResultNode(const nsACString& aTitle,
nsNavHistoryQueryOptions* options,
PRInt64 aFolderId,
const nsACString& aRemoteContainerType);
const nsACString& aDynamicContainerType);
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_COMMON_RESULTNODE_TO_BASE
@ -750,8 +753,6 @@ public:
// after the container is closed until a notification comes in
PRBool mContentsValid;
nsCOMPtr<nsNavHistoryQueryOptions> mOptions;
nsresult FillChildren();
void ClearChildren(PRBool aUnregister);
nsresult Refresh();

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

@ -63,18 +63,10 @@ function run_test() {
uri("http://example.com/"),
uri("http://example.com/rss.xml"), -1);
try {
lmsvc.QueryInterface(Ci.nsIRemoteContainer);
} catch(ex) {
do_throw("Failed to QueryInterface livemark-service to nsIRemoteContainer");
}
do_check_true(lmsvc.childrenReadOnly);
do_check_true(lmsvc.isLivemark(livemarkId));
do_check_true(lmsvc.getSiteURI(livemarkId).spec == "http://example.com/");
do_check_true(lmsvc.getFeedURI(livemarkId).spec == "http://example.com/rss.xml");
do_check_true(bmsvc.getFolderReadonly(livemarkId));
lmsvc.setSiteURI(livemarkId, uri("http://foo.example.com/"));
do_check_true(lmsvc.getSiteURI(livemarkId).spec == "http://foo.example.com/");

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

@ -0,0 +1,103 @@
/* -*- 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 Dynamic Containers unit test code.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Asaf Romano <mano@mozilla.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 ***** */
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
function RemoteContainerSampleService() {
}
RemoteContainerSampleService.prototype = {
get bms() {
if (!this._bms)
this._bms = Cc[BMS_CONTRACTID].getService(Ci.nsINavBookmarksService);
return this._bms;
},
get history() {
if (!this._history)
this._history = Cc[NH_CONTRACTID].getService(Ci.nsINavHistoryService);
return this._history;
},
// IO Service
get ios() {
if (!this._ios)
this._ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
return this._ios;
},
// nsIDynamicContainer
onContainerRemoving: function(container) { },
onContainerMoved: function() { },
onContainerNodeOpening: function(container, options) {
container.appendURINode("http://foo.tld/", "uri 1", 0, 0, null);
var folder = Cc["@mozilla.org/browser/annotation-service;1"].
getService(Ci.nsIAnnotationService).
getItemAnnotation(container.itemId, "exposedFolder");
container.appendFolderNode(folder);
},
onContainerNodeClosed: function() { },
createInstance: function LS_createInstance(outer, iid) {
if (outer != null)
throw Cr.NS_ERROR_NO_AGGREGATION;
return this.QueryInterface(iid);
},
classDescription: "Remote Container Sample Service",
contractID: "@mozilla.org/browser/remote-container-sample;1",
classID: Components.ID("{0d42adc5-f07a-4da2-b8da-3e2ef114cb67}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDynamicContainer]),
};
function NSGetModule(compMgr, fileSpec) {
return XPCOMUtils.generateModule([RemoteContainerSampleService]);
}

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

@ -0,0 +1,87 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* ***** 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 Dynamic Containers unit test code.
*
* The Initial Developer of the Original Code is Mozilla Corporation
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Asaf Romano <mano@mozilla.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 ***** */
var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService);
var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
var annosvc = Cc["@mozilla.org/browser/annotation-service;1"].
getService(Ci.nsIAnnotationService);
// main
function run_test() {
// load our dynamic-container sample service
do_load_module("/toolkit/components/places/tests/unit/nsDynamicContainerServiceSample.js");
var testRoot = bmsvc.createFolder(bmsvc.placesRoot, "test root", bmsvc.DEFAULT_INDEX);
var exposedFolder = bmsvc.createFolder(testRoot, "exposed folder", bmsvc.DEFAULT_INDEX);
var efId1 = bmsvc.insertBookmark(exposedFolder, uri("http://uri1.tld"), bmsvc.DEFAULT_INDEX, "");
// create our dynamic container
var remoteContainer =
bmsvc.createDynamicContainer(testRoot, "remote container sample",
"@mozilla.org/browser/remote-container-sample;1",
bmsvc.DEFAULT_INDEX);
// the service will read this annotation and append a folder node for
// |exposedFolder| to |remoteContainer|
annosvc.setItemAnnotation(remoteContainer, "exposedFolder",
exposedFolder, 0, 0);
// query |remoteContainer|
var options = histsvc.getNewQueryOptions();
var query = histsvc.getNewQuery();
query.setFolders([remoteContainer], 1);
var result = histsvc.executeQuery(query, options);
var rootNode = result.root;
// two nodes should be at the top lop of this container after opening it,
// the first is an arbitrary uri node ("http://foo.tld/"), the second is a
// folder node representing |exposedFolder|.
rootNode.containerOpen = true;
do_check_eq(rootNode.childCount, 2);
do_check_eq(rootNode.getChild(0).uri, "http://foo.tld/");
var folder = rootNode.getChild(1).QueryInterface(Ci.nsINavHistoryContainerResultNode);
do_check_eq(folder.itemId, exposedFolder);
folder.containerOpen = true;
do_check_eq(folder.childCount, 1);
// check live update of a folder exposed within a remote container
bmsvc.insertBookmark(exposedFolder, uri("http://uri2.tld"), bmsvc.DEFAULT_INDEX, "");
do_check_eq(folder.childCount, 2);
}