storage/public/mozStorageHelper.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef MOZSTORAGEHELPER_H
     7 #define MOZSTORAGEHELPER_H
     9 #include "nsAutoPtr.h"
    11 #include "mozIStorageAsyncConnection.h"
    12 #include "mozIStorageConnection.h"
    13 #include "mozIStorageStatement.h"
    14 #include "nsError.h"
    16 /**
    17  * This class wraps a transaction inside a given C++ scope, guaranteeing that
    18  * the transaction will be completed even if you have an exception or
    19  * return early.
    20  *
    21  * aCommitOnComplete controls whether the transaction is committed or rolled
    22  * back when it goes out of scope. A common use is to create an instance with
    23  * commitOnComplete = FALSE (rollback), then call Commit on this object manually
    24  * when your function completes successfully.
    25  *
    26  * Note that nested transactions are not supported by sqlite, so if a transaction
    27  * is already in progress, this object does nothing. Note that in this case,
    28  * you may not get the transaction type you ask for, and you won't be able
    29  * to rollback.
    30  *
    31  * Note: This class is templatized to be also usable with internal data
    32  * structures. External users of this class should generally use
    33  * |mozStorageTransaction| instead.
    34  */
    35 template<typename T, typename U>
    36 class mozStorageTransactionBase
    37 {
    38 public:
    39   mozStorageTransactionBase(T* aConnection,
    40                             bool aCommitOnComplete,
    41                             int32_t aType = mozIStorageConnection::TRANSACTION_DEFERRED)
    42     : mConnection(aConnection),
    43       mHasTransaction(false),
    44       mCommitOnComplete(aCommitOnComplete),
    45       mCompleted(false)
    46   {
    47     // We won't try to get a transaction if one is already in progress.
    48     if (mConnection)
    49       mHasTransaction = NS_SUCCEEDED(mConnection->BeginTransactionAs(aType));
    50   }
    51   ~mozStorageTransactionBase()
    52   {
    53     if (mConnection && mHasTransaction && ! mCompleted) {
    54       if (mCommitOnComplete)
    55         mConnection->CommitTransaction();
    56       else
    57         mConnection->RollbackTransaction();
    58     }
    59   }
    61   /**
    62    * Commits the transaction if one is in progress. If one is not in progress,
    63    * this is a NOP since the actual owner of the transaction outside of our
    64    * scope is in charge of finally comitting or rolling back the transaction.
    65    */
    66   nsresult Commit()
    67   {
    68     if (!mConnection || mCompleted)
    69       return NS_OK; // no connection, or already done
    70     mCompleted = true;
    71     if (! mHasTransaction)
    72       return NS_OK; // transaction not ours, ignore
    73     nsresult rv = mConnection->CommitTransaction();
    74     if (NS_SUCCEEDED(rv))
    75       mHasTransaction = false;
    77     return rv;
    78   }
    80   /**
    81    * Rolls back the transaction in progress. You should only call this function
    82    * if this object has a real transaction (HasTransaction() = true) because
    83    * otherwise, there is no transaction to roll back.
    84    */
    85   nsresult Rollback()
    86   {
    87     if (!mConnection || mCompleted)
    88       return NS_OK; // no connection, or already done
    89     mCompleted = true;
    90     if (! mHasTransaction)
    91       return NS_ERROR_FAILURE;
    93     // It is possible that a rollback will return busy, so we busy wait...
    94     nsresult rv = NS_OK;
    95     do {
    96       rv = mConnection->RollbackTransaction();
    97       if (rv == NS_ERROR_STORAGE_BUSY)
    98         (void)PR_Sleep(PR_INTERVAL_NO_WAIT);
    99     } while (rv == NS_ERROR_STORAGE_BUSY);
   101     if (NS_SUCCEEDED(rv))
   102       mHasTransaction = false;
   104     return rv;
   105   }
   107   /**
   108    * Returns whether this object wraps a real transaction. False means that
   109    * this object doesn't do anything because there was already a transaction in
   110    * progress when it was created.
   111    */
   112   bool HasTransaction()
   113   {
   114     return mHasTransaction;
   115   }
   117   /**
   118    * This sets the default action (commit or rollback) when this object goes
   119    * out of scope.
   120    */
   121   void SetDefaultAction(bool aCommitOnComplete)
   122   {
   123     mCommitOnComplete = aCommitOnComplete;
   124   }
   126 protected:
   127   U mConnection;
   128   bool mHasTransaction;
   129   bool mCommitOnComplete;
   130   bool mCompleted;
   131 };
   133 /**
   134  * An instance of the mozStorageTransaction<> family dedicated
   135  * to |mozIStorageConnection|.
   136  */
   137 typedef mozStorageTransactionBase<mozIStorageConnection,
   138                                   nsCOMPtr<mozIStorageConnection> >
   139 mozStorageTransaction;
   143 /**
   144  * This class wraps a statement so that it is guaraneed to be reset when
   145  * this object goes out of scope.
   146  *
   147  * Note that this always just resets the statement. If the statement doesn't
   148  * need resetting, the reset operation is inexpensive.
   149  */
   150 class MOZ_STACK_CLASS mozStorageStatementScoper
   151 {
   152 public:
   153   mozStorageStatementScoper(mozIStorageStatement* aStatement)
   154       : mStatement(aStatement)
   155   {
   156   }
   157   ~mozStorageStatementScoper()
   158   {
   159     if (mStatement)
   160       mStatement->Reset();
   161   }
   163   /**
   164    * Call this to make the statement not reset. You might do this if you know
   165    * that the statement has been reset.
   166    */
   167   void Abandon()
   168   {
   169     mStatement = nullptr;
   170   }
   172 protected:
   173   nsCOMPtr<mozIStorageStatement> mStatement;
   174 };
   176 // Use this to make queries uniquely identifiable in telemetry
   177 // statistics, especially PRAGMAs.  We don't include __LINE__ so that
   178 // queries are stable in the face of source code changes.
   179 #define MOZ_STORAGE_UNIQUIFY_QUERY_STR "/* " __FILE__ " */ "
   181 #endif /* MOZSTORAGEHELPER_H */

mercurial