storage/src/mozStorageConnection.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: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
     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 #ifndef mozilla_storage_Connection_h
     8 #define mozilla_storage_Connection_h
    10 #include "nsAutoPtr.h"
    11 #include "nsCOMPtr.h"
    12 #include "mozilla/Mutex.h"
    13 #include "nsProxyRelease.h"
    14 #include "nsThreadUtils.h"
    15 #include "nsIInterfaceRequestor.h"
    17 #include "nsDataHashtable.h"
    18 #include "mozIStorageProgressHandler.h"
    19 #include "SQLiteMutex.h"
    20 #include "mozIStorageConnection.h"
    21 #include "mozStorageService.h"
    22 #include "mozIStorageAsyncConnection.h"
    23 #include "mozIStorageCompletionCallback.h"
    25 #include "nsIMutableArray.h"
    26 #include "mozilla/Attributes.h"
    28 #include "sqlite3.h"
    30 struct PRLock;
    31 class nsIFile;
    32 class nsIFileURL;
    33 class nsIEventTarget;
    34 class nsIThread;
    36 namespace mozilla {
    37 namespace storage {
    39 class Connection MOZ_FINAL : public mozIStorageConnection
    40                            , public nsIInterfaceRequestor
    41 {
    42 public:
    43   NS_DECL_THREADSAFE_ISUPPORTS
    44   NS_DECL_MOZISTORAGEASYNCCONNECTION
    45   NS_DECL_MOZISTORAGECONNECTION
    46   NS_DECL_NSIINTERFACEREQUESTOR
    48   /**
    49    * Structure used to describe user functions on the database connection.
    50    */
    51   struct FunctionInfo {
    52     enum FunctionType {
    53       SIMPLE,
    54       AGGREGATE
    55     };
    57     nsCOMPtr<nsISupports> function;
    58     FunctionType type;
    59     int32_t numArgs;
    60   };
    62   /**
    63    * @param aService
    64    *        Pointer to the storage service.  Held onto for the lifetime of the
    65    *        connection.
    66    * @param aFlags
    67    *        The flags to pass to sqlite3_open_v2.
    68    * @param aAsyncOnly
    69    *        If |true|, the Connection only implements asynchronous interface:
    70    *        - |mozIStorageAsyncConnection|;
    71    *        If |false|, the result also implements synchronous interface:
    72    *        - |mozIStorageConnection|.
    73    */
    74   Connection(Service *aService, int aFlags, bool aAsyncOnly);
    76   /**
    77    * Creates the connection to an in-memory database.
    78    */
    79   nsresult initialize();
    81   /**
    82    * Creates the connection to the database.
    83    *
    84    * @param aDatabaseFile
    85    *        The nsIFile of the location of the database to open, or create if it
    86    *        does not exist.
    87    */
    88   nsresult initialize(nsIFile *aDatabaseFile);
    90   /**
    91    * Creates the connection to the database.
    92    *
    93    * @param aFileURL
    94    *        The nsIFileURL of the location of the database to open, or create if it
    95    *        does not exist.
    96    */
    97   nsresult initialize(nsIFileURL *aFileURL);
    99   /**
   100    * Fetches runtime status information for this connection.
   101    *
   102    * @param aStatusOption One of the SQLITE_DBSTATUS options defined at
   103    *        http://www.sqlite.org/c3ref/c_dbstatus_options.html
   104    * @param [optional] aMaxValue if provided, will be set to the highest
   105    *        istantaneous value.
   106    * @return the current value for the specified option.
   107    */
   108   int32_t getSqliteRuntimeStatus(int32_t aStatusOption,
   109                                  int32_t* aMaxValue=nullptr);
   110   /**
   111    * Registers/unregisters a commit hook callback.
   112    *
   113    * @param aCallbackFn a callback function to be invoked on transactions
   114    *        commit.  Pass nullptr to unregister the current callback.
   115    * @param [optional] aData if provided, will be passed to the callback.
   116    * @see http://sqlite.org/c3ref/commit_hook.html
   117    */
   118   void setCommitHook(int (*aCallbackFn)(void *) , void *aData=nullptr) {
   119     MOZ_ASSERT(mDBConn, "A connection must exist at this point");
   120     ::sqlite3_commit_hook(mDBConn, aCallbackFn, aData);
   121   };
   123   /**
   124    * Lazily creates and returns a background execution thread.  In the future,
   125    * the thread may be re-claimed if left idle, so you should call this
   126    * method just before you dispatch and not save the reference.
   127    *
   128    * @returns an event target suitable for asynchronous statement execution.
   129    */
   130   nsIEventTarget *getAsyncExecutionTarget();
   132   /**
   133    * Mutex used by asynchronous statements to protect state.  The mutex is
   134    * declared on the connection object because there is no contention between
   135    * asynchronous statements (they are serialized on mAsyncExecutionThread).
   136    * Currently protects:
   137    *  - Connection.mAsyncExecutionThreadShuttingDown
   138    *  - Connection.mAsyncExecutionThread
   139    *  - Connection.mConnectionClosed
   140    *  - AsyncExecuteStatements.mCancelRequested
   141    */
   142   Mutex sharedAsyncExecutionMutex;
   144   /**
   145    * Wraps the mutex that SQLite gives us from sqlite3_db_mutex.  This is public
   146    * because we already expose the sqlite3* native connection and proper
   147    * operation of the deadlock detector requires everyone to use the same single
   148    * SQLiteMutex instance for correctness.
   149    */
   150   SQLiteMutex sharedDBMutex;
   152   /**
   153    * References the thread this database was opened on.  This MUST be thread it is
   154    * closed on.
   155    */
   156   const nsCOMPtr<nsIThread> threadOpenedOn;
   158   /**
   159    * Closes the SQLite database, and warns about any non-finalized statements.
   160    */
   161   nsresult internalClose(sqlite3 *aDBConn);
   163   /**
   164    * Obtains the filename of the connection.  Useful for logging.
   165    */
   166   nsCString getFilename();
   168   /**
   169    * Creates an sqlite3 prepared statement object from an SQL string.
   170    *
   171    * @param aNativeConnection
   172    *        The underlying Sqlite connection to prepare the statement with.
   173    * @param aSQL
   174    *        The SQL statement string to compile.
   175    * @param _stmt
   176    *        New sqlite3_stmt object.
   177    * @return the result from sqlite3_prepare_v2.
   178    */
   179   int prepareStatement(sqlite3* aNativeConnection,
   180                        const nsCString &aSQL, sqlite3_stmt **_stmt);
   182   /**
   183    * Performs a sqlite3_step on aStatement, while properly handling SQLITE_LOCKED
   184    * when not on the main thread by waiting until we are notified.
   185    *
   186    * @param aNativeConnection
   187    *        The underlying Sqlite connection to step the statement with.
   188    * @param aStatement
   189    *        A pointer to a sqlite3_stmt object.
   190    * @return the result from sqlite3_step.
   191    */
   192   int stepStatement(sqlite3* aNativeConnection, sqlite3_stmt* aStatement);
   194   /**
   195    * Raw connection transaction management.
   196    *
   197    * @see BeginTransactionAs, CommitTransaction, RollbackTransaction.
   198    */
   199   nsresult beginTransactionInternal(sqlite3 *aNativeConnection,
   200                                     int32_t aTransactionType=TRANSACTION_DEFERRED);
   201   nsresult commitTransactionInternal(sqlite3 *aNativeConnection);
   202   nsresult rollbackTransactionInternal(sqlite3 *aNativeConnection);
   204   bool connectionReady();
   206   /**
   207    * True if this connection is shutting down but not yet closed.
   208    */
   209   bool isClosing();
   211   /**
   212    * True if the underlying connection is closed.
   213    * Any sqlite resources may be lost when this returns true, so nothing should
   214    * try to use them.
   215    */
   216   bool isClosed();
   218   nsresult initializeClone(Connection *aClone, bool aReadOnly);
   220 private:
   221   ~Connection();
   222   nsresult initializeInternal(nsIFile *aDatabaseFile);
   224   /**
   225    * Sets the database into a closed state so no further actions can be
   226    * performed.
   227    *
   228    * @note mDBConn is set to nullptr in this method.
   229    */
   230   nsresult setClosedState();
   232   /**
   233    * Helper for calls to sqlite3_exec. Reports long delays to Telemetry.
   234    *
   235    * @param aNativeConnection
   236    *        The underlying Sqlite connection to execute the query with.
   237    * @param aSqlString
   238    *        SQL string to execute
   239    * @return the result from sqlite3_exec.
   240    */
   241   int executeSql(sqlite3 *aNativeConnection, const char *aSqlString);
   243   /**
   244    * Describes a certain primitive type in the database.
   245    *
   246    * Possible Values Are:
   247    *  INDEX - To check for the existence of an index
   248    *  TABLE - To check for the existence of a table
   249    */
   250   enum DatabaseElementType {
   251     INDEX,
   252     TABLE
   253   };
   255   /**
   256    * Determines if the specified primitive exists.
   257    *
   258    * @param aElementType
   259    *        The type of element to check the existence of
   260    * @param aElementName
   261    *        The name of the element to check for
   262    * @returns true if element exists, false otherwise
   263    */
   264   nsresult databaseElementExists(enum DatabaseElementType aElementType,
   265                                  const nsACString& aElementName,
   266                                  bool *_exists);
   268   bool findFunctionByInstance(nsISupports *aInstance);
   270   static int sProgressHelper(void *aArg);
   271   // Generic progress handler
   272   // Dispatch call to registered progress handler,
   273   // if there is one. Do nothing in other cases.
   274   int progressHandler();
   276   sqlite3 *mDBConn;
   277   nsCOMPtr<nsIFileURL> mFileURL;
   278   nsCOMPtr<nsIFile> mDatabaseFile;
   280   /**
   281    * Lazily created thread for asynchronous statement execution.  Consumers
   282    * should use getAsyncExecutionTarget rather than directly accessing this
   283    * field.
   284    */
   285   nsCOMPtr<nsIThread> mAsyncExecutionThread;
   287   /**
   288    * Set to true by Close() or AsyncClose() prior to shutdown.
   289    *
   290    * If false, we guarantee both that the underlying sqlite3 database
   291    * connection is still open and that getAsyncExecutionTarget() can
   292    * return a thread. Once true, either the sqlite3 database
   293    * connection is being shutdown or it has been
   294    * shutdown. Additionally, once true, getAsyncExecutionTarget()
   295    * returns null.
   296    *
   297    * This variable should be accessed while holding the
   298    * sharedAsyncExecutionMutex.
   299    */
   300   bool mAsyncExecutionThreadShuttingDown;
   302   /**
   303    * Set to true just prior to calling sqlite3_close on the
   304    * connection.
   305    *
   306    * This variable should be accessed while holding the
   307    * sharedAsyncExecutionMutex.
   308    */
   309   bool mConnectionClosed;
   311   /**
   312    * Tracks if we have a transaction in progress or not.  Access protected by
   313    * sharedDBMutex.
   314    */
   315   bool mTransactionInProgress;
   317   /**
   318    * Stores the mapping of a given function by name to its instance.  Access is
   319    * protected by sharedDBMutex.
   320    */
   321   nsDataHashtable<nsCStringHashKey, FunctionInfo> mFunctions;
   323   /**
   324    * Stores the registered progress handler for the database connection.  Access
   325    * is protected by sharedDBMutex.
   326    */
   327   nsCOMPtr<mozIStorageProgressHandler> mProgressHandler;
   329   /**
   330    * Stores the flags we passed to sqlite3_open_v2.
   331    */
   332   const int mFlags;
   334   // This is here for two reasons: 1) It's used to make sure that the
   335   // connections do not outlive the service.  2) Our custom collating functions
   336   // call its localeCompareStrings() method.
   337   nsRefPtr<Service> mStorageService;
   339   /**
   340    * If |false|, this instance supports synchronous operations
   341    * and it can be cast to |mozIStorageConnection|.
   342    */
   343   const bool mAsyncOnly;
   344 };
   347 /**
   348  * A Runnable designed to call a mozIStorageCompletionCallback on
   349  * the appropriate thread.
   350  */
   351 class CallbackComplete MOZ_FINAL : public nsRunnable
   352 {
   353 public:
   354   /**
   355    * @param aValue The result to pass to the callback. It must
   356    *               already be owned by the main thread.
   357    * @param aCallback The callback. It must already be owned by the
   358    *                  main thread.
   359    */
   360   CallbackComplete(nsresult aStatus,
   361                    nsISupports* aValue,
   362                    already_AddRefed<mozIStorageCompletionCallback> aCallback)
   363     : mStatus(aStatus)
   364     , mValue(aValue)
   365     , mCallback(aCallback)
   366   {
   367   }
   369   NS_IMETHOD Run() {
   370     MOZ_ASSERT(NS_IsMainThread());
   371     nsresult rv = mCallback->Complete(mStatus, mValue);
   373     // Ensure that we release on the main thread
   374     mValue = nullptr;
   375     mCallback = nullptr;
   376     return rv;
   377   }
   379 private:
   380   nsresult mStatus;
   381   nsCOMPtr<nsISupports> mValue;
   382   // This is a nsRefPtr<T> and not a nsCOMPtr<T> because
   383   // nsCOMP<T> would cause an off-main thread QI, which
   384   // is not a good idea (and crashes XPConnect).
   385   nsRefPtr<mozIStorageCompletionCallback> mCallback;
   386 };
   388 } // namespace storage
   389 } // namespace mozilla
   391 #endif // mozilla_storage_Connection_h

mercurial