Add a mozstorage-based FormHistory implementation, with an importer that uses the MorkReader class. Stop building Mork if building Places. Bug 324170, r=brettw, bsmedberg.

This commit is contained in:
bryner%brianryner.com 2006-01-26 19:17:04 +00:00
parent fa57a77957
commit daed416e86
19 changed files with 1602 additions and 885 deletions

View File

@ -160,7 +160,7 @@ Sanitizer.prototype = {
{
var formHistory = Components.classes["@mozilla.org/satchel/form-history;1"]
.getService(Components.interfaces.nsIFormHistory);
return formHistory.rowCount != 0;
return formHistory.hasEntries;
}
},

View File

@ -137,6 +137,8 @@ MOZ_PROFILESHARING = @MOZ_PROFILESHARING@
MOZ_PROFILELOCKING = @MOZ_PROFILELOCKING@
MOZ_PLACES = @MOZ_PLACES@
MOZ_STORAGE = @MOZ_STORAGE@
MOZ_MORK = @MOZ_MORK@
MOZ_MORKREADER = @MOZ_MORKREADER@
MOZ_NO_XPCOM_OBSOLETE = @MOZ_NO_XPCOM_OBSOLETE@
MOZ_NO_FAST_LOAD = @MOZ_NO_FAST_LOAD@
NS_PRINTING = @NS_PRINTING@

1430
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -4156,6 +4156,8 @@ MOZ_LIBART_CFLAGS=
MOZ_LIBART_LIBS=
MOZ_MAIL_NEWS=
MOZ_MATHML=1
MOZ_MORK=1
MOZ_MORKREADER=
MOZ_AUTH_EXTENSION=1
MOZ_NO_ACTIVEX_SUPPORT=1
MOZ_NO_XPCOM_OBSOLETE=
@ -5476,6 +5478,8 @@ MOZ_ARG_ENABLE_BOOL(places,
MOZ_PLACES= )
if test -n "$MOZ_PLACES"; then
AC_DEFINE(MOZ_PLACES)
MOZ_MORK=
MOZ_MORKREADER=1
fi
dnl ========================================================
@ -6937,6 +6941,18 @@ if test "$MOZ_V1_STRING_ABI"; then
AC_DEFINE(MOZ_V1_STRING_ABI)
fi
dnl Only build Mork if it's required
AC_SUBST(MOZ_MORK)
if test "$MOZ_MORK"; then
AC_DEFINE(MOZ_MORK)
fi
dnl Build the lightweight Mork reader if required
AC_SUBST(MOZ_MORKREADER)
if test "$MOZ_MORKREADER"; then
AC_DEFINE(MOZ_MORKREADER)
fi
dnl ========================================================
if test "$MOZ_DEBUG" || test "$NS_TRACE_MALLOC"; then
MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS=

View File

@ -42,9 +42,10 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
ifdef MOZ_MORK
DIRS = mdb mork
ifdef MOZ_PLACES
endif
ifdef MOZ_MORKREADER
DIRS += morkreader
endif

View File

@ -47,6 +47,7 @@ MODULE = morkreader
LIBRARY_NAME = morkreader_s
MOZILLA_INTERNAL_API = 1
FORCE_STATIC_LIB = 1
EXPORT_LIBRARY = 1
REQUIRES = xpcom \
string \

View File

@ -55,19 +55,26 @@ REQUIRES = xpcom \
string \
dom \
layout \
mork \
unicharutil \
toolkitcomps \
$(NULL)
CPPSRCS = nsAutoCompleteController.cpp \
nsAutoCompleteMdbResult.cpp \
nsAutoCompleteSimpleResult.cpp \
$(NULL)
ifdef MOZ_MORK
REQUIRES += mork
CPPSRCS += nsAutoCompleteMdbResult.cpp
endif
EXTRA_DSO_LDOPTS += \
$(MOZ_UNICHARUTIL_LIBS) \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
ifdef MOZ_MORKREADER
EXTRA_DSO_LDOPTS += $(DIST)/lib/$(LIB_PREFIX)morkreader_s.$(LIB_SUFFIX)
endif
include $(topsrcdir)/config/rules.mk

View File

@ -40,11 +40,12 @@
* ***** END LICENSE BLOCK ***** */
#include "nsAutoCompleteController.h"
#ifdef MOZ_MORK
#include "nsAutoCompleteMdbResult.h"
#endif
#include "nsAutoCompleteSimpleResult.h"
#include "nsToolkitCompsCID.h"
#include "nsIAutoCompleteResultTypes.h"
#include "nsIServiceManager.h"
#include "nsIDOMElement.h"
#include "nsIAtomService.h"
@ -1274,7 +1275,9 @@ nsAutoCompleteController::RowIndexToSearch(PRInt32 aRowIndex, PRInt32 *aSearchIn
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAutoCompleteController)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAutoCompleteSimpleResult)
#ifdef MOZ_MORK
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAutoCompleteMdbResult)
#endif
static const nsModuleComponentInfo components[] =
{
@ -1288,10 +1291,12 @@ static const nsModuleComponentInfo components[] =
NS_AUTOCOMPLETESIMPLERESULT_CONTRACTID,
nsAutoCompleteSimpleResultConstructor },
#ifdef MOZ_MORK
{ "AutoComplete Mdb Result",
NS_AUTOCOMPLETEMDBRESULT_CID,
NS_AUTOCOMPLETEMDBRESULT_CONTRACTID,
nsAutoCompleteMdbResultConstructor },
#endif
};
NS_IMPL_NSGETMODULE(tkAutoCompleteModule, components)

View File

@ -156,7 +156,12 @@ NS_IMETHODIMP
nsAutoCompleteSimpleResult::RemoveValueAt(PRInt32 aRowIndex,
PRBool aRemoveFromDb)
{
return NS_ERROR_NOT_IMPLEMENTED;
NS_ENSURE_TRUE(aRowIndex >= 0 && aRowIndex < mValues.Count(),
NS_ERROR_ILLEGAL_VALUE);
mValues.RemoveStringAt(aRowIndex);
mComments.RemoveStringAt(aRowIndex);
return NS_OK;
}

View File

@ -61,7 +61,6 @@ REQUIRES = \
widget \
layout \
dom \
mork \
pref \
rdf \
intl \

View File

@ -56,6 +56,9 @@
#define NS_FORMHISTORY_CONTRACTID \
"@mozilla.org/satchel/form-history;1"
#define NS_FORMHISTORYIMPORTER_CONTRACTID \
"@mozilla.org/satchel/form-history-importer;1"
#define NS_FORMFILLCONTROLLER_CONTRACTID \
"@mozilla.org/satchel/form-fill-controller;1"
@ -100,6 +103,10 @@
#define NS_FORMHISTORY_CID \
{ 0xa2059c0e, 0x5a58, 0x4c55, { 0xab, 0x7c, 0x26, 0xf0, 0x55, 0x75, 0x46, 0xef } }
// {db340cc2-7f50-4ea3-8427-f529daf6dc87}
#define NS_FORMHISTORYIMPORTER_CID \
{ 0xdb340cc2, 0x7f50, 0x4ea3, { 0x84, 0x27, 0xf5, 0x29, 0xda, 0xf6, 0xdc, 0x87 } }
// {59648a91-5a60-4122-8ff2-54b839c84aed}
#define NS_GLOBALHISTORY_CID \
{ 0x59648a91, 0x5a60, 0x4122, { 0x8f, 0xf2, 0x54, 0xb8, 0x39, 0xc8, 0x4a, 0xed} }

View File

@ -36,39 +36,36 @@
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIFile;
[scriptable, uuid(fa5a871d-29f5-489e-aaa4-c266def52b79)]
/**
* The nsIFormHistory object is a service which holds a set of name/value
* pairs. The names correspond to form field names, and the values correspond
* to values the user has submitted. So, several values may exist for a single
* name.
*
* Note: this interface provides no means to access stored values.
* Stored values are used by the FormFillController to generate
* autocomplete matches.
*/
[scriptable, uuid(a61f0a62-ae0a-4382-b474-d259442ca80c)]
interface nsIFormHistory : nsISupports
{
/**
* The total number of rows in the form history.
* Returns true if the form history has any entries.
*/
readonly attribute unsigned long rowCount;
readonly attribute boolean hasEntries;
/**
* Gets the name and value at a position in the form history.
*/
void getEntryAt(in unsigned long index, out AString name, out AString value);
/**
* Gets just the name at a position in the form history.
*/
void getNameAt(in unsigned long index, out AString name);
/**
* Gets just the value at a position in the form history.
*/
void getValueAt(in unsigned long index, out AString value);
/**
* Appends a name and value pair to the end of the form history.
* Adds a name and value pair to the form history.
*/
void addEntry(in AString name, in AString value);
/**
* Removes the entry at a position.
* Removes a name and value pair from the form history.
*/
void removeEntryAt(in unsigned long index);
void removeEntry(in AString name, in AString value);
/**
* Removes all entries that are paired with a name.
@ -90,3 +87,21 @@ interface nsIFormHistory : nsISupports
*/
boolean entryExists(in AString name, in AString value);
};
/**
* nsIFormHistoryImporter is an interface for importing a Mork formhistory.dat
* file into the new form history storage.
*/
[scriptable, uuid(9e811188-6a5b-4d96-a92d-1bac66a41898)]
interface nsIFormHistoryImporter : nsISupports
{
/**
* Import the given Mork form history file.
* @param file The Mork form history file to import
* @param history A reference to the nsIFormHistory. This is
* supplied since the importer is invoked during
* form history initialization.
*/
void importFormHistory(in nsIFile file, in nsIFormHistory formHistory);
};

View File

@ -64,7 +64,6 @@ REQUIRES = \
content \
view \
locale \
mork \
unicharutil \
intl \
pref \
@ -73,10 +72,25 @@ REQUIRES = \
$(NULL)
CPPSRCS = nsFormFillController.cpp \
nsFormHistory.cpp \
$(NULL)
LOCAL_INCLUDES = -I$(srcdir)/../../passwordmgr/base
ifdef MOZ_STORAGE
REQUIRES += storage
CPPSRCS += nsStorageFormHistory.cpp
ifdef MOZ_MORKREADER
REQUIRES += morkreader
endif
else # MOZ_STORAGE
ifdef MOZ_MORK
REQUIRES += mork
CPPSRCS += nsFormHistory.cpp
endif
endif # MOZ_STORAGE
LOCAL_INCLUDES = \
-I$(srcdir)/../../passwordmgr/base \
-I$(srcdir)/../../build \
$(NULL)
SHARED_LIBRARY_LIBS = \
$(DIST)/lib/$(LIB_PREFIX)passwordmgr_s.$(LIB_SUFFIX) \
@ -91,3 +105,8 @@ EXTRA_DSO_LDOPTS += \
$(MOZ_UNICHARUTIL_LIBS) \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
ifdef MOZ_MORKREADER
EXTRA_DSO_LDOPTS += $(DIST)/lib/$(LIB_PREFIX)morkreader_s.$(LIB_SUFFIX)
endif

View File

@ -39,8 +39,13 @@
#include "nsFormFillController.h"
#ifdef MOZ_STORAGE
#include "nsStorageFormHistory.h"
#include "nsIAutoCompleteSimpleResult.h"
#elif defined(MOZ_MORK)
#include "nsFormHistory.h"
#include "nsIAutoCompleteResultTypes.h"
#endif
#include "nsString.h"
#include "nsReadableUtils.h"
#include "nsIServiceManager.h"
@ -489,17 +494,27 @@ nsFormFillController::StartSearch(const nsAString &aSearchString, const nsAStrin
nsIAutoCompleteResult *aPreviousResult, nsIAutoCompleteObserver *aListener)
{
nsCOMPtr<nsIAutoCompleteResult> result;
nsCOMPtr<nsIAutoCompleteMdbResult> mdbResult = do_QueryInterface(aPreviousResult);
#ifdef MOZ_STORAGE
// This assumes that FormHistory uses nsIAutoCompleteSimpleResult,
// while PasswordManager does not.
nsCOMPtr<nsIAutoCompleteSimpleResult> historyResult;
#elif defined(MOZ_MORK)
nsCOMPtr<nsIAutoCompleteMdbResult> historyResult;
#else
#error either mozstorage or mork must be compiled
#endif
historyResult = do_QueryInterface(aPreviousResult);
nsPasswordManager* passMgr = nsPasswordManager::GetInstance();
if (!passMgr)
return NS_ERROR_OUT_OF_MEMORY;
// Only hand off a previous result to the password manager if it's
// a password manager result (i.e. not an nsIAutoCompleteMdbResult).
// a password manager result (i.e. not an nsIAutoCompleteMdb/SimpleResult).
if (!passMgr->AutoCompleteSearch(aSearchString,
mdbResult ? nsnull : aPreviousResult,
historyResult ? nsnull : aPreviousResult,
mFocusedInput,
getter_AddRefs(result)))
{
@ -507,9 +522,8 @@ nsFormFillController::StartSearch(const nsAString &aSearchString, const nsAStrin
if (history) {
history->AutoCompleteSearch(aSearchParam,
aSearchString,
mdbResult,
historyResult,
getter_AddRefs(result));
NS_RELEASE(history);
}
}
NS_RELEASE(passMgr);
@ -1106,15 +1120,17 @@ nsFormFillController::GetIndexOfDocShell(nsIDocShell *aDocShell)
return -1;
}
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsFormHistory, nsFormHistory::GetInstance)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsFormHistory, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFormFillController)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsPasswordManager, nsPasswordManager::GetInstance)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSingleSignonPrompt)
#if defined(MOZ_STORAGE) && defined(MOZ_MORKREADER)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFormHistoryImporter)
#endif
static void PR_CALLBACK nsFormHistoryModuleDtor(nsIModule* self)
{
nsPasswordManager::Shutdown();
nsFormHistory::ReleaseInstance();
}
static const nsModuleComponentInfo components[] =
@ -1144,7 +1160,14 @@ static const nsModuleComponentInfo components[] =
{ "HTML Form History AutoComplete",
NS_FORMFILLCONTROLLER_CID,
NS_FORMHISTORYAUTOCOMPLETE_CONTRACTID,
nsFormFillControllerConstructor }
nsFormFillControllerConstructor },
#if defined(MOZ_STORAGE) && defined(MOZ_MORKREADER)
{ "Form History Importer",
NS_FORMHISTORYIMPORTER_CID,
NS_FORMHISTORYIMPORTER_CONTRACTID,
nsFormHistoryImporterConstructor },
#endif
};
NS_IMPL_NSGETMODULE_WITH_DTOR(satchel, components, nsFormHistoryModuleDtor)

View File

@ -56,7 +56,8 @@
#include "nsIDocShell.h"
#include "nsIDOMWindow.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsFormHistory.h"
class nsFormHistory;
class nsFormFillController : public nsIFormFillController,
public nsIAutoCompleteInput,

View File

@ -88,18 +88,21 @@ nsFormHistory::nsFormHistory() :
mStore(nsnull),
mTable(nsnull)
{
NS_ASSERTION(!gFormHistory, "nsFormHistory must be used as a service");
gFormHistory = this;
}
nsFormHistory::~nsFormHistory()
{
NS_ASSERTION(gFormHistory == this,
"nsFormHistory must be used as a service");
CloseDatabase();
gFormHistory = nsnull;
}
nsresult
nsFormHistory::Init()
{
gFormHistory = this;
nsCOMPtr<nsIObserverService> service = do_GetService("@mozilla.org/observer-service;1");
if (service)
service->AddObserver(this, NS_FORMSUBMIT_SUBJECT, PR_TRUE);
@ -109,35 +112,6 @@ nsFormHistory::Init()
nsFormHistory *nsFormHistory::gFormHistory = nsnull;
nsFormHistory *
nsFormHistory::GetInstance()
{
if (!gFormHistory) {
gFormHistory = new nsFormHistory();
if (!gFormHistory)
return nsnull;
NS_ADDREF(gFormHistory); // addref for the global
if (NS_FAILED(gFormHistory->Init())) {
NS_RELEASE(gFormHistory);
return nsnull;
}
}
NS_ADDREF(gFormHistory); // addref for the getter
return gFormHistory;
}
void
nsFormHistory::ReleaseInstance()
{
NS_IF_RELEASE(gFormHistory);
}
/* static */ PRBool
nsFormHistory::FormHistoryEnabled()
{
@ -164,60 +138,16 @@ nsFormHistory::FormHistoryEnabled()
//// nsIFormHistory
NS_IMETHODIMP
nsFormHistory::GetRowCount(PRUint32 *aRowCount)
nsFormHistory::GetHasEntries(PRBool *aHasEntries)
{
nsresult rv = OpenDatabase(); // lazily ensure that the database is open
NS_ENSURE_SUCCESS(rv, rv);
mdb_err err = mTable->GetCount(mEnv, aRowCount);
PRUint32 rowCount;
mdb_err err = mTable->GetCount(mEnv, &rowCount);
NS_ENSURE_TRUE(!err, NS_ERROR_FAILURE);
return NS_OK;
}
NS_IMETHODIMP
nsFormHistory::GetEntryAt(PRUint32 aIndex, nsAString &aName, nsAString &aValue)
{
nsresult rv = OpenDatabase(); // lazily ensure that the database is open
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIMdbRow> row;
mdb_err err = mTable->PosToRow(mEnv, aIndex, getter_AddRefs(row));
NS_ENSURE_TRUE(!err, NS_ERROR_FAILURE);
GetRowValue(row, kToken_NameColumn, aName);
GetRowValue(row, kToken_ValueColumn, aValue);
return NS_OK;
}
NS_IMETHODIMP
nsFormHistory::GetNameAt(PRUint32 aIndex, nsAString &aName)
{
nsresult rv = OpenDatabase(); // lazily ensure that the database is open
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIMdbRow> row;
mdb_err err = mTable->PosToRow(mEnv, aIndex, getter_AddRefs(row));
NS_ENSURE_TRUE(!err, NS_ERROR_FAILURE);
GetRowValue(row, kToken_NameColumn, aName);
return NS_OK;
}
NS_IMETHODIMP
nsFormHistory::GetValueAt(PRUint32 aIndex, nsAString &aValue)
{
nsresult rv = OpenDatabase(); // lazily ensure that the database is open
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIMdbRow> row;
mdb_err err = mTable->PosToRow(mEnv, aIndex, getter_AddRefs(row));
NS_ENSURE_TRUE(!err, NS_ERROR_FAILURE);
GetRowValue(row, kToken_ValueColumn, aValue);
*aHasEntries = rowCount != 0;
return NS_OK;
}
@ -235,12 +165,6 @@ nsFormHistory::AddEntry(const nsAString &aName, const nsAString &aValue)
return NS_OK;
}
NS_IMETHODIMP
nsFormHistory::RemoveEntryAt(PRUint32 index)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsFormHistory::EntryExists(const nsAString &aName, const nsAString &aValue, PRBool *_retval)
{
@ -253,6 +177,12 @@ nsFormHistory::NameExists(const nsAString &aName, PRBool *_retval)
return EntriesExistInternal(&aName, nsnull, _retval);
}
NS_IMETHODIMP
nsFormHistory::RemoveEntry(const nsAString &aName, const nsAString &aValue)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsFormHistory::RemoveEntriesForName(const nsAString &aName)
{

View File

@ -47,6 +47,8 @@
#include "nsIPrefBranch.h"
#include "nsWeakReference.h"
#include "mdb.h"
#include "nsIServiceManager.h"
#include "nsToolkitCompsCID.h"
class nsFormHistory : public nsIFormHistory,
public nsIObserver,
@ -65,8 +67,13 @@ public:
virtual ~nsFormHistory();
nsresult Init();
static nsFormHistory *GetInstance();
static void ReleaseInstance(void);
static nsFormHistory *GetInstance()
{
if (!gFormHistory) {
nsCOMPtr<nsIFormHistory> fh = do_GetService(NS_FORMHISTORY_CONTRACTID);
}
return gFormHistory;
}
nsresult AutoCompleteSearch(const nsAString &aInputName, const nsAString &aInputValue,
nsIAutoCompleteMdbResult *aPrevResult, nsIAutoCompleteResult **aNewResult);

View File

@ -0,0 +1,615 @@
/* -*- 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 Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Joe Hewitt <hewitt@netscape.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 "nsStorageFormHistory.h"
#include "nsIServiceManager.h"
#include "nsIObserverService.h"
#include "nsICategoryManager.h"
#include "nsIDirectoryService.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsCRT.h"
#include "nsString.h"
#include "nsUnicharUtils.h"
#include "nsReadableUtils.h"
#include "nsIContent.h"
#include "nsIDOMNode.h"
#include "nsIDOMHTMLFormElement.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsIDOMHTMLCollection.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsIPrefBranch2.h"
#include "nsVoidArray.h"
#include "nsCOMArray.h"
#include "mozStorageHelper.h"
#include "mozStorageCID.h"
#include "nsIAutoCompleteSimpleResult.h"
// nsFormHistoryResult is a specialized autocomplete result class that knows
// how to remove entries from the form history table.
class nsFormHistoryResult : public nsIAutoCompleteSimpleResult
{
public:
nsFormHistoryResult(const nsAString &aFieldName)
: mFieldName(aFieldName) {}
nsresult Init();
NS_DECL_ISUPPORTS
// Forward everything except RemoveValueAt to the internal result
NS_IMETHOD GetSearchString(nsAString &_result)
{ return mResult->GetSearchString(_result); }
NS_IMETHOD GetSearchResult(PRUint16 *_result)
{ return mResult->GetSearchResult(_result); }
NS_IMETHOD GetDefaultIndex(PRInt32 *_result)
{ return mResult->GetDefaultIndex(_result); }
NS_IMETHOD GetErrorDescription(nsAString &_result)
{ return mResult->GetErrorDescription(_result); }
NS_IMETHOD GetMatchCount(PRUint32 *_result)
{ return mResult->GetMatchCount(_result); }
NS_IMETHOD GetValueAt(PRInt32 aIndex, nsAString &_result)
{ return mResult->GetValueAt(aIndex, _result); }
NS_IMETHOD GetCommentAt(PRInt32 aIndex, nsAString &_result)
{ return mResult->GetCommentAt(aIndex, _result); }
NS_IMETHOD GetStyleAt(PRInt32 aIndex, nsAString &_result)
{ return mResult->GetStyleAt(aIndex, _result); }
NS_IMETHOD RemoveValueAt(PRInt32 aRowIndex, PRBool aRemoveFromDB);
NS_FORWARD_NSIAUTOCOMPLETESIMPLERESULT(mResult->)
protected:
nsCOMPtr<nsIAutoCompleteSimpleResult> mResult;
nsString mFieldName;
};
NS_IMPL_ISUPPORTS2(nsFormHistoryResult,
nsIAutoCompleteResult, nsIAutoCompleteSimpleResult)
nsresult
nsFormHistoryResult::Init()
{
nsresult rv;
mResult = do_CreateInstance(NS_AUTOCOMPLETESIMPLERESULT_CONTRACTID, &rv);
return rv;
}
NS_IMETHODIMP
nsFormHistoryResult::RemoveValueAt(PRInt32 aRowIndex, PRBool aRemoveFromDB)
{
if (!aRemoveFromDB) {
return mResult->RemoveValueAt(aRowIndex, aRemoveFromDB);
}
nsAutoString value;
nsresult rv = mResult->GetValueAt(aRowIndex, value);
NS_ENSURE_SUCCESS(rv, rv);
rv = mResult->RemoveValueAt(aRowIndex, aRemoveFromDB);
NS_ENSURE_SUCCESS(rv, rv);
nsFormHistory* fh = nsFormHistory::GetInstance();
NS_ENSURE_TRUE(fh, NS_ERROR_OUT_OF_MEMORY);
return fh->RemoveEntry(mFieldName, value);
}
#define PREF_FORMFILL_BRANCH "browser.formfill."
#define PREF_FORMFILL_ENABLE "enable"
NS_INTERFACE_MAP_BEGIN(nsFormHistory)
NS_INTERFACE_MAP_ENTRY(nsIFormHistory)
// Have to do this one by hand because it's an ambiguous conversion
// to nsISupports.
if (aIID.Equals(NS_GET_IID(nsFormHistory))) {
NS_ADDREF_THIS();
*aInstancePtr = this;
return NS_OK;
} else
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsIFormSubmitObserver)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsFormHistory)
NS_IMPL_RELEASE(nsFormHistory)
PRBool nsFormHistory::gFormHistoryEnabled = PR_FALSE;
PRBool nsFormHistory::gPrefsInitialized = PR_FALSE;
nsFormHistory* nsFormHistory::gFormHistory = nsnull;
nsFormHistory::nsFormHistory()
{
NS_ASSERTION(!gFormHistory, "nsFormHistory must be used as a service");
gFormHistory = this;
}
nsFormHistory::~nsFormHistory()
{
NS_ASSERTION(gFormHistory == this,
"nsFormHistory must be used as a service");
gFormHistory = nsnull;
}
nsresult
nsFormHistory::Init()
{
nsresult rv = OpenDatabase();
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIObserverService> service = do_GetService("@mozilla.org/observer-service;1");
if (service)
service->AddObserver(this, NS_FORMSUBMIT_SUBJECT, PR_TRUE);
return NS_OK;
}
/* static */ PRBool
nsFormHistory::FormHistoryEnabled()
{
if (!gPrefsInitialized) {
nsCOMPtr<nsIPrefService> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
prefService->GetBranch(PREF_FORMFILL_BRANCH,
getter_AddRefs(gFormHistory->mPrefBranch));
gFormHistory->mPrefBranch->GetBoolPref(PREF_FORMFILL_ENABLE,
&gFormHistoryEnabled);
nsCOMPtr<nsIPrefBranch2> branchInternal =
do_QueryInterface(gFormHistory->mPrefBranch);
branchInternal->AddObserver(PREF_FORMFILL_ENABLE, gFormHistory, PR_TRUE);
gPrefsInitialized = PR_TRUE;
}
return gFormHistoryEnabled;
}
////////////////////////////////////////////////////////////////////////
//// nsIFormHistory
NS_IMETHODIMP
nsFormHistory::GetHasEntries(PRBool *aHasEntries)
{
mozStorageStatementScoper scope(mDBSelectEntries);
PRBool hasMore;
*aHasEntries = mDBSelectEntries->ExecuteStep(&hasMore) && hasMore;
return NS_OK;
}
NS_IMETHODIMP
nsFormHistory::AddEntry(const nsAString &aName, const nsAString &aValue)
{
if (!FormHistoryEnabled())
return NS_OK;
mozStorageTransaction transaction(mDBConn, PR_FALSE);
PRBool exists;
EntryExists(aName, aValue, &exists);
if (!exists) {
mozStorageStatementScoper scope(mDBInsertNameValue);
nsresult rv = mDBInsertNameValue->BindStringParameter(0, aName);
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBInsertNameValue->BindStringParameter(1, aValue);
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBInsertNameValue->Execute();
NS_ENSURE_SUCCESS(rv, rv);
}
return transaction.Commit();
}
NS_IMETHODIMP
nsFormHistory::EntryExists(const nsAString &aName,
const nsAString &aValue, PRBool *_retval)
{
mozStorageStatementScoper scope(mDBFindEntry);
nsresult rv = mDBFindEntry->BindStringParameter(0, aName);
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBFindEntry->BindStringParameter(1, aValue);
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasMore;
*_retval = NS_SUCCEEDED(mDBFindEntry->ExecuteStep(&hasMore)) && hasMore;
return NS_OK;
}
NS_IMETHODIMP
nsFormHistory::NameExists(const nsAString &aName, PRBool *_retval)
{
mozStorageStatementScoper scope(mDBFindEntryByName);
nsresult rv = mDBFindEntryByName->BindStringParameter(0, aName);
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasMore;
*_retval = (NS_SUCCEEDED(mDBFindEntryByName->ExecuteStep(&hasMore)) &&
hasMore);
return NS_OK;
}
NS_IMETHODIMP
nsFormHistory::RemoveEntry(const nsAString &aName, const nsAString &aValue)
{
nsCOMPtr<mozIStorageStatement> dbDelete;
nsresult rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("DELETE FROM moz_formhistory WHERE fieldname=?1 AND value=?2"),
getter_AddRefs(dbDelete));
NS_ENSURE_SUCCESS(rv,rv);
rv = dbDelete->BindStringParameter(0, aName);
NS_ENSURE_SUCCESS(rv,rv);
rv = dbDelete->BindStringParameter(1, aValue);
NS_ENSURE_SUCCESS(rv, rv);
return dbDelete->Execute();
}
NS_IMETHODIMP
nsFormHistory::RemoveEntriesForName(const nsAString &aName)
{
nsCOMPtr<mozIStorageStatement> dbDelete;
nsresult rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("DELETE FROM moz_formhistory WHERE fieldname=?1"),
getter_AddRefs(dbDelete));
NS_ENSURE_SUCCESS(rv,rv);
rv = dbDelete->BindStringParameter(0, aName);
NS_ENSURE_SUCCESS(rv,rv);
return dbDelete->Execute();
}
NS_IMETHODIMP
nsFormHistory::RemoveAllEntries()
{
nsCOMPtr<mozIStorageStatement> dbDeleteAll;
nsresult rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("DELETE FROM moz_formhistory"),
getter_AddRefs(dbDeleteAll));
NS_ENSURE_SUCCESS(rv,rv);
return dbDeleteAll->Execute();
}
////////////////////////////////////////////////////////////////////////
//// nsIObserver
NS_IMETHODIMP
nsFormHistory::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)
{
if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
mPrefBranch->GetBoolPref(PREF_FORMFILL_ENABLE, &gFormHistoryEnabled);
}
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
//// nsIFormSubmitObserver
NS_IMETHODIMP
nsFormHistory::Notify(nsIContent* aFormNode, nsIDOMWindowInternal* aWindow, nsIURI* aActionURL, PRBool* aCancelSubmit)
{
if (!FormHistoryEnabled())
return NS_OK;
nsCOMPtr<nsIDOMHTMLFormElement> formElt = do_QueryInterface(aFormNode);
NS_ENSURE_TRUE(formElt, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMHTMLCollection> elts;
formElt->GetElements(getter_AddRefs(elts));
const char *textString = "text";
PRUint32 length;
elts->GetLength(&length);
for (PRUint32 i = 0; i < length; ++i) {
nsCOMPtr<nsIDOMNode> node;
elts->Item(i, getter_AddRefs(node));
nsCOMPtr<nsIDOMHTMLInputElement> inputElt = do_QueryInterface(node);
if (inputElt) {
// Filter only inputs that are of type "text"
nsAutoString type;
inputElt->GetType(type);
if (type.EqualsIgnoreCase(textString)) {
// If this input has a name/id and value, add it to the database
nsAutoString value;
inputElt->GetValue(value);
if (!value.IsEmpty()) {
nsAutoString name;
inputElt->GetName(name);
if (name.IsEmpty())
inputElt->GetId(name);
if (!name.IsEmpty())
AddEntry(name, value);
}
}
}
}
return NS_OK;
}
nsresult
nsFormHistory::OpenDatabase()
{
// init DB service and obtain a connection
nsresult rv;
mStorageService = do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = mStorageService->OpenSpecialDatabase(MOZ_STORAGE_PROFILE_STORAGE_KEY,
getter_AddRefs(mDBConn));
NS_ENSURE_SUCCESS(rv, rv);
PRBool exists;
mDBConn->TableExists(NS_LITERAL_CSTRING("moz_formhistory"), &exists);
if (!exists) {
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("CREATE TABLE moz_formhistory (id INTEGER PRIMARY KEY, fieldname LONGVARCHAR, value LONGVARCHAR)"));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("CREATE INDEX moz_formhistory_index ON moz_formhistory (fieldname)"));
NS_ENSURE_SUCCESS(rv, rv);
}
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("SELECT * FROM moz_formhistory"),
getter_AddRefs(mDBSelectEntries));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("SELECT * FROM moz_formhistory WHERE fieldname=?1 AND value=?2"),
getter_AddRefs(mDBFindEntry));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("SELECT * FROM moz_formhistory WHERE fieldname=?1"),
getter_AddRefs(mDBFindEntryByName));
NS_ENSURE_SUCCESS(rv,rv);
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("SELECT value FROM moz_formhistory WHERE fieldname=?1"),
getter_AddRefs(mDBGetMatchingField));
NS_ENSURE_SUCCESS(rv,rv);
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING("INSERT INTO moz_formhistory (fieldname, value) VALUES (?1, ?2)"),
getter_AddRefs(mDBInsertNameValue));
NS_ENSURE_SUCCESS(rv, rv);
if (!exists) {
// Locate the old formhistory.dat file and import it.
nsCOMPtr<nsIFile> historyFile;
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
getter_AddRefs(historyFile));
if (NS_SUCCEEDED(rv)) {
historyFile->Append(NS_LITERAL_STRING("formhistory.dat"));
nsCOMPtr<nsIFormHistoryImporter> importer = new nsFormHistoryImporter();
NS_ENSURE_TRUE(importer, NS_ERROR_OUT_OF_MEMORY);
importer->ImportFormHistory(historyFile, this);
}
}
return NS_OK;
}
nsresult
nsFormHistory::AutoCompleteSearch(const nsAString &aInputName,
const nsAString &aInputValue,
nsIAutoCompleteSimpleResult *aPrevResult,
nsIAutoCompleteResult **aResult)
{
if (!FormHistoryEnabled())
return NS_OK;
nsCOMPtr<nsIAutoCompleteSimpleResult> result;
if (aPrevResult) {
result = aPrevResult;
PRUint32 matchCount;
result->GetMatchCount(&matchCount);
for (PRInt32 i = matchCount - 1; i >= 0; --i) {
nsAutoString match;
result->GetValueAt(i, match);
if (!StringBeginsWith(match, aInputValue,
nsCaseInsensitiveStringComparator())) {
result->RemoveValueAt(i, PR_FALSE);
}
}
} else {
nsCOMPtr<nsFormHistoryResult> fhResult =
new nsFormHistoryResult(aInputName);
NS_ENSURE_TRUE(fhResult, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = fhResult->Init();
NS_ENSURE_SUCCESS(rv, rv);
NS_REINTERPRET_CAST(nsCOMPtr<nsIAutoCompleteSimpleResult>*, &fhResult)->swap(result);
result->SetSearchString(aInputValue);
// generates query string
mozStorageStatementScoper scope(mDBGetMatchingField);
rv = mDBGetMatchingField->BindStringParameter(0, aInputName);
NS_ENSURE_SUCCESS(rv,rv);
PRBool hasMore = PR_FALSE;
PRUint32 count = 0;
while (NS_SUCCEEDED(mDBGetMatchingField->ExecuteStep(&hasMore)) &&
hasMore) {
nsAutoString entryString;
mDBGetMatchingField->GetString(0, entryString);
// filters out irrelevant results
if(StringBeginsWith(entryString, aInputValue,
nsCaseInsensitiveStringComparator())) {
result->AppendMatch(entryString, EmptyString());
++count;
}
}
if (count > 0) {
result->SetSearchResult(nsIAutoCompleteResult::RESULT_SUCCESS);
result->SetDefaultIndex(0);
} else {
result->SetSearchResult(nsIAutoCompleteResult::RESULT_NOMATCH);
result->SetDefaultIndex(-1);
}
}
*aResult = result;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
#ifdef MOZ_MORKREADER
// Columns for form history rows
enum {
kNameColumn,
kValueColumn,
kColumnCount // keep me last
};
static const char * const gColumnNames[] = {
"Name", "Value"
};
struct FormHistoryImportClosure
{
FormHistoryImportClosure(nsMorkReader *aReader, nsIFormHistory *aFormHistory)
: reader(aReader), formHistory(aFormHistory) { }
// Back pointers to the reader and history we're operating on
nsMorkReader *reader;
nsIFormHistory *formHistory;
// Column ids of the columns that we care about
nsCString columnIDs[kColumnCount];
};
// Enumerator callback to build up the column list
/* static */ PLDHashOperator PR_CALLBACK
nsFormHistoryImporter::EnumerateColumnsCB(const nsACString &aColumnID,
nsCString aName, void *aData)
{
FormHistoryImportClosure *data = NS_STATIC_CAST(FormHistoryImportClosure*,
aData);
for (PRUint32 i = 0; i < kColumnCount; ++i) {
if (aName.Equals(gColumnNames[i])) {
data->columnIDs[i].Assign(aColumnID);
return PL_DHASH_NEXT;
}
}
return PL_DHASH_NEXT;
}
// Enumerator callback to add an entry to the FormHistory
/* static */ PLDHashOperator PR_CALLBACK
nsFormHistoryImporter::AddToFormHistoryCB(const nsACString &aRowID,
const nsMorkReader::StringMap *aMap,
void *aData)
{
FormHistoryImportClosure *data = NS_STATIC_CAST(FormHistoryImportClosure*,
aData);
nsMorkReader *reader = data->reader;
nsCString values[kColumnCount];
const PRUnichar* valueStrings[kColumnCount];
PRUint32 valueLengths[kColumnCount];
nsCString *columnIDs = data->columnIDs;
PRInt32 i;
// Values are in UTF16.
for (i = 0; i < kColumnCount; ++i) {
aMap->Get(columnIDs[i], &values[i]);
reader->NormalizeValue(values[i]);
PRUint32 length;
const char *bytes;
if (values[i].IsEmpty()) {
bytes = "\0";
length = 0;
} else {
length = values[i].Length() / 2;
// add an extra null byte onto the end, so that the buffer ends
// with a complete unicode null character.
values[i].Append('\0');
// XXX this should handle byte swapping, but there's no endianness marker
bytes = values[i].get();
}
valueStrings[i] = NS_REINTERPRET_CAST(const PRUnichar*, bytes);
valueLengths[i] = length;
}
data->formHistory->AddEntry(nsDependentString(valueStrings[kNameColumn],
valueLengths[kNameColumn]),
nsDependentString(valueStrings[kValueColumn],
valueLengths[kValueColumn]));
return PL_DHASH_NEXT;
}
NS_IMPL_ISUPPORTS1(nsFormHistoryImporter, nsIFormHistoryImporter)
NS_IMETHODIMP
nsFormHistoryImporter::ImportFormHistory(nsIFile *aFile,
nsIFormHistory *aFormHistory)
{
nsMorkReader reader;
nsresult rv = reader.Init();
NS_ENSURE_SUCCESS(rv, rv);
rv = reader.Read(aFile);
NS_ENSURE_SUCCESS(rv, rv);
// Gather up the column ids so we don't need to find them on each row
FormHistoryImportClosure data(&reader, aFormHistory);
reader.EnumerateColumns(EnumerateColumnsCB, &data);
// Add the rows to form history
nsCOMPtr<nsFormHistory> formHistory = do_QueryInterface(aFormHistory);
NS_ENSURE_TRUE(formHistory, NS_ERROR_FAILURE);
mozIStorageConnection *conn = formHistory->GetStorageConnection();
NS_ENSURE_TRUE(conn, NS_ERROR_NOT_INITIALIZED);
mozStorageTransaction transaction(conn, PR_FALSE);
reader.EnumerateRows(AddToFormHistoryCB, &data);
return transaction.Commit();
}
#endif

View File

@ -0,0 +1,148 @@
/* -*- 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 Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Joe Hewitt <hewitt@netscape.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 ***** */
#ifndef __nsFormHistory__
#define __nsFormHistory__
#include "nsIFormHistory.h"
#include "nsIFormSubmitObserver.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsIObserver.h"
#include "nsIPrefBranch.h"
#include "nsWeakReference.h"
#include "mozIStorageService.h"
#include "mozIStorageConnection.h"
#include "mozIStorageStatement.h"
#include "nsServiceManagerUtils.h"
#include "nsToolkitCompsCID.h"
#ifdef MOZ_MORKREADER
#include "nsMorkReader.h"
#endif
class nsIAutoCompleteSimpleResult;
class nsIAutoCompleteResult;
#define NS_FORMHISTORY_IID \
{0xc4a47315, 0xaeb5, 0x4039, {0x9f, 0x34, 0x45, 0x11, 0xb3, 0xa7, 0x58, 0xdd}}
class nsFormHistory : public nsIFormHistory,
public nsIObserver,
public nsIFormSubmitObserver,
public nsSupportsWeakReference
{
public:
#ifdef MOZILLA_1_8_BRANCH
NS_DEFINE_STATIC_IID_ACCESSOR(NS_FORMHISTORY_IID)
#else
NS_DECLARE_STATIC_IID_ACCESSOR(NS_FORMHISTORY_IID)
#endif
NS_DECL_ISUPPORTS
NS_DECL_NSIFORMHISTORY
NS_DECL_NSIOBSERVER
// nsIFormSubmitObserver
NS_IMETHOD Notify(nsIContent* formNode, nsIDOMWindowInternal* window, nsIURI* actionURL, PRBool* cancelSubmit);
nsFormHistory();
nsresult Init();
static nsFormHistory* GetInstance()
{
if (!gFormHistory) {
nsCOMPtr<nsIFormHistory> fh = do_GetService(NS_FORMHISTORY_CONTRACTID);
}
return gFormHistory;
}
mozIStorageConnection* GetStorageConnection() { return mDBConn; }
nsresult AutoCompleteSearch(const nsAString &aInputName,
const nsAString &aInputValue,
nsIAutoCompleteSimpleResult *aPrevResult,
nsIAutoCompleteResult **aNewResult);
private:
~nsFormHistory();
protected:
// Database I/O
nsresult OpenDatabase();
nsresult CloseDatabase();
static PRBool FormHistoryEnabled();
static nsFormHistory *gFormHistory;
static PRBool gFormHistoryEnabled;
static PRBool gPrefsInitialized;
nsCOMPtr<nsIPrefBranch> mPrefBranch;
nsCOMPtr<mozIStorageService> mStorageService;
nsCOMPtr<mozIStorageConnection> mDBConn;
nsCOMPtr<mozIStorageStatement> mDBGetMatchingField;
nsCOMPtr<mozIStorageStatement> mDBFindEntry;
nsCOMPtr<mozIStorageStatement> mDBFindEntryByName;
nsCOMPtr<mozIStorageStatement> mDBSelectEntries;
nsCOMPtr<mozIStorageStatement> mDBInsertNameValue;
};
#ifdef MOZ_MORKREADER
class nsFormHistoryImporter : public nsIFormHistoryImporter
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIFORMHISTORYIMPORTER
private:
// Enumerator callback to build up a list of columns
static PLDHashOperator PR_CALLBACK
EnumerateColumnsCB(const nsACString &aColumnID,
nsCString aName,
void *aData);
// Enumerator callback to add a single row to the FormHistory.
static PLDHashOperator PR_CALLBACK
AddToFormHistoryCB(const nsACString &aRowID,
const nsMorkReader::StringMap *aMap,
void *aData);
};
#endif
#endif // __nsFormHistory__