tor-browser

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

mozStorageStatementJSHelper.cpp (7876B)


      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 "nsIXPConnect.h"
      8 #include "mozStorageStatement.h"
      9 #include "mozStorageService.h"
     10 
     11 #include "nsString.h"
     12 #include "nsServiceManagerUtils.h"
     13 
     14 #include "mozStorageStatementJSHelper.h"
     15 
     16 #include "mozStorageStatementRow.h"
     17 #include "mozStorageStatementParams.h"
     18 
     19 #include "jsapi.h"
     20 #include "js/PropertyAndElement.h"  // JS_DefineFunction, JS_DefineProperty, JS_DefinePropertyById
     21 #include "js/Value.h"
     22 
     23 #include "xpc_make_class.h"
     24 
     25 namespace mozilla {
     26 namespace storage {
     27 
     28 ////////////////////////////////////////////////////////////////////////////////
     29 //// Global Functions
     30 
     31 static bool stepFunc(JSContext* aCtx, uint32_t argc, JS::Value* _vp) {
     32  JS::CallArgs args = CallArgsFromVp(argc, _vp);
     33 
     34  nsCOMPtr<nsIXPConnect> xpc(nsIXPConnect::XPConnect());
     35  nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
     36 
     37  if (!args.thisv().isObject()) {
     38    ::JS_ReportErrorASCII(aCtx, "mozIStorageStatement::step() requires object");
     39    return false;
     40  }
     41 
     42  JS::Rooted<JSObject*> obj(aCtx, &args.thisv().toObject());
     43  nsresult rv =
     44      xpc->GetWrappedNativeOfJSObject(aCtx, obj, getter_AddRefs(wrapper));
     45  if (NS_FAILED(rv)) {
     46    ::JS_ReportErrorASCII(
     47        aCtx, "mozIStorageStatement::step() could not obtain native statement");
     48    return false;
     49  }
     50 
     51 #ifdef DEBUG
     52  {
     53    nsCOMPtr<mozIStorageStatement> isStatement(
     54        do_QueryInterface(wrapper->Native()));
     55    NS_ASSERTION(isStatement, "How is this not a statement?!");
     56  }
     57 #endif
     58 
     59  Statement* stmt = static_cast<Statement*>(
     60      static_cast<mozIStorageStatement*>(wrapper->Native()));
     61 
     62  bool hasMore = false;
     63  rv = stmt->ExecuteStep(&hasMore);
     64  if (NS_SUCCEEDED(rv) && !hasMore) {
     65    args.rval().setBoolean(false);
     66    (void)stmt->Reset();
     67    return true;
     68  }
     69 
     70  if (NS_FAILED(rv)) {
     71    ::JS_ReportErrorASCII(aCtx,
     72                          "mozIStorageStatement::step() returned an error");
     73    return false;
     74  }
     75 
     76  args.rval().setBoolean(hasMore);
     77  return true;
     78 }
     79 
     80 ////////////////////////////////////////////////////////////////////////////////
     81 //// StatementJSHelper
     82 
     83 nsresult StatementJSHelper::getRow(Statement* aStatement, JSContext* aCtx,
     84                                   JSObject* aScopeObj, JS::Value* _row) {
     85  MOZ_ASSERT(NS_IsMainThread());
     86 
     87 #ifdef DEBUG
     88  int32_t state;
     89  (void)aStatement->GetState(&state);
     90  NS_ASSERTION(state == mozIStorageStatement::MOZ_STORAGE_STATEMENT_EXECUTING,
     91               "Invalid state to get the row object - all calls will fail!");
     92 #endif
     93 
     94  JS::Rooted<JSObject*> scope(aCtx, aScopeObj);
     95 
     96  if (!aStatement->mStatementRowHolder) {
     97    dom::GlobalObject global(aCtx, scope);
     98    if (global.Failed()) {
     99      return NS_ERROR_UNEXPECTED;
    100    }
    101 
    102    nsCOMPtr<nsPIDOMWindowInner> window =
    103        do_QueryInterface(global.GetAsSupports());
    104 
    105    RefPtr<StatementRow> row(new StatementRow(window, aStatement));
    106    NS_ENSURE_TRUE(row, NS_ERROR_OUT_OF_MEMORY);
    107 
    108    RefPtr<StatementRowHolder> rowHolder = new StatementRowHolder(row);
    109    NS_ENSURE_TRUE(rowHolder, NS_ERROR_OUT_OF_MEMORY);
    110 
    111    aStatement->mStatementRowHolder =
    112        new nsMainThreadPtrHolder<StatementRowHolder>(
    113            "Statement::mStatementRowHolder", rowHolder);
    114  }
    115 
    116  RefPtr<StatementRow> row(aStatement->mStatementRowHolder->Get());
    117  JSObject* obj = row->WrapObject(aCtx, nullptr);
    118  if (!obj) {
    119    return NS_ERROR_UNEXPECTED;
    120  }
    121 
    122  _row->setObject(*obj);
    123  return NS_OK;
    124 }
    125 
    126 nsresult StatementJSHelper::getParams(Statement* aStatement, JSContext* aCtx,
    127                                      JSObject* aScopeObj, JS::Value* _params) {
    128  MOZ_ASSERT(NS_IsMainThread());
    129 
    130 #ifdef DEBUG
    131  int32_t state;
    132  (void)aStatement->GetState(&state);
    133  NS_ASSERTION(state == mozIStorageStatement::MOZ_STORAGE_STATEMENT_READY,
    134               "Invalid state to get the params object - all calls will fail!");
    135 #endif
    136 
    137  JS::Rooted<JSObject*> scope(aCtx, aScopeObj);
    138 
    139  if (!aStatement->mStatementParamsHolder) {
    140    dom::GlobalObject global(aCtx, scope);
    141    if (global.Failed()) {
    142      return NS_ERROR_UNEXPECTED;
    143    }
    144 
    145    nsCOMPtr<nsPIDOMWindowInner> window =
    146        do_QueryInterface(global.GetAsSupports());
    147 
    148    RefPtr<StatementParams> params(new StatementParams(window, aStatement));
    149    NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY);
    150 
    151    RefPtr<StatementParamsHolder> paramsHolder =
    152        new StatementParamsHolder(params);
    153    NS_ENSURE_TRUE(paramsHolder, NS_ERROR_OUT_OF_MEMORY);
    154 
    155    aStatement->mStatementParamsHolder =
    156        new nsMainThreadPtrHolder<StatementParamsHolder>(
    157            "Statement::mStatementParamsHolder", paramsHolder);
    158  }
    159 
    160  RefPtr<StatementParams> params(aStatement->mStatementParamsHolder->Get());
    161  JSObject* obj = params->WrapObject(aCtx, nullptr);
    162  if (!obj) {
    163    return NS_ERROR_UNEXPECTED;
    164  }
    165 
    166  _params->setObject(*obj);
    167  return NS_OK;
    168 }
    169 
    170 NS_IMETHODIMP_(MozExternalRefCountType) StatementJSHelper::AddRef() {
    171  return 2;
    172 }
    173 NS_IMETHODIMP_(MozExternalRefCountType) StatementJSHelper::Release() {
    174  return 1;
    175 }
    176 NS_INTERFACE_MAP_BEGIN(StatementJSHelper)
    177  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
    178  NS_INTERFACE_MAP_ENTRY(nsISupports)
    179 NS_INTERFACE_MAP_END
    180 
    181 ////////////////////////////////////////////////////////////////////////////////
    182 //// nsIXPCScriptable
    183 
    184 #define XPC_MAP_CLASSNAME StatementJSHelper
    185 #define XPC_MAP_QUOTED_CLASSNAME "StatementJSHelper"
    186 #define XPC_MAP_FLAGS \
    187  (XPC_SCRIPTABLE_WANT_RESOLVE | XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE)
    188 #include "xpc_map_end.h"
    189 
    190 NS_IMETHODIMP
    191 StatementJSHelper::Resolve(nsIXPConnectWrappedNative* aWrapper, JSContext* aCtx,
    192                           JSObject* aScopeObj, jsid aId, bool* aResolvedp,
    193                           bool* _retval) {
    194  if (!aId.isString()) return NS_OK;
    195 
    196  JS::Rooted<JSObject*> scope(aCtx, aScopeObj);
    197  JS::Rooted<jsid> id(aCtx, aId);
    198 
    199 #ifdef DEBUG
    200  {
    201    nsCOMPtr<mozIStorageStatement> isStatement(
    202        do_QueryInterface(aWrapper->Native()));
    203    NS_ASSERTION(isStatement, "How is this not a statement?!");
    204  }
    205 #endif
    206 
    207  Statement* stmt = static_cast<Statement*>(
    208      static_cast<mozIStorageStatement*>(aWrapper->Native()));
    209 
    210  JSLinearString* str = id.toLinearString();
    211  if (::JS_LinearStringEqualsLiteral(str, "step")) {
    212    *_retval = ::JS_DefineFunction(aCtx, scope, "step", stepFunc, 0,
    213                                   JSPROP_RESOLVING) != nullptr;
    214    *aResolvedp = true;
    215    return NS_OK;
    216  }
    217 
    218  JS::Rooted<JS::Value> val(aCtx);
    219 
    220  if (::JS_LinearStringEqualsLiteral(str, "row")) {
    221    nsresult rv = getRow(stmt, aCtx, scope, val.address());
    222    NS_ENSURE_SUCCESS(rv, rv);
    223    *_retval = ::JS_DefinePropertyById(aCtx, scope, id, val, JSPROP_RESOLVING);
    224    *aResolvedp = true;
    225    return NS_OK;
    226  }
    227 
    228  if (::JS_LinearStringEqualsLiteral(str, "params")) {
    229    nsresult rv = getParams(stmt, aCtx, scope, val.address());
    230    NS_ENSURE_SUCCESS(rv, rv);
    231    *_retval = ::JS_DefinePropertyById(aCtx, scope, id, val, JSPROP_RESOLVING);
    232    *aResolvedp = true;
    233    return NS_OK;
    234  }
    235 
    236  return NS_OK;
    237 }
    238 
    239 NS_IMPL_ISUPPORTS0(StatementParamsHolder);
    240 
    241 StatementParamsHolder::~StatementParamsHolder() {
    242  MOZ_ASSERT(NS_IsMainThread());
    243  // We are considered dead at this point, so any wrappers for row or params
    244  // need to lose their reference to the statement.
    245  mParams->mStatement = nullptr;
    246 }
    247 
    248 NS_IMPL_ISUPPORTS0(StatementRowHolder);
    249 
    250 StatementRowHolder::~StatementRowHolder() {
    251  MOZ_ASSERT(NS_IsMainThread());
    252  // We are considered dead at this point, so any wrappers for row or params
    253  // need to lose their reference to the statement.
    254  mRow->mStatement = nullptr;
    255 }
    256 
    257 }  // namespace storage
    258 }  // namespace mozilla