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 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozStorage code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Mozilla Corporation.
20 : * Portions created by the Initial Developer are Copyright (C) 2008
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Shawn Wilsher <me@shawnwilsher.com> (Original Author)
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either the GNU General Public License Version 2 or later (the "GPL"), or
28 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "nsIXPConnect.h"
41 : #include "mozStorageStatement.h"
42 : #include "mozStorageService.h"
43 :
44 : #include "nsMemory.h"
45 : #include "nsString.h"
46 : #include "nsServiceManagerUtils.h"
47 :
48 : #include "mozStorageStatementJSHelper.h"
49 :
50 : #include "mozStorageStatementRow.h"
51 : #include "mozStorageStatementParams.h"
52 :
53 : #include "jsapi.h"
54 :
55 : namespace mozilla {
56 : namespace storage {
57 :
58 : ////////////////////////////////////////////////////////////////////////////////
59 : //// Global Functions
60 :
61 : static
62 : JSBool
63 37 : stepFunc(JSContext *aCtx,
64 : PRUint32,
65 : jsval *_vp)
66 : {
67 74 : nsCOMPtr<nsIXPConnect> xpc(Service::getXPConnect());
68 74 : nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
69 37 : JSObject *obj = JS_THIS_OBJECT(aCtx, _vp);
70 37 : if (!obj) {
71 0 : return JS_FALSE;
72 : }
73 :
74 : nsresult rv =
75 37 : xpc->GetWrappedNativeOfJSObject(aCtx, obj, getter_AddRefs(wrapper));
76 37 : if (NS_FAILED(rv)) {
77 0 : ::JS_ReportError(aCtx, "mozIStorageStatement::step() could not obtain native statement");
78 0 : return JS_FALSE;
79 : }
80 :
81 : #ifdef DEBUG
82 : {
83 : nsCOMPtr<mozIStorageStatement> isStatement(
84 37 : do_QueryInterface(wrapper->Native())
85 74 : );
86 37 : NS_ASSERTION(isStatement, "How is this not a statement?!");
87 : }
88 : #endif
89 :
90 : Statement *stmt = static_cast<Statement *>(
91 37 : static_cast<mozIStorageStatement *>(wrapper->Native())
92 37 : );
93 :
94 37 : bool hasMore = false;
95 37 : rv = stmt->ExecuteStep(&hasMore);
96 37 : if (NS_SUCCEEDED(rv) && !hasMore) {
97 0 : *_vp = JSVAL_FALSE;
98 0 : (void)stmt->Reset();
99 0 : return JS_TRUE;
100 : }
101 :
102 37 : if (NS_FAILED(rv)) {
103 0 : ::JS_ReportError(aCtx, "mozIStorageStatement::step() returned an error");
104 0 : return JS_FALSE;
105 : }
106 :
107 37 : *_vp = BOOLEAN_TO_JSVAL(hasMore);
108 37 : return JS_TRUE;
109 : }
110 :
111 : ////////////////////////////////////////////////////////////////////////////////
112 : //// StatementJSHelper
113 :
114 : nsresult
115 21494 : StatementJSHelper::getRow(Statement *aStatement,
116 : JSContext *aCtx,
117 : JSObject *aScopeObj,
118 : jsval *_row)
119 : {
120 : nsresult rv;
121 :
122 : #ifdef DEBUG
123 : PRInt32 state;
124 21494 : (void)aStatement->GetState(&state);
125 21494 : NS_ASSERTION(state == mozIStorageStatement::MOZ_STORAGE_STATEMENT_EXECUTING,
126 : "Invalid state to get the row object - all calls will fail!");
127 : #endif
128 :
129 21494 : if (!aStatement->mStatementRowHolder) {
130 5270 : nsCOMPtr<mozIStorageStatementRow> row(new StatementRow(aStatement));
131 2635 : NS_ENSURE_TRUE(row, NS_ERROR_OUT_OF_MEMORY);
132 :
133 5270 : nsCOMPtr<nsIXPConnect> xpc(Service::getXPConnect());
134 2635 : rv = xpc->WrapNative(
135 : aCtx,
136 : ::JS_GetGlobalForObject(aCtx, aScopeObj),
137 : row,
138 : NS_GET_IID(mozIStorageStatementRow),
139 2635 : getter_AddRefs(aStatement->mStatementRowHolder)
140 2635 : );
141 2635 : NS_ENSURE_SUCCESS(rv, rv);
142 : }
143 :
144 21494 : JSObject *obj = nsnull;
145 21494 : rv = aStatement->mStatementRowHolder->GetJSObject(&obj);
146 21494 : NS_ENSURE_SUCCESS(rv, rv);
147 :
148 21494 : *_row = OBJECT_TO_JSVAL(obj);
149 21494 : return NS_OK;
150 : }
151 :
152 : nsresult
153 73068 : StatementJSHelper::getParams(Statement *aStatement,
154 : JSContext *aCtx,
155 : JSObject *aScopeObj,
156 : jsval *_params)
157 : {
158 : nsresult rv;
159 :
160 : #ifdef DEBUG
161 : PRInt32 state;
162 73068 : (void)aStatement->GetState(&state);
163 73068 : NS_ASSERTION(state == mozIStorageStatement::MOZ_STORAGE_STATEMENT_READY,
164 : "Invalid state to get the params object - all calls will fail!");
165 : #endif
166 :
167 73068 : if (!aStatement->mStatementParamsHolder) {
168 : nsCOMPtr<mozIStorageStatementParams> params =
169 21440 : new StatementParams(aStatement);
170 10720 : NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY);
171 :
172 21440 : nsCOMPtr<nsIXPConnect> xpc(Service::getXPConnect());
173 10720 : rv = xpc->WrapNative(
174 : aCtx,
175 : ::JS_GetGlobalForObject(aCtx, aScopeObj),
176 : params,
177 : NS_GET_IID(mozIStorageStatementParams),
178 10720 : getter_AddRefs(aStatement->mStatementParamsHolder)
179 10720 : );
180 10720 : NS_ENSURE_SUCCESS(rv, rv);
181 : }
182 :
183 73068 : JSObject *obj = nsnull;
184 73068 : rv = aStatement->mStatementParamsHolder->GetJSObject(&obj);
185 73068 : NS_ENSURE_SUCCESS(rv, rv);
186 :
187 73068 : *_params = OBJECT_TO_JSVAL(obj);
188 73068 : return NS_OK;
189 : }
190 :
191 34728 : NS_IMETHODIMP_(nsrefcnt) StatementJSHelper::AddRef() { return 2; }
192 51662 : NS_IMETHODIMP_(nsrefcnt) StatementJSHelper::Release() { return 1; }
193 34298 : NS_INTERFACE_MAP_BEGIN(StatementJSHelper)
194 34298 : NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
195 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
196 0 : NS_INTERFACE_MAP_END
197 :
198 : ////////////////////////////////////////////////////////////////////////////////
199 : //// nsIXPCScriptable
200 :
201 : #define XPC_MAP_CLASSNAME StatementJSHelper
202 : #define XPC_MAP_QUOTED_CLASSNAME "StatementJSHelper"
203 : #define XPC_MAP_WANT_GETPROPERTY
204 : #define XPC_MAP_WANT_NEWRESOLVE
205 : #define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
206 : #include "xpc_map_end.h"
207 :
208 : NS_IMETHODIMP
209 94599 : StatementJSHelper::GetProperty(nsIXPConnectWrappedNative *aWrapper,
210 : JSContext *aCtx,
211 : JSObject *aScopeObj,
212 : jsid aId,
213 : jsval *_result,
214 : bool *_retval)
215 : {
216 94599 : if (!JSID_IS_STRING(aId))
217 0 : return NS_OK;
218 :
219 : #ifdef DEBUG
220 : {
221 : nsCOMPtr<mozIStorageStatement> isStatement(
222 189198 : do_QueryInterface(aWrapper->Native()));
223 94599 : NS_ASSERTION(isStatement, "How is this not a statement?!");
224 : }
225 : #endif
226 :
227 : Statement *stmt = static_cast<Statement *>(
228 94599 : static_cast<mozIStorageStatement *>(aWrapper->Native())
229 94599 : );
230 :
231 94599 : JSFlatString *str = JSID_TO_FLAT_STRING(aId);
232 94599 : if (::JS_FlatStringEqualsAscii(str, "row"))
233 21494 : return getRow(stmt, aCtx, aScopeObj, _result);
234 :
235 73105 : if (::JS_FlatStringEqualsAscii(str, "params"))
236 73068 : return getParams(stmt, aCtx, aScopeObj, _result);
237 :
238 37 : return NS_OK;
239 : }
240 :
241 :
242 : NS_IMETHODIMP
243 111053 : StatementJSHelper::NewResolve(nsIXPConnectWrappedNative *aWrapper,
244 : JSContext *aCtx,
245 : JSObject *aScopeObj,
246 : jsid aId,
247 : PRUint32 aFlags,
248 : JSObject **_objp,
249 : bool *_retval)
250 : {
251 111053 : if (!JSID_IS_STRING(aId))
252 0 : return NS_OK;
253 :
254 111053 : if (::JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(aId), "step")) {
255 : *_retval = ::JS_DefineFunction(aCtx, aScopeObj, "step", stepFunc,
256 37 : 0, 0) != nsnull;
257 37 : *_objp = aScopeObj;
258 37 : return NS_OK;
259 : }
260 111016 : return NS_OK;
261 : }
262 :
263 : } // namespace storage
264 : } // namespace mozilla
|