Moved nsHistoryDataSource implementation into xpfe/components/history.

This commit is contained in:
waterson%netscape.com 1999-05-18 04:09:44 +00:00
Родитель b15112cc42
Коммит fb3c6a734f
8 изменённых файлов: 0 добавлений и 980 удалений

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

@ -23,7 +23,6 @@
*/
#include "nsIFactory.h"
#include "nsIHistoryDataSource.h"
#include "nsILocalStore.h"
#include "nsIRDFContainer.h"
#include "nsIRDFContainerUtils.h"
@ -64,7 +63,6 @@ static NS_DEFINE_CID(kRDFFileSystemDataSourceCID, NS_RDFFILESYSTEMDATASO
static NS_DEFINE_CID(kRDFFindDataSourceCID, NS_RDFFINDDATASOURCE_CID);
static NS_DEFINE_CID(kRDFFTPDataSourceCID, NS_RDFFTPDATASOURCE_CID);
static NS_DEFINE_CID(kRDFHTMLBuilderCID, NS_RDFHTMLBUILDER_CID);
static NS_DEFINE_CID(kRDFHistoryDataSourceCID, NS_RDFHISTORYDATASOURCE_CID);
static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
static NS_DEFINE_CID(kRDFMenuBuilderCID, NS_RDFMENUBUILDER_CID);
static NS_DEFINE_CID(kRDFRelatedLinksDataSourceCID, NS_RDFRELATEDLINKSDATASOURCE_CID);
@ -211,10 +209,6 @@ RDFFactoryImpl::CreateInstance(nsISupports *aOuter,
if (NS_FAILED(rv = NS_NewRDFContainerUtils((nsIRDFContainerUtils**) &inst)))
return rv;
}
else if (mClassID.Equals(kRDFHistoryDataSourceCID)) {
if (NS_FAILED(rv = NS_NewHistoryDataSource((nsIHistoryDataSource**) &inst)))
return rv;
}
else if (mClassID.Equals(kRDFRelatedLinksDataSourceCID)) {
if (NS_FAILED(rv = NS_NewRDFRelatedLinksDataSource((nsIRDFDataSource**) &inst)))
return rv;
@ -358,11 +352,6 @@ NSRegisterSelf(nsISupports* aServMgr , const char* aPath)
NS_RDF_DATASOURCE_PROGID_PREFIX "ftp",
aPath, PR_TRUE, PR_TRUE);
if (NS_FAILED(rv)) goto done;
rv = compMgr->RegisterComponent(kRDFHistoryDataSourceCID,
"RDF History Data Source",
NS_RDF_DATASOURCE_PROGID_PREFIX "history",
aPath, PR_TRUE, PR_TRUE);
if (NS_FAILED(rv)) goto done;
rv = compMgr->RegisterComponent(kRDFRelatedLinksDataSourceCID,
"RDF Related Links Data Source",
NS_RDF_DATASOURCE_PROGID_PREFIX "relatedlinks",
@ -496,8 +485,6 @@ NSUnregisterSelf(nsISupports* aServMgr, const char* aPath)
if (NS_FAILED(rv)) goto done;
rv = compMgr->UnregisterComponent(kRDFFTPDataSourceCID, aPath);
if (NS_FAILED(rv)) goto done;
rv = compMgr->UnregisterComponent(kRDFHistoryDataSourceCID, aPath);
if (NS_FAILED(rv)) goto done;
rv = compMgr->UnregisterComponent(kRDFRelatedLinksDataSourceCID, aPath);
if (NS_FAILED(rv)) goto done;
rv = compMgr->UnregisterComponent(kRDFCompositeDataSourceCID, aPath);

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

@ -1,6 +1,5 @@
nsIBookmarkDataSource.h
nsILocalStore.h
nsIHistoryDataSource.h
nsIRDFFileSystem.h
nsIRDFFind.h
nsIRDFFTP.h

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

@ -27,7 +27,6 @@ MODULE = rdf
EXPORTS = \
nsIBookmarkDataSource.h \
nsILocalStore.h \
nsIHistoryDataSource.h \
nsIRDFFileSystem.h \
nsIRDFFind.h \
nsIRDFFTP.h \

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

@ -23,7 +23,6 @@ DEPTH=..\..\..
EXPORTS = \
nsIBookmarkDataSource.h \
nsILocalStore.h \
nsIHistoryDataSource.h \
nsIRDFFileSystem.h \
nsIRDFFind.h \
nsIRDFFTP.h \

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

@ -1,71 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
The global history data source.
*/
#ifndef nsIHistoryDataSource_h__
#define nsIHistoryDataSource_h__
#include "nscore.h"
#include "nsIRDFDataSource.h"
#include "prtime.h"
// {1A880051-A59D-11d2-80B6-006097B76B8E}
#define NS_IHISTORYDATASOURCE_IID \
{ 0x1a880051, 0xa59d, 0x11d2, { 0x80, 0xb6, 0x0, 0x60, 0x97, 0xb7, 0x6b, 0x8e } }
class nsIHistoryDataSource : public nsIRDFDataSource
{
public:
static const nsIID& GetIID() { static nsIID iid = NS_IHISTORYDATASOURCE_IID; return iid; }
/**
* Add the specified item to history
*/
NS_IMETHOD AddPage (const char* aURI, const char* aRefererURI, PRTime aDate) = 0;
/**
* Set the title of the page
*/
NS_IMETHOD SetPageTitle (const char* aURI, const PRUnichar* aTitle) = 0;
/**
* Remove the page from history
*/
NS_IMETHOD RemovePage (const char* aURI) = 0;
/**
* Get the uri's last visit date
*/
NS_IMETHOD GetLastVisitDate (const char* aURI, uint32 *aDate) = 0;
/**
* Get the preferred completion
*/
NS_IMETHOD CompleteURL (const char* aPrefix, char** aPreferredCompletions) = 0;
};
nsresult
NS_NewHistoryDataSource(nsIHistoryDataSource** result);
#endif /* nsIHistoryDataSource_h__ */

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

@ -32,7 +32,6 @@ CPPSRCS = \
nsFileSystemDataSource.cpp \
nsFindDataSource.cpp \
nsFTPDataSource.cpp \
nsHistoryDataSource.cpp \
nsRelatedLinksDataSource.cpp \
nsXULContentSink.cpp \
$(NULL)

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

@ -23,7 +23,6 @@ LCFLAGS=-DMOZ_BRPROF
CPP_OBJS=\
.\$(OBJDIR)\nsBookmarkDataSource.obj \
.\$(OBJDIR)\nsHistoryDataSource.obj \
.\$(OBJDIR)\nsFileSystemDataSource.obj \
.\$(OBJDIR)\nsFindDataSource.obj \
.\$(OBJDIR)\nsFTPDataSource.obj \

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

@ -1,891 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
Implementation for the history data source.
*/
#include <ctype.h> // for toupper()
#include <stdio.h>
#include "nscore.h"
#include "nsIRDFNode.h"
#include "nsIRDFObserver.h"
#include "nsIServiceManager.h"
#include "nsIComponentManager.h"
#include "nsString.h"
#include "nsVoidArray.h" // XXX introduces dependency on raptorbase
#include "nsXPIDLString.h"
#include "nsRDFCID.h"
#include "rdfutil.h"
#include "nsIHistoryDataSource.h"
#include "nsIRDFService.h"
#include "plhash.h"
#include "plstr.h"
#include "prmem.h"
#include "prprf.h"
#include "prio.h"
#include "prtime.h"
#include "prlog.h"
#include "prlong.h"
#include "rdf.h"
#if defined(MOZ_BRPROF)
#include "nsIBrowsingProfile.h"
#endif
#include "nsFileSpec.h"
#include "nsFileStream.h"
#include "nsSpecialSystemDirectory.h"
#include "prio.h"
#ifdef DEBUG_warren
#include "nsIBrowsingProfile.h" // XXX here to bootstrap browsing profile service
#endif
////////////////////////////////////////////////////////////////////////
// Interface IDs
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
#if defined(MOZ_BRPROF)
static NS_DEFINE_CID(kBrowsingProfileCID, NS_BROWSINGPROFILE_CID);
#endif
////////////////////////////////////////////////////////////////////////
// RDF property & resource declarations
static const char kURIHistoryRoot[] = "HistoryRoot";
static nsIRDFService* gRDFService = nsnull;
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, instanceOf);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, child);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Name);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, URL);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, VisitCount);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Folder);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Title);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Page);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Date);
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Referer);
DEFINE_RDF_VOCAB(WEB_NAMESPACE_URI, WEB, LastVisitDate);
DEFINE_RDF_VOCAB(WEB_NAMESPACE_URI, WEB, LastModifiedDate);
class HistoryEntry {
public:
PRTime date;
char* url;
char* referer;
HistoryEntry(PRTime& aDate, const char* aURL, const char* aRefererURL)
: date(aDate)
{
url = PL_strdup(aURL);
if (aRefererURL)
referer = PL_strdup(aRefererURL);
else
referer = nsnull;
}
~HistoryEntry() {
PL_strfree(url);
if (referer)
PL_strfree(referer);
}
};
typedef HistoryEntry* HE;
static PLHashNumber
rdf_HashPointer(const void* key)
{
return (PLHashNumber) key;
}
class nsHistoryDataSource : public nsIHistoryDataSource {
protected:
nsIRDFDataSource* mInner;
nsVoidArray mFiles;
nsFileSpec mCurrentFileSpec;
nsVoidArray mPendingWrites;
PLHashTable* mLastVisitDateHash;
PRExplodedTime mSessionTime;
#if defined(MOZ_BRPROF)
nsIBrowsingProfile* mBrowsingProfile;
#endif
static PRInt32 gRefCnt;
static nsIRDFResource* mResourcePage;
static nsIRDFResource* mResourceDate;
static nsIRDFResource* mResourceVisitCount;
static nsIRDFResource* mResourceTitle;
static nsIRDFResource* mResourceReferer;
static nsIRDFResource* mResourceChild;
static nsIRDFResource* mResourceURL;
static nsIRDFResource* mResourceHistoryBySite;
static nsIRDFResource* mResourceHistoryByDate;
nsresult ReadHistory(void);
nsresult ReadOneHistoryFile(nsInputFileStream& aStream, const nsFileSpec& aFileSpec);
nsresult AddPageToGraph(const char* url, const PRUnichar* title, const char* referer, PRUint32 visitCount, PRTime date);
nsresult AddToDateHierarchy (PRTime date, const char *url);
nsresult getSiteOfURL(const char* url, nsIRDFResource** resource);
public:
// nsISupports
NS_DECL_ISUPPORTS
nsHistoryDataSource(void);
virtual ~nsHistoryDataSource(void);
NS_IMETHOD Init(const char* uri) ;
NS_IMETHOD GetURI(char* *uri) {
return mInner->GetURI(uri);
}
NS_IMETHOD GetSource(nsIRDFResource* property,
nsIRDFNode* target,
PRBool tv, nsIRDFResource** source) {
return mInner->GetSource(property, target, tv, source);
}
NS_IMETHOD GetSources(nsIRDFResource* property,
nsIRDFNode* target, PRBool tv,
nsISimpleEnumerator** sources) {
return mInner->GetSources(property, target, tv, sources);
}
NS_IMETHOD GetTarget(nsIRDFResource* source,
nsIRDFResource* property,
PRBool tv,
nsIRDFNode** target)
{
if (tv && property == mResourceURL)
{
nsXPIDLCString uri;
nsresult rv;
if (NS_FAILED(rv = source->GetValue( getter_Copies(uri) )))
{
NS_ERROR("unable to get source's URI");
return(rv);
}
nsAutoString url(uri);
if (url.Find("NC:") == 0)
return(NS_RDF_NO_VALUE);
nsIRDFLiteral *literal;
if (NS_FAILED(rv = gRDFService->GetLiteral(url.GetUnicode(), &literal)))
{
NS_ERROR("unable to construct literal for URL");
return rv;
}
*target = (nsIRDFNode*)literal;
return NS_OK;
}
return mInner->GetTarget(source, property, tv, target);
}
NS_IMETHOD GetTargets(nsIRDFResource* source,
nsIRDFResource* property,
PRBool tv,
nsISimpleEnumerator** targets) {
return mInner->GetTargets(source, property, tv, targets);
}
NS_IMETHOD Assert(nsIRDFResource* source,
nsIRDFResource* property,
nsIRDFNode* target,
PRBool tv) {
// History cannot be modified
return NS_RDF_ASSERTION_REJECTED;
}
NS_IMETHOD Unassert(nsIRDFResource* source,
nsIRDFResource* property,
nsIRDFNode* target) {
// History cannot be modified
return NS_RDF_ASSERTION_REJECTED;
}
NS_IMETHOD HasAssertion(nsIRDFResource* source,
nsIRDFResource* property,
nsIRDFNode* target, PRBool tv,
PRBool* hasAssertion) {
return mInner->HasAssertion(source, property, target, tv, hasAssertion);
}
NS_IMETHOD AddObserver(nsIRDFObserver* n) {
return mInner->AddObserver(n);
}
NS_IMETHOD RemoveObserver(nsIRDFObserver* n) {
return mInner->RemoveObserver(n);
}
NS_IMETHOD ArcLabelsIn(nsIRDFNode* node,
nsISimpleEnumerator** labels) {
return mInner->ArcLabelsIn(node, labels);
}
NS_IMETHOD ArcLabelsOut(nsIRDFResource* source,
nsISimpleEnumerator** labels) {
return mInner->ArcLabelsOut(source, labels);
}
NS_IMETHOD Flush() {
return mInner->Flush();
}
NS_IMETHOD GetAllCommands(nsIRDFResource* source,
nsIEnumerator/*<nsIRDFResource>*/** commands) {
return mInner->GetAllCommands(source, commands);
}
NS_IMETHOD IsCommandEnabled(nsISupportsArray/*<nsIRDFResource>*/* aSources,
nsIRDFResource* aCommand,
nsISupportsArray/*<nsIRDFResource>*/* aArguments,
PRBool* aResult) {
return mInner->IsCommandEnabled(aSources, aCommand, aArguments, aResult);
}
NS_IMETHOD DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
nsIRDFResource* aCommand,
nsISupportsArray/*<nsIRDFResource>*/* aArguments) {
// XXX Uh oh, this could cause problems wrt. the "dirty" flag
// if it changes the in-memory store's internal state.
return mInner->DoCommand(aSources, aCommand, aArguments);
}
NS_IMETHOD GetAllResources(nsISimpleEnumerator** aResult) {
return mInner->GetAllResources(aResult);
}
NS_IMETHOD AddPage (const char* aURI, const char* aRefererURI, PRTime aTime);
NS_IMETHOD SetPageTitle (const char* aURI, const PRUnichar* aTitle);
NS_IMETHOD RemovePage (const char* aURI) {
return NS_OK;
}
NS_IMETHOD GetLastVisitDate (const char* aURI, uint32 *aDate) {
nsIRDFResource* res;
PRBool found = 0;
*aDate = 0;
gRDFService->GetResource(aURI, &res);
*aDate = (uint32)PL_HashTableLookup(mLastVisitDateHash, res);
NS_RELEASE(res);
return NS_OK;
}
nsresult UpdateLastVisitDate (nsIRDFResource* res, uint32 date) {
uint32 edate = (uint32) PL_HashTableLookup(mLastVisitDateHash, res);
if (edate && (edate > date)) return NS_OK;
PL_HashTableAdd(mLastVisitDateHash, res, (void*)date);
return NS_OK;
}
NS_IMETHOD CompleteURL (const char* prefix, char** preferredCompletion) {
return NS_OK;
}
};
PRInt32 nsHistoryDataSource::gRefCnt;
nsIRDFResource *nsHistoryDataSource::mResourcePage;
nsIRDFResource *nsHistoryDataSource::mResourceDate;
nsIRDFResource *nsHistoryDataSource::mResourceVisitCount;
nsIRDFResource *nsHistoryDataSource::mResourceTitle;
nsIRDFResource *nsHistoryDataSource::mResourceReferer;
nsIRDFResource *nsHistoryDataSource::mResourceChild;
nsIRDFResource *nsHistoryDataSource::mResourceURL;
nsIRDFResource *nsHistoryDataSource::mResourceHistoryBySite;
nsIRDFResource *nsHistoryDataSource::mResourceHistoryByDate;
nsHistoryDataSource::nsHistoryDataSource(void)
: mInner(nsnull),
mLastVisitDateHash(nsnull)
#if defined(MOZ_BRPROF)
, mBrowsingProfile(nsnull)
#endif
{
NS_INIT_REFCNT();
if (gRefCnt++ == 0)
{
nsresult rv;
rv = nsServiceManager::GetService(kRDFServiceCID,
nsIRDFService::GetIID(),
(nsISupports**) &gRDFService);
PR_ASSERT(NS_SUCCEEDED(rv));
gRDFService->GetResource(kURINC_Page, &mResourcePage);
gRDFService->GetResource(kURINC_Date, &mResourceDate);
gRDFService->GetResource(kURINC_VisitCount, &mResourceVisitCount);
gRDFService->GetResource(kURINC_Name, &mResourceTitle);
gRDFService->GetResource(kURINC_Referer, &mResourceReferer);
gRDFService->GetResource(kURINC_child, &mResourceChild);
gRDFService->GetResource(kURINC_URL, &mResourceURL);
gRDFService->GetResource("NC:HistoryBySite", &mResourceHistoryBySite);
gRDFService->GetResource("NC:HistoryByDate", &mResourceHistoryByDate);
}
}
nsHistoryDataSource::~nsHistoryDataSource(void)
{
gRDFService->UnregisterDataSource(this);
if (--gRefCnt == 0)
{
NS_IF_RELEASE(mInner);
NS_IF_RELEASE(mResourcePage);
NS_IF_RELEASE(mResourceDate);
NS_IF_RELEASE(mResourceVisitCount);
NS_IF_RELEASE(mResourceTitle);
NS_IF_RELEASE(mResourceReferer);
NS_IF_RELEASE(mResourceChild);
NS_IF_RELEASE(mResourceURL);
NS_IF_RELEASE(mResourceHistoryBySite);
NS_IF_RELEASE(mResourceHistoryByDate);
nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService);
#if defined(MOZ_BRPROF)
nsServiceManager::ReleaseService(kBrowsingProfileCID, mBrowsingProfile);
#endif
gRDFService = nsnull;
}
if (mLastVisitDateHash)
PL_HashTableDestroy(mLastVisitDateHash);
PRInt32 index;
for (index = mPendingWrites.Count() - 1; index >= 0; --index) {
HistoryEntry* entry = (HistoryEntry*) mPendingWrites.ElementAt(index);
delete entry;
}
}
NS_IMPL_ADDREF(nsHistoryDataSource);
NS_IMPL_RELEASE(nsHistoryDataSource);
NS_IMETHODIMP
nsHistoryDataSource::QueryInterface(REFNSIID aIID, void** aResult)
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(nsIHistoryDataSource::GetIID()) ||
aIID.Equals(nsIRDFDataSource::GetIID()) ||
aIID.Equals(nsISupports::GetIID())) {
*aResult = NS_STATIC_CAST(nsIHistoryDataSource*, this);
NS_ADDREF(this);
return NS_OK;
}
else {
*aResult = nsnull;
return NS_NOINTERFACE;
}
}
NS_IMETHODIMP
nsHistoryDataSource::Init(const char* uri)
{
nsresult rv;
if (NS_FAILED(rv = nsComponentManager::CreateInstance(kRDFInMemoryDataSourceCID,
nsnull, nsIRDFDataSource::GetIID(), (void**) &mInner)))
return rv;
if (NS_FAILED(rv = mInner->Init(uri)))
return rv;
// register this as a named data source with the RDF service
if (NS_FAILED(rv = gRDFService->RegisterDataSource(this, PR_FALSE)))
return rv;
#if defined(MOZ_BRPROF)
{
// Force the browsing profile to be loaded and initialized
// here. Mostly we do this so that it's not on the netlib
// thread, which seems to be broken right now.
rv = nsServiceManager::GetService(kBrowsingProfileCID,
nsIBrowsingProfile::GetIID(),
(nsISupports**) &mBrowsingProfile);
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get browsing profile");
if (NS_SUCCEEDED(rv)) {
rv = mBrowsingProfile->Init(nsnull);
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to intialize browsing profile");
}
}
#endif
mLastVisitDateHash = PL_NewHashTable(400, rdf_HashPointer,
PL_CompareValues,
PL_CompareValues,
nsnull, nsnull);
PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &mSessionTime);
if (NS_FAILED(rv = ReadHistory()))
return rv;
char filename[256];
// XXX since we're not really printing an unsinged long, but
// rather an unsigned long-long, this is sure to break at some
// point.
PR_snprintf(filename, sizeof(filename), "%lu.hst", PR_Now());
nsSpecialSystemDirectory historyFile(nsSpecialSystemDirectory::OS_CurrentProcessDirectory);
historyFile += "res";
historyFile += "rdf";
historyFile += "History";
#ifdef XP_MAC
PRBool wasAlias = PR_FALSE;
historyFile.ResolveAlias(wasAlias);
#endif
// historyFile.SetLeafName(filename);
historyFile += filename;
mCurrentFileSpec = historyFile;
#ifdef DEBUG_warren
// XXX here to bootstrap the browsing profile code -- move later
{
static NS_DEFINE_CID(kBrowsingProfileCID, NS_BROWSINGPROFILE_CID);
NS_WITH_SERVICE(nsIRDFObserver, brProf, kBrowsingProfileCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = AddObserver(brProf);
}
#endif
return rv;
}
NS_IMETHODIMP
nsHistoryDataSource::AddPage (const char* aURI, const char* aRefererURI, PRTime aTime)
{
NS_PRECONDITION(aURI != nsnull, "null ptr");
if (! aURI)
return NS_ERROR_NULL_POINTER;
HistoryEntry* he = new HistoryEntry(aTime, aURI, aRefererURI);
if (! he)
return NS_ERROR_OUT_OF_MEMORY;
mPendingWrites.AppendElement(he);
return NS_OK;
}
NS_IMETHODIMP
nsHistoryDataSource::SetPageTitle (const char* aURI, const PRUnichar* aTitle)
{
for (PRInt32 i = mPendingWrites.Count() - 1; i >= 0; --i)
{
HE wr = (HE) mPendingWrites.ElementAt(i);
if (strcmp(wr->url, aURI) == 0)
{
char timeBuffer[256];
PRExplodedTime etime;
PR_ExplodeTime(wr->date, PR_LocalTimeParameters, &etime);
PR_FormatTimeUSEnglish(timeBuffer, 256, "%a %b %d %H:%M:%S %Y", &etime);
nsAutoString title(aTitle);
char *cTitle = title.ToNewCString();
char *buffer = PR_smprintf("%s\t%s\t%s\t%lu\t%s\n", wr->url,
((cTitle) ? cTitle:""),
((wr->referer) ? wr->referer : ""),
1L, timeBuffer);
if (cTitle)
{
delete [] cTitle;
cTitle = nsnull;
}
if (buffer)
{
nsOutputFileStream out(mCurrentFileSpec, PR_WRONLY | PR_CREATE_FILE | PR_APPEND, 0744);
// XXX because PR_APPEND is broken
out.seek(mCurrentFileSpec.GetFileSize());
out << buffer;
PR_smprintf_free(buffer);
}
mPendingWrites.RemoveElement(wr);
AddPageToGraph(wr->url, aTitle, wr->referer, 1L, PR_Now());
delete wr;
return NS_OK;
}
}
return NS_OK;
}
PRBool
endsWith (const char* pattern, const char* uuid)
{
short l1 = strlen(pattern);
short l2 = strlen(uuid);
short index;
if (l2 < l1) return PR_FALSE;
for (index = 1; index <= l1; index++)
{
if (pattern[l1-index] != uuid[l2-index])
return PR_FALSE;
}
return PR_TRUE;
}
nsresult
nsHistoryDataSource::ReadHistory(void)
{
nsSpecialSystemDirectory historyDir(nsSpecialSystemDirectory::OS_CurrentProcessDirectory);
historyDir += "res";
historyDir += "rdf";
historyDir += "History";
#ifdef XP_MAC
PRBool wasAlias = PR_FALSE;
historyDir.ResolveAlias(wasAlias);
#endif
for (nsDirectoryIterator i(historyDir); i.Exists(); i++)
{
const nsNativeFileSpec nativeSpec = (const nsNativeFileSpec &)i;
nsFilePath filePath(nativeSpec);
nsFileSpec fileSpec(filePath);
const char *fileURL = (const char*) fileSpec;
if (fileURL)
{
if (endsWith(".hst", fileURL))
{
nsInputFileStream strm(fileSpec);
if (strm.is_open())
{
ReadOneHistoryFile(strm, fileSpec);
}
}
}
}
return(NS_OK);
}
nsresult
nsHistoryDataSource::ReadOneHistoryFile(nsInputFileStream& aStream, const nsFileSpec& aFileSpec)
{
nsAutoString buffer;
while (! aStream.eof() && ! aStream.failed()) {
nsresult rv;
char c = aStream.get();
if ((c != '\r') && (c != '\n')) {
buffer += c;
continue;
}
char buf[256];
char* p = buf;
if (buffer.Length() >= sizeof(buf))
p = new char[buffer.Length() + 1];
if (! p)
return NS_ERROR_OUT_OF_MEMORY;
buffer.ToCString(p, buffer.Length() + 1);
if (PL_strlen(p) > 0) do {
char* url = p;
char* title = PL_strchr(p, '\t');
if (! title)
break;
*(title++) = '\0';
char* referer = PL_strchr(title, '\t');
if (! referer)
break;
*(referer++) = '\0';
char* visitcount = PL_strchr(referer, '\t');
if (! visitcount)
break;
*(visitcount++) = '\0';
char* date = PL_strchr(visitcount, '\t');
if (! date)
break;
*(date++) = '\0';
PRTime time;
PR_ParseTimeString(date, 0, &time);
PRExplodedTime etime;
PR_ExplodeTime(time, PR_LocalTimeParameters, &etime);
// While we parse this file, check to see if it has any
// history elements in it from today. If it does, then
// we'll re-use it as the current history file.
//
// XXX Isn't this a little over-ambitious? I could see one
// file growing into a monstrous thing if somebody
// regularly stays up past midnight.
if (etime.tm_yday == mSessionTime.tm_yday)
mCurrentFileSpec = aFileSpec;
rv = AddPageToGraph(url, nsAutoString(title).GetUnicode(), referer,
(PRUint32) atol(visitcount), time);
} while (0);
if (p != buf)
delete[] p;
if (NS_FAILED(rv))
return rv;
buffer.Truncate();
}
return NS_OK;
}
nsresult
nsHistoryDataSource::getSiteOfURL(const char* url, nsIRDFResource** resource)
{
char* str = strstr(url, "://");
char buff[256];
nsIRDFLiteral *titleLiteral;
if (!str) return NS_ERROR_FAILURE;
str = str + 3;
if (str[0] == '/') str++;
char* estr = strchr(str, '/');
if (!estr) estr = str + strlen(str);
if ((estr - str) > 256) return NS_ERROR_FAILURE;
memset(buff, '\0', 256);
// Note: start with "NC:" so that URL won't be shown
static const char kHistoryURLPrefix[] = "NC:hst:site?";
strcpy(buff, kHistoryURLPrefix);
strncat(buff, str, (estr-str));
// XXXwaterson: fix this
//if (NS_OK != gRDFService->FindResource(buff, resource, &foundp)) return NS_ERROR_FAILURE;
//if (foundp) return NS_OK;
if (NS_OK != gRDFService->GetResource(buff, resource)) return NS_ERROR_FAILURE;
mInner->Assert(mResourceHistoryBySite, mResourceChild, *resource, 1);
nsAutoString ptitle(buff + sizeof(kHistoryURLPrefix) - 1);
gRDFService->GetLiteral(ptitle.GetUnicode(), &titleLiteral);
mInner->Assert(*resource, mResourceTitle, titleLiteral, 1);
return NS_OK;
}
nsresult
nsHistoryDataSource::AddPageToGraph(const char* url, const PRUnichar* title,
const char* referer, PRUint32 visitCount, PRTime date)
{
nsresult rv = NS_ERROR_OUT_OF_MEMORY;
char *histURL = PR_smprintf("hst://%s", url);
if (histURL)
{
nsIRDFResource *siteResource;
rv = getSiteOfURL(url, &siteResource);
if (rv == NS_OK)
{
nsCOMPtr<nsIRDFResource> pageResource, refererResource, histResource;
nsCOMPtr<nsIRDFLiteral> titleLiteral;
nsCOMPtr<nsIRDFDate> dateLiteral;
nsCOMPtr<nsIRDFInt> visitCountLiteral;
gRDFService->GetResource(url, getter_AddRefs(pageResource));
gRDFService->GetResource(histURL, getter_AddRefs(histResource));
if (referer)
gRDFService->GetResource(referer, getter_AddRefs(refererResource));
gRDFService->GetDateLiteral(date, getter_AddRefs(dateLiteral));
gRDFService->GetIntLiteral(visitCount, getter_AddRefs(visitCountLiteral));
if (title)
{
nsAutoString ptitle(title);
if (ptitle.Length() > 0)
{
gRDFService->GetLiteral(ptitle.GetUnicode(), getter_AddRefs(titleLiteral));
mInner->Assert(pageResource, mResourceTitle, titleLiteral, 1);
}
}
mInner->Assert(histResource, mResourcePage, pageResource, 1);
mInner->Assert(histResource, mResourceDate, dateLiteral, 1);
mInner->Assert(histResource, mResourceVisitCount, visitCountLiteral, 1);
if (referer)
mInner->Assert(histResource, mResourceReferer, refererResource, 1);
mInner->Assert(siteResource, mResourceChild, pageResource, 1);
AddToDateHierarchy(date, url);
UpdateLastVisitDate (pageResource, 1/* date */);
}
PR_smprintf_free(histURL);
}
return(rv);
}
nsresult
nsHistoryDataSource::AddToDateHierarchy (PRTime date, const char *url)
{
char timeBuffer[128], timeNameBuffer[128], dayBuffer[128], dayNameBuffer[128];
PRExplodedTime enow, etime;
timeBuffer[0] = timeNameBuffer[0] = dayBuffer[0] = dayNameBuffer[0] = '\0';
PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &enow);
PR_ExplodeTime(date, PR_LocalTimeParameters, &etime);
if ((enow.tm_year == etime.tm_year) && (enow.tm_yday == etime.tm_yday))
{
PR_snprintf(timeBuffer, sizeof(timeBuffer), "NC:hst:date?today");
PR_snprintf(timeNameBuffer, sizeof(timeNameBuffer), "Today"); // XXX localization
}
else if ((enow.tm_year == etime.tm_year) && ((enow.tm_yday - 1) == etime.tm_yday))
{
PR_snprintf(timeBuffer, sizeof(timeBuffer), "NC:hst:date?yesterday");
PR_snprintf(timeNameBuffer, sizeof(timeNameBuffer), "Yesterday"); // XXX localization
}
else if ((enow.tm_year == etime.tm_year) && ((enow.tm_yday - etime.tm_yday) < 7)) // XXX calculation is not quite right
{
PR_FormatTimeUSEnglish(timeBuffer, sizeof(timeBuffer), "NC:hst:date?%A, %B %d, %Y", &etime);
PR_FormatTimeUSEnglish(timeNameBuffer, sizeof(timeNameBuffer), "%A", &etime);
}
else
{
PR_FormatTimeUSEnglish(dayBuffer, sizeof(dayBuffer), "NC:hst:day?%A, %B %d, %Y", &etime);
PR_FormatTimeUSEnglish(dayNameBuffer, sizeof(dayNameBuffer), "%A, %B %d, %Y", &etime);
if (etime.tm_wday > 0)
{
PRUint64 microSecsInSec, secsInDay, temp;
LL_I2L(microSecsInSec, PR_USEC_PER_SEC);
LL_I2L(secsInDay, (60L*60L*24L*etime.tm_wday));
LL_MUL(temp, microSecsInSec, secsInDay);
LL_SUB(date, date, temp);
PR_ExplodeTime(date, PR_LocalTimeParameters, &etime);
}
PR_FormatTimeUSEnglish(timeBuffer, sizeof(timeBuffer), "NC:hst:weekof?%B %d, %Y", &etime);
PR_FormatTimeUSEnglish(timeNameBuffer, sizeof(timeNameBuffer), "Week of %B %d, %Y", &etime); // XXX localization
}
nsIRDFResource *timeResource, *dayResource, *resource, *parent;
parent = mResourceHistoryByDate;
if (NS_OK != gRDFService->GetResource(url, &resource))
return NS_ERROR_FAILURE;
PRBool found = PR_FALSE;
//XXXwaterson: fix this
//if (NS_OK != gRDFService->FindResource(timeBuffer, &timeResource, &found))
//return NS_ERROR_FAILURE;
if (found == PR_FALSE)
{
if (NS_OK != gRDFService->GetResource(timeBuffer, &timeResource))
return NS_ERROR_FAILURE;
// set name of synthesized history container
nsAutoString ptitle(timeNameBuffer);
nsIRDFLiteral *titleLiteral;
gRDFService->GetLiteral(ptitle.GetUnicode(), &titleLiteral);
mInner->Assert(timeResource, mResourceTitle, titleLiteral, 1);
}
mInner->Assert(parent, mResourceChild, timeResource, 1);
parent = timeResource;
if (dayBuffer[0])
{
PRBool found = PR_FALSE;
// XXXwaterson: fix this
//if (NS_OK != gRDFService->FindResource(dayBuffer, &dayResource, &found))
//return NS_ERROR_FAILURE;
if (found == PR_FALSE)
{
if (NS_OK != gRDFService->GetResource(dayBuffer, &dayResource))
return NS_ERROR_FAILURE;
// set name of synthesized history container
nsAutoString dayTitle(dayNameBuffer);
nsIRDFLiteral *dayLiteral;
gRDFService->GetLiteral(dayTitle.GetUnicode(), &dayLiteral);
mInner->Assert(dayResource, mResourceTitle, dayLiteral, 1);
}
mInner->Assert(parent, mResourceChild, dayResource, 1);
parent = dayResource;
}
mInner->Assert(parent, mResourceChild, resource, 1);
return(NS_OK);
}
nsresult
NS_NewHistoryDataSource(nsIHistoryDataSource** result)
{
nsHistoryDataSource* ds = new nsHistoryDataSource();
if (! ds)
return NS_ERROR_NULL_POINTER;
*result = ds;
NS_ADDREF(*result);
return(NS_OK);
}