Back to index

lightning-sunbird  0.9+nobinonly
nsGlobalHistory.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Chris Waterson <waterson@netscape.com>
00024  *   Blake Ross <blaker@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #ifndef nsglobalhistory__h____
00041 #define nsglobalhistory__h____
00042 
00043 #include "mdb.h"
00044 #include "nsIBrowserHistory.h"
00045 #include "nsIObserver.h"
00046 #include "nsIPrefBranch.h"
00047 #include "nsIRDFDataSource.h"
00048 #include "nsIRDFRemoteDataSource.h"
00049 #include "nsIRDFService.h"
00050 #include "nsISupportsArray.h"
00051 #include "nsIStringBundle.h"
00052 #include "nsWeakReference.h"
00053 #include "nsVoidArray.h"
00054 #include "nsHashtable.h"
00055 #include "nsCOMPtr.h"
00056 #include "nsAString.h"
00057 #include "nsString.h"
00058 #include "nsITimer.h"
00059 #include "nsIAutoCompleteSession.h"
00060 #include "nsHashSets.h"
00061 
00062 //----------------------------------------------------------------------
00063 //
00064 //  nsMdbTableEnumerator
00065 //
00066 //    An nsISimpleEnumerator implementation that returns the value of
00067 //    a column as an nsISupports. Allows for some simple selection.
00068 //
00069 
00070 class nsMdbTableEnumerator : public nsISimpleEnumerator
00071 {
00072 protected:
00073   nsMdbTableEnumerator();
00074   virtual ~nsMdbTableEnumerator();
00075 
00076   nsIMdbEnv*   mEnv;
00077 
00078 private:
00079   // subclasses should not tweak these
00080   nsIMdbTable* mTable;
00081   nsIMdbTableRowCursor* mCursor;
00082   nsIMdbRow*            mCurrent;
00083 
00084 public:
00085   // nsISupports methods
00086   NS_DECL_ISUPPORTS
00087 
00088   // nsISimpleEnumeratorMethods
00089   NS_IMETHOD HasMoreElements(PRBool* _result);
00090   NS_IMETHOD GetNext(nsISupports** _result);
00091 
00092   // Implementation methods
00093   virtual nsresult Init(nsIMdbEnv* aEnv, nsIMdbTable* aTable);
00094 
00095 protected:
00096   virtual PRBool   IsResult(nsIMdbRow* aRow) = 0;
00097   virtual nsresult ConvertToISupports(nsIMdbRow* aRow, nsISupports** aResult) = 0;
00098 };
00099 
00100 typedef PRBool (*rowMatchCallback)(nsIMdbRow *aRow, void *closure);
00101 
00102 struct matchHost_t;
00103 struct searchQuery;
00104 class searchTerm;
00105 
00106 // Number of prefixes used in the autocomplete sort comparison function
00107 #define AUTOCOMPLETE_PREFIX_LIST_COUNT 6
00108 // Size of visit count boost to give to urls which are sites or paths
00109 #define AUTOCOMPLETE_NONPAGE_VISIT_COUNT_BOOST 5
00110 
00111 //----------------------------------------------------------------------
00112 //
00113 // nsGlobalHistory
00114 //
00115 //   This class is the browser's implementation of the
00116 //   nsIGlobalHistory interface.
00117 //
00118 
00119 
00120 // Used to describe what prefixes shouldn't be cut from
00121 // history urls when doing an autocomplete url comparison.
00122 struct AutocompleteExclude {
00123   PRInt32 schemePrefix;
00124   PRInt32 hostnamePrefix;
00125 };
00126 
00127 class nsGlobalHistory : nsSupportsWeakReference,
00128                         public nsIBrowserHistory,
00129                         public nsIObserver,
00130                         public nsIRDFDataSource,
00131                         public nsIRDFRemoteDataSource,
00132                         public nsIAutoCompleteSession
00133 {
00134 public:
00135   // nsISupports methods 
00136   NS_DECL_ISUPPORTS
00137 
00138   NS_DECL_NSIGLOBALHISTORY2
00139   NS_DECL_NSIBROWSERHISTORY
00140   NS_DECL_NSIOBSERVER
00141   NS_DECL_NSIRDFDATASOURCE
00142   NS_DECL_NSIRDFREMOTEDATASOURCE
00143   NS_DECL_NSIAUTOCOMPLETESESSION
00144 
00145   NS_METHOD Init();
00146 
00147   nsGlobalHistory(void);
00148   virtual ~nsGlobalHistory();
00149 
00150   // these must be public so that the callbacks can call them
00151   PRBool MatchExpiration(nsIMdbRow *row, PRTime* expirationDate);
00152   PRBool MatchHost(nsIMdbRow *row, matchHost_t *hostInfo);
00153   PRBool RowMatches(nsIMdbRow* aRow, searchQuery *aQuery);
00154 
00155   PRTime  GetNow();
00156   PRTime  NormalizeTime(PRTime aTime);
00157   PRInt32 GetAgeInDays(PRTime aDate);
00158 
00159 protected:
00160 
00161   //
00162   // database junk
00163   //
00164   enum eCommitType 
00165   {
00166     kLargeCommit = 0,
00167     kSessionCommit = 1,
00168     kCompressCommit = 2
00169   };
00170   
00171   PRInt64   mFileSizeOnDisk;
00172   nsresult OpenDB();
00173   nsresult OpenExistingFile(nsIMdbFactory *factory, const char *filePath);
00174   nsresult OpenNewFile(nsIMdbFactory *factory, const char *filePath);
00175   nsresult CreateTokens();
00176   nsresult CloseDB();
00177   nsresult CheckHostnameEntries();
00178   nsresult Commit(eCommitType commitType);
00179 
00180   //
00181   // expiration/removal stuff
00182   //
00183   PRInt32   mExpireDays;
00184   nsresult ExpireEntries(PRBool notify);
00185   nsresult RemoveMatchingRows(rowMatchCallback aMatchFunc,
00186                               void *aClosure, PRBool notify);
00187 
00188   //
00189   // search stuff - find URL stuff, etc
00190   //
00191   nsresult GetRootDayQueries(nsISimpleEnumerator **aResult);
00192   nsresult GetFindUriName(const char *aURL, nsIRDFNode **aResult);
00193   nsresult CreateFindEnumerator(nsIRDFResource *aSource,
00194                                 nsISimpleEnumerator **aResult);
00195   
00196   static nsresult FindUrlToTokenList(const char *aURL, nsVoidArray& aResult);
00197   static void FreeTokenList(nsVoidArray& tokens);
00198   static void FreeSearchQuery(searchQuery& aQuery);
00199   static PRBool IsFindResource(nsIRDFResource *aResource);
00200   void GetFindUriPrefix(const searchQuery& aQuery,
00201                         const PRBool aDoGroupBy,
00202                         nsACString& aResult);
00203   
00204   nsresult TokenListToSearchQuery(const nsVoidArray& tokens,
00205                                   searchQuery& aResult);
00206   nsresult FindUrlToSearchQuery(const char *aURL, searchQuery& aResult);
00207   nsresult NotifyFindAssertions(nsIRDFResource *aSource, nsIMdbRow *aRow);
00208   nsresult NotifyFindUnassertions(nsIRDFResource *aSource, nsIMdbRow *aRow);
00209     
00210   // 
00211   // autocomplete stuff
00212   //
00213   PRBool mAutocompleteOnlyTyped;
00214   nsStringArray mIgnoreSchemes;
00215   nsStringArray mIgnoreHostnames;
00216   
00217   nsresult AutoCompleteSearch(const nsAString& aSearchString,
00218                               AutocompleteExclude* aExclude,
00219                               nsIAutoCompleteResults* aPrevResults,
00220                               nsIAutoCompleteResults* aResults);
00221   void AutoCompleteCutPrefix(nsAString& aURL, AutocompleteExclude* aExclude);
00222   void AutoCompleteGetExcludeInfo(const nsAString& aURL, AutocompleteExclude* aExclude);
00223   nsString AutoCompletePrefilter(const nsAString& aSearchString);
00224   PRBool AutoCompleteCompare(nsAString& aHistoryURL, 
00225                              const nsAString& aUserURL,
00226                              AutocompleteExclude* aExclude);
00227   PR_STATIC_CALLBACK(int)
00228   AutoCompleteSortComparison(const void *v1, const void *v2, void *unused);
00229 
00230   // AutoCompleteSortClosure - used to pass info into 
00231   // AutoCompleteSortComparison from the NS_QuickSort() function
00232   struct AutoCompleteSortClosure
00233   {
00234     nsGlobalHistory* history;
00235     size_t prefixCount;
00236     const nsAFlatString* prefixes[AUTOCOMPLETE_PREFIX_LIST_COUNT];
00237   };
00238 
00239   // caching of PR_Now() so we don't call it every time we do
00240   // a history query
00241   PRTime    mLastNow;           // cache the last PR_Now()
00242   PRInt64   mCachedGMTOffset;   // cached offset from GMT
00243 
00244   PRInt32   mBatchesInProgress;
00245   PRBool    mNowValid;          // is mLastNow valid?
00246   nsCOMPtr<nsITimer> mExpireNowTimer;
00247   
00248   void ExpireNow();
00249   
00250   static void expireNowTimer(nsITimer *aTimer, void *aClosure)
00251   {((nsGlobalHistory *)aClosure)->ExpireNow(); }
00252   
00253   //
00254   // sync stuff to write the db to disk every so often
00255   //
00256   PRBool    mDirty;             // if we've changed history
00257   nsCOMPtr<nsITimer> mSyncTimer;
00258   
00259   void Sync();
00260   nsresult SetDirty();
00261   
00262   static void fireSyncTimer(nsITimer *aTimer, void *aClosure)
00263   {((nsGlobalHistory *)aClosure)->Sync(); }
00264 
00265   //
00266   // RDF stuff
00267   //
00268   nsCOMPtr<nsISupportsArray> mObservers;
00269   
00270   PRBool IsURLInHistory(nsIRDFResource* aResource);
00271   
00272   nsresult NotifyAssert(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aValue);
00273   nsresult NotifyUnassert(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aValue);
00274   nsresult NotifyChange(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aOldValue, nsIRDFNode* aNewValue);
00275 
00276   //
00277   // row-oriented stuff
00278   //
00279   
00280   // N.B., these are MDB interfaces, _not_ XPCOM interfaces.
00281   nsIMdbEnv* mEnv;         // OWNER
00282   nsIMdbStore* mStore;     // OWNER
00283   nsIMdbTable* mTable;     // OWNER
00284   
00285   nsCOMPtr<nsIMdbRow> mMetaRow;
00286   
00287   mdb_scope  kToken_HistoryRowScope;
00288   mdb_kind   kToken_HistoryKind;
00289 
00290   mdb_column kToken_URLColumn;
00291   mdb_column kToken_ReferrerColumn;
00292   mdb_column kToken_LastVisitDateColumn;
00293   mdb_column kToken_FirstVisitDateColumn;
00294   mdb_column kToken_VisitCountColumn;
00295   mdb_column kToken_NameColumn;
00296   mdb_column kToken_HostnameColumn;
00297   mdb_column kToken_HiddenColumn;
00298   mdb_column kToken_TypedColumn;
00299 
00300   // meta-data tokens
00301   mdb_column kToken_LastPageVisited;
00302   mdb_column kToken_ByteOrder;
00303   
00304   nsCStringHashSet mTypedHiddenURIs;
00305 
00306   //
00307   // AddPage-oriented stuff
00308   //
00309   nsresult AddExistingPageToDatabase(nsIMdbRow *row,
00310                                      PRTime aDate,
00311                                      const char *aReferrer,
00312                                      PRTime *aOldDate,
00313                                      PRInt32 *aOldCount);
00314   nsresult AddNewPageToDatabase(const char *aURL,
00315                                 PRTime aDate,
00316                                 const char *aReferrer,
00317                                 nsIMdbRow **aResult);
00318 
00319   nsresult RemovePageInternal(const char *aSpec);
00320 
00321   //
00322   // generic routines for setting/retrieving various datatypes
00323   //
00324   nsresult SetRowValue(nsIMdbRow *aRow, mdb_column aCol, const PRTime& aValue);
00325   nsresult SetRowValue(nsIMdbRow *aRow, mdb_column aCol, const PRInt32 aValue);
00326   nsresult SetRowValue(nsIMdbRow *aRow, mdb_column aCol, const char *aValue);
00327   nsresult SetRowValue(nsIMdbRow *aRow, mdb_column aCol, const PRUnichar *aValue);
00328 
00329   nsresult GetRowValue(nsIMdbRow *aRow, mdb_column aCol, nsAString& aResult);
00330   nsresult GetRowValue(nsIMdbRow *aRow, mdb_column aCol, nsACString& aResult);
00331   nsresult GetRowValue(nsIMdbRow *aRow, mdb_column aCol, PRTime* aResult);
00332   nsresult GetRowValue(nsIMdbRow *aRow, mdb_column aCol, PRInt32* aResult);
00333 
00334   // Look up a row in mStore and returns success if it is found or failure
00335   // if it is not.  |aResult| may be null if only testing for row existance.
00336   nsresult FindRow(mdb_column aCol, const char *aURL, nsIMdbRow **aResult);
00337 
00338   //
00339   // byte order
00340   //
00341   nsresult SaveByteOrder(const char *aByteOrder);
00342   nsresult GetByteOrder(char **_retval);
00343   nsresult InitByteOrder(PRBool aForce);
00344   void SwapBytes(const PRUnichar *source, PRUnichar *dest, PRInt32 aLen);
00345   PRBool mReverseByteOrder;
00346 
00347   //
00348   // misc unrelated stuff
00349   //
00350   nsCOMPtr<nsIStringBundle> mBundle;
00351 
00352   // pseudo-constants. although the global history really is a
00353   // singleton, we'll use this metaphor to be consistent.
00354   static PRInt32 gRefCnt;
00355   static nsIRDFService* gRDFService;
00356   static nsIRDFResource* kNC_Page; // XXX do we need?
00357   static nsIRDFResource* kNC_Date;
00358   static nsIRDFResource* kNC_FirstVisitDate;
00359   static nsIRDFResource* kNC_VisitCount;
00360   static nsIRDFResource* kNC_AgeInDays;
00361   static nsIRDFResource* kNC_Name;
00362   static nsIRDFResource* kNC_NameSort;
00363   static nsIRDFResource* kNC_Hostname;
00364   static nsIRDFResource* kNC_Referrer;
00365   static nsIRDFResource* kNC_child;
00366   static nsIRDFResource* kNC_URL;  // XXX do we need?
00367   static nsIRDFResource* kNC_HistoryRoot;
00368   static nsIRDFResource* kNC_HistoryByDate;
00369 
00370   static nsIMdbFactory* gMdbFactory;
00371   static nsIPrefBranch* gPrefBranch;
00372   //
00373   // custom enumerators
00374   //
00375 
00376   // URLEnumerator - for searching for a specific set of rows which
00377   // match a particular column
00378   class URLEnumerator : public nsMdbTableEnumerator
00379   {
00380   protected:
00381     mdb_column mURLColumn;
00382     mdb_column mHiddenColumn;
00383     mdb_column mSelectColumn;
00384     void*      mSelectValue;
00385     PRInt32    mSelectValueLen;
00386 
00387     virtual ~URLEnumerator();
00388 
00389   public:
00390     URLEnumerator(mdb_column aURLColumn,
00391                   mdb_column aHiddenColumn,
00392                   mdb_column aSelectColumn = mdb_column(0),
00393                   void* aSelectValue = nsnull,
00394                   PRInt32 aSelectValueLen = 0) :
00395       mURLColumn(aURLColumn),
00396       mHiddenColumn(aHiddenColumn),
00397       mSelectColumn(aSelectColumn),
00398       mSelectValue(aSelectValue),
00399       mSelectValueLen(aSelectValueLen)
00400     {}
00401 
00402   protected:
00403     virtual PRBool   IsResult(nsIMdbRow* aRow);
00404     virtual nsresult ConvertToISupports(nsIMdbRow* aRow, nsISupports** aResult);
00405   };
00406 
00407   // SearchEnumerator - for matching a set of rows based on a search query
00408   class SearchEnumerator : public nsMdbTableEnumerator
00409   {
00410   public:
00411     SearchEnumerator(searchQuery *aQuery,
00412                      mdb_column aHiddenColumn,
00413                      nsGlobalHistory *aHistory) :
00414       mQuery(aQuery),
00415       mHiddenColumn(aHiddenColumn),
00416       mHistory(aHistory)
00417     {}
00418 
00419     virtual ~SearchEnumerator();
00420 
00421   protected:
00422     searchQuery *mQuery;
00423     mdb_column mHiddenColumn;
00424     nsGlobalHistory *mHistory;
00425     nsHashtable mUniqueRows;
00426     
00427     nsCString mFindUriPrefix;
00428 
00429     virtual PRBool IsResult(nsIMdbRow* aRow);
00430     virtual nsresult ConvertToISupports(nsIMdbRow* aRow,
00431                                         nsISupports** aResult);
00432     
00433     PRBool RowMatches(nsIMdbRow* aRow, searchQuery *aQuery);
00434   };
00435 
00436   // AutoCompleteEnumerator - for searching for a partial url match  
00437   class AutoCompleteEnumerator : public nsMdbTableEnumerator
00438   {
00439   protected:
00440     nsGlobalHistory* mHistory;
00441     mdb_column mURLColumn;
00442     mdb_column mHiddenColumn;
00443     mdb_column mTypedColumn;
00444     mdb_column mCommentColumn;
00445     AutocompleteExclude* mExclude;
00446     const nsAString& mSelectValue;
00447     PRBool mMatchOnlyTyped;
00448 
00449     virtual ~AutoCompleteEnumerator();
00450   
00451   public:
00452     AutoCompleteEnumerator(nsGlobalHistory* aHistory,
00453                            mdb_column aURLColumn,
00454                            mdb_column aCommentColumn,
00455                            mdb_column aHiddenColumn,
00456                            mdb_column aTypedColumn,
00457                            PRBool aMatchOnlyTyped,
00458                            const nsAString& aSelectValue,
00459                            AutocompleteExclude* aExclude) :
00460       mHistory(aHistory),
00461       mURLColumn(aURLColumn),
00462       mHiddenColumn(aHiddenColumn),
00463       mTypedColumn(aTypedColumn),
00464       mCommentColumn(aCommentColumn),
00465       mExclude(aExclude),
00466       mSelectValue(aSelectValue), 
00467       mMatchOnlyTyped(aMatchOnlyTyped) {}
00468 
00469   protected:
00470     virtual PRBool   IsResult(nsIMdbRow* aRow);
00471     virtual nsresult ConvertToISupports(nsIMdbRow* aRow, nsISupports** aResult);
00472   };
00473 
00474 
00475   friend class URLEnumerator;
00476   friend class SearchEnumerator;
00477   friend class AutoCompleteEnumerator;
00478 };
00479 
00480 
00481 #endif // nsglobalhistory__h____