mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out 4 changesets (bug 497003) for intermittent OSX crashes.
Backed out changeset 43223a927976 (bug 497003) Backed out changeset 26c1d80edf1f (bug 497003) Backed out changeset 841ed173ba2b (bug 497003) Backed out changeset f70770fc6dce (bug 497003)
This commit is contained in:
parent
30e55b0314
commit
ca0cc81efe
@ -95,8 +95,6 @@ XPIDL_SOURCES += [
|
||||
'nsIStrictTransportSecurityService.idl',
|
||||
'nsISyncStreamListener.idl',
|
||||
'nsISystemProxySettings.idl',
|
||||
'nsIThreadRetargetableRequest.idl',
|
||||
'nsIThreadRetargetableStreamListener.idl',
|
||||
'nsITimedChannel.idl',
|
||||
'nsITraceableChannel.idl',
|
||||
'nsITransport.idl',
|
||||
|
@ -11,11 +11,10 @@ interface nsIStreamListener;
|
||||
* nsIInputStreamPump
|
||||
*
|
||||
* This interface provides a means to configure and use a input stream pump
|
||||
* instance. The input stream pump will asynchronously read from an input
|
||||
* stream, and push data to an nsIStreamListener instance. It utilizes the
|
||||
* instance. The input stream pump will asynchronously read from a input
|
||||
* stream, and push data to a nsIStreamListener instance. It utilizes the
|
||||
* current thread's nsIEventTarget in order to make reading from the stream
|
||||
* asynchronous. A different thread can be used if the pump also implements
|
||||
* nsIThreadRetargetableRequest.
|
||||
* asynchronous.
|
||||
*
|
||||
* If the given stream supports nsIAsyncInputStream, then the stream pump will
|
||||
* call the stream's AsyncWait method to drive the stream listener. Otherwise,
|
||||
|
@ -1,34 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIEventTarget.idl"
|
||||
|
||||
/**
|
||||
* nsIThreadRetargetableRequest
|
||||
*
|
||||
* Should be implemented by requests that support retargeting delivery of
|
||||
* OnDataAvailable and OnStopRequest off the main thread.
|
||||
*/
|
||||
[uuid(27b84c48-5a73-4ba4-a8a4-8b5e649a145e)]
|
||||
interface nsIThreadRetargetableRequest : nsISupports
|
||||
{
|
||||
/**
|
||||
* Called to retarget delivery of OnDataAvailable and OnStopRequest to
|
||||
* another thread. Should only be called within the context of OnStartRequest
|
||||
* on the main thread.
|
||||
*
|
||||
* @param aNewTarget New event target, e.g. thread or threadpool.
|
||||
*
|
||||
* Note: no return value is given. If the retargeting cannot be handled,
|
||||
* normal delivery to the main thread will continue. As such, listeners
|
||||
* should be ready to deal with OnDataAvailable and OnStopRequest on
|
||||
* either the main thread or the new target thread.
|
||||
*/
|
||||
void retargetDeliveryTo(in nsIEventTarget aNewTarget);
|
||||
};
|
||||
|
||||
|
@ -1,34 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* nsIThreadRetargetableListener
|
||||
*
|
||||
* To be used by classes which implement nsIStreamListener and whose
|
||||
* OnDataAvailable and OnStopRequest may be retargeted for delivery off the
|
||||
* main thread.
|
||||
*/
|
||||
[uuid(fb2304b8-f82f-4433-af68-d874a2ebbdc1)]
|
||||
interface nsIThreadRetargetableStreamListener : nsISupports
|
||||
{
|
||||
/**
|
||||
* Checks this listener and any next listeners it may have to verify that
|
||||
* they can receive OnDataAvailable and OnStopRequest off the main thread.
|
||||
* It is the responsibility of the implementing class to decide on the
|
||||
* criteria to determine if retargeted delivery of these methods is
|
||||
* possible, but it must check any and all nsIStreamListener objects that
|
||||
* might be called in the listener chain.
|
||||
*
|
||||
* An exception should be thrown if a listener in the chain does not
|
||||
* support retargeted delivery, i.e. if the next listener does not implement
|
||||
* nsIThreadRetargetableStreamListener, or a call to its checkListenerChain()
|
||||
* fails.
|
||||
*/
|
||||
void checkListenerChain();
|
||||
};
|
||||
|
@ -8,13 +8,11 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIRequestObserver.h"
|
||||
#include "nsIThreadRetargetableStreamListener.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
// Wrapper class to make replacement of nsHttpChannel's listener
|
||||
// from JavaScript possible. It is workaround for bug 433711 and 682305.
|
||||
class nsStreamListenerWrapper MOZ_FINAL : public nsIStreamListener
|
||||
, public nsIThreadRetargetableStreamListener
|
||||
{
|
||||
public:
|
||||
nsStreamListenerWrapper(nsIStreamListener *listener)
|
||||
@ -26,7 +24,6 @@ public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_FORWARD_NSIREQUESTOBSERVER(mListener->)
|
||||
NS_FORWARD_NSISTREAMLISTENER(mListener->)
|
||||
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
|
||||
|
||||
private:
|
||||
~nsStreamListenerWrapper() {}
|
||||
|
@ -11,13 +11,10 @@
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsISeekableStream.h"
|
||||
#include "nsITransport.h"
|
||||
#include "nsIThreadRetargetableStreamListener.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "prlog.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include <algorithm>
|
||||
|
||||
@ -44,7 +41,6 @@ nsInputStreamPump::nsInputStreamPump()
|
||||
, mLoadFlags(LOAD_NORMAL)
|
||||
, mWaiting(false)
|
||||
, mCloseWhenDone(false)
|
||||
, mRetargeting(false)
|
||||
{
|
||||
#if defined(PR_LOGGING)
|
||||
if (!gStreamPumpLog)
|
||||
@ -123,18 +119,14 @@ nsresult
|
||||
nsInputStreamPump::EnsureWaiting()
|
||||
{
|
||||
// no need to worry about multiple threads... an input stream pump lives
|
||||
// on only one thread at a time.
|
||||
MOZ_ASSERT(mAsyncStream);
|
||||
// on only one thread.
|
||||
|
||||
if (!mWaiting) {
|
||||
MOZ_ASSERT(mTargetThread);
|
||||
nsresult rv = mAsyncStream->AsyncWait(this, 0, 0, mTargetThread);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("AsyncWait failed");
|
||||
return rv;
|
||||
}
|
||||
// Any retargeting during STATE_START or START_TRANSFER is complete
|
||||
// after the call to AsyncWait; next callback wil be on mTargetThread.
|
||||
mRetargeting = false;
|
||||
mWaiting = true;
|
||||
}
|
||||
return NS_OK;
|
||||
@ -147,9 +139,8 @@ nsInputStreamPump::EnsureWaiting()
|
||||
// although this class can only be accessed from one thread at a time, we do
|
||||
// allow its ownership to move from thread to thread, assuming the consumer
|
||||
// understands the limitations of this.
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS4(nsInputStreamPump,
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS3(nsInputStreamPump,
|
||||
nsIRequest,
|
||||
nsIThreadRetargetableRequest,
|
||||
nsIInputStreamCallback,
|
||||
nsIInputStreamPump)
|
||||
|
||||
@ -389,30 +380,15 @@ nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream *stream)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
bool stillTransferring = (mState == STATE_TRANSFER &&
|
||||
nextState == STATE_TRANSFER);
|
||||
if (stillTransferring) {
|
||||
NS_ASSERTION(NS_SUCCEEDED(mStatus),
|
||||
"Should not have failed status for ongoing transfer");
|
||||
} else {
|
||||
NS_ASSERTION(mState != nextState,
|
||||
"Only OnStateTransfer can be called more than once.");
|
||||
}
|
||||
if (mRetargeting) {
|
||||
NS_ASSERTION(mState != STATE_STOP,
|
||||
"Retargeting should not happen during OnStateStop.");
|
||||
}
|
||||
if (mState == nextState && !mSuspendCount) {
|
||||
NS_ASSERTION(mState == STATE_TRANSFER, "unexpected state");
|
||||
NS_ASSERTION(NS_SUCCEEDED(mStatus), "unexpected status");
|
||||
|
||||
// Wait asynchronously if there is still data to transfer, or if
|
||||
// delivery of data has been requested on another thread.
|
||||
if (!mSuspendCount && (stillTransferring || mRetargeting)) {
|
||||
mState = nextState;
|
||||
mWaiting = false;
|
||||
mStatus = EnsureWaiting();
|
||||
if (NS_SUCCEEDED(mStatus))
|
||||
break;
|
||||
|
||||
// Failure to start asynchronous wait: stop transfer.
|
||||
nextState = STATE_STOP;
|
||||
}
|
||||
|
||||
@ -575,7 +551,6 @@ nsInputStreamPump::OnStateStop()
|
||||
mAsyncStream = 0;
|
||||
mTargetThread = 0;
|
||||
mIsPending = false;
|
||||
mRetargeting = false;
|
||||
|
||||
mListener->OnStopRequest(this, mListenerContext, mStatus);
|
||||
mListener = 0;
|
||||
@ -586,37 +561,3 @@ nsInputStreamPump::OnStateStop()
|
||||
|
||||
return STATE_IDLE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsIThreadRetargetableRequest
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsInputStreamPump::RetargetDeliveryTo(nsIEventTarget* aNewTarget)
|
||||
{
|
||||
NS_ENSURE_ARG(aNewTarget);
|
||||
if (aNewTarget == mTargetThread) {
|
||||
NS_WARNING("Retargeting delivery to same thread");
|
||||
return NS_OK;
|
||||
}
|
||||
NS_ENSURE_TRUE(mState == STATE_START || mState == STATE_TRANSFER,
|
||||
NS_ERROR_UNEXPECTED);
|
||||
|
||||
// Ensure that |mListener| and any subsequent listeners can be retargeted
|
||||
// to another thread.
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
|
||||
do_QueryInterface(mListener, &rv);
|
||||
if (NS_SUCCEEDED(rv) && retargetableListener) {
|
||||
rv = retargetableListener->CheckListenerChain();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mTargetThread = aNewTarget;
|
||||
mRetargeting = true;
|
||||
}
|
||||
}
|
||||
LOG(("nsInputStreamPump::RetargetDeliveryTo [this=%x aNewTarget=%p] "
|
||||
"%s listener [%p] rv[%x]",
|
||||
this, aNewTarget, (mTargetThread == aNewTarget ? "success" : "failure"),
|
||||
(nsIStreamListener*)mListener, rv));
|
||||
return rv;
|
||||
}
|
||||
|
@ -15,20 +15,17 @@
|
||||
#include "nsIProgressEventSink.h"
|
||||
#include "nsIAsyncInputStream.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsIThreadRetargetableRequest.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
class nsInputStreamPump MOZ_FINAL : public nsIInputStreamPump
|
||||
, public nsIInputStreamCallback
|
||||
, public nsIThreadRetargetableRequest
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIREQUEST
|
||||
NS_DECL_NSIINPUTSTREAMPUMP
|
||||
NS_DECL_NSIINPUTSTREAMCALLBACK
|
||||
NS_DECL_NSITHREADRETARGETABLEREQUEST
|
||||
|
||||
nsInputStreamPump();
|
||||
~nsInputStreamPump();
|
||||
@ -74,7 +71,7 @@ protected:
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
nsCOMPtr<nsIStreamListener> mListener;
|
||||
nsCOMPtr<nsISupports> mListenerContext;
|
||||
nsCOMPtr<nsIEventTarget> mTargetThread;
|
||||
nsCOMPtr<nsIThread> mTargetThread;
|
||||
nsCOMPtr<nsIInputStream> mStream;
|
||||
nsCOMPtr<nsIAsyncInputStream> mAsyncStream;
|
||||
uint64_t mStreamOffset;
|
||||
@ -87,7 +84,6 @@ protected:
|
||||
bool mIsPending;
|
||||
bool mWaiting; // true if waiting on async source
|
||||
bool mCloseWhenDone;
|
||||
bool mRetargeting;
|
||||
};
|
||||
|
||||
#endif // !nsInputStreamChannel_h__
|
||||
|
@ -5,11 +5,10 @@
|
||||
#include "nsStreamListenerTee.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS4(nsStreamListenerTee,
|
||||
nsIStreamListener,
|
||||
nsIRequestObserver,
|
||||
nsIStreamListenerTee,
|
||||
nsIThreadRetargetableStreamListener)
|
||||
NS_IMPL_ISUPPORTS3(nsStreamListenerTee,
|
||||
nsIStreamListener,
|
||||
nsIRequestObserver,
|
||||
nsIStreamListenerTee)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStreamListenerTee::OnStartRequest(nsIRequest *request,
|
||||
@ -93,29 +92,6 @@ nsStreamListenerTee::OnDataAvailable(nsIRequest *request,
|
||||
return mListener->OnDataAvailable(request, context, tee, offset, count);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStreamListenerTee::CheckListenerChain()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread!");
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
|
||||
do_QueryInterface(mListener, &rv);
|
||||
if (retargetableListener) {
|
||||
rv = retargetableListener->CheckListenerChain();
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (!mObserver) {
|
||||
return rv;
|
||||
}
|
||||
retargetableListener = do_QueryInterface(mObserver, &rv);
|
||||
if (retargetableListener) {
|
||||
rv = retargetableListener->CheckListenerChain();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStreamListenerTee::Init(nsIStreamListener *listener,
|
||||
nsIOutputStream *sink,
|
||||
|
@ -6,20 +6,17 @@
|
||||
#define nsStreamListenerTee_h__
|
||||
|
||||
#include "nsIStreamListenerTee.h"
|
||||
#include "nsIThreadRetargetableStreamListener.h"
|
||||
#include "nsIInputStreamTee.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIEventTarget.h"
|
||||
|
||||
class nsStreamListenerTee : public nsIStreamListenerTee
|
||||
, public nsIThreadRetargetableStreamListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
|
||||
NS_DECL_NSISTREAMLISTENERTEE
|
||||
|
||||
nsStreamListenerTee() { }
|
||||
|
@ -3,22 +3,8 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsStreamListenerWrapper.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsStreamListenerWrapper,
|
||||
NS_IMPL_ISUPPORTS2(nsStreamListenerWrapper,
|
||||
nsIStreamListener,
|
||||
nsIRequestObserver,
|
||||
nsIThreadRetargetableStreamListener)
|
||||
nsIRequestObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStreamListenerWrapper::CheckListenerChain()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread!");
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
|
||||
do_QueryInterface(mListener, &rv);
|
||||
if (retargetableListener) {
|
||||
rv = retargetableListener->CheckListenerChain();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "nsIRedirectResultListener.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsError.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsAlgorithm.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "nsIConsoleService.h"
|
||||
@ -4253,8 +4252,6 @@ NS_INTERFACE_MAP_BEGIN(nsHttpChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectCallback)
|
||||
NS_INTERFACE_MAP_ENTRY(nsITimedChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableRequest)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableStreamListener)
|
||||
NS_INTERFACE_MAP_END_INHERITING(HttpBaseChannel)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -4946,42 +4943,6 @@ nsHttpChannel::ContinueOnStartRequest3(nsresult result)
|
||||
return CallOnStartRequest();
|
||||
}
|
||||
|
||||
class OnStopRequestCleanupEvent : public nsRunnable
|
||||
{
|
||||
public:
|
||||
OnStopRequestCleanupEvent(nsHttpChannel *aHttpChannel,
|
||||
nsresult aStatus)
|
||||
: mHttpChannel(aHttpChannel)
|
||||
, mStatus(aStatus)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread(), "Shouldn't be created on main thread");
|
||||
NS_ASSERTION(aHttpChannel, "aHttpChannel should not be null");
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Should run on main thread");
|
||||
if (mHttpChannel) {
|
||||
mHttpChannel->OnStopRequestCleanup(mStatus);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
nsRefPtr<nsHttpChannel> mHttpChannel;
|
||||
nsresult mStatus;
|
||||
};
|
||||
|
||||
nsresult
|
||||
nsHttpChannel::OnStopRequestCleanup(nsresult aStatus)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread");
|
||||
if (mLoadGroup) {
|
||||
mLoadGroup->RemoveRequest(this, nullptr, aStatus);
|
||||
}
|
||||
ReleaseListeners();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult status)
|
||||
{
|
||||
@ -5111,17 +5072,14 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult st
|
||||
if (mOfflineCacheEntry)
|
||||
CloseOfflineCacheEntry();
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
OnStopRequestCleanup(status);
|
||||
} else {
|
||||
nsresult rv = NS_DispatchToMainThread(
|
||||
new OnStopRequestCleanupEvent(this, status));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
if (mLoadGroup)
|
||||
mLoadGroup->RemoveRequest(this, nullptr, status);
|
||||
|
||||
// We don't need this info anymore
|
||||
CleanRedirectCacheChainIfNecessary();
|
||||
|
||||
ReleaseListeners();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -5129,37 +5087,6 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult st
|
||||
// nsHttpChannel::nsIStreamListener
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class OnTransportStatusAsyncEvent : public nsRunnable
|
||||
{
|
||||
public:
|
||||
OnTransportStatusAsyncEvent(nsITransportEventSink* aEventSink,
|
||||
nsresult aTransportStatus,
|
||||
uint64_t aProgress,
|
||||
uint64_t aProgressMax)
|
||||
: mEventSink(aEventSink)
|
||||
, mTransportStatus(aTransportStatus)
|
||||
, mProgress(aProgress)
|
||||
, mProgressMax(aProgressMax)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread(), "Shouldn't be created on main thread");
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Should run on main thread");
|
||||
if (mEventSink) {
|
||||
mEventSink->OnTransportStatus(nullptr, mTransportStatus,
|
||||
mProgress, mProgressMax);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
nsCOMPtr<nsITransportEventSink> mEventSink;
|
||||
nsresult mTransportStatus;
|
||||
uint64_t mProgress;
|
||||
uint64_t mProgressMax;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctxt,
|
||||
nsIInputStream *input,
|
||||
@ -5204,14 +5131,7 @@ nsHttpChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctxt,
|
||||
uint64_t progress = mLogicalOffset + uint64_t(count);
|
||||
MOZ_ASSERT(progress <= progressMax, "unexpected progress values");
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
OnTransportStatus(nullptr, transportStatus, progress, progressMax);
|
||||
} else {
|
||||
nsresult rv = NS_DispatchToMainThread(
|
||||
new OnTransportStatusAsyncEvent(this, transportStatus,
|
||||
progress, progressMax));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
OnTransportStatus(nullptr, transportStatus, progress, progressMax);
|
||||
|
||||
//
|
||||
// we have to manually keep the logical offset of the stream up-to-date.
|
||||
@ -5235,67 +5155,6 @@ nsHttpChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctxt,
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpChannel::nsIThreadRetargetableRequest
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::RetargetDeliveryTo(nsIEventTarget* aNewTarget)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Should be called on main thread only");
|
||||
|
||||
NS_ENSURE_ARG(aNewTarget);
|
||||
if (aNewTarget == NS_GetCurrentThread()) {
|
||||
NS_WARNING("Retargeting delivery to same thread");
|
||||
return NS_OK;
|
||||
}
|
||||
NS_ENSURE_TRUE(mTransactionPump || mCachePump, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
// If both cache pump and transaction pump exist, we're probably dealing
|
||||
// with partially cached content. So, we must be able to retarget both.
|
||||
nsCOMPtr<nsIThreadRetargetableRequest> retargetableCachePump;
|
||||
nsCOMPtr<nsIThreadRetargetableRequest> retargetableTransactionPump;
|
||||
if (mCachePump) {
|
||||
retargetableCachePump = do_QueryObject(mCachePump);
|
||||
// nsInputStreamPump should implement this interface.
|
||||
MOZ_ASSERT(retargetableCachePump);
|
||||
rv = retargetableCachePump->RetargetDeliveryTo(aNewTarget);
|
||||
}
|
||||
if (NS_SUCCEEDED(rv) && mTransactionPump) {
|
||||
retargetableTransactionPump = do_QueryObject(mTransactionPump);
|
||||
// nsInputStreamPump should implement this interface.
|
||||
MOZ_ASSERT(retargetableTransactionPump);
|
||||
rv = retargetableTransactionPump->RetargetDeliveryTo(aNewTarget);
|
||||
|
||||
// If retarget fails for transaction pump, we must restore mCachePump.
|
||||
if (NS_FAILED(rv) && retargetableCachePump) {
|
||||
nsCOMPtr<nsIThread> mainThread;
|
||||
rv = NS_GetMainThread(getter_AddRefs(mainThread));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = retargetableCachePump->RetargetDeliveryTo(mainThread);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpChannel::nsThreadRetargetableStreamListener
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::CheckListenerChain()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread!");
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
|
||||
do_QueryInterface(mListener, &rv);
|
||||
if (retargetableListener) {
|
||||
rv = retargetableListener->CheckListenerChain();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpChannel::nsITransportEventSink
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -28,8 +28,6 @@
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "nsITimedChannel.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIThreadRetargetableRequest.h"
|
||||
#include "nsIThreadRetargetableStreamListener.h"
|
||||
#include "nsDNSPrefetch.h"
|
||||
#include "TimingStruct.h"
|
||||
#include "AutoClose.h"
|
||||
@ -56,14 +54,11 @@ class nsHttpChannel : public HttpBaseChannel
|
||||
, public nsIApplicationCacheChannel
|
||||
, public nsIAsyncVerifyRedirectCallback
|
||||
, public nsITimedChannel
|
||||
, public nsIThreadRetargetableRequest
|
||||
, public nsIThreadRetargetableStreamListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
|
||||
NS_DECL_NSICACHEINFOCHANNEL
|
||||
NS_DECL_NSICACHINGCHANNEL
|
||||
NS_DECL_NSICACHELISTENER
|
||||
@ -74,7 +69,6 @@ public:
|
||||
NS_DECL_NSIAPPLICATIONCACHECHANNEL
|
||||
NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
|
||||
NS_DECL_NSITIMEDCHANNEL
|
||||
NS_DECL_NSITHREADRETARGETABLEREQUEST
|
||||
|
||||
// nsIHttpAuthenticableChannel. We can't use
|
||||
// NS_DECL_NSIHTTPAUTHENTICABLECHANNEL because it duplicates cancel() and
|
||||
@ -156,8 +150,6 @@ public: /* internal necko use only */
|
||||
|
||||
OfflineCacheEntryAsForeignMarker* GetOfflineCacheEntryAsForeignMarker();
|
||||
|
||||
nsresult OnStopRequestCleanup(nsresult aStatus);
|
||||
|
||||
private:
|
||||
typedef nsresult (nsHttpChannel::*nsContinueRedirectionFunc)(nsresult result);
|
||||
|
||||
|
@ -1,21 +0,0 @@
|
||||
# -*- Mode: Makefile; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
# vim: set ts=8 sts=2 et sw=2 tw=80:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DEPTH = @DEPTH@
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = @relativesrcdir@
|
||||
FAIL_ON_WARNINGS := 1
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MOCHITEST_FILES = \
|
||||
partial_content.sjs \
|
||||
test_partially_cached_content.html \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
@ -1,7 +0,0 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
MODULE = 'test_necko'
|
@ -1,154 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Debug and Error wrapper functions for dump().
|
||||
*/
|
||||
function ERR(response, responseCode, responseCodeStr, msg)
|
||||
{
|
||||
// Reset state var.
|
||||
setState("expectedRequestType", "");
|
||||
// Dump to console log and send to client in response.
|
||||
dump("SERVER ERROR: " + msg + "\n");
|
||||
response.write("HTTP/1.1" + responseCode + responseCodeStr + "\r\n");
|
||||
response.write("Content-Type: text/html; charset=UTF-8\r\n");
|
||||
response.write("Content-Length: " + msg.length + "\r\n");
|
||||
response.write("\r\n");
|
||||
response.write(msg);
|
||||
}
|
||||
|
||||
function DBG(msg)
|
||||
{
|
||||
// enable when you want to debug
|
||||
if (0) {
|
||||
// Dump to console only.
|
||||
dump("SERVER DEBUG: " + msg + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Delivers content in parts to test partially cached content: requires two
|
||||
* requests for the same resource.
|
||||
*
|
||||
* First call will respond with partial content, but a 200 header and
|
||||
* Content-Length equal to the full content length. No Range or If-Range
|
||||
* headers are allowed in the request.
|
||||
*
|
||||
* Second call will require Range and If-Range in the request headers, and
|
||||
* will respond with the range requested.
|
||||
*/
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
DBG("Trying to seize power");
|
||||
response.seizePower();
|
||||
|
||||
DBG("About to check state vars");
|
||||
// Get state var to determine if this is the first or second request.
|
||||
var expectedRequestType;
|
||||
var lastModified;
|
||||
if (getState("expectedRequestType") === "") {
|
||||
DBG("First call: Should be requesting full content.");
|
||||
expectedRequestType = "fullRequest";
|
||||
// Set state var for second request.
|
||||
setState("expectedRequestType", "partialRequest");
|
||||
// Create lastModified variable for responses.
|
||||
lastModified = (new Date()).toUTCString();
|
||||
setState("lastModified", lastModified);
|
||||
} else if (getState("expectedRequestType") === "partialRequest") {
|
||||
DBG("Second call: Should be requesting undelivered content.");
|
||||
expectedRequestType = "partialRequest";
|
||||
// Reset state var for first request.
|
||||
setState("expectedRequestType", "");
|
||||
// Get last modified date and reset state var.
|
||||
lastModified = getState("lastModified");
|
||||
} else {
|
||||
ERR(response, 500, "Internal Server Error",
|
||||
"Invalid expectedRequestType \"" + expectedRequestType + "\"in " +
|
||||
"server state db.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Look for Range and If-Range
|
||||
var range = request.hasHeader("Range") ? request.getHeader("Range") : "";
|
||||
var ifRange = request.hasHeader("If-Range") ? request.getHeader("If-Range") : "";
|
||||
|
||||
if (expectedRequestType === "fullRequest") {
|
||||
// Should not have Range or If-Range in first request.
|
||||
if (range && range.length > 0) {
|
||||
ERR(response, 400, "Bad Request",
|
||||
"Should not receive \"Range: " + range + "\" for first, full request.");
|
||||
return;
|
||||
}
|
||||
if (ifRange && ifRange.length > 0) {
|
||||
ERR(response, 400, "Bad Request",
|
||||
"Should not receive \"Range: " + range + "\" for first, full request.");
|
||||
return;
|
||||
}
|
||||
} else if (expectedRequestType === "partialRequest") {
|
||||
// Range AND If-Range should both be present in second request.
|
||||
if (!range) {
|
||||
ERR(response, 400, "Bad Request",
|
||||
"Should receive \"Range: \" for second, partial request.");
|
||||
return;
|
||||
}
|
||||
if (!ifRange) {
|
||||
ERR(response, 400, "Bad Request",
|
||||
"Should receive \"If-Range: \" for second, partial request.");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Somewhat redundant, but a check for errors in this test code.
|
||||
ERR(response, 500, "Internal Server Error",
|
||||
"expectedRequestType not set correctly: \"" + expectedRequestType + "\"");
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare content in two parts for responses.
|
||||
var partialContent = "<html><head></head><body><p id=\"firstResponse\">" +
|
||||
"First response</p>";
|
||||
var remainderContent = "<p id=\"secondResponse\">Second response</p>" +
|
||||
"</body></html>";
|
||||
var totalLength = partialContent.length + remainderContent.length;
|
||||
|
||||
DBG("totalLength: " + totalLength);
|
||||
|
||||
// Prepare common headers for the two responses.
|
||||
date = new Date();
|
||||
DBG("Date: " + date.toUTCString() + ", Last-Modified: " + lastModified);
|
||||
var commonHeaders = "Date: " + date.toUTCString() + "\r\n" +
|
||||
"Last-Modified: " + lastModified + "\r\n" +
|
||||
"Content-Type: text/html; charset=UTF-8\r\n" +
|
||||
"ETag: abcd0123\r\n" +
|
||||
"Accept-Ranges: bytes\r\n";
|
||||
|
||||
|
||||
// Prepare specific headers and content for first and second responses.
|
||||
if (expectedRequestType === "fullRequest") {
|
||||
DBG("First response: Sending partial content with a full header");
|
||||
response.write("HTTP/1.1 200 OK\r\n");
|
||||
response.write(commonHeaders);
|
||||
// Set Content-Length to full length of resource.
|
||||
response.write("Content-Length: " + totalLength + "\r\n");
|
||||
response.write("\r\n");
|
||||
response.write(partialContent);
|
||||
} else if (expectedRequestType === "partialRequest") {
|
||||
DBG("Second response: Sending remaining content with a range header");
|
||||
response.write("HTTP/1.1 206 Partial Content\r\n");
|
||||
response.write(commonHeaders);
|
||||
// Set Content-Length to length of bytes transmitted.
|
||||
response.write("Content-Length: " + remainderContent.length + "\r\n");
|
||||
response.write("Content-Range: bytes " + partialContent.length + "-" +
|
||||
(totalLength - 1) + "/" + totalLength + "\r\n");
|
||||
response.write("\r\n");
|
||||
response.write(remainderContent);
|
||||
} else {
|
||||
// Somewhat redundant, but a check for errors in this test code.
|
||||
ERR(response, 500, "Internal Server Error",
|
||||
"Something very bad happened here: expectedRequestType is invalid " +
|
||||
"towards the end of handleRequest! - \"" + expectedRequestType + "\"");
|
||||
return;
|
||||
}
|
||||
|
||||
response.finish();
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=497003
|
||||
|
||||
This test verifies that partially cached content is read from the cache first
|
||||
and then from the network. It is written in the mochitest framework to take
|
||||
thread retargeting into consideration of nsIStreamListener callbacks (inc.
|
||||
nsIRequestObserver). E.g. HTML5 Stream Parser requesting retargeting of
|
||||
nsIStreamListener callbacks to the parser thread.
|
||||
-->
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Test for Bug 497003: support sending OnDataAvailable() to other threads</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=497003">Mozilla Bug 497003: support sending OnDataAvailable() to other threads</a></p>
|
||||
<p><iframe id="contentFrame" src="partial_content.sjs"></iframe></p>
|
||||
|
||||
<pre id="test">
|
||||
<script>
|
||||
|
||||
|
||||
|
||||
/* Check that the iframe has initial content only after the first load.
|
||||
*/
|
||||
function expectInitialContent(e) {
|
||||
info("expectInitialContent",
|
||||
"First response received: should have partial content");
|
||||
var frameWindow = document.getElementById('contentFrame').contentWindow;
|
||||
|
||||
// Expect "First response" in received HTML.
|
||||
var firstResponse = frameWindow.document.getElementById('firstResponse');
|
||||
ok(firstResponse, "First response should exist");
|
||||
if (firstResponse) {
|
||||
is(firstResponse.innerHTML, "First response",
|
||||
"First response should be correct");
|
||||
}
|
||||
|
||||
// Expect NOT to get any second response element.
|
||||
var secondResponse = frameWindow.document.getElementById('secondResponse');
|
||||
ok(!secondResponse, "Should not get text for second response in first.");
|
||||
|
||||
// Set up listener for second load.
|
||||
e.target.removeEventListener("load", expectInitialContent, false);
|
||||
e.target.addEventListener("load", expectFullContent, false);
|
||||
|
||||
// Reload.
|
||||
e.target.src="partial_content.sjs";
|
||||
}
|
||||
|
||||
/* Check that the iframe has all the content after the second load.
|
||||
*/
|
||||
function expectFullContent(e)
|
||||
{
|
||||
info("expectFullContent",
|
||||
"Second response received: should complete content from first load");
|
||||
var frameWindow = document.getElementById('contentFrame').contentWindow;
|
||||
|
||||
// Expect "First response" to still be there
|
||||
var firstResponse = frameWindow.document.getElementById('firstResponse');
|
||||
ok(firstResponse, "First response should exist");
|
||||
if (firstResponse) {
|
||||
is(firstResponse.innerHTML, "First response",
|
||||
"First response should be correct");
|
||||
}
|
||||
|
||||
// Expect "Second response" to be there also.
|
||||
var secondResponse = frameWindow.document.getElementById('secondResponse');
|
||||
ok(secondResponse, "Second response should exist");
|
||||
if (secondResponse) {
|
||||
is(secondResponse.innerHTML, "Second response",
|
||||
"Second response should be correct");
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
// Set listener for first load to expect partial content.
|
||||
document.getElementById('contentFrame')
|
||||
.addEventListener("load", expectInitialContent, false);
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -4,7 +4,7 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
TEST_DIRS += ['httpserver', 'browser', 'mochitests']
|
||||
TEST_DIRS += ['httpserver', 'browser']
|
||||
|
||||
MODULE = 'test_necko'
|
||||
|
||||
|
@ -26,8 +26,6 @@
|
||||
#include "nsINestedURI.h"
|
||||
#include "nsCharsetSource.h"
|
||||
#include "nsIWyciwygChannel.h"
|
||||
#include "nsIThreadRetargetableRequest.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
||||
#include "mozilla/dom/EncodingUtils.h"
|
||||
|
||||
@ -75,10 +73,9 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(nsHtml5StreamParser)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsHtml5StreamParser)
|
||||
|
||||
NS_INTERFACE_TABLE_HEAD(nsHtml5StreamParser)
|
||||
NS_INTERFACE_TABLE3(nsHtml5StreamParser,
|
||||
NS_INTERFACE_TABLE2(nsHtml5StreamParser,
|
||||
nsIStreamListener,
|
||||
nsICharsetDetectionObserver,
|
||||
nsIThreadRetargetableStreamListener)
|
||||
nsICharsetDetectionObserver)
|
||||
NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsHtml5StreamParser)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
@ -929,14 +926,6 @@ nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
|
||||
mReparseForbidden = true;
|
||||
mFeedChardet = false; // can't restart anyway
|
||||
}
|
||||
|
||||
// Attempt to retarget delivery of data (via OnDataAvailable) to the parser
|
||||
// thread, rather than through the main thread.
|
||||
nsCOMPtr<nsIThreadRetargetableRequest> threadRetargetableRequest =
|
||||
do_QueryInterface(mRequest);
|
||||
if (threadRetargetableRequest) {
|
||||
threadRetargetableRequest->RetargetDeliveryTo(mThread);
|
||||
}
|
||||
}
|
||||
|
||||
if (mCharsetSource == kCharsetFromParentFrame) {
|
||||
@ -971,22 +960,6 @@ nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHtml5StreamParser::CheckListenerChain()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on the main thread!");
|
||||
if (!mObserver) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIThreadRetargetableStreamListener> retargetable =
|
||||
do_QueryInterface(mObserver, &rv);
|
||||
if (NS_SUCCEEDED(rv) && retargetable) {
|
||||
rv = retargetable->CheckListenerChain();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5StreamParser::DoStopRequest()
|
||||
{
|
||||
@ -1040,24 +1013,19 @@ nsHtml5StreamParser::OnStopRequest(nsIRequest* aRequest,
|
||||
nsresult status)
|
||||
{
|
||||
NS_ASSERTION(mRequest == aRequest, "Got Stop on wrong stream.");
|
||||
NS_ASSERTION(NS_IsMainThread() || IsParserThread(), "Wrong thread!");
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
if (mObserver) {
|
||||
mObserver->OnStopRequest(aRequest, aContext, status);
|
||||
}
|
||||
if (NS_IsMainThread()) {
|
||||
nsCOMPtr<nsIRunnable> stopper = new nsHtml5RequestStopper(this);
|
||||
if (NS_FAILED(mThread->Dispatch(stopper, nsIThread::DISPATCH_NORMAL))) {
|
||||
NS_WARNING("Dispatching StopRequest event failed.");
|
||||
}
|
||||
} else {
|
||||
mozilla::MutexAutoLock autoLock(mTokenizerMutex);
|
||||
DoStopRequest();
|
||||
nsCOMPtr<nsIRunnable> stopper = new nsHtml5RequestStopper(this);
|
||||
if (NS_FAILED(mThread->Dispatch(stopper, nsIThread::DISPATCH_NORMAL))) {
|
||||
NS_WARNING("Dispatching StopRequest event failed.");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5StreamParser::DoDataAvailable(const uint8_t* aBuffer, uint32_t aLength)
|
||||
nsHtml5StreamParser::DoDataAvailable(uint8_t* aBuffer, uint32_t aLength)
|
||||
{
|
||||
NS_ASSERTION(IsParserThread(), "Wrong thread!");
|
||||
NS_PRECONDITION(STREAM_BEING_READ == mStreamState,
|
||||
@ -1142,58 +1110,24 @@ nsHtml5StreamParser::OnDataAvailable(nsIRequest* aRequest,
|
||||
|
||||
NS_ASSERTION(mRequest == aRequest, "Got data on wrong stream.");
|
||||
uint32_t totalRead;
|
||||
// Main thread to parser thread dispatch requires copying to buffer first.
|
||||
if (NS_IsMainThread()) {
|
||||
const mozilla::fallible_t fallible = mozilla::fallible_t();
|
||||
nsAutoArrayPtr<uint8_t> data(new (fallible) uint8_t[aLength]);
|
||||
if (!data) {
|
||||
return mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
rv = aInStream->Read(reinterpret_cast<char*>(data.get()),
|
||||
aLength, &totalRead);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(totalRead <= aLength, "Read more bytes than were available?");
|
||||
|
||||
nsCOMPtr<nsIRunnable> dataAvailable = new nsHtml5DataAvailable(this,
|
||||
data.forget(),
|
||||
totalRead);
|
||||
if (NS_FAILED(mThread->Dispatch(dataAvailable, nsIThread::DISPATCH_NORMAL))) {
|
||||
NS_WARNING("Dispatching DataAvailable event failed.");
|
||||
}
|
||||
return rv;
|
||||
} else {
|
||||
NS_ASSERTION(IsParserThread(), "Wrong thread!");
|
||||
mozilla::MutexAutoLock autoLock(mTokenizerMutex);
|
||||
|
||||
// Read directly from response buffer.
|
||||
rv = aInStream->ReadSegments(CopySegmentsToParser, this, aLength,
|
||||
&totalRead);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed reading response data to parser");
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
const mozilla::fallible_t fallible = mozilla::fallible_t();
|
||||
nsAutoArrayPtr<uint8_t> data(new (fallible) uint8_t[aLength]);
|
||||
if (!data) {
|
||||
return mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
rv = aInStream->Read(reinterpret_cast<char*>(data.get()),
|
||||
aLength, &totalRead);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(totalRead <= aLength, "Read more bytes than were available?");
|
||||
nsCOMPtr<nsIRunnable> dataAvailable = new nsHtml5DataAvailable(this,
|
||||
data.forget(),
|
||||
totalRead);
|
||||
if (NS_FAILED(mThread->Dispatch(dataAvailable, nsIThread::DISPATCH_NORMAL))) {
|
||||
NS_WARNING("Dispatching DataAvailable event failed.");
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* static */
|
||||
NS_METHOD
|
||||
nsHtml5StreamParser::CopySegmentsToParser(nsIInputStream *aInStream,
|
||||
void *aClosure,
|
||||
const char *aFromSegment,
|
||||
uint32_t aToOffset,
|
||||
uint32_t aCount,
|
||||
uint32_t *aWriteCount)
|
||||
{
|
||||
nsHtml5StreamParser* parser = static_cast<nsHtml5StreamParser*>(aClosure);
|
||||
|
||||
parser->DoDataAvailable((const uint8_t*)aFromSegment, aCount);
|
||||
// Assume DoDataAvailable consumed all available bytes.
|
||||
*aWriteCount = aCount;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
nsHtml5StreamParser::PreferredForInternalEncodingDecl(nsACString& aEncoding)
|
||||
{
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "nsHtml5Speculation.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsICharsetDetector.h"
|
||||
#include "nsIThreadRetargetableStreamListener.h"
|
||||
|
||||
class nsHtml5Parser;
|
||||
|
||||
@ -102,7 +101,6 @@ enum eHtml5StreamState {
|
||||
};
|
||||
|
||||
class nsHtml5StreamParser : public nsIStreamListener,
|
||||
public nsIThreadRetargetableStreamListener,
|
||||
public nsICharsetDetectionObserver {
|
||||
|
||||
friend class nsHtml5RequestStopper;
|
||||
@ -127,8 +125,6 @@ class nsHtml5StreamParser : public nsIStreamListener,
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
// nsIStreamListener methods:
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
// nsIThreadRetargetableStreamListener methods:
|
||||
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
|
||||
|
||||
// nsICharsetDetectionObserver
|
||||
/**
|
||||
@ -243,14 +239,7 @@ class nsHtml5StreamParser : public nsIStreamListener,
|
||||
|
||||
void DoStopRequest();
|
||||
|
||||
void DoDataAvailable(const uint8_t* aBuffer, uint32_t aLength);
|
||||
|
||||
static NS_METHOD CopySegmentsToParser(nsIInputStream *aInStream,
|
||||
void *aClosure,
|
||||
const char *aFromSegment,
|
||||
uint32_t aToOffset,
|
||||
uint32_t aCount,
|
||||
uint32_t *aWriteCount);
|
||||
void DoDataAvailable(uint8_t* aBuffer, uint32_t aLength);
|
||||
|
||||
bool IsTerminatedOrInterrupted() {
|
||||
mozilla::MutexAutoLock autoLock(mTerminatedMutex);
|
||||
|
@ -228,6 +228,7 @@ class nsHtml5TreeOpExecutor : public nsContentSink,
|
||||
* value if broken.
|
||||
*/
|
||||
inline nsresult IsBroken() {
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
return mBroken;
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include "nsURILoader.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsIURIContentListener.h"
|
||||
#include "nsIContentHandler.h"
|
||||
#include "nsILoadGroup.h"
|
||||
@ -31,12 +30,10 @@
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsIDocShellTreeOwner.h"
|
||||
#include "nsIThreadRetargetableStreamListener.h"
|
||||
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsString.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsError.h"
|
||||
|
||||
@ -66,7 +63,6 @@ PRLogModuleInfo* nsURILoader::mLog = nullptr;
|
||||
* (or aborted).
|
||||
*/
|
||||
class nsDocumentOpenInfo MOZ_FINAL : public nsIStreamListener
|
||||
, public nsIThreadRetargetableStreamListener
|
||||
{
|
||||
public:
|
||||
// Needed for nsCOMPtr to work right... Don't call this!
|
||||
@ -114,8 +110,6 @@ public:
|
||||
// nsIStreamListener methods:
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
|
||||
// nsIThreadRetargetableStreamListener
|
||||
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
|
||||
protected:
|
||||
~nsDocumentOpenInfo();
|
||||
|
||||
@ -130,7 +124,7 @@ protected:
|
||||
* The stream listener to forward nsIStreamListener notifications
|
||||
* to. This is set once the load is dispatched.
|
||||
*/
|
||||
nsMainThreadPtrHandle<nsIStreamListener> m_targetStreamListener;
|
||||
nsCOMPtr<nsIStreamListener> m_targetStreamListener;
|
||||
|
||||
/**
|
||||
* A pointer to the entity that originated the load. We depend on getting
|
||||
@ -165,7 +159,6 @@ NS_INTERFACE_MAP_BEGIN(nsDocumentOpenInfo)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRequestObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableStreamListener)
|
||||
NS_INTERFACE_MAP_END_THREADSAFE
|
||||
|
||||
nsDocumentOpenInfo::nsDocumentOpenInfo()
|
||||
@ -273,22 +266,6 @@ NS_IMETHODIMP nsDocumentOpenInfo::OnStartRequest(nsIRequest *request, nsISupport
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocumentOpenInfo::CheckListenerChain()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on the main thread!");
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
|
||||
do_QueryInterface(m_targetStreamListener, &rv);
|
||||
if (retargetableListener) {
|
||||
rv = retargetableListener->CheckListenerChain();
|
||||
}
|
||||
LOG(("[0x%p] nsDocumentOpenInfo::CheckListenerChain %s listener %p rv %x",
|
||||
this, (NS_SUCCEEDED(rv) ? "success" : "failure"),
|
||||
(nsIStreamListener*)m_targetStreamListener, rv));
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocumentOpenInfo::OnDataAvailable(nsIRequest *request, nsISupports * aCtxt,
|
||||
nsIInputStream * inStr,
|
||||
@ -311,7 +288,7 @@ NS_IMETHODIMP nsDocumentOpenInfo::OnStopRequest(nsIRequest *request, nsISupports
|
||||
|
||||
if ( m_targetStreamListener)
|
||||
{
|
||||
nsMainThreadPtrHandle<nsIStreamListener> listener = m_targetStreamListener;
|
||||
nsCOMPtr<nsIStreamListener> listener(m_targetStreamListener);
|
||||
|
||||
// If this is a multipart stream, we could get another
|
||||
// OnStartRequest after this... reset state.
|
||||
@ -537,15 +514,11 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest *request, nsISupports *
|
||||
aChannel->SetContentType(NS_LITERAL_CSTRING(APPLICATION_GUESS_FROM_EXT));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIStreamListener> listener;
|
||||
rv = helperAppService->DoContent(mContentType,
|
||||
request,
|
||||
m_originalContext,
|
||||
false,
|
||||
getter_AddRefs(listener));
|
||||
// Passing false here to allow off main thread use.
|
||||
m_targetStreamListener
|
||||
= new nsMainThreadPtrHolder<nsIStreamListener>(listener, false);
|
||||
getter_AddRefs(m_targetStreamListener));
|
||||
if (NS_FAILED(rv)) {
|
||||
request->SetLoadFlags(loadFlags);
|
||||
m_targetStreamListener = nullptr;
|
||||
@ -585,7 +558,7 @@ nsDocumentOpenInfo::ConvertData(nsIRequest *request,
|
||||
// stream is split up into multiple destination streams. This
|
||||
// intermediate instance is used to target these "decoded" streams...
|
||||
//
|
||||
nsRefPtr<nsDocumentOpenInfo> nextLink =
|
||||
nsCOMPtr<nsDocumentOpenInfo> nextLink =
|
||||
new nsDocumentOpenInfo(m_originalContext, mFlags, mURILoader);
|
||||
if (!nextLink) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
@ -608,16 +581,11 @@ nsDocumentOpenInfo::ConvertData(nsIRequest *request,
|
||||
// stream converter and sets the output end of the stream converter to
|
||||
// nextLink. As we pump data into m_targetStreamListener the stream
|
||||
// converter will convert it and pass the converted data to nextLink.
|
||||
nsCOMPtr<nsIStreamListener> listener;
|
||||
rv = StreamConvService->AsyncConvertData(PromiseFlatCString(aSrcContentType).get(),
|
||||
PromiseFlatCString(aOutContentType).get(),
|
||||
nextLink,
|
||||
request,
|
||||
getter_AddRefs(listener));
|
||||
// Passing false here to allow off main thread use.
|
||||
m_targetStreamListener
|
||||
= new nsMainThreadPtrHolder<nsIStreamListener>(listener, false);
|
||||
return rv;
|
||||
return StreamConvService->AsyncConvertData(PromiseFlatCString(aSrcContentType).get(),
|
||||
PromiseFlatCString(aOutContentType).get(),
|
||||
nextLink,
|
||||
request,
|
||||
getter_AddRefs(m_targetStreamListener));
|
||||
}
|
||||
|
||||
bool
|
||||
@ -662,7 +630,7 @@ nsDocumentOpenInfo::TryContentListener(nsIURIContentListener* aListener,
|
||||
// m_targetStreamListener is now the input end of the converter, and we can
|
||||
// just pump the data in there, if it exists. If it does not, we need to
|
||||
// try other nsIURIContentListeners.
|
||||
return m_targetStreamListener.get() != nullptr;
|
||||
return m_targetStreamListener != nullptr;
|
||||
}
|
||||
|
||||
// At this point, aListener wants data of type mContentType. Let 'em have
|
||||
@ -684,15 +652,12 @@ nsDocumentOpenInfo::TryContentListener(nsIURIContentListener* aListener,
|
||||
|
||||
bool abort = false;
|
||||
bool isPreferred = (mFlags & nsIURILoader::IS_CONTENT_PREFERRED) != 0;
|
||||
nsCOMPtr<nsIStreamListener> listener;
|
||||
nsresult rv = aListener->DoContent(mContentType.get(),
|
||||
isPreferred,
|
||||
aChannel,
|
||||
getter_AddRefs(listener),
|
||||
getter_AddRefs(m_targetStreamListener),
|
||||
&abort);
|
||||
// Passing false here to allow off main thread use.
|
||||
m_targetStreamListener
|
||||
= new nsMainThreadPtrHolder<nsIStreamListener>(listener, false);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG_ERROR((" DoContent failed"));
|
||||
|
||||
@ -847,7 +812,7 @@ nsresult nsURILoader::OpenChannel(nsIChannel* channel,
|
||||
|
||||
// we need to create a DocumentOpenInfo object which will go ahead and open
|
||||
// the url and discover the content type....
|
||||
nsRefPtr<nsDocumentOpenInfo> loader =
|
||||
nsCOMPtr<nsDocumentOpenInfo> loader =
|
||||
new nsDocumentOpenInfo(aWindowContext, aFlags, this);
|
||||
|
||||
if (!loader) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
@ -203,8 +203,6 @@ class nsMainThreadPtrHandle
|
||||
operator T*() { return get(); }
|
||||
T* operator->() { return get(); }
|
||||
|
||||
operator bool() { return get(); }
|
||||
|
||||
// These are safe to call on other threads with appropriate external locking.
|
||||
bool operator==(const nsMainThreadPtrHandle<T>& aOther) const {
|
||||
if (!mPtr || !aOther.mPtr)
|
||||
|
Loading…
Reference in New Issue
Block a user