1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3
* The contents of this file are subject to the Mozilla Public
4
* License Version 1.1 (the "License"); you may not use this file
5
* except in compliance with the License. You may obtain a copy of
6
* the License at http://www.mozilla.org/MPL/
8
* Software distributed under the License is distributed on an "AS
9
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10
* implied. See the License for the specific language governing
11
* rights and limitations under the License.
13
* The Original Code is mozilla.org code.
15
* The Initial Developer of the Original Code is Netscape
16
* Communications Corporation. Portions created by Netscape are
17
* Copyright (C) 2001 Netscape Communications Corporation.
18
* All Rights Reserved.
21
* Stuart Parmenter <pavlov@netscape.com>
24
#include "imgRequestProxy.h"
26
#include "nsIInputStream.h"
27
#include "nsIComponentManager.h"
28
#include "nsIServiceManager.h"
30
#include "nsAutoLock.h"
32
#include "nsXPIDLString.h"
33
#include "nsReadableUtils.h"
36
#include "ImageErrors.h"
37
#include "ImageLogging.h"
42
NS_IMPL_THREADSAFE_ISUPPORTS2(imgRequestProxy, imgIRequest, nsIRequest)
44
imgRequestProxy::imgRequestProxy() :
47
mLoadFlags(nsIRequest::LOAD_NORMAL),
49
mIsInLoadGroup(PR_FALSE),
52
/* member initializers and constructor code */
57
imgRequestProxy::~imgRequestProxy()
60
NS_PRECONDITION(!mListener, "Someone forgot to properly cancel this request!");
68
/* set mListener to null so that we don't forward any callbacks that
69
RemoveProxy might generate
75
/* Call RemoveProxy with a successful status. This will keep the
76
channel, if still downloading data, from being canceled if 'this' is
77
the last observer. This allows the image to continue to download and
78
be cached even if no one is using it currently.
80
mOwner->RemoveProxy(this, NS_OK, PR_FALSE);
86
PR_DestroyLock(mLock);
91
nsresult imgRequestProxy::Init(imgRequest *request, nsILoadGroup *aLoadGroup, imgIDecoderObserver *aObserver)
93
NS_PRECONDITION(request, "no request");
95
return NS_ERROR_NULL_POINTER;
97
LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequestProxy::Init", "request", request);
104
mListener = aObserver;
106
mLoadGroup = aLoadGroup;
110
request->AddProxy(this, PR_FALSE); // Pass PR_FALSE here so that AddProxy doesn't send all the On* notifications immediatly
115
nsresult imgRequestProxy::ChangeOwner(imgRequest *aNewOwner)
122
mOwner->RemoveProxy(this, NS_IMAGELIB_CHANGING_OWNER, PR_FALSE);
128
mOwner->AddProxy(this, PR_FALSE);
135
void imgRequestProxy::AddToLoadGroup()
137
NS_ASSERTION(!mIsInLoadGroup, "Whaa, we're already in the loadgroup!");
139
if (!mIsInLoadGroup && mLoadGroup) {
140
mLoadGroup->AddRequest(this, nsnull);
141
mIsInLoadGroup = PR_TRUE;
145
void imgRequestProxy::RemoveFromLoadGroup()
150
/* calling RemoveFromLoadGroup may cause the document to finish
151
loading, which could result in our death. We need to make sure
152
that we stay alive long enough to fight another battle... at
153
least until we exit this function.
155
nsCOMPtr<imgIRequest> kungFuDeathGrip(this);
157
mLoadGroup->RemoveRequest(this, NS_OK, nsnull);
158
mIsInLoadGroup = PR_FALSE;
160
// We're done with the loadgroup, release it.
165
/** nsIRequest / imgIRequest methods **/
167
/* readonly attribute wstring name; */
168
NS_IMETHODIMP imgRequestProxy::GetName(nsACString &aName)
172
nsCOMPtr<nsIURI> uri;
173
mOwner->GetURI(getter_AddRefs(uri));
180
/* boolean isPending (); */
181
NS_IMETHODIMP imgRequestProxy::IsPending(PRBool *_retval)
183
return NS_ERROR_NOT_IMPLEMENTED;
186
/* readonly attribute nsresult status; */
187
NS_IMETHODIMP imgRequestProxy::GetStatus(nsresult *aStatus)
189
return NS_ERROR_NOT_IMPLEMENTED;
192
/* void cancel (in nsresult status); */
193
NS_IMETHODIMP imgRequestProxy::Cancel(nsresult status)
195
if (mCanceled || !mOwner)
196
return NS_ERROR_FAILURE;
198
LOG_SCOPE(gImgLog, "imgRequestProxy::Cancel");
207
mOwner->RemoveProxy(this, status, PR_FALSE);
212
/* void suspend (); */
213
NS_IMETHODIMP imgRequestProxy::Suspend()
215
return NS_ERROR_NOT_IMPLEMENTED;
218
/* void resume (); */
219
NS_IMETHODIMP imgRequestProxy::Resume()
221
return NS_ERROR_NOT_IMPLEMENTED;
224
/* attribute nsILoadGroup loadGroup */
225
NS_IMETHODIMP imgRequestProxy::GetLoadGroup(nsILoadGroup **loadGroup)
227
nsAutoLock lock(mLock);
228
NS_IF_ADDREF(*loadGroup = mLoadGroup.get());
231
NS_IMETHODIMP imgRequestProxy::SetLoadGroup(nsILoadGroup *loadGroup)
233
nsAutoLock lock(mLock);
234
mLoadGroup = loadGroup;
238
/* attribute nsLoadFlags loadFlags */
239
NS_IMETHODIMP imgRequestProxy::GetLoadFlags(nsLoadFlags *flags)
244
NS_IMETHODIMP imgRequestProxy::SetLoadFlags(nsLoadFlags flags)
250
/** imgIRequest methods **/
252
/* attribute imgIContainer image; */
253
NS_IMETHODIMP imgRequestProxy::GetImage(imgIContainer * *aImage)
256
return NS_ERROR_FAILURE;
258
nsAutoLock lock(mLock);
259
mOwner->GetImage(aImage);
263
/* readonly attribute unsigned long imageStatus; */
264
NS_IMETHODIMP imgRequestProxy::GetImageStatus(PRUint32 *aStatus)
267
*aStatus = imgIRequest::STATUS_ERROR;
268
return NS_ERROR_FAILURE;
271
nsAutoLock lock(mLock);
272
*aStatus = mOwner->GetImageStatus();
276
/* readonly attribute nsIURI URI; */
277
NS_IMETHODIMP imgRequestProxy::GetURI(nsIURI **aURI)
280
return NS_ERROR_FAILURE;
282
nsAutoLock lock(mLock);
283
return mOwner->GetURI(aURI);
286
/* readonly attribute imgIDecoderObserver decoderObserver; */
287
NS_IMETHODIMP imgRequestProxy::GetDecoderObserver(imgIDecoderObserver **aDecoderObserver)
289
*aDecoderObserver = mListener;
290
NS_IF_ADDREF(*aDecoderObserver);
294
/* readonly attribute string mimeType; */
295
NS_IMETHODIMP imgRequestProxy::GetMimeType(char **aMimeType)
298
return NS_ERROR_FAILURE;
300
const char *type = mOwner->GetMimeType();
302
return NS_ERROR_FAILURE;
304
*aMimeType = nsCRT::strdup(type);
309
NS_IMETHODIMP imgRequestProxy::Clone(imgIDecoderObserver* aObserver,
310
imgIRequest** aClone)
312
NS_PRECONDITION(aClone, "Null out param");
314
imgRequestProxy* clone = new imgRequestProxy();
316
return NS_ERROR_OUT_OF_MEMORY;
320
// It is important to call |SetLoadFlags()| before calling |Init()| because
321
// |Init()| adds the request to the loadgroup.
322
clone->SetLoadFlags(mLoadFlags);
323
nsresult rv = clone->Init(mOwner, mLoadGroup, aObserver);
329
// Send the notifications to the clone's observer
330
mOwner->NotifyProxyListener(clone);
336
/** imgIContainerObserver methods **/
338
void imgRequestProxy::FrameChanged(imgIContainer *container, gfxIImageFrame *newframe, nsRect * dirtyRect)
340
LOG_FUNC(gImgLog, "imgRequestProxy::FrameChanged");
343
// Hold a ref to the listener while we call it, just in case.
344
nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener);
345
mListener->FrameChanged(container, newframe, dirtyRect);
349
/** imgIDecoderObserver methods **/
351
void imgRequestProxy::OnStartDecode()
353
LOG_FUNC(gImgLog, "imgRequestProxy::OnStartDecode");
356
// Hold a ref to the listener while we call it, just in case.
357
nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener);
358
mListener->OnStartDecode(this);
362
void imgRequestProxy::OnStartContainer(imgIContainer *image)
364
LOG_FUNC(gImgLog, "imgRequestProxy::OnStartContainer");
367
// Hold a ref to the listener while we call it, just in case.
368
nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener);
369
mListener->OnStartContainer(this, image);
373
void imgRequestProxy::OnStartFrame(gfxIImageFrame *frame)
375
LOG_FUNC(gImgLog, "imgRequestProxy::OnStartFrame");
378
// Hold a ref to the listener while we call it, just in case.
379
nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener);
380
mListener->OnStartFrame(this, frame);
384
void imgRequestProxy::OnDataAvailable(gfxIImageFrame *frame, const nsRect * rect)
386
LOG_FUNC(gImgLog, "imgRequestProxy::OnDataAvailable");
389
// Hold a ref to the listener while we call it, just in case.
390
nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener);
391
mListener->OnDataAvailable(this, frame, rect);
395
void imgRequestProxy::OnStopFrame(gfxIImageFrame *frame)
397
LOG_FUNC(gImgLog, "imgRequestProxy::OnStopFrame");
400
// Hold a ref to the listener while we call it, just in case.
401
nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener);
402
mListener->OnStopFrame(this, frame);
406
void imgRequestProxy::OnStopContainer(imgIContainer *image)
408
LOG_FUNC(gImgLog, "imgRequestProxy::OnStopContainer");
411
// Hold a ref to the listener while we call it, just in case.
412
nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener);
413
mListener->OnStopContainer(this, image);
417
void imgRequestProxy::OnStopDecode(nsresult status, const PRUnichar *statusArg)
419
LOG_FUNC(gImgLog, "imgRequestProxy::OnStopDecode");
422
// Hold a ref to the listener while we call it, just in case.
423
nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener);
424
mListener->OnStopDecode(this, status, statusArg);
430
void imgRequestProxy::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
435
LOG_FUNC_WITH_PARAM(gImgLog, "imgRequestProxy::OnStartRequest", "name", name.get());
439
void imgRequestProxy::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult statusCode)
444
LOG_FUNC_WITH_PARAM(gImgLog, "imgRequestProxy::OnStopRequest", "name", name.get());
447
RemoveFromLoadGroup();