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  *   Joe Hewitt <hewitt@netscape.com>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either the GNU General Public License Version 2 or later (the "GPL"), or
00029  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 #ifndef nsglobalhistory__h____
00042 #define nsglobalhistory__h____
00043 
00044 #include "nsIBrowserHistory.h"
00045 
00046 #include "mdb.h"
00047 #include "nsIObserver.h"
00048 #include "nsIPrefBranch.h"
00049 #include "nsIRDFDataSource.h"
00050 #include "nsIRDFRemoteDataSource.h"
00051 #include "nsIRDFService.h"
00052 #include "nsISupportsArray.h"
00053 #include "nsIStringBundle.h"
00054 #include "nsWeakReference.h"
00055 #include "nsVoidArray.h"
00056 #include "nsHashtable.h"
00057 #include "nsCOMPtr.h"
00058 #include "nsString.h"
00059 #include "nsITimer.h"
00060 #include "nsIAutoCompleteSearch.h"
00061 #include "nsIAutoCompleteResult.h"
00062 #include "nsIAutoCompleteResultTypes.h"
00063 #include "nsHashSets.h"
00064 
00065 //----------------------------------------------------------------------
00066 //
00067 //  nsMdbTableEnumerator
00068 //
00069 //    An nsISimpleEnumerator implementation that returns the value of
00070 //    a column as an nsISupports. Allows for some simple selection.
00071 //
00072 
00073 class nsMdbTableEnumerator : public nsISimpleEnumerator
00074 {
00075 protected:
00076   nsMdbTableEnumerator();
00077   virtual ~nsMdbTableEnumerator();
00078 
00079   nsIMdbEnv*   mEnv;
00080 
00081 private:
00082   // subclasses should not tweak these
00083   nsIMdbTable* mTable;
00084   nsIMdbTableRowCursor* mCursor;
00085   nsIMdbRow*            mCurrent;
00086 
00087 public:
00088   // nsISupports methods
00089   NS_DECL_ISUPPORTS
00090 
00091   // nsISimpleEnumeratorMethods
00092   NS_IMETHOD HasMoreElements(PRBool* _result);
00093   NS_IMETHOD GetNext(nsISupports** _result);
00094 
00095   // Implementation methods
00096   virtual nsresult Init(nsIMdbEnv* aEnv, nsIMdbTable* aTable);
00097 
00098 protected:
00099   virtual PRBool   IsResult(nsIMdbRow* aRow) = 0;
00100   virtual nsresult ConvertToISupports(nsIMdbRow* aRow, nsISupports** aResult) = 0;
00101 };
00102 
00103 typedef PRBool (*rowMatchCallback)(nsIMdbRow *aRow, void *closure);
00104 
00105 struct matchHost_t;
00106 struct searchQuery;
00107 class searchTerm;
00108 
00109 // Number of prefixes used in the autocomplete sort comparison function
00110 #define AUTOCOMPLETE_PREFIX_LIST_COUNT 6
00111 // Size of visit count boost to give to urls which are sites or paths
00112 #define AUTOCOMPLETE_NONPAGE_VISIT_COUNT_BOOST 5
00113 
00114 //----------------------------------------------------------------------
00115 //
00116 // nsGlobalHistory
00117 //
00118 //   This class is the browser's implementation of the
00119 //   nsIGlobalHistory interface.
00120 //
00121 
00122 
00123 // Used to describe what prefixes shouldn't be cut from
00124 // history urls when doing an autocomplete url comparison.
00125 struct AutocompleteExclude {
00126   PRInt32 schemePrefix;
00127   PRInt32 hostnamePrefix;
00128 };
00129 
00130 class nsGlobalHistory : nsSupportsWeakReference,
00131                         public nsIBrowserHistory,
00132                         public nsIObserver,
00133                         public nsIRDFDataSource,
00134                         public nsIRDFRemoteDataSource,
00135                         public nsIAutoCompleteSearch
00136 {
00137 public:
00138   // nsISupports methods 
00139   NS_DECL_ISUPPORTS
00140 
00141   NS_DECL_NSIGLOBALHISTORY2
00142   NS_DECL_NSIBROWSERHISTORY
00143   NS_DECL_NSIOBSERVER
00144   NS_DECL_NSIRDFDATASOURCE
00145   NS_DECL_NSIRDFREMOTEDATASOURCE
00146   NS_DECL_NSIAUTOCOMPLETESEARCH
00147 
00148   NS_METHOD Init();
00149 
00150   nsGlobalHistory(void);
00151   virtual ~nsGlobalHistory();
00152 
00153   // these must be public so that the callbacks can call them
00154   PRBool MatchExpiration(nsIMdbRow *row, PRTime* expirationDate);
00155   PRBool MatchHost(nsIMdbRow *row, matchHost_t *hostInfo);
00156   PRBool RowMatches(nsIMdbRow* aRow, searchQuery *aQuery, PRBool caseSensitive);
00157 
00158 protected:
00159 
00160   //
00161   // database junk
00162   //
00163   enum eCommitType 
00164   {
00165     kLargeCommit = 0,
00166     kSessionCommit = 1,
00167     kCompressCommit = 2
00168   };
00169   
00170   PRInt64   mFileSizeOnDisk;
00171   nsresult OpenDB();
00172   nsresult OpenExistingFile(nsIMdbFactory *factory, const char *filePath);
00173   nsresult OpenNewFile(nsIMdbFactory *factory, const char *filePath);
00174   nsresult CreateTokens();
00175   nsresult CloseDB();
00176   nsresult CheckHostnameEntries();
00177   nsresult Commit(eCommitType commitType);
00178 
00179   //
00180   // expiration/removal stuff
00181   //
00182   PRInt32   mExpireDays;
00183   nsresult ExpireEntries(PRBool notify);
00184   nsresult RemoveMatchingRows(rowMatchCallback aMatchFunc,
00185                               void *aClosure, PRBool notify);
00186 
00187   //
00188   // search stuff - find URL stuff, etc
00189   //
00190   nsresult GetRootDayQueries(nsISimpleEnumerator **aResult, PRBool aBySite);
00191   nsresult GetFindUriName(const char *aURL, nsIRDFNode **aResult);
00192   nsresult CreateFindEnumerator(nsIRDFResource *aSource,
00193                                 nsISimpleEnumerator **aResult);
00194   
00195   static nsresult FindUrlToTokenList(const char *aURL, nsVoidArray& aResult);
00196   static void FreeTokenList(nsVoidArray& tokens);
00197   static void FreeSearchQuery(searchQuery& aQuery);
00198   static PRBool IsFindResource(nsIRDFResource *aResource);
00199   void GetFindUriPrefix(const searchQuery& aQuery,
00200                         const PRBool aDoGroupBy,
00201                         nsACString& aResult);
00202   
00203   nsresult TokenListToSearchQuery(const nsVoidArray& tokens,
00204                                   searchQuery& aResult);
00205   nsresult FindUrlToSearchQuery(const char *aURL, searchQuery& aResult);
00206   nsresult NotifyFindAssertions(nsIRDFResource *aSource, nsIMdbRow *aRow);
00207   nsresult NotifyFindUnassertions(nsIRDFResource *aSource, nsIMdbRow *aRow);
00208     
00209   // 
00210   // autocomplete stuff
00211   //
00212   PRBool mAutocompleteOnlyTyped;
00213   nsStringArray mIgnoreSchemes;
00214   nsStringArray mIgnoreHostnames;
00215   
00216   nsresult AutoCompleteTypedSearch(nsIAutoCompleteMdbResult2 **aResult);
00217   nsresult AutoCompleteSearch(const nsAString& aSearchString,
00218                               AutocompleteExclude* aExclude,
00219                               nsIAutoCompleteMdbResult2* aPrevResult,
00220                               nsIAutoCompleteMdbResult2** aResult);
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(nsIMdbRow *row1, nsIMdbRow *row2, void *closureVoid);
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   PRInt32   mBatchesInProgress;
00243   PRBool    mNowValid;          // is mLastNow valid?
00244   nsCOMPtr<nsITimer> mExpireNowTimer;
00245   
00246   PRTime GetNow();
00247   void ExpireNow();
00248   
00249   static void expireNowTimer(nsITimer *aTimer, void *aClosure)
00250   {((nsGlobalHistory *)aClosure)->ExpireNow(); }
00251   
00252   //
00253   // sync stuff to write the db to disk every so often
00254   //
00255   PRBool    mDirty;             // if we've changed history
00256   nsCOMPtr<nsITimer> mSyncTimer;
00257   
00258   void Sync();
00259   nsresult SetDirty();
00260   
00261   static void fireSyncTimer(nsITimer *aTimer, void *aClosure)
00262   {((nsGlobalHistory *)aClosure)->Sync(); }
00263 
00264   //
00265   // RDF stuff
00266   //
00267   nsCOMPtr<nsISupportsArray> mObservers;
00268   
00269   PRBool IsURLInHistory(nsIRDFResource* aResource);
00270   
00271   nsresult NotifyAssert(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aValue);
00272   nsresult NotifyUnassert(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aValue);
00273   nsresult NotifyChange(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aOldValue, nsIRDFNode* aNewValue);
00274 
00275   //
00276   // row-oriented stuff
00277   //
00278   
00279   // N.B., these are MDB interfaces, _not_ XPCOM interfaces.
00280   nsIMdbEnv* mEnv;         // OWNER
00281   nsIMdbStore* mStore;     // OWNER
00282   nsIMdbTable* mTable;     // OWNER
00283   
00284   nsCOMPtr<nsIMdbRow> mMetaRow;
00285   
00286   mdb_scope  kToken_HistoryRowScope;
00287   mdb_kind   kToken_HistoryKind;
00288 
00289   mdb_column kToken_URLColumn;
00290   mdb_column kToken_ReferrerColumn;
00291   mdb_column kToken_LastVisitDateColumn;
00292   mdb_column kToken_FirstVisitDateColumn;
00293   mdb_column kToken_VisitCountColumn;
00294   mdb_column kToken_NameColumn;
00295   mdb_column kToken_HostnameColumn;
00296   mdb_column kToken_HiddenColumn;
00297   mdb_column kToken_TypedColumn;
00298 
00299   mdb_column kToken_ByteOrder;
00300   // meta-data tokens
00301   mdb_column kToken_LastPageVisited;
00302 
00303   // A set of the page URI specs that have been typed but not yet loaded
00304   nsCStringHashSet mTypedHiddenURIs;
00305   
00306   //
00307   // AddPage-oriented stuff
00308   //
00309   nsresult AddPageToDatabase(nsIURI* aURI, PRBool aRedirect, PRBool aTopLevel,
00310                              PRTime aLastVisitDate, nsIURI * aReferrer);
00311   nsresult AddExistingPageToDatabase(nsIMdbRow *row,
00312                                      PRTime aDate,
00313                                      nsIURI *aReferrer,
00314                                      PRTime *aOldDate,
00315                                      PRInt32 *aOldCount);
00316   nsresult AddNewPageToDatabase(nsIURI* aURI,
00317                                 PRTime aDate,
00318                                 PRBool aRedirect,
00319                                 PRBool aTopLevel,
00320                                 nsIURI *aReferrer,
00321                                 nsIMdbRow **aResult);
00322 
00323   nsresult RemovePageInternal(const char *aSpec);
00324 
00325   //
00326   // generic routines for setting/retrieving various datatypes
00327   //
00328   nsresult SetRowValue(nsIMdbRow *aRow, mdb_column aCol, const PRTime& aValue);
00329   nsresult SetRowValue(nsIMdbRow *aRow, mdb_column aCol, const PRInt32 aValue);
00330   nsresult SetRowValue(nsIMdbRow *aRow, mdb_column aCol, const char *aValue);
00331   nsresult SetRowValue(nsIMdbRow *aRow, mdb_column aCol, const PRUnichar *aValue);
00332 
00333   nsresult GetRowValue(nsIMdbRow *aRow, mdb_column aCol, nsAString& aResult);
00334   // byte order
00335   //
00336   nsresult SaveByteOrder(const char *aByteOrder);
00337   nsresult GetByteOrder(char **_retval);
00338   nsresult InitByteOrder(PRBool aForce);
00339   void SwapBytes(const PRUnichar *source, PRUnichar *dest, PRInt32 aLen);
00340   PRBool mReverseByteOrder;
00341 
00342   //
00343   nsresult GetRowValue(nsIMdbRow *aRow, mdb_column aCol, nsACString& aResult);
00344   nsresult GetRowValue(nsIMdbRow *aRow, mdb_column aCol, PRTime* aResult);
00345   nsresult GetRowValue(nsIMdbRow *aRow, mdb_column aCol, PRInt32* aResult);
00346 
00347   // Look up a row in mStore and returns success if it is found or failure
00348   // if it is not.  |aResult| may be null if only testing for row existance.
00349   nsresult FindRow(mdb_column aCol, const char *aURL, nsIMdbRow **aResult);
00350 
00351   //
00352   // misc unrelated stuff
00353   //
00354   nsCOMPtr<nsIStringBundle> mBundle;
00355 
00356   // pseudo-constants. although the global history really is a
00357   // singleton, we'll use this metaphor to be consistent.
00358   static PRInt32 gRefCnt;
00359   static nsIRDFService* gRDFService;
00360   static nsIRDFResource* kNC_Page; // XXX do we need?
00361   static nsIRDFResource* kNC_Date;
00362   static nsIRDFResource* kNC_FirstVisitDate;
00363   static nsIRDFResource* kNC_VisitCount;
00364   static nsIRDFResource* kNC_AgeInDays;
00365   static nsIRDFResource* kNC_Name;
00366   static nsIRDFResource* kNC_NameSort;
00367   static nsIRDFResource* kNC_Hostname;
00368   static nsIRDFResource* kNC_Referrer;
00369   static nsIRDFResource* kNC_child;
00370   static nsIRDFResource* kNC_URL;  // XXX do we need?
00371   static nsIRDFResource* kNC_HistoryRoot;
00372   static nsIRDFResource* kNC_HistoryByDate;
00373   static nsIRDFResource* kNC_HistoryByDateAndSite;
00374   static nsIRDFResource* kNC_DayFolderIndex;
00375 
00376   static nsIMdbFactory* gMdbFactory;
00377   static nsIPrefBranch* gPrefBranch;
00378   //
00379   // custom enumerators
00380   //
00381 
00382   // URLEnumerator - for searching for a specific set of rows which
00383   // match a particular column
00384   class URLEnumerator : public nsMdbTableEnumerator
00385   {
00386   protected:
00387     mdb_column mURLColumn;
00388     mdb_column mHiddenColumn;
00389     mdb_column mSelectColumn;
00390     void*      mSelectValue;
00391     PRInt32    mSelectValueLen;
00392 
00393     virtual ~URLEnumerator();
00394 
00395   public:
00396     URLEnumerator(mdb_column aURLColumn,
00397                   mdb_column aHiddenColumn,
00398                   mdb_column aSelectColumn = mdb_column(0),
00399                   void* aSelectValue = nsnull,
00400                   PRInt32 aSelectValueLen = 0) :
00401       mURLColumn(aURLColumn),
00402       mHiddenColumn(aHiddenColumn),
00403       mSelectColumn(aSelectColumn),
00404       mSelectValue(aSelectValue),
00405       mSelectValueLen(aSelectValueLen)
00406     {}
00407 
00408   protected:
00409     virtual PRBool   IsResult(nsIMdbRow* aRow);
00410     virtual nsresult ConvertToISupports(nsIMdbRow* aRow, nsISupports** aResult);
00411   };
00412 
00413   // SearchEnumerator - for matching a set of rows based on a search query
00414   class SearchEnumerator : public nsMdbTableEnumerator
00415   {
00416   public:
00417     SearchEnumerator(searchQuery *aQuery,
00418                      mdb_column aHiddenColumn,
00419                      nsGlobalHistory *aHistory) :
00420       mQuery(aQuery),
00421       mHiddenColumn(aHiddenColumn),
00422       mHistory(aHistory)
00423     {}
00424 
00425     virtual ~SearchEnumerator();
00426 
00427   protected:
00428     searchQuery *mQuery;
00429     mdb_column mHiddenColumn;
00430     nsGlobalHistory *mHistory;
00431     nsHashtable mUniqueRows;
00432     
00433     nsCString mFindUriPrefix;
00434 
00435     virtual PRBool IsResult(nsIMdbRow* aRow);
00436     virtual nsresult ConvertToISupports(nsIMdbRow* aRow,
00437                                         nsISupports** aResult);
00438     
00439     PRBool RowMatches(nsIMdbRow* aRow, searchQuery *aQuery);
00440   };
00441 
00442 
00443   friend class URLEnumerator;
00444   friend class SearchEnumerator;
00445 };
00446 
00447 
00448 #endif // nsglobalhistory__h____