rdf/datasource/src/nsLocalStore.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* vim: set cindent tabstop=4 expandtab shiftwidth=4: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /*
     9   Implementation for the local store
    11  */
    13 #include "nsNetUtil.h"
    14 #include "nsIURI.h"
    15 #include "nsIIOService.h"
    16 #include "nsIOutputStream.h"
    17 #include "nsIComponentManager.h"
    18 #include "nsILocalStore.h"
    19 #include "nsIRDFDataSource.h"
    20 #include "nsIRDFRemoteDataSource.h"
    21 #include "nsIRDFService.h"
    22 #include "nsIServiceManager.h"
    23 #include "nsRDFCID.h"
    24 #include "nsXPIDLString.h"
    25 #include "plstr.h"
    26 #include "rdf.h"
    27 #include "nsCOMPtr.h"
    28 #include "nsWeakPtr.h"
    29 #include "nsAppDirectoryServiceDefs.h"
    30 #include "nsIObserver.h"
    31 #include "nsIObserverService.h"
    32 #include "nsWeakReference.h"
    33 #include "nsCRTGlue.h"
    34 #include "nsCRT.h"
    35 #include "nsEnumeratorUtils.h"
    36 #include "nsCycleCollectionParticipant.h"
    38 ////////////////////////////////////////////////////////////////////////
    40 class LocalStoreImpl : public nsILocalStore,
    41                        public nsIRDFDataSource,
    42                        public nsIRDFRemoteDataSource,
    43                        public nsIObserver,
    44                        public nsSupportsWeakReference
    45 {
    46 protected:
    47     nsCOMPtr<nsIRDFDataSource> mInner;
    49     LocalStoreImpl();
    50     virtual ~LocalStoreImpl();
    51     nsresult Init();
    52     nsresult CreateLocalStore(nsIFile* aFile);
    53     nsresult LoadData();
    55     friend nsresult
    56     NS_NewLocalStore(nsISupports* aOuter, REFNSIID aIID, void** aResult);
    58     nsCOMPtr<nsIRDFService>    mRDFService;
    60 public:
    61     // nsISupports interface
    62     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    63     NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(LocalStoreImpl, nsILocalStore)
    65     // nsILocalStore interface
    67     // nsIRDFDataSource interface. Most of these are just delegated to
    68     // the inner, in-memory datasource.
    69     NS_IMETHOD GetURI(char* *aURI);
    71     NS_IMETHOD GetSource(nsIRDFResource* aProperty,
    72                          nsIRDFNode* aTarget,
    73                          bool aTruthValue,
    74                          nsIRDFResource** aSource) {
    75         return mInner->GetSource(aProperty, aTarget, aTruthValue, aSource);
    76     }
    78     NS_IMETHOD GetSources(nsIRDFResource* aProperty,
    79                           nsIRDFNode* aTarget,
    80                           bool aTruthValue,
    81                           nsISimpleEnumerator** aSources) {
    82         return mInner->GetSources(aProperty, aTarget, aTruthValue, aSources);
    83     }
    85     NS_IMETHOD GetTarget(nsIRDFResource* aSource,
    86                          nsIRDFResource* aProperty,
    87                          bool aTruthValue,
    88                          nsIRDFNode** aTarget) {
    89         return mInner->GetTarget(aSource, aProperty, aTruthValue, aTarget);
    90     }
    92     NS_IMETHOD GetTargets(nsIRDFResource* aSource,
    93                           nsIRDFResource* aProperty,
    94                           bool aTruthValue,
    95                           nsISimpleEnumerator** aTargets) {
    96         return mInner->GetTargets(aSource, aProperty, aTruthValue, aTargets);
    97     }
    99     NS_IMETHOD Assert(nsIRDFResource* aSource, 
   100                       nsIRDFResource* aProperty, 
   101                       nsIRDFNode* aTarget,
   102                       bool aTruthValue) {
   103         return mInner->Assert(aSource, aProperty, aTarget, aTruthValue);
   104     }
   106     NS_IMETHOD Unassert(nsIRDFResource* aSource,
   107                         nsIRDFResource* aProperty,
   108                         nsIRDFNode* aTarget) {
   109         return mInner->Unassert(aSource, aProperty, aTarget);
   110     }
   112     NS_IMETHOD Change(nsIRDFResource* aSource,
   113                       nsIRDFResource* aProperty,
   114                       nsIRDFNode* aOldTarget,
   115                       nsIRDFNode* aNewTarget) {
   116         return mInner->Change(aSource, aProperty, aOldTarget, aNewTarget);
   117     }
   119     NS_IMETHOD Move(nsIRDFResource* aOldSource,
   120                     nsIRDFResource* aNewSource,
   121                     nsIRDFResource* aProperty,
   122                     nsIRDFNode* aTarget) {
   123         return mInner->Move(aOldSource, aNewSource, aProperty, aTarget);
   124     }
   126     NS_IMETHOD HasAssertion(nsIRDFResource* aSource,
   127                             nsIRDFResource* aProperty,
   128                             nsIRDFNode* aTarget,
   129                             bool aTruthValue,
   130                             bool* hasAssertion) {
   131         return mInner->HasAssertion(aSource, aProperty, aTarget, aTruthValue, hasAssertion);
   132     }
   134     NS_IMETHOD AddObserver(nsIRDFObserver* aObserver) {
   135         return NS_ERROR_NOT_IMPLEMENTED;
   136     }
   138     NS_IMETHOD RemoveObserver(nsIRDFObserver* aObserver) {
   139         return NS_ERROR_NOT_IMPLEMENTED;
   140     }
   142     NS_IMETHOD HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, bool *_retval) {
   143         return mInner->HasArcIn(aNode, aArc, _retval);
   144     }
   146     NS_IMETHOD HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, bool *_retval) {
   147         return mInner->HasArcOut(aSource, aArc, _retval);
   148     }
   150     NS_IMETHOD ArcLabelsIn(nsIRDFNode* aNode,
   151                            nsISimpleEnumerator** aLabels) {
   152         return mInner->ArcLabelsIn(aNode, aLabels);
   153     }
   155     NS_IMETHOD ArcLabelsOut(nsIRDFResource* aSource,
   156                             nsISimpleEnumerator** aLabels) {
   157         return mInner->ArcLabelsOut(aSource, aLabels);
   158     }
   160     NS_IMETHOD GetAllResources(nsISimpleEnumerator** aResult) {
   161         return mInner->GetAllResources(aResult);
   162     }
   164     NS_IMETHOD GetAllCmds(nsIRDFResource* aSource,
   165                               nsISimpleEnumerator/*<nsIRDFResource>*/** aCommands);
   167     NS_IMETHOD IsCommandEnabled(nsISupportsArray/*<nsIRDFResource>*/* aSources,
   168                                 nsIRDFResource*   aCommand,
   169                                 nsISupportsArray/*<nsIRDFResource>*/* aArguments,
   170                                 bool* aResult);
   172     NS_IMETHOD DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
   173                          nsIRDFResource*   aCommand,
   174                          nsISupportsArray/*<nsIRDFResource>*/* aArguments);
   176     NS_IMETHOD BeginUpdateBatch() {
   177         return mInner->BeginUpdateBatch();
   178     }
   180     NS_IMETHOD EndUpdateBatch() {
   181         return mInner->EndUpdateBatch();
   182     }
   184     NS_IMETHOD GetLoaded(bool* _result);
   185     NS_IMETHOD Init(const char *uri);
   186     NS_IMETHOD Flush();
   187     NS_IMETHOD FlushTo(const char *aURI);
   188     NS_IMETHOD Refresh(bool sync);
   190     // nsIObserver
   191     NS_DECL_NSIOBSERVER
   192 };
   194 ////////////////////////////////////////////////////////////////////////
   197 LocalStoreImpl::LocalStoreImpl(void)
   198 {
   199 }
   201 LocalStoreImpl::~LocalStoreImpl(void)
   202 {
   203     if (mRDFService)
   204         mRDFService->UnregisterDataSource(this);
   205 }
   208 nsresult
   209 NS_NewLocalStore(nsISupports* aOuter, REFNSIID aIID, void** aResult)
   210 {
   211     NS_PRECONDITION(aOuter == nullptr, "no aggregation");
   212     if (aOuter)
   213         return NS_ERROR_NO_AGGREGATION;
   215     NS_PRECONDITION(aResult != nullptr, "null ptr");
   216     if (! aResult)
   217         return NS_ERROR_NULL_POINTER;
   219     LocalStoreImpl* impl = new LocalStoreImpl();
   220     if (! impl)
   221         return NS_ERROR_OUT_OF_MEMORY;
   223     NS_ADDREF(impl);
   225     nsresult rv;
   226     rv = impl->Init();
   227     if (NS_SUCCEEDED(rv)) {
   228         // Set up the result pointer
   229         rv = impl->QueryInterface(aIID, aResult);
   230     }
   232     NS_RELEASE(impl);
   233     return rv;
   234 }
   236 NS_IMPL_CYCLE_COLLECTION(LocalStoreImpl, mInner)
   237 NS_IMPL_CYCLE_COLLECTING_ADDREF(LocalStoreImpl)
   238 NS_IMPL_CYCLE_COLLECTING_RELEASE(LocalStoreImpl)
   240 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(LocalStoreImpl)
   241     NS_INTERFACE_MAP_ENTRY(nsILocalStore)
   242     NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
   243     NS_INTERFACE_MAP_ENTRY(nsIRDFRemoteDataSource)
   244     NS_INTERFACE_MAP_ENTRY(nsIObserver)
   245     NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   246     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsILocalStore)
   247 NS_INTERFACE_MAP_END
   249 // nsILocalStore interface
   251 // nsIRDFDataSource interface
   253 NS_IMETHODIMP
   254 LocalStoreImpl::GetLoaded(bool* _result)
   255 {
   256 	nsCOMPtr<nsIRDFRemoteDataSource> remote = do_QueryInterface(mInner);
   257     NS_ASSERTION(remote != nullptr, "not an nsIRDFRemoteDataSource");
   258 	if (! remote)
   259         return NS_ERROR_UNEXPECTED;
   261     return remote->GetLoaded(_result);
   262 }
   265 NS_IMETHODIMP
   266 LocalStoreImpl::Init(const char *uri)
   267 {
   268 	return(NS_OK);
   269 }
   271 NS_IMETHODIMP
   272 LocalStoreImpl::Flush()
   273 {
   274 	nsCOMPtr<nsIRDFRemoteDataSource> remote = do_QueryInterface(mInner);
   275     // FIXME Bug 340242: Temporarily make this a warning rather than an
   276     // assertion until we sort out the ordering of how we write
   277     // everything to the localstore, flush it, and disconnect it when
   278     // we're getting profile-change notifications.
   279     NS_WARN_IF_FALSE(remote != nullptr, "not an nsIRDFRemoteDataSource");
   280 	if (! remote)
   281         return NS_ERROR_UNEXPECTED;
   283     return remote->Flush();
   284 }
   286 NS_IMETHODIMP
   287 LocalStoreImpl::FlushTo(const char *aURI)
   288 {
   289   // Do not ever implement this (security)
   290   return NS_ERROR_NOT_IMPLEMENTED;
   291 }
   293 NS_IMETHODIMP
   294 LocalStoreImpl::Refresh(bool sync)
   295 {
   296 	nsCOMPtr<nsIRDFRemoteDataSource> remote = do_QueryInterface(mInner);
   297     NS_ASSERTION(remote != nullptr, "not an nsIRDFRemoteDataSource");
   298 	if (! remote)
   299         return NS_ERROR_UNEXPECTED;
   301     return remote->Refresh(sync);
   302 }
   304 nsresult
   305 LocalStoreImpl::Init()
   306 {
   307     nsresult rv;
   309     rv = LoadData();
   310     if (NS_FAILED(rv)) return rv;
   312     // register this as a named data source with the RDF service
   313     mRDFService = do_GetService(NS_RDF_CONTRACTID "/rdf-service;1", &rv);
   314     if (NS_FAILED(rv)) return rv;
   316     mRDFService->RegisterDataSource(this, false);
   318     // Register as an observer of profile changes
   319     nsCOMPtr<nsIObserverService> obs =
   320         do_GetService("@mozilla.org/observer-service;1");
   322     if (obs) {
   323         obs->AddObserver(this, "profile-before-change", true);
   324         obs->AddObserver(this, "profile-do-change", true);
   325     }
   327     return NS_OK;
   328 }
   330 nsresult
   331 LocalStoreImpl::CreateLocalStore(nsIFile* aFile)
   332 {
   333     nsresult rv;
   335     rv = aFile->Create(nsIFile::NORMAL_FILE_TYPE, 0666);
   336     if (NS_FAILED(rv)) return rv;
   338     nsCOMPtr<nsIOutputStream> outStream;
   339     rv = NS_NewLocalFileOutputStream(getter_AddRefs(outStream), aFile);
   340     if (NS_FAILED(rv)) return rv;
   342     const char defaultRDF[] = 
   343         "<?xml version=\"1.0\"?>\n" \
   344         "<RDF:RDF xmlns:RDF=\"" RDF_NAMESPACE_URI "\"\n" \
   345         "         xmlns:NC=\""  NC_NAMESPACE_URI "\">\n" \
   346         "  <!-- Empty -->\n" \
   347         "</RDF:RDF>\n";
   349     uint32_t count;
   350     rv = outStream->Write(defaultRDF, sizeof(defaultRDF)-1, &count);
   351     if (NS_FAILED(rv)) return rv;
   353     if (count != sizeof(defaultRDF)-1)
   354         return NS_ERROR_UNEXPECTED;
   356     // Okay, now see if the file exists _for real_. If it's still
   357     // not there, it could be that the profile service gave us
   358     // back a read-only directory. Whatever.
   359     bool fileExistsFlag = false;
   360     aFile->Exists(&fileExistsFlag);
   361     if (!fileExistsFlag)
   362         return NS_ERROR_UNEXPECTED;
   364     return NS_OK;
   365 }
   367 nsresult
   368 LocalStoreImpl::LoadData()
   369 {
   370     nsresult rv;
   372     // Look for localstore.rdf in the current profile
   373     // directory. Bomb if we can't find it.
   375     nsCOMPtr<nsIFile> aFile;
   376     rv = NS_GetSpecialDirectory(NS_APP_LOCALSTORE_50_FILE, getter_AddRefs(aFile));
   377     if (NS_FAILED(rv)) return rv;
   379     bool fileExistsFlag = false;
   380     (void)aFile->Exists(&fileExistsFlag);
   381     if (!fileExistsFlag) {
   382         // if file doesn't exist, create it
   383         rv = CreateLocalStore(aFile);
   384         if (NS_FAILED(rv)) return rv;
   385     }
   387     mInner = do_CreateInstance(NS_RDF_DATASOURCE_CONTRACTID_PREFIX "xml-datasource", &rv);
   388     if (NS_FAILED(rv)) return rv;
   390     nsCOMPtr<nsIRDFRemoteDataSource> remote = do_QueryInterface(mInner, &rv);
   391     if (NS_FAILED(rv)) return rv;
   393     nsCOMPtr<nsIURI> aURI;
   394     rv = NS_NewFileURI(getter_AddRefs(aURI), aFile);
   395     if (NS_FAILED(rv)) return rv;
   397     nsAutoCString spec;
   398     rv = aURI->GetSpec(spec);
   399     if (NS_FAILED(rv)) return rv;
   401     rv = remote->Init(spec.get());
   402     if (NS_FAILED(rv)) return rv;
   404     // Read the datasource synchronously.
   405     rv = remote->Refresh(true);
   407     if (NS_FAILED(rv)) {
   408         // Load failed, delete and recreate a fresh localstore
   409         aFile->Remove(true);
   410         rv = CreateLocalStore(aFile);
   411         if (NS_FAILED(rv)) return rv;
   413         rv = remote->Refresh(true);
   414     }
   416     return rv;
   417 }
   420 NS_IMETHODIMP
   421 LocalStoreImpl::GetURI(char* *aURI)
   422 {
   423     NS_PRECONDITION(aURI != nullptr, "null ptr");
   424     if (! aURI)
   425         return NS_ERROR_NULL_POINTER;
   427     *aURI = NS_strdup("rdf:local-store");
   428     if (! *aURI)
   429         return NS_ERROR_OUT_OF_MEMORY;
   431     return NS_OK;
   432 }
   435 NS_IMETHODIMP
   436 LocalStoreImpl::GetAllCmds(nsIRDFResource* aSource,
   437                                nsISimpleEnumerator/*<nsIRDFResource>*/** aCommands)
   438 {
   439 	return(NS_NewEmptyEnumerator(aCommands));
   440 }
   442 NS_IMETHODIMP
   443 LocalStoreImpl::IsCommandEnabled(nsISupportsArray/*<nsIRDFResource>*/* aSources,
   444                                  nsIRDFResource*   aCommand,
   445                                  nsISupportsArray/*<nsIRDFResource>*/* aArguments,
   446                                  bool* aResult)
   447 {
   448     *aResult = true;
   449     return NS_OK;
   450 }
   452 NS_IMETHODIMP
   453 LocalStoreImpl::DoCommand(nsISupportsArray* aSources,
   454                           nsIRDFResource*   aCommand,
   455                           nsISupportsArray* aArguments)
   456 {
   457     // no-op
   458     return NS_OK;
   459 }
   461 NS_IMETHODIMP
   462 LocalStoreImpl::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *someData)
   463 {
   464     nsresult rv = NS_OK;
   466     if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
   467         // Write out the old datasource's contents.
   468         if (mInner) {
   469             nsCOMPtr<nsIRDFRemoteDataSource> remote = do_QueryInterface(mInner);
   470             if (remote)
   471                 remote->Flush();
   472         }
   474         // Create an in-memory datasource for use while we're
   475         // profile-less.
   476         mInner = do_CreateInstance(NS_RDF_DATASOURCE_CONTRACTID_PREFIX "in-memory-datasource");
   478         if (!nsCRT::strcmp(NS_ConvertUTF16toUTF8(someData).get(), "shutdown-cleanse")) {
   479             nsCOMPtr<nsIFile> aFile;
   480             rv = NS_GetSpecialDirectory(NS_APP_LOCALSTORE_50_FILE, getter_AddRefs(aFile));
   481             if (NS_SUCCEEDED(rv))
   482                 rv = aFile->Remove(false);
   483         }
   484     }
   485     else if (!nsCRT::strcmp(aTopic, "profile-do-change")) {
   486         rv = LoadData();
   487     }
   488     return rv;
   489 }

mercurial