Bug 1333099 - Fix crash when incorrectly access EventSourceImpl::mEventSource. r=baku

MozReview-Commit-ID: K8nepp9G1Ho
This commit is contained in:
Stone Shih 2017-01-24 10:26:30 +08:00
parent 98c86f084f
commit b5f1768cea

View File

@ -159,8 +159,8 @@ public:
uint16_t ReadyState()
{
MutexAutoLock lock(mMutex);
if (mEventSource) {
MutexAutoLock lock(mMutex);
return mEventSource->mReadyState;
}
// EventSourceImpl keeps EventSource alive. If mEventSource is null, it
@ -170,8 +170,9 @@ public:
void SetReadyState(uint16_t aReadyState)
{
MOZ_ASSERT(mEventSource);
MutexAutoLock lock(mMutex);
MOZ_ASSERT(mEventSource);
MOZ_ASSERT(!mIsShutDown);
mEventSource->mReadyState = aReadyState;
}
@ -192,6 +193,19 @@ public:
return ReadyState() == CLOSED;
}
void ShutDown()
{
MutexAutoLock lock(mMutex);
MOZ_ASSERT(!mIsShutDown);
mIsShutDown = true;
}
bool IsShutDown()
{
MutexAutoLock lock(mMutex);
return mIsShutDown;
}
RefPtr<EventSource> mEventSource;
/**
@ -293,7 +307,7 @@ public:
// Whether the EventSource is run on main thread.
bool mIsMainThread;
// Whether the EventSourceImpl is going to be destroyed.
bool mIsClosing;
bool mIsShutDown;
// Event Source owner information:
// - the script file name
@ -342,7 +356,7 @@ EventSourceImpl::EventSourceImpl(EventSource* aEventSource)
, mFrozen(false)
, mGoingToDispatchAllMessages(false)
, mIsMainThread(NS_IsMainThread())
, mIsClosing(false)
, mIsShutDown(false)
, mScriptLine(0)
, mScriptColumn(0)
, mInnerWindowID(0)
@ -398,14 +412,12 @@ EventSourceImpl::CloseInternal()
{
AssertIsOnTargetThread();
MOZ_ASSERT(IsClosed());
if (mIsClosing) {
if (IsShutDown()) {
return;
}
mIsClosing = true;
while (mMessagesToDispatch.GetSize() != 0) {
delete static_cast<Message*>(mMessagesToDispatch.PopFront());
}
// Invoke CleanupOnMainThread before cleaning any members. It will call
// ShutDown, which is supposed to be called before cleaning any members.
if (NS_IsMainThread()) {
CleanupOnMainThread();
} else {
@ -418,6 +430,9 @@ EventSourceImpl::CloseInternal()
UnregisterWorkerHolder();
}
while (mMessagesToDispatch.GetSize() != 0) {
delete static_cast<Message*>(mMessagesToDispatch.PopFront());
}
SetFrozen(false);
ResetDecoder();
mUnicodeDecoder = nullptr;
@ -429,6 +444,11 @@ EventSourceImpl::CloseInternal()
void EventSourceImpl::CleanupOnMainThread()
{
AssertIsOnMainThread();
MOZ_ASSERT(IsClosed());
// Call ShutDown before cleaning any members.
ShutDown();
if (mIsMainThread) {
RemoveWindowObservers();
}
@ -490,6 +510,7 @@ nsresult
EventSourceImpl::ParseURL(const nsAString& aURL)
{
AssertIsOnMainThread();
MOZ_ASSERT(!IsShutDown());
// get the src
nsCOMPtr<nsIURI> baseURI;
nsresult rv = GetBaseURI(getter_AddRefs(baseURI));
@ -518,6 +539,7 @@ EventSourceImpl::AddWindowObservers()
{
AssertIsOnMainThread();
MOZ_ASSERT(mIsMainThread);
MOZ_ASSERT(!IsShutDown());
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
NS_ENSURE_STATE(os);
@ -535,6 +557,7 @@ EventSourceImpl::RemoveWindowObservers()
{
AssertIsOnMainThread();
MOZ_ASSERT(mIsMainThread);
MOZ_ASSERT(IsClosed());
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os) {
os->RemoveObserver(this, DOM_WINDOW_DESTROYED_TOPIC);
@ -550,9 +573,7 @@ EventSourceImpl::Init(nsIPrincipal* aPrincipal,
{
AssertIsOnMainThread();
MOZ_ASSERT(aPrincipal);
if (IsClosed()) {
return;
}
MOZ_ASSERT(ReadyState() == CONNECTING);
mPrincipal = aPrincipal;
aRv = ParseURL(aURL);
if (NS_WARN_IF(aRv.Failed())) {
@ -694,6 +715,7 @@ EventSourceImpl::StreamReaderFunc(nsIInputStream* aInputStream,
return NS_ERROR_FAILURE;
}
thisObject->AssertIsOnTargetThread();
MOZ_ASSERT(!thisObject->IsShutDown());
thisObject->ParseSegment((const char*)aFromRawSegment, aCount);
*aWriteCount = aCount;
return NS_OK;
@ -846,6 +868,9 @@ EventSourceImpl::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
nsIAsyncVerifyRedirectCallback* aCallback)
{
AssertIsOnMainThread();
if (IsClosed()) {
return NS_ERROR_ABORT;
}
nsCOMPtr<nsIRequest> aOldRequest = do_QueryInterface(aOldChannel);
NS_PRECONDITION(aOldRequest, "Redirect from a null request?");
@ -895,6 +920,11 @@ NS_IMETHODIMP
EventSourceImpl::GetInterface(const nsIID& aIID, void** aResult)
{
AssertIsOnMainThread();
if (IsClosed()) {
return NS_ERROR_FAILURE;
}
if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) {
*aResult = static_cast<nsIChannelEventSink*>(this);
NS_ADDREF_THIS();
@ -935,6 +965,7 @@ nsresult
EventSourceImpl::GetBaseURI(nsIURI** aBaseURI)
{
AssertIsOnMainThread();
MOZ_ASSERT(!IsShutDown());
NS_ENSURE_ARG_POINTER(aBaseURI);
*aBaseURI = nullptr;
@ -963,6 +994,7 @@ void
EventSourceImpl::SetupHttpChannel()
{
AssertIsOnMainThread();
MOZ_ASSERT(!IsShutDown());
mHttpChannel->SetRequestMethod(NS_LITERAL_CSTRING("GET"));
/* set the http request headers */
@ -982,6 +1014,7 @@ nsresult
EventSourceImpl::SetupReferrerPolicy()
{
AssertIsOnMainThread();
MOZ_ASSERT(!IsShutDown());
nsCOMPtr<nsIDocument> doc = mEventSource->GetDocumentIfCurrent();
if (doc) {
nsresult rv = mHttpChannel->SetReferrerWithPolicy(doc->GetDocumentURI(),
@ -1152,6 +1185,9 @@ nsresult
EventSourceImpl::RestartConnection()
{
AssertIsOnMainThread();
if (IsClosed()) {
return NS_ERROR_ABORT;
}
nsresult rv = ResetConnection();
NS_ENSURE_SUCCESS(rv, rv);
rv = SetReconnectionTimeout();
@ -1224,6 +1260,7 @@ EventSourceImpl::PrintErrorOnConsole(const char* aBundleURI,
uint32_t aFormatStringsLen)
{
AssertIsOnMainThread();
MOZ_ASSERT(!IsShutDown());
nsCOMPtr<nsIStringBundleService> bundleService =
mozilla::services::GetStringBundleService();
NS_ENSURE_STATE(bundleService);
@ -1271,6 +1308,7 @@ nsresult
EventSourceImpl::ConsoleError()
{
AssertIsOnMainThread();
MOZ_ASSERT(!IsShutDown());
nsAutoCString targetSpec;
nsresult rv = mSrc->GetSpec(targetSpec);
NS_ENSURE_SUCCESS(rv, rv);
@ -1401,6 +1439,7 @@ nsresult
EventSourceImpl::DispatchCurrentMessageEvent()
{
AssertIsOnTargetThread();
MOZ_ASSERT(!IsShutDown());
UniquePtr<Message> message(Move(mCurrentMessage));
ClearFields();
@ -1519,6 +1558,7 @@ EventSourceImpl::ClearFields()
nsresult
EventSourceImpl::SetFieldAndClear()
{
MOZ_ASSERT(!IsShutDown());
AssertIsOnTargetThread();
if (mLastFieldName.IsEmpty()) {
mLastFieldValue.Truncate();
@ -1848,6 +1888,7 @@ private:
bool EventSourceImpl::RegisterWorkerHolder()
{
MOZ_ASSERT(!IsShutDown());
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(!mWorkerHolder);
@ -1888,6 +1929,10 @@ EventSourceImpl::Dispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aFlags)
if (mIsMainThread) {
return NS_DispatchToMainThread(event_ref.forget());
}
if (IsShutDown()) {
return NS_OK;
}
MOZ_ASSERT(mWorkerPrivate);
// If the target is a worker, we have to use a custom WorkerRunnableDispatcher
// runnable.