1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
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/
9 : *
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
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #include "nsStreamLoader.h"
39 : #include "nsIInputStream.h"
40 : #include "nsIChannel.h"
41 : #include "nsNetError.h"
42 : #include "sampler.h"
43 :
44 16 : nsStreamLoader::nsStreamLoader()
45 : : mData(nsnull),
46 : mAllocated(0),
47 16 : mLength(0)
48 : {
49 16 : }
50 :
51 32 : nsStreamLoader::~nsStreamLoader()
52 : {
53 16 : if (mData) {
54 16 : NS_Free(mData);
55 : }
56 16 : }
57 :
58 : NS_IMETHODIMP
59 16 : nsStreamLoader::Init(nsIStreamLoaderObserver* observer)
60 : {
61 16 : NS_ENSURE_ARG_POINTER(observer);
62 16 : mObserver = observer;
63 16 : return NS_OK;
64 : }
65 :
66 : nsresult
67 16 : nsStreamLoader::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
68 : {
69 16 : if (aOuter) return NS_ERROR_NO_AGGREGATION;
70 :
71 16 : nsStreamLoader* it = new nsStreamLoader();
72 16 : if (it == nsnull)
73 0 : return NS_ERROR_OUT_OF_MEMORY;
74 16 : NS_ADDREF(it);
75 16 : nsresult rv = it->QueryInterface(aIID, aResult);
76 16 : NS_RELEASE(it);
77 16 : return rv;
78 : }
79 :
80 364 : NS_IMPL_ISUPPORTS3(nsStreamLoader, nsIStreamLoader,
81 : nsIRequestObserver, nsIStreamListener)
82 :
83 : NS_IMETHODIMP
84 0 : nsStreamLoader::GetNumBytesRead(PRUint32* aNumBytes)
85 : {
86 0 : *aNumBytes = mLength;
87 0 : return NS_OK;
88 : }
89 :
90 : /* readonly attribute nsIRequest request; */
91 : NS_IMETHODIMP
92 20 : nsStreamLoader::GetRequest(nsIRequest **aRequest)
93 : {
94 20 : NS_IF_ADDREF(*aRequest = mRequest);
95 20 : return NS_OK;
96 : }
97 :
98 : NS_IMETHODIMP
99 16 : nsStreamLoader::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
100 : {
101 32 : nsCOMPtr<nsIChannel> chan( do_QueryInterface(request) );
102 16 : if (chan) {
103 10 : PRInt32 contentLength = -1;
104 10 : chan->GetContentLength(&contentLength);
105 10 : if (contentLength >= 0) {
106 : // preallocate buffer
107 10 : mData = static_cast<PRUint8*>(NS_Alloc(contentLength));
108 10 : if (!mData) {
109 0 : return NS_ERROR_OUT_OF_MEMORY;
110 : }
111 10 : mAllocated = contentLength;
112 : }
113 : }
114 16 : mContext = ctxt;
115 16 : return NS_OK;
116 : }
117 :
118 : NS_IMETHODIMP
119 16 : nsStreamLoader::OnStopRequest(nsIRequest* request, nsISupports *ctxt,
120 : nsresult aStatus)
121 : {
122 32 : SAMPLE_LABEL("network", "nsStreamLoader::OnStopRequest");
123 16 : if (mObserver) {
124 : // provide nsIStreamLoader::request during call to OnStreamComplete
125 16 : mRequest = request;
126 16 : nsresult rv = mObserver->OnStreamComplete(this, mContext, aStatus,
127 16 : mLength, mData);
128 16 : if (rv == NS_SUCCESS_ADOPTED_DATA) {
129 : // the observer now owns the data buffer, and the loader must
130 : // not deallocate it
131 0 : mData = nsnull;
132 0 : mLength = 0;
133 0 : mAllocated = 0;
134 : }
135 : // done.. cleanup
136 16 : mRequest = 0;
137 16 : mObserver = 0;
138 16 : mContext = 0;
139 : }
140 16 : return NS_OK;
141 : }
142 :
143 : NS_METHOD
144 18 : nsStreamLoader::WriteSegmentFun(nsIInputStream *inStr,
145 : void *closure,
146 : const char *fromSegment,
147 : PRUint32 toOffset,
148 : PRUint32 count,
149 : PRUint32 *writeCount)
150 : {
151 18 : nsStreamLoader *self = (nsStreamLoader *) closure;
152 :
153 18 : if (count > PR_UINT32_MAX - self->mLength) {
154 0 : return NS_ERROR_ILLEGAL_VALUE; // is there a better error to use here?
155 : }
156 :
157 18 : if (self->mLength + count > self->mAllocated) {
158 : self->mData = static_cast<PRUint8*>(NS_Realloc(self->mData,
159 8 : self->mLength + count));
160 8 : if (!self->mData) {
161 0 : self->mLength = 0;
162 0 : self->mAllocated = 0;
163 0 : return NS_ERROR_OUT_OF_MEMORY;
164 : }
165 8 : self->mAllocated = self->mLength + count;
166 : }
167 :
168 18 : ::memcpy(self->mData + self->mLength, fromSegment, count);
169 18 : self->mLength += count;
170 :
171 18 : *writeCount = count;
172 :
173 18 : return NS_OK;
174 : }
175 :
176 : NS_IMETHODIMP
177 18 : nsStreamLoader::OnDataAvailable(nsIRequest* request, nsISupports *ctxt,
178 : nsIInputStream *inStr,
179 : PRUint32 sourceOffset, PRUint32 count)
180 : {
181 : PRUint32 countRead;
182 18 : return inStr->ReadSegments(WriteSegmentFun, this, count, &countRead);
183 : }
|