transport: pass correct channel
[abstract.git] / transport / sqlite / src / aaSqliteChannel.cpp
blobbf73f9d9db7937bd37d0a061a41a0bf82a2fa604
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent tw=79 ft=cpp: */
3 /*
4 * Copyright (C) 2008 Sergey Yanovich <ynvich@gmail.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
22 #include "xpcom-config.h"
24 #include "nsCOMPtr.h"
25 #include "nsAutoPtr.h"
26 #include "nsServiceManagerUtils.h"
27 #include "nsStringAPI.h"
28 #include "nsNetCID.h"
29 #include "nsIStreamListener.h"
30 #include "nsIURL.h"
31 #include "nsIFileURL.h"
32 #include "nsINetUtil.h"
33 #include "nsComponentManagerUtils.h"
34 #include "nsNetUtil.h"
36 /* Unfrozen API */
37 #include "nsThreadUtils.h"
38 #include "nsIRunnable.h"
39 #include "nsIThread.h"
41 /* Project includes */
43 #include "aaSqliteChannel.h"
44 #include "aaSqlitePump.h"
46 aaSqliteChannel::aaSqliteChannel(nsIURI *aURI)
47 : mURI(aURI)
48 , mContentType("text/dbxml")
49 , mStarted(PR_FALSE)
50 , mHadStart(PR_FALSE)
51 , mLoadFlags(0)
52 , mStatus(NS_OK)
53 , mCancelled(PR_FALSE)
56 NS_IMPL_THREADSAFE_ISUPPORTS4(aaSqliteChannel,
57 nsIRequest,
58 nsIChannel,
59 nsIStreamListener,
60 nsIRequestObserver)
62 /* nsIRequest */
63 NS_IMETHODIMP
64 aaSqliteChannel::GetName(nsACString & aName)
66 return NS_ERROR_NOT_IMPLEMENTED;
69 NS_IMETHODIMP
70 aaSqliteChannel::IsPending(PRBool *_retval NS_OUTPARAM)
72 NS_ENSURE_ARG_POINTER(_retval);
73 *_retval = !!mObserver;
74 return NS_OK;
77 NS_IMETHODIMP
78 aaSqliteChannel::GetStatus(nsresult *aStatus)
80 NS_ENSURE_ARG_POINTER(aStatus);
81 *aStatus = mStatus;
82 return NS_OK;
85 NS_IMETHODIMP
86 aaSqliteChannel::Cancel(nsresult aStatus)
88 NS_ENSURE_STATE(mObserver);
89 if (NS_UNLIKELY(mCancelled)) return NS_ERROR_UNEXPECTED;
91 mStatus = aStatus;
92 mCancelled = PR_TRUE;
93 return NS_OK;
96 NS_IMETHODIMP
97 aaSqliteChannel::Suspend()
99 return NS_ERROR_NOT_IMPLEMENTED;
102 NS_IMETHODIMP
103 aaSqliteChannel::Resume()
105 return NS_ERROR_NOT_IMPLEMENTED;
108 NS_IMETHODIMP
109 aaSqliteChannel::GetLoadGroup(nsILoadGroup * *aLoadGroup)
111 NS_ENSURE_ARG_POINTER(aLoadGroup);
112 NS_IF_ADDREF(*aLoadGroup = mLoadGroup);
113 return NS_OK;
115 NS_IMETHODIMP
116 aaSqliteChannel::SetLoadGroup(nsILoadGroup * aLoadGroup)
118 mLoadGroup = aLoadGroup;
119 return NS_OK;
122 NS_IMETHODIMP
123 aaSqliteChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
125 NS_ENSURE_ARG_POINTER(aLoadFlags);
126 *aLoadFlags = mLoadFlags;
127 return NS_OK;
129 NS_IMETHODIMP
130 aaSqliteChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
132 mLoadFlags = aLoadFlags;
133 return NS_OK;
136 /* nsIChannel */
137 NS_IMETHODIMP
138 aaSqliteChannel::GetOriginalURI(nsIURI * *aOriginalURI)
140 NS_ENSURE_ARG_POINTER(aOriginalURI);
141 NS_IF_ADDREF(*aOriginalURI = mURI);
142 return NS_OK;
144 NS_IMETHODIMP
145 aaSqliteChannel::SetOriginalURI(nsIURI * aOriginalURI)
147 return NS_ERROR_NOT_IMPLEMENTED;
150 NS_IMETHODIMP
151 aaSqliteChannel::GetURI(nsIURI * *aURI)
153 NS_ENSURE_ARG_POINTER(aURI);
154 NS_IF_ADDREF(*aURI = mURI);
155 return NS_OK;
158 NS_IMETHODIMP
159 aaSqliteChannel::GetOwner(nsISupports * *aOwner)
161 NS_ENSURE_ARG_POINTER(aOwner);
162 NS_IF_ADDREF(*aOwner = mOwner);
163 return NS_OK;
165 NS_IMETHODIMP
166 aaSqliteChannel::SetOwner(nsISupports * aOwner)
168 mOwner = aOwner;
169 return NS_OK;
172 NS_IMETHODIMP
173 aaSqliteChannel::GetNotificationCallbacks(nsIInterfaceRequestor *
174 *aNotificationCallbacks)
176 NS_ENSURE_ARG_POINTER(aNotificationCallbacks);
177 NS_IF_ADDREF(*aNotificationCallbacks = mCallbacks);
178 return NS_OK;
180 NS_IMETHODIMP
181 aaSqliteChannel::SetNotificationCallbacks(nsIInterfaceRequestor *
182 aNotificationCallbacks)
184 mCallbacks = aNotificationCallbacks;
185 return NS_OK;
188 NS_IMETHODIMP
189 aaSqliteChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
191 return NS_ERROR_NOT_IMPLEMENTED;
194 NS_IMETHODIMP
195 aaSqliteChannel::GetContentType(nsACString & aContentType)
197 aContentType.Assign(mContentType);
198 return NS_OK;
200 NS_IMETHODIMP
201 aaSqliteChannel::SetContentType(const nsACString & aContentType)
203 nsresult rv = NS_OK;
204 if(NS_UNLIKELY(mStarted && !mHadStart))
205 return NS_ERROR_UNEXPECTED;
207 if (mHadStart)
209 nsCAutoString contentCharset;
210 rv = NS_ParseContentType(aContentType, mContentType, contentCharset);
211 NS_ENSURE_SUCCESS(rv, rv);
214 return NS_OK;
217 NS_IMETHODIMP
218 aaSqliteChannel::GetContentCharset(nsACString & aContentCharset)
220 return NS_ERROR_NOT_IMPLEMENTED;
222 NS_IMETHODIMP
223 aaSqliteChannel::SetContentCharset(const nsACString & aContentCharset)
225 return NS_ERROR_NOT_IMPLEMENTED;
228 NS_IMETHODIMP
229 aaSqliteChannel::GetContentLength(PRInt32 *aContentLength)
231 NS_ENSURE_ARG_POINTER(aContentLength);
232 *aContentLength = -1;
233 return NS_OK;
235 NS_IMETHODIMP
236 aaSqliteChannel::SetContentLength(PRInt32 aContentLength)
238 return NS_OK;
241 NS_IMETHODIMP
242 aaSqliteChannel::Open(nsIInputStream **_retval NS_OUTPARAM)
244 return NS_ERROR_NOT_IMPLEMENTED;
247 NS_IMETHODIMP
248 aaSqliteChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
250 NS_ENSURE_ARG_POINTER(aListener);
251 NS_ENSURE_STATE(mURI);
252 nsresult rv;
254 if (NS_UNLIKELY(mStarted)) return NS_ERROR_ALREADY_OPENED;
256 nsCOMPtr<nsIEventTarget> worker =
257 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
258 NS_ENSURE_SUCCESS(rv, rv);
260 mObserver = aListener;
262 nsCOMPtr<nsIURL> url = do_QueryInterface(mURI, &rv);
263 NS_ENSURE_SUCCESS(rv, rv);
265 nsCAutoString query;
266 rv = url->GetQuery(query);
267 NS_ENSURE_SUCCESS(rv, rv);
269 NS_ENSURE_TRUE(StringBeginsWith(query, NS_LITERAL_CSTRING("sql=")),
270 NS_ERROR_INVALID_ARG);
271 const nsACString& sqlQuery = Substring(query, 4);
273 nsCOMPtr<nsINetUtil> netUtil = do_CreateInstance(NS_NETUTIL_CONTRACTID, &rv);
274 NS_ENSURE_SUCCESS(rv, rv);
276 nsCAutoString sql;
277 rv = netUtil->UnescapeString(sqlQuery, nsINetUtil::ESCAPE_XALPHAS, sql);
278 NS_ENSURE_SUCCESS(rv, rv);
280 nsCOMPtr<nsIFile> db;
281 PRBool schemeIsSqlite = PR_FALSE;
282 rv = mURI->SchemeIs("sqlite", &schemeIsSqlite);
283 NS_ENSURE_SUCCESS(rv, rv);
284 if (schemeIsSqlite)
286 nsCOMPtr<nsIURL> url = do_QueryInterface(mURI, &rv);
287 NS_ENSURE_SUCCESS(rv, rv);
289 nsCAutoString filePath;
290 rv = url->GetFilePath(filePath);
291 NS_ENSURE_SUCCESS(rv, rv);
293 nsCOMPtr<nsILocalFile> localFile =
294 do_CreateInstance("@mozilla.org/file/local;1", &rv);
295 NS_ENSURE_SUCCESS(rv, rv);
297 rv = localFile->InitWithNativePath(filePath);
298 NS_ENSURE_SUCCESS(rv, rv);
300 db = do_QueryInterface(localFile, &rv);
301 NS_ENSURE_SUCCESS(rv, rv);
303 else
305 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(mURI, &rv);
306 NS_ENSURE_SUCCESS(rv, rv);
308 rv = fileURL->GetFile(getter_AddRefs(db));
309 NS_ENSURE_SUCCESS(rv, rv);
312 nsRefPtr<aaSqlitePump> pump = new aaSqlitePump(db, sql.get(), this);
313 NS_ENSURE_TRUE(pump, NS_ERROR_OUT_OF_MEMORY);
315 rv = worker->Dispatch(pump, NS_DISPATCH_NORMAL);
316 NS_ENSURE_SUCCESS(rv, rv);
318 mStarted = PR_TRUE;
320 if (mLoadGroup) mLoadGroup->AddRequest(this, nsnull);
321 return NS_OK;
324 NS_IMETHODIMP
325 aaSqliteChannel::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
327 NS_ENSURE_STATE(mObserver && !mHadStart);
328 mHadStart = PR_TRUE;
330 nsresult rv = NS_OK;
331 rv = mObserver->OnStartRequest(this, aContext);
332 if (NS_FAILED(rv) && !IsCancelled())
334 Cancel(rv);
336 return rv;
339 NS_IMETHODIMP
340 aaSqliteChannel::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
341 nsresult aStatusCode)
343 NS_ENSURE_STATE(mObserver && mHadStart);
344 nsresult rv = NS_OK;
346 if (NS_SUCCEEDED(mStatus))
347 mStatus = aStatusCode;
348 rv = mObserver->OnStopRequest(this, aContext, mStatus);
349 mObserver = nsnull;
351 if (mLoadGroup) mLoadGroup->RemoveRequest(this, nsnull, mStatus);
352 mCallbacks = nsnull;
353 return rv;
356 NS_IMETHODIMP
357 aaSqliteChannel::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext,
358 nsIInputStream *aInputStream, PRUint32 aOffset, PRUint32 aCount)
360 NS_ENSURE_STATE(mObserver && mHadStart);
362 nsresult rv = NS_OK;
363 rv = mObserver->OnDataAvailable(this, aContext, aInputStream,
364 aOffset, aCount);
365 if (NS_FAILED(rv) && !IsCancelled())
367 Cancel(rv);
369 return rv;