tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

mozStorageBindingParams.cpp (18714B)


      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/. */
      6 
      7 #include <limits.h>
      8 
      9 #include "mozilla/UniquePtrExtensions.h"
     10 #include "nsString.h"
     11 
     12 #include "mozStorageError.h"
     13 #include "mozStoragePrivateHelpers.h"
     14 #include "mozStorageBindingParams.h"
     15 #include "Variant.h"
     16 #include "sqlite3_static_ext.h"
     17 
     18 namespace mozilla::storage {
     19 
     20 ////////////////////////////////////////////////////////////////////////////////
     21 //// Local Helper Objects
     22 
     23 namespace {
     24 
     25 struct BindingColumnData {
     26  BindingColumnData(sqlite3_stmt* aStmt, int aColumn)
     27      : stmt(aStmt), column(aColumn) {}
     28  sqlite3_stmt* stmt;
     29  int column;
     30 };
     31 
     32 ////////////////////////////////////////////////////////////////////////////////
     33 //// Variant Specialization Functions (variantToSQLiteT)
     34 
     35 int sqlite3_T_int(BindingColumnData aData, int aValue) {
     36  return ::sqlite3_bind_int(aData.stmt, aData.column + 1, aValue);
     37 }
     38 
     39 int sqlite3_T_int64(BindingColumnData aData, sqlite3_int64 aValue) {
     40  return ::sqlite3_bind_int64(aData.stmt, aData.column + 1, aValue);
     41 }
     42 
     43 int sqlite3_T_double(BindingColumnData aData, double aValue) {
     44  return ::sqlite3_bind_double(aData.stmt, aData.column + 1, aValue);
     45 }
     46 
     47 int sqlite3_T_text(BindingColumnData aData, const nsCString& aValue) {
     48  return ::sqlite3_bind_text(aData.stmt, aData.column + 1, aValue.get(),
     49                             aValue.Length(), SQLITE_TRANSIENT);
     50 }
     51 
     52 int sqlite3_T_text16(BindingColumnData aData, const nsString& aValue) {
     53  return ::sqlite3_bind_text16(
     54      aData.stmt, aData.column + 1, aValue.get(),
     55      aValue.Length() * sizeof(char16_t),  // Length in bytes!
     56      SQLITE_TRANSIENT);
     57 }
     58 
     59 int sqlite3_T_null(BindingColumnData aData) {
     60  return ::sqlite3_bind_null(aData.stmt, aData.column + 1);
     61 }
     62 
     63 int sqlite3_T_blob(BindingColumnData aData, const void* aBlob, int aSize) {
     64  return ::sqlite3_bind_blob(aData.stmt, aData.column + 1, aBlob, aSize, free);
     65 }
     66 
     67 int sqlite3_T_array(BindingColumnData aData, void* aArray, int aSize,
     68                    int aType) {
     69  // In debug builds ensure that the statement includes at least one `carray()`.
     70  MOZ_ASSERT(
     71      ::strstr(::sqlite3_sql(aData.stmt), "carray("),
     72      "Binding arrays to SQL statements requires using the carray() function.");
     73 
     74  if (aType == CARRAY_TEXT) {
     75    // We don't manage the string buffers lifecycle, thus let SQLite make its
     76    // own copy.
     77    int srv = ::sqlite3_carray_bind(aData.stmt, aData.column + 1, aArray, aSize,
     78                                    aType, SQLITE_TRANSIENT);
     79    free(aArray);
     80    return srv;
     81  }
     82  return ::sqlite3_carray_bind(aData.stmt, aData.column + 1, aArray, aSize,
     83                               aType, free);
     84 }
     85 
     86 #include "variantToSQLiteT_impl.h"
     87 
     88 }  // namespace
     89 
     90 ////////////////////////////////////////////////////////////////////////////////
     91 //// BindingParams
     92 
     93 BindingParams::BindingParams(mozIStorageBindingParamsArray* aOwningArray,
     94                             Statement* aOwningStatement)
     95    : mLocked(false),
     96      mOwningArray(aOwningArray),
     97      mOwningStatement(aOwningStatement),
     98      mParamCount(0) {
     99  (void)mOwningStatement->GetParameterCount(&mParamCount);
    100  mParameters.SetCapacity(mParamCount);
    101 }
    102 
    103 BindingParams::BindingParams(mozIStorageBindingParamsArray* aOwningArray)
    104    : mLocked(false),
    105      mOwningArray(aOwningArray),
    106      mOwningStatement(nullptr),
    107      mParamCount(0) {}
    108 
    109 AsyncBindingParams::AsyncBindingParams(
    110    mozIStorageBindingParamsArray* aOwningArray)
    111    : BindingParams(aOwningArray) {}
    112 
    113 void BindingParams::lock() {
    114  NS_ASSERTION(mLocked == false, "Parameters have already been locked!");
    115  mLocked = true;
    116 
    117  // We no longer need to hold a reference to our statement or our owning array.
    118  // The array owns us at this point, and it will own a reference to the
    119  // statement.
    120  mOwningStatement = nullptr;
    121  mOwningArray = nullptr;
    122 }
    123 
    124 void BindingParams::unlock(Statement* aOwningStatement) {
    125  NS_ASSERTION(mLocked == true, "Parameters were not yet locked!");
    126  mLocked = false;
    127  mOwningStatement = aOwningStatement;
    128 }
    129 
    130 const mozIStorageBindingParamsArray* BindingParams::getOwner() const {
    131  return mOwningArray;
    132 }
    133 
    134 ////////////////////////////////////////////////////////////////////////////////
    135 //// nsISupports
    136 
    137 NS_IMPL_ISUPPORTS(BindingParams, mozIStorageBindingParams,
    138                  IStorageBindingParamsInternal)
    139 
    140 ////////////////////////////////////////////////////////////////////////////////
    141 //// IStorageBindingParamsInternal
    142 
    143 already_AddRefed<mozIStorageError> BindingParams::bind(
    144    sqlite3_stmt* aStatement) {
    145  // Iterate through all of our stored data, and bind it.
    146  for (size_t i = 0; i < mParameters.Length(); i++) {
    147    int rc = variantToSQLiteT(BindingColumnData(aStatement, i), mParameters[i]);
    148    if (rc != SQLITE_OK) {
    149      // We had an error while trying to bind.  Now we need to create an error
    150      // object with the right message.  Note that we special case
    151      // SQLITE_MISMATCH, but otherwise get the message from SQLite.
    152      const char* msg = "Could not covert nsIVariant to SQLite type.";
    153      if (rc != SQLITE_MISMATCH) {
    154        msg = ::sqlite3_errmsg(::sqlite3_db_handle(aStatement));
    155      }
    156 
    157      nsCOMPtr<mozIStorageError> err(new Error(rc, msg));
    158      return err.forget();
    159    }
    160  }
    161 
    162  return nullptr;
    163 }
    164 
    165 already_AddRefed<mozIStorageError> AsyncBindingParams::bind(
    166    sqlite3_stmt* aStatement) {
    167  nsCOMPtr<mozIStorageError> err;
    168 
    169  for (const auto& entry : mNamedParameters) {
    170    const nsACString& key = entry.GetKey();
    171 
    172    // We do not accept any forms of names other than ":name", but we need to
    173    // add the colon for SQLite.
    174    nsAutoCString name(":");
    175    name.Append(key);
    176    int oneIdx = ::sqlite3_bind_parameter_index(aStatement, name.get());
    177 
    178    if (oneIdx == 0) {
    179      nsAutoCString errMsg(key);
    180      errMsg.AppendLiteral(" is not a valid named parameter.");
    181      err = new Error(SQLITE_RANGE, errMsg.get());
    182      return err.forget();
    183    }
    184 
    185    if (mParameters.Length() <= static_cast<uint32_t>(oneIdx - 1)) {
    186      mParameters.SetLength(oneIdx - 1);
    187      mParameters.AppendElement(entry.GetWeak());
    188    } else {
    189      mParameters.ReplaceElementAt(oneIdx - 1, entry.GetWeak());
    190    }
    191  }
    192 
    193  // Now bind using the super class.
    194  return BindingParams::bind(aStatement);
    195 }
    196 
    197 ///////////////////////////////////////////////////////////////////////////////
    198 //// mozIStorageBindingParams
    199 
    200 NS_IMETHODIMP
    201 BindingParams::BindByName(const nsACString& aName, nsIVariant* aValue) {
    202  NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
    203 
    204  // Get the column index that we need to store this at.
    205  uint32_t index;
    206  nsresult rv = mOwningStatement->GetParameterIndex(aName, &index);
    207  NS_ENSURE_SUCCESS(rv, rv);
    208 
    209  return BindByIndex(index, aValue);
    210 }
    211 
    212 NS_IMETHODIMP
    213 AsyncBindingParams::BindByName(const nsACString& aName, nsIVariant* aValue) {
    214  NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
    215 
    216  RefPtr<Variant_base> variant = convertVariantToStorageVariant(aValue);
    217  if (!variant) return NS_ERROR_UNEXPECTED;
    218  mNamedParameters.InsertOrUpdate(aName, std::move(variant));
    219  return NS_OK;
    220 }
    221 
    222 NS_IMETHODIMP
    223 BindingParams::BindUTF8StringByName(const nsACString& aName,
    224                                    const nsACString& aValue) {
    225  nsCOMPtr<nsIVariant> value(new UTF8TextVariant(aValue));
    226  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    227 
    228  return BindByName(aName, value);
    229 }
    230 
    231 NS_IMETHODIMP
    232 BindingParams::BindStringByName(const nsACString& aName,
    233                                const nsAString& aValue) {
    234  nsCOMPtr<nsIVariant> value(new TextVariant(aValue));
    235  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    236 
    237  return BindByName(aName, value);
    238 }
    239 
    240 NS_IMETHODIMP
    241 BindingParams::BindDoubleByName(const nsACString& aName, double aValue) {
    242  nsCOMPtr<nsIVariant> value(new FloatVariant(aValue));
    243  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    244 
    245  return BindByName(aName, value);
    246 }
    247 
    248 NS_IMETHODIMP
    249 BindingParams::BindInt32ByName(const nsACString& aName, int32_t aValue) {
    250  nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
    251  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    252 
    253  return BindByName(aName, value);
    254 }
    255 
    256 NS_IMETHODIMP
    257 BindingParams::BindInt64ByName(const nsACString& aName, int64_t aValue) {
    258  nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
    259  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    260 
    261  return BindByName(aName, value);
    262 }
    263 
    264 NS_IMETHODIMP
    265 BindingParams::BindNullByName(const nsACString& aName) {
    266  nsCOMPtr<nsIVariant> value(new NullVariant());
    267  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    268 
    269  return BindByName(aName, value);
    270 }
    271 
    272 NS_IMETHODIMP
    273 BindingParams::BindBlobByName(const nsACString& aName, const uint8_t* aValue,
    274                              uint32_t aValueSize) {
    275  NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
    276  std::pair<const void*, int> data(static_cast<const void*>(aValue),
    277                                   int(aValueSize));
    278  nsCOMPtr<nsIVariant> value(new BlobVariant(data));
    279  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    280 
    281  return BindByName(aName, value);
    282 }
    283 
    284 NS_IMETHODIMP
    285 BindingParams::BindBlobArrayByName(const nsACString& aName,
    286                                   const nsTArray<uint8_t>& aValue) {
    287  return BindBlobByName(aName, aValue.Elements(), aValue.Length());
    288 }
    289 
    290 NS_IMETHODIMP
    291 BindingParams::BindStringAsBlobByName(const nsACString& aName,
    292                                      const nsAString& aValue) {
    293  return DoBindStringAsBlobByName(this, aName, aValue);
    294 }
    295 
    296 NS_IMETHODIMP
    297 BindingParams::BindUTF8StringAsBlobByName(const nsACString& aName,
    298                                          const nsACString& aValue) {
    299  return DoBindStringAsBlobByName(this, aName, aValue);
    300 }
    301 
    302 NS_IMETHODIMP
    303 BindingParams::BindAdoptedBlobByName(const nsACString& aName, uint8_t* aValue,
    304                                     uint32_t aValueSize) {
    305  UniqueFreePtr<uint8_t> uniqueValue(aValue);
    306  NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
    307  std::pair<uint8_t*, int> data(uniqueValue.release(), int(aValueSize));
    308  nsCOMPtr<nsIVariant> value(new AdoptedBlobVariant(data));
    309 
    310  return BindByName(aName, value);
    311 }
    312 
    313 NS_IMETHODIMP
    314 BindingParams::BindArrayOfIntegersByName(const nsACString& aName,
    315                                         const nsTArray<int64_t>& aValue) {
    316  NS_ENSURE_ARG_MAX(aValue.Length(), INT_MAX);
    317  std::pair<const void*, int> data(static_cast<const void*>(aValue.Elements()),
    318                                   int(aValue.Length()));
    319  nsCOMPtr<nsIVariant> value(new ArrayOfIntegersVariant(data));
    320  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    321 
    322  return BindByName(aName, value);
    323 }
    324 
    325 NS_IMETHODIMP
    326 BindingParams::BindArrayOfDoublesByName(const nsACString& aName,
    327                                        const nsTArray<double>& aValue) {
    328  NS_ENSURE_ARG_MAX(aValue.Length(), INT_MAX);
    329  std::pair<const void*, int> data(static_cast<const void*>(aValue.Elements()),
    330                                   int(aValue.Length()));
    331  nsCOMPtr<nsIVariant> value(new ArrayOfDoublesVariant(data));
    332  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    333 
    334  return BindByName(aName, value);
    335 }
    336 
    337 NS_IMETHODIMP
    338 BindingParams::BindArrayOfStringsByName(const nsACString& aName,
    339                                        const nsTArray<nsString>& aValue) {
    340  NS_ENSURE_ARG_MAX(aValue.Length(), INT_MAX);
    341  nsTArray<nsCString> UTF8Strings(aValue.Length());
    342  for (const nsString& str : aValue) {
    343    UTF8Strings.AppendElement(NS_ConvertUTF16toUTF8(str));
    344  }
    345  std::pair<const void*, int> data(
    346      static_cast<const void*>(UTF8Strings.Elements()),
    347      int(UTF8Strings.Length()));
    348  // The variant will make a copy of all the buffers.
    349  nsCOMPtr<nsIVariant> value(new ArrayOfUTF8StringsVariant(data));
    350  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    351 
    352  return BindByName(aName, value);
    353 }
    354 
    355 NS_IMETHODIMP
    356 BindingParams::BindArrayOfUTF8StringsByName(const nsACString& aName,
    357                                            const nsTArray<nsCString>& aValue) {
    358  NS_ENSURE_ARG_MAX(aValue.Length(), INT_MAX);
    359  std::pair<const void*, int> data(static_cast<const void*>(aValue.Elements()),
    360                                   int(aValue.Length()));
    361  // The variant will make a copy of all the buffers.
    362  nsCOMPtr<nsIVariant> value(new ArrayOfUTF8StringsVariant(data));
    363  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    364 
    365  return BindByName(aName, value);
    366 }
    367 
    368 NS_IMETHODIMP
    369 BindingParams::BindByIndex(uint32_t aIndex, nsIVariant* aValue) {
    370  NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
    371  ENSURE_INDEX_VALUE(aIndex, mParamCount);
    372 
    373  // Store the variant for later use.
    374  RefPtr<Variant_base> variant = convertVariantToStorageVariant(aValue);
    375  if (!variant) return NS_ERROR_UNEXPECTED;
    376  if (mParameters.Length() <= aIndex) {
    377    (void)mParameters.SetLength(aIndex);
    378    (void)mParameters.AppendElement(variant);
    379  } else {
    380    mParameters.ReplaceElementAt(aIndex, variant);
    381  }
    382  return NS_OK;
    383 }
    384 
    385 NS_IMETHODIMP
    386 AsyncBindingParams::BindByIndex(uint32_t aIndex, nsIVariant* aValue) {
    387  NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
    388  // In the asynchronous case we do not know how many parameters there are to
    389  // bind to, so we cannot check the validity of aIndex.
    390 
    391  RefPtr<Variant_base> variant = convertVariantToStorageVariant(aValue);
    392  if (!variant) return NS_ERROR_UNEXPECTED;
    393  if (mParameters.Length() <= aIndex) {
    394    mParameters.SetLength(aIndex);
    395    mParameters.AppendElement(variant);
    396  } else {
    397    mParameters.ReplaceElementAt(aIndex, variant);
    398  }
    399  return NS_OK;
    400 }
    401 
    402 NS_IMETHODIMP
    403 BindingParams::BindUTF8StringByIndex(uint32_t aIndex,
    404                                     const nsACString& aValue) {
    405  nsCOMPtr<nsIVariant> value(new UTF8TextVariant(aValue));
    406  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    407 
    408  return BindByIndex(aIndex, value);
    409 }
    410 
    411 NS_IMETHODIMP
    412 BindingParams::BindStringByIndex(uint32_t aIndex, const nsAString& aValue) {
    413  nsCOMPtr<nsIVariant> value(new TextVariant(aValue));
    414  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    415 
    416  return BindByIndex(aIndex, value);
    417 }
    418 
    419 NS_IMETHODIMP
    420 BindingParams::BindDoubleByIndex(uint32_t aIndex, double aValue) {
    421  nsCOMPtr<nsIVariant> value(new FloatVariant(aValue));
    422  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    423 
    424  return BindByIndex(aIndex, value);
    425 }
    426 
    427 NS_IMETHODIMP
    428 BindingParams::BindInt32ByIndex(uint32_t aIndex, int32_t aValue) {
    429  nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
    430  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    431 
    432  return BindByIndex(aIndex, value);
    433 }
    434 
    435 NS_IMETHODIMP
    436 BindingParams::BindInt64ByIndex(uint32_t aIndex, int64_t aValue) {
    437  nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
    438  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    439 
    440  return BindByIndex(aIndex, value);
    441 }
    442 
    443 NS_IMETHODIMP
    444 BindingParams::BindNullByIndex(uint32_t aIndex) {
    445  nsCOMPtr<nsIVariant> value(new NullVariant());
    446  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    447 
    448  return BindByIndex(aIndex, value);
    449 }
    450 
    451 NS_IMETHODIMP
    452 BindingParams::BindBlobByIndex(uint32_t aIndex, const uint8_t* aValue,
    453                               uint32_t aValueSize) {
    454  NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
    455  std::pair<const void*, int> data(static_cast<const void*>(aValue),
    456                                   int(aValueSize));
    457  nsCOMPtr<nsIVariant> value(new BlobVariant(data));
    458  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    459 
    460  return BindByIndex(aIndex, value);
    461 }
    462 
    463 NS_IMETHODIMP
    464 BindingParams::BindBlobArrayByIndex(uint32_t aIndex,
    465                                    const nsTArray<uint8_t>& aValue) {
    466  return BindBlobByIndex(aIndex, aValue.Elements(), aValue.Length());
    467 }
    468 
    469 NS_IMETHODIMP
    470 BindingParams::BindStringAsBlobByIndex(uint32_t aIndex,
    471                                       const nsAString& aValue) {
    472  return DoBindStringAsBlobByIndex(this, aIndex, aValue);
    473 }
    474 
    475 NS_IMETHODIMP
    476 BindingParams::BindUTF8StringAsBlobByIndex(uint32_t aIndex,
    477                                           const nsACString& aValue) {
    478  return DoBindStringAsBlobByIndex(this, aIndex, aValue);
    479 }
    480 
    481 NS_IMETHODIMP
    482 BindingParams::BindAdoptedBlobByIndex(uint32_t aIndex, uint8_t* aValue,
    483                                      uint32_t aValueSize) {
    484  UniqueFreePtr<uint8_t> uniqueValue(aValue);
    485  NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
    486  std::pair<uint8_t*, int> data(uniqueValue.release(), int(aValueSize));
    487  nsCOMPtr<nsIVariant> value(new AdoptedBlobVariant(data));
    488 
    489  return BindByIndex(aIndex, value);
    490 }
    491 
    492 NS_IMETHODIMP
    493 BindingParams::BindArrayOfIntegersByIndex(uint32_t aIndex,
    494                                          const nsTArray<int64_t>& aValue) {
    495  NS_ENSURE_ARG_MAX(aValue.Length(), INT_MAX);
    496  std::pair<const void*, int> data(static_cast<const void*>(aValue.Elements()),
    497                                   int(aValue.Length()));
    498  nsCOMPtr<nsIVariant> value(new ArrayOfIntegersVariant(data));
    499  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    500 
    501  return BindByIndex(aIndex, value);
    502 }
    503 
    504 NS_IMETHODIMP
    505 BindingParams::BindArrayOfDoublesByIndex(uint32_t aIndex,
    506                                         const nsTArray<double>& aValue) {
    507  NS_ENSURE_ARG_MAX(aValue.Length(), INT_MAX);
    508  std::pair<const void*, int> data(static_cast<const void*>(aValue.Elements()),
    509                                   int(aValue.Length()));
    510  nsCOMPtr<nsIVariant> value(new ArrayOfDoublesVariant(data));
    511  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    512 
    513  return BindByIndex(aIndex, value);
    514 }
    515 
    516 NS_IMETHODIMP
    517 BindingParams::BindArrayOfStringsByIndex(uint32_t aIndex,
    518                                         const nsTArray<nsString>& aValue) {
    519  NS_ENSURE_ARG_MAX(aValue.Length(), INT_MAX);
    520  nsTArray<nsCString> UTF8Strings(aValue.Length());
    521  for (const nsString& str : aValue) {
    522    UTF8Strings.AppendElement(NS_ConvertUTF16toUTF8(str).get());
    523  }
    524  std::pair<const void*, int> data(
    525      static_cast<const void*>(UTF8Strings.Elements()),
    526      int(UTF8Strings.Length()));
    527  // The variant will make a copy of all the buffers.
    528  nsCOMPtr<nsIVariant> value(new ArrayOfUTF8StringsVariant(data));
    529  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    530 
    531  return BindByIndex(aIndex, value);
    532 }
    533 
    534 NS_IMETHODIMP
    535 BindingParams::BindArrayOfUTF8StringsByIndex(
    536    uint32_t aIndex, const nsTArray<nsCString>& aValue) {
    537  NS_ENSURE_ARG_MAX(aValue.Length(), INT_MAX);
    538  std::pair<const void*, int> data(static_cast<const void*>(aValue.Elements()),
    539                                   int(aValue.Length()));
    540  // The variant will make a copy of all the buffers.
    541  nsCOMPtr<nsIVariant> value(new ArrayOfUTF8StringsVariant(data));
    542  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
    543 
    544  return BindByIndex(aIndex, value);
    545 }
    546 
    547 }  // namespace mozilla::storage