storage/src/StorageBaseStatementInternal.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.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
michael@0 2 * vim: sw=2 ts=2 sts=2 expandtab
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef mozilla_storage_StorageBaseStatementInternal_h_
michael@0 8 #define mozilla_storage_StorageBaseStatementInternal_h_
michael@0 9
michael@0 10 #include "nsISupports.h"
michael@0 11 #include "nsCOMPtr.h"
michael@0 12 #include "nsAutoPtr.h"
michael@0 13
michael@0 14 struct sqlite3;
michael@0 15 struct sqlite3_stmt;
michael@0 16 class mozIStorageError;
michael@0 17 class mozIStorageBindingParamsArray;
michael@0 18 class mozIStorageBindingParams;
michael@0 19 class mozIStorageStatementCallback;
michael@0 20 class mozIStoragePendingStatement;
michael@0 21
michael@0 22 namespace mozilla {
michael@0 23 namespace storage {
michael@0 24
michael@0 25 #define STORAGEBASESTATEMENTINTERNAL_IID \
michael@0 26 {0xd18856c9, 0xbf07, 0x4ae2, {0x94, 0x5b, 0x1a, 0xdd, 0x49, 0x19, 0x55, 0x2a}}
michael@0 27
michael@0 28 class Connection;
michael@0 29 class StatementData;
michael@0 30
michael@0 31 class AsyncStatementFinalizer;
michael@0 32
michael@0 33 /**
michael@0 34 * Implementation-only interface and shared logix mix-in corresponding to
michael@0 35 * mozIStorageBaseStatement. Both Statement and AsyncStatement inherit from
michael@0 36 * this. The interface aspect makes them look the same to implementation innards
michael@0 37 * that aren't publicly accessible. The mix-in avoids code duplication in
michael@0 38 * common implementations of mozIStorageBaseStatement, albeit with some minor
michael@0 39 * performance/space overhead because we have to use defines to officially
michael@0 40 * implement the methods on Statement/AsyncStatement (and proxy to this base
michael@0 41 * class.)
michael@0 42 */
michael@0 43 class StorageBaseStatementInternal : public nsISupports
michael@0 44 {
michael@0 45 public:
michael@0 46 NS_DECLARE_STATIC_IID_ACCESSOR(STORAGEBASESTATEMENTINTERNAL_IID)
michael@0 47
michael@0 48 /**
michael@0 49 * @return the connection that this statement belongs to.
michael@0 50 */
michael@0 51 Connection *getOwner()
michael@0 52 {
michael@0 53 return mDBConnection;
michael@0 54 }
michael@0 55
michael@0 56 /**
michael@0 57 * Return the asynchronous statement, creating it if required.
michael@0 58 *
michael@0 59 * This is for use by the asynchronous execution code for StatementData
michael@0 60 * created by AsyncStatements. Statement internally uses this method to
michael@0 61 * prepopulate StatementData with the sqlite3_stmt.
michael@0 62 *
michael@0 63 * @param[out] stmt
michael@0 64 * The sqlite3_stmt for asynchronous use.
michael@0 65 * @return The SQLite result code for creating the statement if created,
michael@0 66 * SQLITE_OK if creation was not required.
michael@0 67 */
michael@0 68 virtual int getAsyncStatement(sqlite3_stmt **_stmt) = 0;
michael@0 69
michael@0 70 /**
michael@0 71 * Obtains the StatementData needed for asynchronous execution.
michael@0 72 *
michael@0 73 * This is for use by Connection to retrieve StatementData from statements
michael@0 74 * when executeAsync is invoked.
michael@0 75 *
michael@0 76 * @param[out] _data
michael@0 77 * A reference to a StatementData object that will be populated
michael@0 78 * upon successful execution of this method.
michael@0 79 * @return NS_OK if we were able to assemble the data, failure otherwise.
michael@0 80 */
michael@0 81 virtual nsresult getAsynchronousStatementData(StatementData &_data) = 0;
michael@0 82
michael@0 83 /**
michael@0 84 * Construct a new BindingParams to be owned by the provided binding params
michael@0 85 * array. This method exists so that BindingParamsArray does not need
michael@0 86 * factory logic to determine what type of BindingParams to instantiate.
michael@0 87 *
michael@0 88 * @param aOwner
michael@0 89 * The binding params array to own the newly created binding params.
michael@0 90 * @return The new mozIStorageBindingParams instance appropriate to the
michael@0 91 * underlying statement type.
michael@0 92 */
michael@0 93 virtual already_AddRefed<mozIStorageBindingParams> newBindingParams(
michael@0 94 mozIStorageBindingParamsArray *aOwner
michael@0 95 ) = 0;
michael@0 96
michael@0 97 protected: // mix-in bits are protected
michael@0 98 StorageBaseStatementInternal();
michael@0 99
michael@0 100 nsRefPtr<Connection> mDBConnection;
michael@0 101 sqlite3 *mNativeConnection;
michael@0 102
michael@0 103 /**
michael@0 104 * Our asynchronous statement.
michael@0 105 *
michael@0 106 * For Statement this is populated by the first invocation to
michael@0 107 * getAsyncStatement.
michael@0 108 *
michael@0 109 * For AsyncStatement, this is null at creation time and initialized by the
michael@0 110 * async thread when it calls getAsyncStatement the first time the statement
michael@0 111 * is executed. (Or in the event of badly formed SQL, every time.)
michael@0 112 */
michael@0 113 sqlite3_stmt *mAsyncStatement;
michael@0 114
michael@0 115 /**
michael@0 116 * Initiate asynchronous finalization by dispatching an event to the
michael@0 117 * asynchronous thread to finalize mAsyncStatement. This acquires a reference
michael@0 118 * to this statement and proxies it back to the connection's owning thread
michael@0 119 * for release purposes.
michael@0 120 *
michael@0 121 * In the event the asynchronous thread is already gone or we otherwise fail
michael@0 122 * to dispatch an event to it we failover to invoking internalAsyncFinalize
michael@0 123 * directly. (That's what the asynchronous finalizer would have called.)
michael@0 124 *
michael@0 125 * @note You must not call this method from your destructor because its
michael@0 126 * operation assumes we are still alive. Call internalAsyncFinalize
michael@0 127 * directly in that case.
michael@0 128 */
michael@0 129 void asyncFinalize();
michael@0 130
michael@0 131 /**
michael@0 132 * Cleanup the async sqlite3_stmt stored in mAsyncStatement if it exists by
michael@0 133 * attempting to dispatch to the asynchronous thread if available, finalizing
michael@0 134 * on this thread if it is not.
michael@0 135 *
michael@0 136 * @note Call this from your destructor, call asyncFinalize otherwise.
michael@0 137 */
michael@0 138 void destructorAsyncFinalize();
michael@0 139
michael@0 140 NS_IMETHOD NewBindingParamsArray(mozIStorageBindingParamsArray **_array);
michael@0 141 NS_IMETHOD ExecuteAsync(mozIStorageStatementCallback *aCallback,
michael@0 142 mozIStoragePendingStatement **_stmt);
michael@0 143 NS_IMETHOD EscapeStringForLIKE(const nsAString &aValue,
michael@0 144 const char16_t aEscapeChar,
michael@0 145 nsAString &_escapedString);
michael@0 146
michael@0 147 // Needs access to internalAsyncFinalize
michael@0 148 friend class AsyncStatementFinalizer;
michael@0 149 };
michael@0 150
michael@0 151 NS_DEFINE_STATIC_IID_ACCESSOR(StorageBaseStatementInternal,
michael@0 152 STORAGEBASESTATEMENTINTERNAL_IID)
michael@0 153
michael@0 154 #define NS_DECL_STORAGEBASESTATEMENTINTERNAL \
michael@0 155 virtual Connection *getOwner(); \
michael@0 156 virtual int getAsyncStatement(sqlite3_stmt **_stmt); \
michael@0 157 virtual nsresult getAsynchronousStatementData(StatementData &_data); \
michael@0 158 virtual already_AddRefed<mozIStorageBindingParams> newBindingParams( \
michael@0 159 mozIStorageBindingParamsArray *aOwner);
michael@0 160
michael@0 161 /**
michael@0 162 * Helper macro to implement the proxying implementations. Because we are
michael@0 163 * implementing methods that are part of mozIStorageBaseStatement and the
michael@0 164 * implementation classes already use NS_DECL_MOZISTORAGEBASESTATEMENT we don't
michael@0 165 * need to provide declaration support.
michael@0 166 */
michael@0 167 #define MIX_IMPL(_class, _optionalGuard, _method, _declArgs, _invokeArgs) \
michael@0 168 NS_IMETHODIMP _class::_method _declArgs \
michael@0 169 { \
michael@0 170 _optionalGuard \
michael@0 171 return StorageBaseStatementInternal::_method _invokeArgs; \
michael@0 172 }
michael@0 173
michael@0 174
michael@0 175 /**
michael@0 176 * Define proxying implementation for the given _class. If a state invariant
michael@0 177 * needs to be checked and an early return possibly performed, pass the clause
michael@0 178 * to use as _optionalGuard.
michael@0 179 */
michael@0 180 #define MIXIN_IMPL_STORAGEBASESTATEMENTINTERNAL(_class, _optionalGuard) \
michael@0 181 MIX_IMPL(_class, _optionalGuard, \
michael@0 182 NewBindingParamsArray, \
michael@0 183 (mozIStorageBindingParamsArray **_array), \
michael@0 184 (_array)) \
michael@0 185 MIX_IMPL(_class, _optionalGuard, \
michael@0 186 ExecuteAsync, \
michael@0 187 (mozIStorageStatementCallback *aCallback, \
michael@0 188 mozIStoragePendingStatement **_stmt), \
michael@0 189 (aCallback, _stmt)) \
michael@0 190 MIX_IMPL(_class, _optionalGuard, \
michael@0 191 EscapeStringForLIKE, \
michael@0 192 (const nsAString &aValue, const char16_t aEscapeChar, \
michael@0 193 nsAString &_escapedString), \
michael@0 194 (aValue, aEscapeChar, _escapedString))
michael@0 195
michael@0 196 /**
michael@0 197 * Name-building helper for BIND_GEN_IMPL.
michael@0 198 */
michael@0 199 #define BIND_NAME_CONCAT(_nameBit, _concatBit) \
michael@0 200 Bind##_nameBit##_concatBit
michael@0 201
michael@0 202 /**
michael@0 203 * We have type-specific convenience methods for C++ implementations in
michael@0 204 * 3 different forms; 2 by index, 1 by name. The following macro allows
michael@0 205 * us to avoid having to define repetitive things by hand.
michael@0 206 *
michael@0 207 * Because of limitations of macros and our desire to avoid requiring special
michael@0 208 * permutations for the null and blob cases (whose argument count varies),
michael@0 209 * we require that the argument declarations and corresponding invocation
michael@0 210 * usages are passed in.
michael@0 211 *
michael@0 212 * @param _class
michael@0 213 * The class name.
michael@0 214 * @param _guard
michael@0 215 * The guard clause to inject.
michael@0 216 * @param _declName
michael@0 217 * The argument list (with parens) for the ByName variants.
michael@0 218 * @param _declIndex
michael@0 219 * The argument list (with parens) for the index variants.
michael@0 220 * @param _invArgs
michael@0 221 * The invocation argumment list.
michael@0 222 */
michael@0 223 #define BIND_GEN_IMPL(_class, _guard, _name, _declName, _declIndex, _invArgs) \
michael@0 224 NS_IMETHODIMP _class::BIND_NAME_CONCAT(_name, ByName) _declName \
michael@0 225 { \
michael@0 226 _guard \
michael@0 227 mozIStorageBindingParams *params = getParams(); \
michael@0 228 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \
michael@0 229 return params->BIND_NAME_CONCAT(_name, ByName) _invArgs; \
michael@0 230 } \
michael@0 231 NS_IMETHODIMP _class::BIND_NAME_CONCAT(_name, ByIndex) _declIndex \
michael@0 232 { \
michael@0 233 _guard \
michael@0 234 mozIStorageBindingParams *params = getParams(); \
michael@0 235 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \
michael@0 236 return params->BIND_NAME_CONCAT(_name, ByIndex) _invArgs; \
michael@0 237 } \
michael@0 238 NS_IMETHODIMP _class::BIND_NAME_CONCAT(_name, Parameter) _declIndex \
michael@0 239 { \
michael@0 240 _guard \
michael@0 241 mozIStorageBindingParams *params = getParams(); \
michael@0 242 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \
michael@0 243 return params->BIND_NAME_CONCAT(_name, ByIndex) _invArgs; \
michael@0 244 }
michael@0 245
michael@0 246 /**
michael@0 247 * Implement BindByName/BindByIndex for the given class.
michael@0 248 *
michael@0 249 * @param _class The class name.
michael@0 250 * @param _optionalGuard The guard clause to inject.
michael@0 251 */
michael@0 252 #define BIND_BASE_IMPLS(_class, _optionalGuard) \
michael@0 253 NS_IMETHODIMP _class::BindByName(const nsACString &aName, \
michael@0 254 nsIVariant *aValue) \
michael@0 255 { \
michael@0 256 _optionalGuard \
michael@0 257 mozIStorageBindingParams *params = getParams(); \
michael@0 258 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \
michael@0 259 return params->BindByName(aName, aValue); \
michael@0 260 } \
michael@0 261 NS_IMETHODIMP _class::BindByIndex(uint32_t aIndex, \
michael@0 262 nsIVariant *aValue) \
michael@0 263 { \
michael@0 264 _optionalGuard \
michael@0 265 mozIStorageBindingParams *params = getParams(); \
michael@0 266 NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY); \
michael@0 267 return params->BindByIndex(aIndex, aValue); \
michael@0 268 }
michael@0 269
michael@0 270 /**
michael@0 271 * Define the various Bind*Parameter, Bind*ByIndex, Bind*ByName stubs that just
michael@0 272 * end up proxying to the params object.
michael@0 273 */
michael@0 274 #define BOILERPLATE_BIND_PROXIES(_class, _optionalGuard) \
michael@0 275 BIND_BASE_IMPLS(_class, _optionalGuard) \
michael@0 276 BIND_GEN_IMPL(_class, _optionalGuard, \
michael@0 277 UTF8String, \
michael@0 278 (const nsACString &aWhere, \
michael@0 279 const nsACString &aValue), \
michael@0 280 (uint32_t aWhere, \
michael@0 281 const nsACString &aValue), \
michael@0 282 (aWhere, aValue)) \
michael@0 283 BIND_GEN_IMPL(_class, _optionalGuard, \
michael@0 284 String, \
michael@0 285 (const nsACString &aWhere, \
michael@0 286 const nsAString &aValue), \
michael@0 287 (uint32_t aWhere, \
michael@0 288 const nsAString &aValue), \
michael@0 289 (aWhere, aValue)) \
michael@0 290 BIND_GEN_IMPL(_class, _optionalGuard, \
michael@0 291 Double, \
michael@0 292 (const nsACString &aWhere, \
michael@0 293 double aValue), \
michael@0 294 (uint32_t aWhere, \
michael@0 295 double aValue), \
michael@0 296 (aWhere, aValue)) \
michael@0 297 BIND_GEN_IMPL(_class, _optionalGuard, \
michael@0 298 Int32, \
michael@0 299 (const nsACString &aWhere, \
michael@0 300 int32_t aValue), \
michael@0 301 (uint32_t aWhere, \
michael@0 302 int32_t aValue), \
michael@0 303 (aWhere, aValue)) \
michael@0 304 BIND_GEN_IMPL(_class, _optionalGuard, \
michael@0 305 Int64, \
michael@0 306 (const nsACString &aWhere, \
michael@0 307 int64_t aValue), \
michael@0 308 (uint32_t aWhere, \
michael@0 309 int64_t aValue), \
michael@0 310 (aWhere, aValue)) \
michael@0 311 BIND_GEN_IMPL(_class, _optionalGuard, \
michael@0 312 Null, \
michael@0 313 (const nsACString &aWhere), \
michael@0 314 (uint32_t aWhere), \
michael@0 315 (aWhere)) \
michael@0 316 BIND_GEN_IMPL(_class, _optionalGuard, \
michael@0 317 Blob, \
michael@0 318 (const nsACString &aWhere, \
michael@0 319 const uint8_t *aValue, \
michael@0 320 uint32_t aValueSize), \
michael@0 321 (uint32_t aWhere, \
michael@0 322 const uint8_t *aValue, \
michael@0 323 uint32_t aValueSize), \
michael@0 324 (aWhere, aValue, aValueSize)) \
michael@0 325 BIND_GEN_IMPL(_class, _optionalGuard, \
michael@0 326 AdoptedBlob, \
michael@0 327 (const nsACString &aWhere, \
michael@0 328 uint8_t *aValue, \
michael@0 329 uint32_t aValueSize), \
michael@0 330 (uint32_t aWhere, \
michael@0 331 uint8_t *aValue, \
michael@0 332 uint32_t aValueSize), \
michael@0 333 (aWhere, aValue, aValueSize))
michael@0 334
michael@0 335
michael@0 336
michael@0 337 } // storage
michael@0 338 } // mozilla
michael@0 339
michael@0 340 #endif // mozilla_storage_StorageBaseStatementInternal_h_

mercurial