1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* ***** BEGIN LICENSE BLOCK *****
3
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
5
* The contents of this file are subject to the Mozilla Public License Version
6
* 1.1 (the "License"); you may not use this file except in compliance with
7
* the License. You may obtain a copy of the License at
8
* http://www.mozilla.org/MPL/
10
* Software distributed under the License is distributed on an "AS IS" basis,
11
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
* for the specific language governing rights and limitations under the
15
* The Original Code is mozilla.org code.
17
* The Initial Developer of the Original Code is
18
* Netscape Communications Corporation.
19
* Portions created by the Initial Developer are Copyright (C) 2002
20
* the Initial Developer. All Rights Reserved.
23
* Boris Zbarsky <bzbarsky@mit.edu> (original author)
25
* Alternatively, the contents of this file may be used under the terms of
26
* either the GNU General Public License Version 2 or later (the "GPL"), or
27
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28
* in which case the provisions of the GPL or the LGPL are applicable instead
29
* of those above. If you wish to allow use of your version of this file only
30
* under the terms of either the GPL or the LGPL, and not to allow others to
31
* use your version of this file under the terms of the MPL, indicate your
32
* decision by deleting the provisions above and replace them with the notice
33
* and other provisions required by the GPL or the LGPL. If you do not delete
34
* the provisions above, a recipient may use your version of this file under
35
* the terms of any one of the MPL, the GPL or the LGPL.
37
* ***** END LICENSE BLOCK ***** */
39
#include "nsUnicharStreamLoader.h"
41
#include "nsIChannel.h"
42
#include "nsNetUtil.h"
43
#include "nsProxiedService.h"
44
#include "nsIChannel.h"
45
#include "nsIUnicharInputStream.h"
46
#include "nsIConverterInputStream.h"
49
#ifdef DEBUG // needed for IsASCII assertion
50
#include "nsReadableUtils.h"
53
static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
56
nsUnicharStreamLoader::Init(nsIChannel *aChannel,
57
nsIUnicharStreamLoaderObserver *aObserver,
58
nsISupports *aContext,
59
PRUint32 aSegmentSize)
61
NS_ENSURE_ARG_POINTER(aChannel);
62
NS_ENSURE_ARG_POINTER(aObserver);
64
if (aSegmentSize <= 0) {
65
aSegmentSize = nsIUnicharStreamLoader::DEFAULT_SEGMENT_SIZE;
68
nsresult rv = aChannel->AsyncOpen(this, aContext);
71
// don't callback synchronously as it puts the caller
72
// in a recursive situation and breaks the asynchronous
73
// semantics of nsIStreamLoader
75
nsCOMPtr<nsIProxyObjectManager> pIProxyObjectManager =
76
do_GetService(kProxyObjectManagerCID, &rv2);
80
nsCOMPtr<nsIUnicharStreamLoaderObserver> pObserver;
82
pIProxyObjectManager->GetProxyForObject(NS_CURRENT_EVENTQ,
83
NS_GET_IID(nsIUnicharStreamLoaderObserver),
85
PROXY_ASYNC | PROXY_ALWAYS,
86
getter_AddRefs(pObserver));
90
rv = pObserver->OnStreamComplete(this, aContext, rv, nsnull);
93
mObserver = aObserver;
96
mChannel = nsnull; // Leave this null till OnStopRequest
97
mSegmentSize = aSegmentSize;
102
nsUnicharStreamLoader::Create(nsISupports *aOuter,
106
if (aOuter) return NS_ERROR_NO_AGGREGATION;
108
nsUnicharStreamLoader* it = new nsUnicharStreamLoader();
110
return NS_ERROR_OUT_OF_MEMORY;
112
nsresult rv = it->QueryInterface(aIID, aResult);
117
NS_IMPL_ISUPPORTS3(nsUnicharStreamLoader, nsIUnicharStreamLoader,
118
nsIRequestObserver, nsIStreamListener)
120
/* readonly attribute nsIChannel channel; */
122
nsUnicharStreamLoader::GetChannel(nsIChannel **aChannel)
124
NS_IF_ADDREF(*aChannel = mChannel);
128
/* readonly attribute nsACString charset */
130
nsUnicharStreamLoader::GetCharset(nsACString& aCharset)
136
/* nsIRequestObserver implementation */
138
nsUnicharStreamLoader::OnStartRequest(nsIRequest* request,
145
nsUnicharStreamLoader::OnStopRequest(nsIRequest *request,
149
// if we trigger this assertion, then it means that the channel called
150
// OnStopRequest before returning from AsyncOpen, which is totally
151
// unexpected behavior.
153
NS_ERROR("No way we should not have an mObserver here!");
154
return NS_ERROR_UNEXPECTED;
159
// We got some data at some point. I guess we should tell our
160
// observer about it or something....
162
// Make sure mChannel points to the channel that we ended up with
163
mChannel = do_QueryInterface(request);
165
// Determine the charset
166
PRUint32 readCount = 0;
167
rv = mInputStream->ReadSegments(WriteSegmentFun,
172
rv = mObserver->OnStreamComplete(this, mContext, rv, nsnull);
176
nsCOMPtr<nsIConverterInputStream> uin =
177
do_CreateInstance("@mozilla.org/intl/converter-input-stream;1",
180
rv = mObserver->OnStreamComplete(this, mContext, rv, nsnull);
184
rv = uin->Init(mInputStream,
190
rv = mObserver->OnStreamComplete(this, mContext, rv, nsnull);
194
mObserver->OnStreamComplete(this, mContext, aStatus, uin);
197
// We never got any data, so just tell our observer that we are
198
// done and give them no stream
199
mObserver->OnStreamComplete(this, mContext, aStatus, nsnull);
207
mInputStream = nsnull;
208
mOutputStream = nsnull;
212
/* nsIStreamListener implementation */
214
nsUnicharStreamLoader::WriteSegmentFun(nsIInputStream *aInputStream,
216
const char *aSegment,
219
PRUint32 *aWriteCount)
221
nsUnicharStreamLoader *self = (nsUnicharStreamLoader *) aClosure;
222
if (self->mCharset.IsEmpty()) {
223
// First time through. Call our observer.
224
NS_ASSERTION(self->mObserver, "This should never be possible");
226
nsresult rv = self->mObserver->OnDetermineCharset(self,
232
if (NS_FAILED(rv) || self->mCharset.IsEmpty()) {
233
// The observer told us nothing useful
234
self->mCharset = NS_LITERAL_CSTRING("ISO-8859-1");
237
NS_ASSERTION(IsASCII(self->mCharset),
238
"Why is the charset name non-ascii? Whose bright idea was that?");
240
// Don't consume any data
242
return NS_BASE_STREAM_WOULD_BLOCK;
247
nsUnicharStreamLoader::OnDataAvailable(nsIRequest *aRequest,
248
nsISupports *aContext,
249
nsIInputStream *aInputStream,
250
PRUint32 aSourceOffset,
255
// We are not initialized. Time to set things up.
256
NS_ASSERTION(!mOutputStream, "Why are we sorta-initialized?");
257
rv = NS_NewPipe(getter_AddRefs(mInputStream),
258
getter_AddRefs(mOutputStream),
260
PRUint32(-1), // give me all the data you can!
261
PR_TRUE, // non-blocking input
262
PR_TRUE); // non-blocking output
267
PRUint32 writeCount = 0;
269
rv = mOutputStream->WriteFrom(aInputStream, aCount, &writeCount);
270
if (NS_FAILED(rv)) return rv;
271
aCount -= writeCount;
272
} while (aCount > 0);