mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 1724101 - Protect nsHtml5StreamListener::mDelegate with a monitor. r=smaug, a=RyanVM
Differential Revision: https://phabricator.services.mozilla.com/D122471
This commit is contained in:
parent
d77388fc92
commit
2a771d53ae
@ -38,6 +38,7 @@ EXPORTS += [
|
||||
"nsHtml5StreamListener.h",
|
||||
"nsHtml5StreamParser.h",
|
||||
"nsHtml5StreamParserPtr.h",
|
||||
"nsHtml5StreamParserReleaser.h",
|
||||
"nsHtml5String.h",
|
||||
"nsHtml5StringParser.h",
|
||||
"nsHtml5SVGLoadDispatcher.h",
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#include "nsHtml5StreamListener.h"
|
||||
|
||||
#include "nsHtml5StreamParserReleaser.h"
|
||||
|
||||
NS_IMPL_ADDREF(nsHtml5StreamListener)
|
||||
NS_IMPL_RELEASE(nsHtml5StreamListener)
|
||||
|
||||
@ -15,14 +17,40 @@ NS_INTERFACE_MAP_BEGIN(nsHtml5StreamListener)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
nsHtml5StreamListener::nsHtml5StreamListener(nsHtml5StreamParser* aDelegate)
|
||||
: mDelegate(aDelegate) {}
|
||||
: mDelegateMonitor("nsHtml5StreamListener mDelegateMonitor"),
|
||||
mDelegate(aDelegate) {
|
||||
MOZ_ASSERT(aDelegate, "Must have delegate");
|
||||
aDelegate->AddRef();
|
||||
}
|
||||
|
||||
nsHtml5StreamListener::~nsHtml5StreamListener() {}
|
||||
nsHtml5StreamListener::~nsHtml5StreamListener() { DropDelegateImpl(); }
|
||||
|
||||
void nsHtml5StreamListener::DropDelegate() {
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Must not call DropDelegate from non-main threads.");
|
||||
mDelegate = nullptr;
|
||||
DropDelegateImpl();
|
||||
}
|
||||
|
||||
void nsHtml5StreamListener::DropDelegateImpl() {
|
||||
mozilla::ReentrantMonitorAutoEnter autoEnter(mDelegateMonitor);
|
||||
if (mDelegate) {
|
||||
nsCOMPtr<nsIRunnable> releaser = new nsHtml5StreamParserReleaser(mDelegate);
|
||||
if (NS_FAILED(mDelegate->DispatchToMain(releaser.forget()))) {
|
||||
NS_WARNING("Failed to dispatch releaser event.");
|
||||
}
|
||||
mDelegate = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
nsHtml5StreamParser* nsHtml5StreamListener::GetDelegate() {
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
|
||||
// Let's acquire the monitor in order to always access mDelegate
|
||||
// with monitor held. Since this can be called only on the main
|
||||
// thread and DropDelegate() can only be called on the main thread
|
||||
// it's OK that the monitor here doesn't protect the use of the
|
||||
// return value.
|
||||
mozilla::ReentrantMonitorAutoEnter autoEnter(mDelegateMonitor);
|
||||
return mDelegate;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -35,6 +63,7 @@ nsHtml5StreamListener::CheckListenerChain() {
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHtml5StreamListener::OnStartRequest(nsIRequest* aRequest) {
|
||||
mozilla::ReentrantMonitorAutoEnter autoEnter(mDelegateMonitor);
|
||||
if (MOZ_UNLIKELY(!mDelegate)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
@ -43,6 +72,7 @@ nsHtml5StreamListener::OnStartRequest(nsIRequest* aRequest) {
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHtml5StreamListener::OnStopRequest(nsIRequest* aRequest, nsresult aStatus) {
|
||||
mozilla::ReentrantMonitorAutoEnter autoEnter(mDelegateMonitor);
|
||||
if (MOZ_UNLIKELY(!mDelegate)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
@ -54,6 +84,7 @@ nsHtml5StreamListener::OnDataAvailable(nsIRequest* aRequest,
|
||||
nsIInputStream* aInStream,
|
||||
uint64_t aSourceOffset,
|
||||
uint32_t aLength) {
|
||||
mozilla::ReentrantMonitorAutoEnter autoEnter(mDelegateMonitor);
|
||||
if (MOZ_UNLIKELY(!mDelegate)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
@ -7,8 +7,8 @@
|
||||
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIThreadRetargetableStreamListener.h"
|
||||
#include "nsHtml5StreamParserPtr.h"
|
||||
#include "nsHtml5StreamParser.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
|
||||
/**
|
||||
* The purpose of this class is to reconcile the problem that
|
||||
@ -38,14 +38,23 @@ class nsHtml5StreamListener : public nsIStreamListener,
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
|
||||
|
||||
inline nsHtml5StreamParser* GetDelegate() { return mDelegate; }
|
||||
// Main-thread-only
|
||||
nsHtml5StreamParser* GetDelegate();
|
||||
|
||||
// Main-thread-only
|
||||
void DropDelegate();
|
||||
|
||||
private:
|
||||
void DropDelegateImpl();
|
||||
virtual ~nsHtml5StreamListener();
|
||||
|
||||
nsHtml5StreamParserPtr mDelegate;
|
||||
// ReentrantMonitor instead of Mutex, because `GetDelegate()`
|
||||
// can be called from within the Necko callbacks when Necko events
|
||||
// are delivered on the main thread.
|
||||
mozilla::ReentrantMonitor mDelegateMonitor;
|
||||
// Owning pointer with manually-managed refcounting, protected by
|
||||
// mDelegateMonitor.
|
||||
nsHtml5StreamParser* mDelegate;
|
||||
};
|
||||
|
||||
#endif // nsHtml5StreamListener_h
|
||||
|
@ -191,6 +191,7 @@ class nsHtml5StreamParser final : public nsISupports {
|
||||
friend class nsHtml5StreamParserContinuation;
|
||||
friend class nsHtml5TimerKungFu;
|
||||
friend class nsHtml5StreamParserPtr;
|
||||
friend class nsHtml5StreamListener;
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
@ -7,22 +7,10 @@
|
||||
#define nsHtml5StreamParserPtr_h
|
||||
|
||||
#include "nsHtml5StreamParser.h"
|
||||
#include "nsHtml5StreamParserReleaser.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/dom/DocGroup.h"
|
||||
|
||||
class nsHtml5StreamParserReleaser : public mozilla::Runnable {
|
||||
private:
|
||||
nsHtml5StreamParser* mPtr;
|
||||
|
||||
public:
|
||||
explicit nsHtml5StreamParserReleaser(nsHtml5StreamParser* aPtr)
|
||||
: mozilla::Runnable("nsHtml5StreamParserReleaser"), mPtr(aPtr) {}
|
||||
NS_IMETHOD Run() override {
|
||||
mPtr->Release();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Like nsRefPtr except release is proxied to the main
|
||||
* thread. Mostly copied from nsRefPtr.
|
||||
|
25
parser/html/nsHtml5StreamParserReleaser.h
Normal file
25
parser/html/nsHtml5StreamParserReleaser.h
Normal file
@ -0,0 +1,25 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef nsHtml5StreamParserReleaser_h
|
||||
#define nsHtml5StreamParserReleaser_h
|
||||
|
||||
#include "nsHtml5StreamParser.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
class nsHtml5StreamParserReleaser : public mozilla::Runnable {
|
||||
private:
|
||||
nsHtml5StreamParser* mPtr;
|
||||
|
||||
public:
|
||||
explicit nsHtml5StreamParserReleaser(nsHtml5StreamParser* aPtr)
|
||||
: mozilla::Runnable("nsHtml5StreamParserReleaser"), mPtr(aPtr) {}
|
||||
NS_IMETHOD Run() override {
|
||||
mPtr->Release();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // nsHtml5StreamParserReleaser_h
|
Loading…
Reference in New Issue
Block a user