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: */
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"
25 #include "nsAutoPtr.h"
26 #include "nsServiceManagerUtils.h"
27 #include "nsStringAPI.h"
29 #include "nsIStreamListener.h"
31 #include "nsIFileURL.h"
32 #include "nsINetUtil.h"
33 #include "nsComponentManagerUtils.h"
34 #include "nsNetUtil.h"
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
)
48 , mContentType("text/dbxml")
53 , mCancelled(PR_FALSE
)
56 NS_IMPL_THREADSAFE_ISUPPORTS4(aaSqliteChannel
,
64 aaSqliteChannel::GetName(nsACString
& aName
)
66 return NS_ERROR_NOT_IMPLEMENTED
;
70 aaSqliteChannel::IsPending(PRBool
*_retval NS_OUTPARAM
)
72 NS_ENSURE_ARG_POINTER(_retval
);
73 *_retval
= !!mObserver
;
78 aaSqliteChannel::GetStatus(nsresult
*aStatus
)
80 NS_ENSURE_ARG_POINTER(aStatus
);
86 aaSqliteChannel::Cancel(nsresult aStatus
)
88 NS_ENSURE_STATE(mObserver
);
89 if (NS_UNLIKELY(mCancelled
)) return NS_ERROR_UNEXPECTED
;
97 aaSqliteChannel::Suspend()
99 return NS_ERROR_NOT_IMPLEMENTED
;
103 aaSqliteChannel::Resume()
105 return NS_ERROR_NOT_IMPLEMENTED
;
109 aaSqliteChannel::GetLoadGroup(nsILoadGroup
* *aLoadGroup
)
111 NS_ENSURE_ARG_POINTER(aLoadGroup
);
112 NS_IF_ADDREF(*aLoadGroup
= mLoadGroup
);
116 aaSqliteChannel::SetLoadGroup(nsILoadGroup
* aLoadGroup
)
118 mLoadGroup
= aLoadGroup
;
123 aaSqliteChannel::GetLoadFlags(nsLoadFlags
*aLoadFlags
)
125 NS_ENSURE_ARG_POINTER(aLoadFlags
);
126 *aLoadFlags
= mLoadFlags
;
130 aaSqliteChannel::SetLoadFlags(nsLoadFlags aLoadFlags
)
132 mLoadFlags
= aLoadFlags
;
138 aaSqliteChannel::GetOriginalURI(nsIURI
* *aOriginalURI
)
140 NS_ENSURE_ARG_POINTER(aOriginalURI
);
141 NS_IF_ADDREF(*aOriginalURI
= mURI
);
145 aaSqliteChannel::SetOriginalURI(nsIURI
* aOriginalURI
)
147 return NS_ERROR_NOT_IMPLEMENTED
;
151 aaSqliteChannel::GetURI(nsIURI
* *aURI
)
153 NS_ENSURE_ARG_POINTER(aURI
);
154 NS_IF_ADDREF(*aURI
= mURI
);
159 aaSqliteChannel::GetOwner(nsISupports
* *aOwner
)
161 NS_ENSURE_ARG_POINTER(aOwner
);
162 NS_IF_ADDREF(*aOwner
= mOwner
);
166 aaSqliteChannel::SetOwner(nsISupports
* aOwner
)
173 aaSqliteChannel::GetNotificationCallbacks(nsIInterfaceRequestor
*
174 *aNotificationCallbacks
)
176 NS_ENSURE_ARG_POINTER(aNotificationCallbacks
);
177 NS_IF_ADDREF(*aNotificationCallbacks
= mCallbacks
);
181 aaSqliteChannel::SetNotificationCallbacks(nsIInterfaceRequestor
*
182 aNotificationCallbacks
)
184 mCallbacks
= aNotificationCallbacks
;
189 aaSqliteChannel::GetSecurityInfo(nsISupports
* *aSecurityInfo
)
191 return NS_ERROR_NOT_IMPLEMENTED
;
195 aaSqliteChannel::GetContentType(nsACString
& aContentType
)
197 aContentType
.Assign(mContentType
);
201 aaSqliteChannel::SetContentType(const nsACString
& aContentType
)
204 if(NS_UNLIKELY(mStarted
&& !mHadStart
))
205 return NS_ERROR_UNEXPECTED
;
209 nsCAutoString contentCharset
;
210 rv
= NS_ParseContentType(aContentType
, mContentType
, contentCharset
);
211 NS_ENSURE_SUCCESS(rv
, rv
);
218 aaSqliteChannel::GetContentCharset(nsACString
& aContentCharset
)
220 return NS_ERROR_NOT_IMPLEMENTED
;
223 aaSqliteChannel::SetContentCharset(const nsACString
& aContentCharset
)
225 return NS_ERROR_NOT_IMPLEMENTED
;
229 aaSqliteChannel::GetContentLength(PRInt32
*aContentLength
)
231 NS_ENSURE_ARG_POINTER(aContentLength
);
232 *aContentLength
= -1;
236 aaSqliteChannel::SetContentLength(PRInt32 aContentLength
)
242 aaSqliteChannel::Open(nsIInputStream
**_retval NS_OUTPARAM
)
244 return NS_ERROR_NOT_IMPLEMENTED
;
248 aaSqliteChannel::AsyncOpen(nsIStreamListener
*aListener
, nsISupports
*aContext
)
250 NS_ENSURE_ARG_POINTER(aListener
);
251 NS_ENSURE_STATE(mURI
);
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
);
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
);
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
);
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
);
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
);
320 if (mLoadGroup
) mLoadGroup
->AddRequest(this, nsnull
);
325 aaSqliteChannel::OnStartRequest(nsIRequest
*aRequest
, nsISupports
*aContext
)
327 NS_ENSURE_STATE(mObserver
&& !mHadStart
);
331 rv
= mObserver
->OnStartRequest(this, aContext
);
332 if (NS_FAILED(rv
) && !IsCancelled())
340 aaSqliteChannel::OnStopRequest(nsIRequest
*aRequest
, nsISupports
*aContext
,
341 nsresult aStatusCode
)
343 NS_ENSURE_STATE(mObserver
&& mHadStart
);
346 if (NS_SUCCEEDED(mStatus
))
347 mStatus
= aStatusCode
;
348 rv
= mObserver
->OnStopRequest(this, aContext
, mStatus
);
351 if (mLoadGroup
) mLoadGroup
->RemoveRequest(this, nsnull
, mStatus
);
357 aaSqliteChannel::OnDataAvailable(nsIRequest
*aRequest
, nsISupports
*aContext
,
358 nsIInputStream
*aInputStream
, PRUint32 aOffset
, PRUint32 aCount
)
360 NS_ENSURE_STATE(mObserver
&& mHadStart
);
363 rv
= mObserver
->OnDataAvailable(this, aContext
, aInputStream
,
365 if (NS_FAILED(rv
) && !IsCancelled())