storage/src/mozStorageBindingParams.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
michael@0 2 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
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 #include <limits.h>
michael@0 8
michael@0 9 #include "nsString.h"
michael@0 10
michael@0 11 #include "mozStorageError.h"
michael@0 12 #include "mozStoragePrivateHelpers.h"
michael@0 13 #include "mozStorageBindingParams.h"
michael@0 14 #include "mozStorageBindingParamsArray.h"
michael@0 15 #include "Variant.h"
michael@0 16
michael@0 17 namespace mozilla {
michael@0 18 namespace storage {
michael@0 19
michael@0 20 ////////////////////////////////////////////////////////////////////////////////
michael@0 21 //// Local Helper Objects
michael@0 22
michael@0 23 namespace {
michael@0 24
michael@0 25 struct BindingColumnData
michael@0 26 {
michael@0 27 BindingColumnData(sqlite3_stmt *aStmt,
michael@0 28 int aColumn)
michael@0 29 : stmt(aStmt)
michael@0 30 , column(aColumn)
michael@0 31 {
michael@0 32 }
michael@0 33 sqlite3_stmt *stmt;
michael@0 34 int column;
michael@0 35 };
michael@0 36
michael@0 37 ////////////////////////////////////////////////////////////////////////////////
michael@0 38 //// Variant Specialization Functions (variantToSQLiteT)
michael@0 39
michael@0 40 int
michael@0 41 sqlite3_T_int(BindingColumnData aData,
michael@0 42 int aValue)
michael@0 43 {
michael@0 44 return ::sqlite3_bind_int(aData.stmt, aData.column + 1, aValue);
michael@0 45 }
michael@0 46
michael@0 47 int
michael@0 48 sqlite3_T_int64(BindingColumnData aData,
michael@0 49 sqlite3_int64 aValue)
michael@0 50 {
michael@0 51 return ::sqlite3_bind_int64(aData.stmt, aData.column + 1, aValue);
michael@0 52 }
michael@0 53
michael@0 54 int
michael@0 55 sqlite3_T_double(BindingColumnData aData,
michael@0 56 double aValue)
michael@0 57 {
michael@0 58 return ::sqlite3_bind_double(aData.stmt, aData.column + 1, aValue);
michael@0 59 }
michael@0 60
michael@0 61 int
michael@0 62 sqlite3_T_text(BindingColumnData aData,
michael@0 63 const nsCString& aValue)
michael@0 64 {
michael@0 65 return ::sqlite3_bind_text(aData.stmt,
michael@0 66 aData.column + 1,
michael@0 67 aValue.get(),
michael@0 68 aValue.Length(),
michael@0 69 SQLITE_TRANSIENT);
michael@0 70 }
michael@0 71
michael@0 72 int
michael@0 73 sqlite3_T_text16(BindingColumnData aData,
michael@0 74 const nsString& aValue)
michael@0 75 {
michael@0 76 return ::sqlite3_bind_text16(aData.stmt,
michael@0 77 aData.column + 1,
michael@0 78 aValue.get(),
michael@0 79 aValue.Length() * 2, // Length in bytes!
michael@0 80 SQLITE_TRANSIENT);
michael@0 81 }
michael@0 82
michael@0 83 int
michael@0 84 sqlite3_T_null(BindingColumnData aData)
michael@0 85 {
michael@0 86 return ::sqlite3_bind_null(aData.stmt, aData.column + 1);
michael@0 87 }
michael@0 88
michael@0 89 int
michael@0 90 sqlite3_T_blob(BindingColumnData aData,
michael@0 91 const void *aBlob,
michael@0 92 int aSize)
michael@0 93 {
michael@0 94 return ::sqlite3_bind_blob(aData.stmt, aData.column + 1, aBlob, aSize,
michael@0 95 NS_Free);
michael@0 96
michael@0 97 }
michael@0 98
michael@0 99 #include "variantToSQLiteT_impl.h"
michael@0 100
michael@0 101 } // anonymous namespace
michael@0 102
michael@0 103 ////////////////////////////////////////////////////////////////////////////////
michael@0 104 //// BindingParams
michael@0 105
michael@0 106 BindingParams::BindingParams(mozIStorageBindingParamsArray *aOwningArray,
michael@0 107 Statement *aOwningStatement)
michael@0 108 : mLocked(false)
michael@0 109 , mOwningArray(aOwningArray)
michael@0 110 , mOwningStatement(aOwningStatement)
michael@0 111 {
michael@0 112 (void)mOwningStatement->GetParameterCount(&mParamCount);
michael@0 113 (void)mParameters.SetCapacity(mParamCount);
michael@0 114 }
michael@0 115
michael@0 116 BindingParams::BindingParams(mozIStorageBindingParamsArray *aOwningArray)
michael@0 117 : mLocked(false)
michael@0 118 , mOwningArray(aOwningArray)
michael@0 119 , mOwningStatement(nullptr)
michael@0 120 , mParamCount(0)
michael@0 121 {
michael@0 122 }
michael@0 123
michael@0 124 AsyncBindingParams::AsyncBindingParams(
michael@0 125 mozIStorageBindingParamsArray *aOwningArray
michael@0 126 )
michael@0 127 : BindingParams(aOwningArray)
michael@0 128 {
michael@0 129 }
michael@0 130
michael@0 131 void
michael@0 132 BindingParams::lock()
michael@0 133 {
michael@0 134 NS_ASSERTION(mLocked == false, "Parameters have already been locked!");
michael@0 135 mLocked = true;
michael@0 136
michael@0 137 // We no longer need to hold a reference to our statement or our owning array.
michael@0 138 // The array owns us at this point, and it will own a reference to the
michael@0 139 // statement.
michael@0 140 mOwningStatement = nullptr;
michael@0 141 mOwningArray = nullptr;
michael@0 142 }
michael@0 143
michael@0 144 void
michael@0 145 BindingParams::unlock(Statement *aOwningStatement)
michael@0 146 {
michael@0 147 NS_ASSERTION(mLocked == true, "Parameters were not yet locked!");
michael@0 148 mLocked = false;
michael@0 149 mOwningStatement = aOwningStatement;
michael@0 150 }
michael@0 151
michael@0 152 const mozIStorageBindingParamsArray *
michael@0 153 BindingParams::getOwner() const
michael@0 154 {
michael@0 155 return mOwningArray;
michael@0 156 }
michael@0 157
michael@0 158 PLDHashOperator
michael@0 159 AsyncBindingParams::iterateOverNamedParameters(const nsACString &aName,
michael@0 160 nsIVariant *aValue,
michael@0 161 void *voidClosureThunk)
michael@0 162 {
michael@0 163 NamedParameterIterationClosureThunk *closureThunk =
michael@0 164 static_cast<NamedParameterIterationClosureThunk *>(voidClosureThunk);
michael@0 165
michael@0 166 // We do not accept any forms of names other than ":name", but we need to add
michael@0 167 // the colon for SQLite.
michael@0 168 nsAutoCString name(":");
michael@0 169 name.Append(aName);
michael@0 170 int oneIdx = ::sqlite3_bind_parameter_index(closureThunk->statement,
michael@0 171 name.get());
michael@0 172
michael@0 173 if (oneIdx == 0) {
michael@0 174 nsAutoCString errMsg(aName);
michael@0 175 errMsg.Append(NS_LITERAL_CSTRING(" is not a valid named parameter."));
michael@0 176 closureThunk->err = new Error(SQLITE_RANGE, errMsg.get());
michael@0 177 return PL_DHASH_STOP;
michael@0 178 }
michael@0 179
michael@0 180 // XPCVariant's AddRef and Release are not thread-safe and so we must not do
michael@0 181 // anything that would invoke them here on the async thread. As such we can't
michael@0 182 // cram aValue into self->mParameters using ReplaceObjectAt so that we can
michael@0 183 // freeload off of the BindingParams::Bind implementation.
michael@0 184 int rc = variantToSQLiteT(BindingColumnData(closureThunk->statement,
michael@0 185 oneIdx - 1),
michael@0 186 aValue);
michael@0 187 if (rc != SQLITE_OK) {
michael@0 188 // We had an error while trying to bind. Now we need to create an error
michael@0 189 // object with the right message. Note that we special case
michael@0 190 // SQLITE_MISMATCH, but otherwise get the message from SQLite.
michael@0 191 const char *msg = "Could not covert nsIVariant to SQLite type.";
michael@0 192 if (rc != SQLITE_MISMATCH)
michael@0 193 msg = ::sqlite3_errmsg(::sqlite3_db_handle(closureThunk->statement));
michael@0 194
michael@0 195 closureThunk->err = new Error(rc, msg);
michael@0 196 return PL_DHASH_STOP;
michael@0 197 }
michael@0 198 return PL_DHASH_NEXT;
michael@0 199 }
michael@0 200
michael@0 201 ////////////////////////////////////////////////////////////////////////////////
michael@0 202 //// nsISupports
michael@0 203
michael@0 204 NS_IMPL_ISUPPORTS(
michael@0 205 BindingParams
michael@0 206 , mozIStorageBindingParams
michael@0 207 , IStorageBindingParamsInternal
michael@0 208 )
michael@0 209
michael@0 210
michael@0 211 ////////////////////////////////////////////////////////////////////////////////
michael@0 212 //// IStorageBindingParamsInternal
michael@0 213
michael@0 214 already_AddRefed<mozIStorageError>
michael@0 215 BindingParams::bind(sqlite3_stmt *aStatement)
michael@0 216 {
michael@0 217 // Iterate through all of our stored data, and bind it.
michael@0 218 for (int32_t i = 0; i < mParameters.Count(); i++) {
michael@0 219 int rc = variantToSQLiteT(BindingColumnData(aStatement, i), mParameters[i]);
michael@0 220 if (rc != SQLITE_OK) {
michael@0 221 // We had an error while trying to bind. Now we need to create an error
michael@0 222 // object with the right message. Note that we special case
michael@0 223 // SQLITE_MISMATCH, but otherwise get the message from SQLite.
michael@0 224 const char *msg = "Could not covert nsIVariant to SQLite type.";
michael@0 225 if (rc != SQLITE_MISMATCH)
michael@0 226 msg = ::sqlite3_errmsg(::sqlite3_db_handle(aStatement));
michael@0 227
michael@0 228 nsCOMPtr<mozIStorageError> err(new Error(rc, msg));
michael@0 229 return err.forget();
michael@0 230 }
michael@0 231 }
michael@0 232
michael@0 233 return nullptr;
michael@0 234 }
michael@0 235
michael@0 236 already_AddRefed<mozIStorageError>
michael@0 237 AsyncBindingParams::bind(sqlite3_stmt * aStatement)
michael@0 238 {
michael@0 239 // We should bind by index using the super-class if there is nothing in our
michael@0 240 // hashtable.
michael@0 241 if (!mNamedParameters.Count())
michael@0 242 return BindingParams::bind(aStatement);
michael@0 243
michael@0 244 // Enumerate over everyone in the map, propagating them into mParameters if
michael@0 245 // we can and creating an error immediately when we cannot.
michael@0 246 NamedParameterIterationClosureThunk closureThunk = {this, aStatement, nullptr};
michael@0 247 (void)mNamedParameters.EnumerateRead(iterateOverNamedParameters,
michael@0 248 (void *)&closureThunk);
michael@0 249
michael@0 250 return closureThunk.err.forget();
michael@0 251 }
michael@0 252
michael@0 253
michael@0 254 ///////////////////////////////////////////////////////////////////////////////
michael@0 255 //// mozIStorageBindingParams
michael@0 256
michael@0 257 NS_IMETHODIMP
michael@0 258 BindingParams::BindByName(const nsACString &aName,
michael@0 259 nsIVariant *aValue)
michael@0 260 {
michael@0 261 NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
michael@0 262
michael@0 263 // Get the column index that we need to store this at.
michael@0 264 uint32_t index;
michael@0 265 nsresult rv = mOwningStatement->GetParameterIndex(aName, &index);
michael@0 266 NS_ENSURE_SUCCESS(rv, rv);
michael@0 267
michael@0 268 return BindByIndex(index, aValue);
michael@0 269 }
michael@0 270
michael@0 271 NS_IMETHODIMP
michael@0 272 AsyncBindingParams::BindByName(const nsACString &aName,
michael@0 273 nsIVariant *aValue)
michael@0 274 {
michael@0 275 NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
michael@0 276
michael@0 277 mNamedParameters.Put(aName, aValue);
michael@0 278 return NS_OK;
michael@0 279 }
michael@0 280
michael@0 281
michael@0 282 NS_IMETHODIMP
michael@0 283 BindingParams::BindUTF8StringByName(const nsACString &aName,
michael@0 284 const nsACString &aValue)
michael@0 285 {
michael@0 286 nsCOMPtr<nsIVariant> value(new UTF8TextVariant(aValue));
michael@0 287 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
michael@0 288
michael@0 289 return BindByName(aName, value);
michael@0 290 }
michael@0 291
michael@0 292 NS_IMETHODIMP
michael@0 293 BindingParams::BindStringByName(const nsACString &aName,
michael@0 294 const nsAString &aValue)
michael@0 295 {
michael@0 296 nsCOMPtr<nsIVariant> value(new TextVariant(aValue));
michael@0 297 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
michael@0 298
michael@0 299 return BindByName(aName, value);
michael@0 300 }
michael@0 301
michael@0 302 NS_IMETHODIMP
michael@0 303 BindingParams::BindDoubleByName(const nsACString &aName,
michael@0 304 double aValue)
michael@0 305 {
michael@0 306 nsCOMPtr<nsIVariant> value(new FloatVariant(aValue));
michael@0 307 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
michael@0 308
michael@0 309 return BindByName(aName, value);
michael@0 310 }
michael@0 311
michael@0 312 NS_IMETHODIMP
michael@0 313 BindingParams::BindInt32ByName(const nsACString &aName,
michael@0 314 int32_t aValue)
michael@0 315 {
michael@0 316 nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
michael@0 317 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
michael@0 318
michael@0 319 return BindByName(aName, value);
michael@0 320 }
michael@0 321
michael@0 322 NS_IMETHODIMP
michael@0 323 BindingParams::BindInt64ByName(const nsACString &aName,
michael@0 324 int64_t aValue)
michael@0 325 {
michael@0 326 nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
michael@0 327 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
michael@0 328
michael@0 329 return BindByName(aName, value);
michael@0 330 }
michael@0 331
michael@0 332 NS_IMETHODIMP
michael@0 333 BindingParams::BindNullByName(const nsACString &aName)
michael@0 334 {
michael@0 335 nsCOMPtr<nsIVariant> value(new NullVariant());
michael@0 336 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
michael@0 337
michael@0 338 return BindByName(aName, value);
michael@0 339 }
michael@0 340
michael@0 341 NS_IMETHODIMP
michael@0 342 BindingParams::BindBlobByName(const nsACString &aName,
michael@0 343 const uint8_t *aValue,
michael@0 344 uint32_t aValueSize)
michael@0 345 {
michael@0 346 NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
michael@0 347 std::pair<const void *, int> data(
michael@0 348 static_cast<const void *>(aValue),
michael@0 349 int(aValueSize)
michael@0 350 );
michael@0 351 nsCOMPtr<nsIVariant> value(new BlobVariant(data));
michael@0 352 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
michael@0 353
michael@0 354 return BindByName(aName, value);
michael@0 355 }
michael@0 356
michael@0 357
michael@0 358 NS_IMETHODIMP
michael@0 359 BindingParams::BindAdoptedBlobByName(const nsACString &aName,
michael@0 360 uint8_t *aValue,
michael@0 361 uint32_t aValueSize)
michael@0 362 {
michael@0 363 NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
michael@0 364 std::pair<uint8_t *, int> data(
michael@0 365 aValue,
michael@0 366 int(aValueSize)
michael@0 367 );
michael@0 368 nsCOMPtr<nsIVariant> value(new AdoptedBlobVariant(data));
michael@0 369
michael@0 370 return BindByName(aName, value);
michael@0 371 }
michael@0 372
michael@0 373 NS_IMETHODIMP
michael@0 374 BindingParams::BindByIndex(uint32_t aIndex,
michael@0 375 nsIVariant *aValue)
michael@0 376 {
michael@0 377 NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
michael@0 378 ENSURE_INDEX_VALUE(aIndex, mParamCount);
michael@0 379
michael@0 380 // Store the variant for later use.
michael@0 381 NS_ENSURE_TRUE(mParameters.ReplaceObjectAt(aValue, aIndex),
michael@0 382 NS_ERROR_OUT_OF_MEMORY);
michael@0 383 return NS_OK;
michael@0 384 }
michael@0 385
michael@0 386 NS_IMETHODIMP
michael@0 387 AsyncBindingParams::BindByIndex(uint32_t aIndex,
michael@0 388 nsIVariant *aValue)
michael@0 389 {
michael@0 390 NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
michael@0 391 // In the asynchronous case we do not know how many parameters there are to
michael@0 392 // bind to, so we cannot check the validity of aIndex.
michael@0 393
michael@0 394 // Store the variant for later use.
michael@0 395 NS_ENSURE_TRUE(mParameters.ReplaceObjectAt(aValue, aIndex),
michael@0 396 NS_ERROR_OUT_OF_MEMORY);
michael@0 397 return NS_OK;
michael@0 398 }
michael@0 399
michael@0 400 NS_IMETHODIMP
michael@0 401 BindingParams::BindUTF8StringByIndex(uint32_t aIndex,
michael@0 402 const nsACString &aValue)
michael@0 403 {
michael@0 404 nsCOMPtr<nsIVariant> value(new UTF8TextVariant(aValue));
michael@0 405 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
michael@0 406
michael@0 407 return BindByIndex(aIndex, value);
michael@0 408 }
michael@0 409
michael@0 410 NS_IMETHODIMP
michael@0 411 BindingParams::BindStringByIndex(uint32_t aIndex,
michael@0 412 const nsAString &aValue)
michael@0 413 {
michael@0 414 nsCOMPtr<nsIVariant> value(new TextVariant(aValue));
michael@0 415 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
michael@0 416
michael@0 417 return BindByIndex(aIndex, value);
michael@0 418 }
michael@0 419
michael@0 420 NS_IMETHODIMP
michael@0 421 BindingParams::BindDoubleByIndex(uint32_t aIndex,
michael@0 422 double aValue)
michael@0 423 {
michael@0 424 nsCOMPtr<nsIVariant> value(new FloatVariant(aValue));
michael@0 425 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
michael@0 426
michael@0 427 return BindByIndex(aIndex, value);
michael@0 428 }
michael@0 429
michael@0 430 NS_IMETHODIMP
michael@0 431 BindingParams::BindInt32ByIndex(uint32_t aIndex,
michael@0 432 int32_t aValue)
michael@0 433 {
michael@0 434 nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
michael@0 435 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
michael@0 436
michael@0 437 return BindByIndex(aIndex, value);
michael@0 438 }
michael@0 439
michael@0 440 NS_IMETHODIMP
michael@0 441 BindingParams::BindInt64ByIndex(uint32_t aIndex,
michael@0 442 int64_t aValue)
michael@0 443 {
michael@0 444 nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
michael@0 445 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
michael@0 446
michael@0 447 return BindByIndex(aIndex, value);
michael@0 448 }
michael@0 449
michael@0 450 NS_IMETHODIMP
michael@0 451 BindingParams::BindNullByIndex(uint32_t aIndex)
michael@0 452 {
michael@0 453 nsCOMPtr<nsIVariant> value(new NullVariant());
michael@0 454 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
michael@0 455
michael@0 456 return BindByIndex(aIndex, value);
michael@0 457 }
michael@0 458
michael@0 459 NS_IMETHODIMP
michael@0 460 BindingParams::BindBlobByIndex(uint32_t aIndex,
michael@0 461 const uint8_t *aValue,
michael@0 462 uint32_t aValueSize)
michael@0 463 {
michael@0 464 NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
michael@0 465 std::pair<const void *, int> data(
michael@0 466 static_cast<const void *>(aValue),
michael@0 467 int(aValueSize)
michael@0 468 );
michael@0 469 nsCOMPtr<nsIVariant> value(new BlobVariant(data));
michael@0 470 NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
michael@0 471
michael@0 472 return BindByIndex(aIndex, value);
michael@0 473 }
michael@0 474
michael@0 475 NS_IMETHODIMP
michael@0 476 BindingParams::BindAdoptedBlobByIndex(uint32_t aIndex,
michael@0 477 uint8_t *aValue,
michael@0 478 uint32_t aValueSize)
michael@0 479 {
michael@0 480 NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
michael@0 481 std::pair<uint8_t *, int> data(
michael@0 482 static_cast<uint8_t *>(aValue),
michael@0 483 int(aValueSize)
michael@0 484 );
michael@0 485 nsCOMPtr<nsIVariant> value(new AdoptedBlobVariant(data));
michael@0 486
michael@0 487 return BindByIndex(aIndex, value);
michael@0 488 }
michael@0 489
michael@0 490 } // namespace storage
michael@0 491 } // namespace mozilla

mercurial