Coverage Report

Created: 2018-09-25 14:53

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