From df1557b64e30556d06d9473a8f33443b71839a95 Mon Sep 17 00:00:00 2001 From: "alecf%netscape.com" Date: Tue, 7 Jan 2003 21:37:30 +0000 Subject: [PATCH] adding chrome url parsing stuff to the lite chrome registry, minor tweaks to the embed lite module. not part of build git-svn-id: svn://10.0.0.236/trunk@135942 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/embedding/lite/Makefile.in | 19 +- .../embedding/lite/nsEmbedChromeRegistry.cpp | 250 +++++++- .../embedding/lite/nsEmbedChromeRegistry.h | 14 + .../embedding/lite/nsEmbedGlobalHistory.cpp | 553 ++++++++++++++++++ mozilla/embedding/lite/nsEmbedGlobalHistory.h | 96 +++ mozilla/embedding/lite/nsEmbedLiteModule.cpp | 20 +- .../embedding/lite/nsEmbedWindowMediator.cpp | 48 -- .../embedding/lite/nsEmbedWindowMediator.h | 59 -- 8 files changed, 943 insertions(+), 116 deletions(-) create mode 100644 mozilla/embedding/lite/nsEmbedGlobalHistory.cpp create mode 100644 mozilla/embedding/lite/nsEmbedGlobalHistory.h delete mode 100644 mozilla/embedding/lite/nsEmbedWindowMediator.cpp delete mode 100644 mozilla/embedding/lite/nsEmbedWindowMediator.h diff --git a/mozilla/embedding/lite/Makefile.in b/mozilla/embedding/lite/Makefile.in index b1990ca744a..4c637fbb484 100644 --- a/mozilla/embedding/lite/Makefile.in +++ b/mozilla/embedding/lite/Makefile.in @@ -25,24 +25,39 @@ VPATH = @srcdir@ MODULE = embed_lite LIBRARY_NAME = embed_lite +IS_COMPONENT = 1 include $(DEPTH)/config/autoconf.mk REQUIRES = xpcom \ string \ chrome \ - appshell \ necko \ + history \ + pref \ + content \ + caps \ + xpconnect \ + js \ + xuldoc \ $(NULL) CPPSRCS = \ nsEmbedChromeRegistry.cpp \ - nsEmbedWindowMediator.cpp \ + nsEmbedGlobalHistory.cpp \ nsEmbedLiteModule.cpp \ $(NULL) +# bring in the chrome protocol handler +LOBJS = $(topsrcdir)/rdf/chrome/src/nsChromeProtocolHandler.$(OBJ_SUFFIX) + + +LOCAL_INCLUDES = -I$(DEPTH)/rdf/chrome/src + EXTRA_DSO_LDOPTS = \ $(MOZ_COMPONENT_LIBS) \ $(NULL) +NO_DIST_INSTALL = 1 + include $(topsrcdir)/config/rules.mk diff --git a/mozilla/embedding/lite/nsEmbedChromeRegistry.cpp b/mozilla/embedding/lite/nsEmbedChromeRegistry.cpp index 270faf57ef1..df947ad2117 100644 --- a/mozilla/embedding/lite/nsEmbedChromeRegistry.cpp +++ b/mozilla/embedding/lite/nsEmbedChromeRegistry.cpp @@ -39,6 +39,120 @@ #include "nsEmbedChromeRegistry.h" #include "nsString.h" #include "nsReadableUtils.h" +#include "plstr.h" + +#include "nsIDirectoryService.h" +#include "nsAppDirectoryServiceDefs.h" +#include "nsIProperties.h" +#include "nsILocalFile.h" + +#define CHROME_TYPE_CONTENT 0 +#define CHROME_TYPE_LOCALE 1 +#define CHROME_TYPE_SKIN 2 + +const char kChromePrefix[] = "chrome://"; + +static nsresult +SplitURL(nsIURI *aChromeURI, nsCString& aPackage, nsCString& aProvider, nsCString& aFile, + PRBool *aModified = nsnull) +{ + // Splits a "chrome:" URL into its package, provider, and file parts. + // Here are the current portions of a + // chrome: url that make up the chrome- + // + // chrome://global/skin/foo?bar + // \------/ \----/\---/ \-----/ + // | | | | + // | | | `-- RemainingPortion + // | | | + // | | `-- Provider + // | | + // | `-- Package + // | + // `-- Always "chrome://" + // + // + + nsresult rv; + + nsCAutoString str; + rv = aChromeURI->GetSpec(str); + if (NS_FAILED(rv)) return rv; + + // We only want to deal with "chrome:" URLs here. We could return + // an error code if the URL isn't properly prefixed here... + if (PL_strncmp(str.get(), kChromePrefix, sizeof(kChromePrefix) - 1) != 0) + return NS_ERROR_INVALID_ARG; + + // Cull out the "package" string; e.g., "navigator" + aPackage = str.get() + sizeof(kChromePrefix) - 1; + + PRInt32 idx; + idx = aPackage.FindChar('/'); + if (idx < 0) + return NS_OK; + + // Cull out the "provider" string; e.g., "content" + aPackage.Right(aProvider, aPackage.Length() - (idx + 1)); + aPackage.Truncate(idx); + + idx = aProvider.FindChar('/'); + if (idx < 0) { + // Force the provider to end with a '/' + idx = aProvider.Length(); + aProvider.Append('/'); + } + + // Cull out the "file"; e.g., "navigator.xul" + aProvider.Right(aFile, aProvider.Length() - (idx + 1)); + aProvider.Truncate(idx); + + PRBool nofile = (aFile.Length() == 0); + if (nofile) { + // If there is no file, then construct the default file + aFile = aPackage; + + if (aProvider.Equals("content")) { + aFile += ".xul"; + } + else if (aProvider.Equals("skin")) { + aFile += ".css"; + } + else if (aProvider.Equals("locale")) { + aFile += ".dtd"; + } + else { + NS_ERROR("unknown provider"); + return NS_ERROR_FAILURE; + } + } else { + // Protect against URIs containing .. that reach up out of the + // chrome directory to grant chrome privileges to non-chrome files. + int depth = 0; + PRBool sawSlash = PR_TRUE; // .. at the beginning is suspect as well as /.. + for (const char* p=aFile.get(); *p; p++) { + if (sawSlash) { + if (p[0] == '.' && p[1] == '.'){ + depth--; // we have /.., decrement depth. + } else { + static const char escape[] = "%2E%2E"; + if (PL_strncasecmp(p, escape, sizeof(escape)-1) == 0) + depth--; // we have the HTML-escaped form of /.., decrement depth. + } + } else if (p[0] != '/') { + depth++; // we have /x for some x that is not / + } + sawSlash = (p[0] == '/'); + + if (depth < 0) { + return NS_ERROR_FAILURE; + } + } + } + if (aModified) + *aModified = nofile; + return NS_OK; +} NS_IMPL_ISUPPORTS1(nsEmbedChromeRegistry, nsIChromeRegistry) @@ -50,11 +164,145 @@ nsEmbedChromeRegistry::nsEmbedChromeRegistry() nsresult nsEmbedChromeRegistry::Init() { + NS_ASSERTION(0, "Creating embedding chrome registry\n"); nsresult rv; rv = NS_NewISupportsArray(getter_AddRefs(mEmptyArray)); if (NS_FAILED(rv)) return rv; + rv = ReadChromeRegistry(); + if (NS_FAILED(rv)) return rv; + + return NS_OK; +} + +nsresult +nsEmbedChromeRegistry::ReadChromeRegistry() +{ + nsresult rv; + nsCOMPtr directoryService = + do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr listFile; + rv = directoryService->Get(NS_APP_CHROME_DIR, NS_GET_IID(nsILocalFile), + getter_AddRefs(listFile)); + if (NS_FAILED(rv)) return rv; + + rv = listFile->AppendRelativeNativePath(NS_LITERAL_CSTRING("installed-chrome.txt")); + if (NS_FAILED(rv)) return rv; + + PRFileDesc *file; + rv = listFile->OpenNSPRFileDesc(PR_RDONLY, 0, &file); + if (NS_FAILED(rv)) return rv; + + PRFileInfo finfo; + + if (PR_GetOpenFileInfo(file, &finfo) == PR_SUCCESS) { + char *dataBuffer = new char[finfo.size+1]; + if (dataBuffer) { + PRInt32 bufferSize = PR_Read(file, dataBuffer, finfo.size); + if (bufferSize > 0) { + dataBuffer[bufferSize] = '\r'; + rv = ProcessNewChromeBuffer(dataBuffer, bufferSize); + } + delete [] dataBuffer; + } + } + PR_Close(file); + + return rv; +} + +nsresult +nsEmbedChromeRegistry::ProcessNewChromeBuffer(char* aBuffer, PRInt32 aLength) +{ + nsresult rv = NS_OK; + while (aLength > 0) { + PRInt32 processedBytes = ProcessChromeLine(aBuffer, aLength); + aBuffer += processedBytes; + aLength -= processedBytes; + } + return NS_OK; +} + +#define MAX_TOKENS 5 +struct chromeToken { + const char *tokenStart; + const char *tokenEnd; +}; + +PRInt32 +nsEmbedChromeRegistry::ProcessChromeLine(const char* aBuffer, PRInt32 aLength) +{ + PRInt32 bytesProcessed = 0; + chromeToken tokens[MAX_TOKENS]; + PRInt32 tokenCount = 0; + PRBool expectingToken = PR_TRUE; + + while (bytesProcessed <= aLength && + *aBuffer != '\n' && *aBuffer != '\r' && + tokenCount < MAX_TOKENS) { + + if (*aBuffer == ',') { + tokenCount++; + expectingToken = PR_TRUE; + } + else if (expectingToken) + tokens[tokenCount].tokenStart = aBuffer; + else + tokens[tokenCount].tokenEnd = aBuffer; + + + aBuffer++; + bytesProcessed++; + } + NS_ASSERTION(tokenCount == 4, "Unexpected tokens in line"); + + nsDependentSingleFragmentCSubstring + chromeType(tokens[0].tokenStart, tokens[0].tokenEnd); + nsDependentSingleFragmentCSubstring + chromeProfile(tokens[1].tokenStart, tokens[1].tokenEnd); + nsDependentSingleFragmentCSubstring + chromeLocType(tokens[2].tokenStart, tokens[2].tokenEnd); + nsDependentSingleFragmentCSubstring + chromeLocation(tokens[3].tokenStart, tokens[3].tokenEnd); + + RegisterChrome(chromeType, chromeProfile, chromeLocType, chromeLocation); + return bytesProcessed; +} + +nsresult +nsEmbedChromeRegistry::RegisterChrome(const nsACString& aChromeType, + const nsACString& aChromeProfile, + const nsACString& aChromeLocType, + const nsACString& aChromeLocation) +{ + PRInt32 chromeType; + if (aChromeType.Equals(NS_LITERAL_CSTRING("skin"))) + chromeType = CHROME_TYPE_SKIN; + else if (aChromeType.Equals(NS_LITERAL_CSTRING("locale"))) + chromeType = CHROME_TYPE_LOCALE; + else + chromeType = CHROME_TYPE_CONTENT; + + PRBool chromeIsProfile = + aChromeProfile.Equals(NS_LITERAL_CSTRING("profile")); + + PRBool chromeIsURL = + aChromeProfile.Equals(NS_LITERAL_CSTRING("url")); + + return RegisterChrome(chromeType, chromeIsProfile, chromeIsURL, + aChromeLocation); +} + +nsresult +nsEmbedChromeRegistry::RegisterChrome(PRInt32 aChromeType, // CHROME_TYPE_CONTENT, etc + PRBool aChromeIsProfile, // per-profile? + PRBool aChromeIsURL, // is it a url? (else path) + const nsACString& aChromeLocation) +{ + return NS_OK; } @@ -68,7 +316,7 @@ nsEmbedChromeRegistry::CheckForNewChrome() NS_IMETHODIMP nsEmbedChromeRegistry::Canonify(nsIURI* aChromeURI) { -#if 0 +#if 1 // Canonicalize 'chrome:' URLs. We'll take any 'chrome:' URL // without a filename, and change it to a URL -with- a filename; // e.g., "chrome://navigator/content" to diff --git a/mozilla/embedding/lite/nsEmbedChromeRegistry.h b/mozilla/embedding/lite/nsEmbedChromeRegistry.h index 4974ee8d281..a9f26d4ffe4 100644 --- a/mozilla/embedding/lite/nsEmbedChromeRegistry.h +++ b/mozilla/embedding/lite/nsEmbedChromeRegistry.h @@ -55,6 +55,20 @@ public: NS_DECL_ISUPPORTS NS_DECL_NSICHROMEREGISTRY + + nsresult ReadChromeRegistry(); + nsresult ProcessNewChromeBuffer(char* aBuffer, PRInt32 aLength); + PRInt32 ProcessChromeLine(const char* aBuffer, PRInt32 aLength); + nsresult RegisterChrome(const nsACString& aChromeType, + const nsACString& aChromeProfile, + const nsACString& aChromeLocType, + const nsACString& aChromeLocation); + nsresult RegisterChrome(PRInt32 aChromeType, // CHROME_TYPE_CONTENT, etc + PRBool aChromeIsProfile, // per-profile? + PRBool aChromeIsURL, // is it a url? (else path) + const nsACString& aChromeLocation); + + private: nsCOMPtr mEmptyArray; diff --git a/mozilla/embedding/lite/nsEmbedGlobalHistory.cpp b/mozilla/embedding/lite/nsEmbedGlobalHistory.cpp new file mode 100644 index 00000000000..3b7643bf57c --- /dev/null +++ b/mozilla/embedding/lite/nsEmbedGlobalHistory.cpp @@ -0,0 +1,553 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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.org 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): + * Conrad Carlen + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsEmbedGlobalHistory.h" +#include "nsIObserver.h" +#include "nsIObserverService.h" +#include "nsWeakReference.h" +#include "nsAppDirectoryServiceDefs.h" +#include "nsHashTable.h" +#include "nsInt64.h" +#include "prtypes.h" +#include "nsFixedSizeAllocator.h" +#include "nsVoidArray.h" +#include "nsIPrefService.h" + +// Constants +static const PRInt32 kNewEntriesBetweenFlush = 10; + +static const PRUint32 kDefaultExpirationIntervalDays = 7; + +static const PRInt64 kMSecsPerDay = LL_INIT(0, 60 * 60 * 24 * 1000); +static const PRInt64 kOneThousand = LL_INIT(0, 1000); + +#define PREF_BROWSER_HISTORY_EXPIRE_DAYS "browser.history_expire_days" + +// Static Routine Prototypes +static nsresult readEntry(FILE *inStream, nsCString& url, HistoryEntry **entry); +static nsresult writeEntry(FILE *outStm, nsCStringKey *url, HistoryEntry *entry); + +static PRIntn enumWriteEntry(nsHashKey *aKey, void *aData, void* closure); +static PRIntn enumWriteEntryIfUnwritten(nsHashKey *aKey, void *aData, void* closure); +static PRIntn enumDeleteEntry(nsHashKey *aKey, void *aData, void* closure); + +//***************************************************************************** +// HistoryEntry +//***************************************************************************** + +class HistoryEntry { +public: + HistoryEntry() : + mWritten(PR_FALSE) {} + + + void OnVisited() + { + mLastVisitTime = PR_Now(); + LL_DIV(mLastVisitTime, mLastVisitTime, kOneThousand); + } + + PRInt64 GetLastVisitTime() + { return mLastVisitTime; } + void SetLastVisitTime(const PRInt64& aTime) + { mLastVisitTime = aTime; } + + PRBool GetIsWritten() + { return mWritten; } + void SetIsWritten(PRBool written = PR_TRUE) + { mWritten = PR_TRUE; } + + // Memory management stuff + static void* operator new(size_t size); + static void operator delete(void *p, size_t size); + + // Must be called when done with all HistoryEntry objects + static void ReleasePool(); + + private: + PRInt64 mLastVisitTime; // Millisecs + PRPackedBool mWritten; // TRUE if ever persisted + + static nsresult InitPool(); + static nsFixedSizeAllocator *sPool; +}; + +nsFixedSizeAllocator *HistoryEntry::sPool; + +//***************************************************************************** + +void* HistoryEntry::operator new(size_t size) +{ + if (size != sizeof(HistoryEntry)) + return ::operator new(size); + if (!sPool && NS_FAILED(InitPool())) + return nsnull; + + return sPool->Alloc(size); +} + +void HistoryEntry::operator delete(void *p, size_t size) +{ + if (!p) + return; + if (size != sizeof(HistoryEntry)) + ::operator delete(p); + if (!sPool) { + NS_ERROR("HistoryEntry outlived its memory pool"); + return; + } + sPool->Free(p, size); +} + +nsresult HistoryEntry::InitPool() +{ + if (!sPool) { + sPool = new nsFixedSizeAllocator; + if (!sPool) + return NS_ERROR_OUT_OF_MEMORY; + + static const size_t kBucketSizes[] = + { sizeof(HistoryEntry) }; + static const PRInt32 kInitialPoolSize = + NS_SIZE_IN_HEAP(sizeof(HistoryEntry)) * 256; + + nsresult rv = sPool->Init("EmbedLite HistoryEntry Pool", kBucketSizes, 1, kInitialPoolSize); + if (NS_FAILED(rv)) + return rv; + } + return NS_OK; +} + +void HistoryEntry::ReleasePool() +{ + delete sPool; + sPool = nsnull; +} + +//***************************************************************************** +// nsEmbedGlobalHistory - Creation/Destruction +//***************************************************************************** + +NS_IMPL_ISUPPORTS3(nsEmbedGlobalHistory, nsIGlobalHistory, nsIObserver, nsISupportsWeakReference) + +nsEmbedGlobalHistory::nsEmbedGlobalHistory() : + mDataIsLoaded(PR_FALSE), mEntriesAddedSinceFlush(0), + mURLTable(nsnull) +{ + NS_INIT_REFCNT(); + + LL_I2L(mExpirationInterval, kDefaultExpirationIntervalDays); + LL_MUL(mExpirationInterval, mExpirationInterval, kMSecsPerDay); +} + +nsEmbedGlobalHistory::~nsEmbedGlobalHistory() +{ + FlushData(); + delete mURLTable; + HistoryEntry::ReleasePool(); +} + +NS_IMETHODIMP nsEmbedGlobalHistory::Init() +{ + mURLTable = new nsHashtable; + NS_ENSURE_TRUE(mURLTable, NS_ERROR_OUT_OF_MEMORY); + + // Get Pref and convert to millisecs + nsCOMPtr prefs(do_GetService("@mozilla.org/preferences-service;1")); + if (prefs) { + PRInt32 expireDays; + prefs->GetIntPref(PREF_BROWSER_HISTORY_EXPIRE_DAYS, &expireDays); + LL_I2L(mExpirationInterval, expireDays); + LL_MUL(mExpirationInterval, mExpirationInterval, kMSecsPerDay); + } + + // register to observe profile changes + nsCOMPtr observerService = + do_GetService("@mozilla.org/observer-service;1"); + NS_ASSERTION(observerService, "failed to get observer service"); + if (observerService) + observerService->AddObserver(this, "profile-before-change", PR_TRUE); + + return NS_OK; +} + +//***************************************************************************** +// nsEmbedGlobalHistory::nsIGlobalHistory +//***************************************************************************** + +NS_IMETHODIMP nsEmbedGlobalHistory::AddPage(const char *aURL) +{ + NS_ENSURE_ARG(aURL); + + nsresult rv = LoadData(); + NS_ENSURE_SUCCESS(rv, rv); + + nsCStringKey asKey(aURL); + HistoryEntry *entry = NS_STATIC_CAST(HistoryEntry *, mURLTable->Get(&asKey)); + if (!entry) { + + if (++mEntriesAddedSinceFlush >= kNewEntriesBetweenFlush) + FlushData(kFlushModeAppend); + + HistoryEntry *newEntry = new HistoryEntry; + if (!newEntry) + return NS_ERROR_FAILURE; + (void)mURLTable->Put(&asKey, newEntry); + entry = newEntry; + } + entry->OnVisited(); + + return NS_OK; +} + +NS_IMETHODIMP nsEmbedGlobalHistory::IsVisited(const char *aURL, PRBool *_retval) +{ + NS_ENSURE_ARG(aURL); + NS_ENSURE_ARG_POINTER(_retval); + + nsresult rv = LoadData(); + NS_ENSURE_SUCCESS(rv, rv); + + nsCStringKey asKey(aURL); + + *_retval = (mURLTable->Exists(&asKey)); + return NS_OK; +} + +//***************************************************************************** +// nsEmbedGlobalHistory::nsIObserver +//***************************************************************************** + +NS_IMETHODIMP nsEmbedGlobalHistory::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData) +{ + nsresult rv = NS_OK; + + if (strcmp(aTopic, "profile-before-change") == 0) { + (void)FlushData(); + (void)ResetData(); + } + return rv; +} + +//***************************************************************************** +// nsEmbedGlobalHistory +//***************************************************************************** + +nsresult nsEmbedGlobalHistory::LoadData() +{ + if (!mDataIsLoaded) { + + nsresult rv; + PRBool exists; + + mDataIsLoaded = PR_TRUE; + + rv = GetHistoryFile(); + if (NS_FAILED(rv)) + return rv; + rv = mHistoryFile->Exists(&exists); + if (NS_FAILED(rv)) + return rv; + if (!exists) + return NS_OK; + + FILE *stdFile; + rv = mHistoryFile->OpenANSIFileDesc("r", &stdFile); + if (NS_FAILED(rv)) + return rv; + + nsCAutoString outString; + HistoryEntry *newEntry; + while (NS_SUCCEEDED(readEntry(stdFile, outString, &newEntry))) { + if (EntryHasExpired(newEntry)) { + delete newEntry; + } + else { + nsCStringKey asKey(outString); + mURLTable->Put(&asKey, newEntry); + } + } + + fclose(stdFile); + } + return NS_OK; +} + +nsresult nsEmbedGlobalHistory::FlushData(PRIntn mode) +{ + if (mHistoryFile) { + + const char* openMode = (mode == kFlushModeAppend ? "a" : "w"); + FILE *stdFile; + nsresult rv = mHistoryFile->OpenANSIFileDesc(openMode, &stdFile); + if (NS_FAILED(rv)) return rv; + + // Before flushing either way, remove dead entries + mURLTable->Enumerate(enumRemoveEntryIfExpired, this); + + if (mode == kFlushModeAppend) + mURLTable->Enumerate(enumWriteEntryIfUnwritten, stdFile); + else + mURLTable->Enumerate(enumWriteEntry, stdFile); + + mEntriesAddedSinceFlush = 0; + fclose(stdFile); + } + return NS_OK; +} + +nsresult nsEmbedGlobalHistory::ResetData() +{ + mURLTable->Reset(enumDeleteEntry); + mHistoryFile = 0; + mDataIsLoaded = PR_FALSE; + mEntriesAddedSinceFlush = 0; + return NS_OK; +} + +nsresult nsEmbedGlobalHistory::GetHistoryFile() +{ + nsresult rv; + + // Get the history file in our profile dir. + // Notice we are not just getting NS_APP_HISTORY_50_FILE + // because it is used by the "real" global history component. + + nsCOMPtr aFile; + rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(aFile)); + NS_ENSURE_SUCCESS(rv, rv); + rv = aFile->Append(NS_LITERAL_STRING("history.txt")); + NS_ENSURE_SUCCESS(rv, rv); + mHistoryFile = do_QueryInterface(aFile); + return NS_OK; +} + +PRBool nsEmbedGlobalHistory::EntryHasExpired(HistoryEntry *entry) +{ + // convert "now" from microsecs to millisecs + PRInt64 nowInMilliSecs = PR_Now(); + LL_DIV(nowInMilliSecs, nowInMilliSecs, kOneThousand); + + // determine when the entry would have expired + PRInt64 expirationIntervalAgo; + LL_SUB(expirationIntervalAgo, nowInMilliSecs, mExpirationInterval); + + PRInt64 lastVisitTime = entry->GetLastVisitTime(); + return (LL_CMP(lastVisitTime, <, expirationIntervalAgo)); +} + +PRIntn nsEmbedGlobalHistory::enumRemoveEntryIfExpired(nsHashKey *aKey, void *aData, void* closure) +{ + HistoryEntry *entry = NS_STATIC_CAST(HistoryEntry*, aData); + if (!entry) + return PR_FALSE; + nsEmbedGlobalHistory *history = NS_STATIC_CAST(nsEmbedGlobalHistory*, closure); + if (!history) + return PR_FALSE; + + if (history->EntryHasExpired(entry)) { + // what do do here? + //delete entry; + return PR_TRUE; + } + return PR_TRUE; +} + + +//***************************************************************************** +// Static Functions +//***************************************************************************** + +static nsresult parsePRInt64(FILE *inStm, PRInt64& outValue) +{ + int c, charsRead = 0; + nsInt64 value = 0; + + while (PR_TRUE) { + c = fgetc(inStm); + if (c == EOF || !isdigit(c)) + break; + + ++charsRead; + PRInt32 digit = c - '0'; + value *= nsInt64(10); + value += nsInt64(digit); + } + if (!charsRead) + return NS_ERROR_FAILURE; + outValue = value; + return NS_OK; +} + +nsresult readEntry(FILE *inStream, nsCString& outURL, HistoryEntry **outEntry) +{ + nsresult rv; + + // Get the last visted date + PRInt64 value; + rv = parsePRInt64(inStream, value); + if (NS_FAILED(rv)) + return rv; + + // Get the URL + int c; + char buf[1024]; + char *next, *end = buf + sizeof(buf); + + outURL.Truncate(0); + next = buf; + + while (PR_TRUE) { + c = fgetc(inStream); + + if (c == EOF) + break; + else if (c == '\n') + break; + else if (c == '\r') { + c = fgetc(inStream); + if (c != '\n') + ungetc(c, inStream); + break; + } + else { + *next++ = c; + if (next >= end) { + outURL.Append(buf, next - buf); + next = buf; + } + } + } + if (next > buf) + outURL.Append(buf, next - buf); + + if (!outURL.Length() && c == EOF) + return NS_ERROR_FAILURE; + + *outEntry = new HistoryEntry; + if (!*outEntry) + return NS_ERROR_OUT_OF_MEMORY; + (*outEntry)->SetLastVisitTime(value); + (*outEntry)->SetIsWritten(); + + return NS_OK; +} + +static nsresult writePRInt64(FILE *outStm, const PRInt64& inValue) +{ + nsInt64 value(inValue); + + if (value == nsInt64(0)) { + fputc('0', outStm); + return NS_OK; + } + + nsCAutoString tempString; + + while (value != nsInt64(0)) { + PRInt32 ones = PRInt32(value % nsInt64(10)); + value /= nsInt64(10); + tempString.Insert(char('0' + ones), 0); + } + int result = fputs(tempString.get(), outStm); + return (result == EOF) ? NS_ERROR_FAILURE : NS_OK; +} + +nsresult writeEntry(FILE *outStm, nsCStringKey *url, HistoryEntry *entry) +{ + writePRInt64(outStm, entry->GetLastVisitTime()); + fputc(':', outStm); + + fputs(url->GetString(), outStm); + entry->SetIsWritten(); + +#if defined (XP_PC) + fputc('\r', outStm); + fputc('\n', outStm); +#elif defined(XP_UNIX) + fputc('\n', outStm); +#else + fputc('\r', outStm); +#endif + + return NS_OK; +} + +PRBool enumWriteEntry(nsHashKey *aKey, void *aData, void* closure) +{ + FILE *outStm = NS_STATIC_CAST(FILE*, closure); + if (!outStm) + return PR_FALSE; + nsCStringKey *stringKey = NS_STATIC_CAST(nsCStringKey*, aKey); + if (!stringKey) + return PR_FALSE; + HistoryEntry *entry = NS_STATIC_CAST(HistoryEntry*, aData); + if (!entry) + return PR_FALSE; + + nsresult rv = writeEntry(outStm, stringKey, entry); + + return NS_SUCCEEDED(rv) ? PR_TRUE : PR_FALSE; +} + +PRBool enumWriteEntryIfUnwritten(nsHashKey *aKey, void *aData, void* closure) +{ + FILE *outStm = NS_STATIC_CAST(FILE*, closure); + if (!outStm) + return PR_FALSE; + nsCStringKey *stringKey = NS_STATIC_CAST(nsCStringKey*, aKey); + if (!stringKey) + return PR_FALSE; + HistoryEntry *entry = NS_STATIC_CAST(HistoryEntry*, aData); + if (!entry) + return PR_FALSE; + + nsresult rv; + if (!entry->GetIsWritten()) + rv = writeEntry(outStm, stringKey, entry); + + return NS_SUCCEEDED(rv) ? PR_TRUE : PR_FALSE; +} + +PRIntn enumDeleteEntry(nsHashKey *aKey, void *aData, void* closure) +{ + HistoryEntry *entry = NS_STATIC_CAST(HistoryEntry*, aData); + delete entry; + + return PR_TRUE; +} diff --git a/mozilla/embedding/lite/nsEmbedGlobalHistory.h b/mozilla/embedding/lite/nsEmbedGlobalHistory.h new file mode 100644 index 00000000000..bc10034a4c1 --- /dev/null +++ b/mozilla/embedding/lite/nsEmbedGlobalHistory.h @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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.org 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): + * Conrad Carlen + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __nsEmbedGlobalHistory_h__ +#define __nsEmbedGlobalHistory_h__ + +#include "nsIGlobalHistory.h" +#include "nsIObserver.h" +#include "nsWeakReference.h" +#include "nsILocalFile.h" +#include "nsString.h" + +class nsHashtable; +class nsHashKey; +class nsCStringKey; +class HistoryEntry; + +//***************************************************************************** +// nsEmbedGlobalHistory +//***************************************************************************** + +// {2f977d51-5485-11d4-87e2-0010a4e75ef2} +#define NS_EMBEDGLOBALHISTORY_CID \ + { 0x2f977d51, 0x5485, 0x11d4, \ + { 0x87, 0xe2, 0x00, 0x10, 0xa4, 0xe7, 0x5e, 0xf2 } } + +class nsEmbedGlobalHistory: public nsIGlobalHistory, + public nsIObserver, + public nsSupportsWeakReference +{ +public: + nsEmbedGlobalHistory(); + virtual ~nsEmbedGlobalHistory(); + + NS_IMETHOD Init(); + + NS_DECL_ISUPPORTS + NS_DECL_NSIGLOBALHISTORY + NS_DECL_NSIOBSERVER + +protected: + enum { kFlushModeAppend, kFlushModeFullWrite }; + + nsresult LoadData(); + nsresult FlushData(PRIntn mode = kFlushModeFullWrite); + nsresult ResetData(); + + nsresult GetHistoryFile(); + + PRBool EntryHasExpired(HistoryEntry *entry); + static PRIntn enumRemoveEntryIfExpired(nsHashKey *aKey, void *aData, void* closure); + +protected: + PRBool mDataIsLoaded; + PRUint32 mEntriesAddedSinceFlush; + nsCOMPtr mHistoryFile; + nsHashtable *mURLTable; + PRInt64 mExpirationInterval; +}; + +#endif diff --git a/mozilla/embedding/lite/nsEmbedLiteModule.cpp b/mozilla/embedding/lite/nsEmbedLiteModule.cpp index b8241a8301a..f84c84a9b7f 100644 --- a/mozilla/embedding/lite/nsEmbedLiteModule.cpp +++ b/mozilla/embedding/lite/nsEmbedLiteModule.cpp @@ -39,23 +39,31 @@ #include "nsIGenericFactory.h" #include "nsEmbedChromeRegistry.h" -#include "nsEmbedWindowMediator.h" +#include "nsEmbedGlobalHistory.h" +#include "nsChromeProtocolHandler.h" NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsEmbedChromeRegistry, Init) -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsEmbedWindowMediator, Init) +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsEmbedGlobalHistory, Init) static const nsModuleComponentInfo components[] = { +#if 1 // Don't hook up until implementation is finished { "Chrome Registry", NS_EMBEDCHROMEREGISTRY_CID, "@mozilla.org/chrome/chrome-registry;1", nsEmbedChromeRegistryConstructor, }, - { "Window mediator", - NS_EMBEDWINDOWMEDIATOR_CID, - NS_WINDOWMEDIATOR_CONTRACTID, - nsEmbedWindowMediatorConstructor, +#endif + { "Global History", + NS_EMBEDGLOBALHISTORY_CID, + "@mozilla.org/browser/global-history;1", + nsEmbedGlobalHistoryConstructor, }, + { "Chrome Protocol Handler", + NS_CHROMEPROTOCOLHANDLER_CID, + NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "chrome", + nsChromeProtocolHandler::Create + } }; NS_IMPL_NSGETMODULE("EmbedLite components", components); diff --git a/mozilla/embedding/lite/nsEmbedWindowMediator.cpp b/mozilla/embedding/lite/nsEmbedWindowMediator.cpp deleted file mode 100644 index 6f03676f3f5..00000000000 --- a/mozilla/embedding/lite/nsEmbedWindowMediator.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: NPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Netscape 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/NPL/ - * - * 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.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2001 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * - * 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 NPL, 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 NPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsIFactory.h" -#include "nsEmbedWindowMediator.h" - -NS_IMPL_ISUPPORTS1(nsEmbedWindowMediator, nsIWindowMediator) - -nsresult -nsEmbedWindowMediator::Init() -{ - return NS_OK; -} diff --git a/mozilla/embedding/lite/nsEmbedWindowMediator.h b/mozilla/embedding/lite/nsEmbedWindowMediator.h deleted file mode 100644 index 3081de13ad4..00000000000 --- a/mozilla/embedding/lite/nsEmbedWindowMediator.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: NPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Netscape 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/NPL/ - * - * 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.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2001 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * - * 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 NPL, 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 NPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsIWindowMediator.h" - -// {486E344C-F33A-45f6-B4B3-A55B7F67AE89} -#define NS_EMBEDWINDOWMEDIATOR_CID \ -{ 0x486e344c, 0xf33a, 0x45f6, \ - { 0xb4, 0xb3, 0xa5, 0x5b, 0x7f, 0x67, 0xae, 0x89 } } - - -class nsEmbedWindowMediator : public nsIWindowMediator -{ - public: - nsEmbedWindowMediator() { NS_INIT_ISUPPORTS(); } - virtual ~nsEmbedWindowMediator() {} - - nsresult Init(); - - NS_DECL_ISUPPORTS - NS_DECL_NSIWINDOWMEDIATOR - -}; -