Bug 1455020 - Extend CheckInnerWindowCorrectness() to check the state of the worker, r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D25486

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Andrea Marchesini 2019-04-01 16:46:46 +00:00
Родитель fd7ed41616
Коммит 484db81418
17 изменённых файлов: 101 добавлений и 46 удалений

Просмотреть файл

@ -138,7 +138,7 @@ void DOMRequest::FireDetailedError(DOMException& aError) {
void DOMRequest::FireEvent(const nsAString& aType, bool aBubble,
bool aCancelable) {
if (NS_FAILED(CheckInnerWindowCorrectness())) {
if (NS_FAILED(CheckCurrentGlobalCorrectness())) {
return;
}

Просмотреть файл

@ -1782,7 +1782,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(Document)
for (MediaQueryList* mql = tmp->mDOMMediaQueryLists.getFirst(); mql;
mql = static_cast<LinkedListElement<MediaQueryList>*>(mql)->getNext()) {
if (mql->HasListeners() &&
NS_SUCCEEDED(mql->CheckInnerWindowCorrectness())) {
NS_SUCCEEDED(mql->CheckCurrentGlobalCorrectness())) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mDOMMediaQueryLists item");
cb.NoteXPCOMChild(mql);
}

Просмотреть файл

@ -797,7 +797,7 @@ EventSourceImpl::AsyncOnChannelRedirect(
(NS_SUCCEEDED(newURI->SchemeIs("https", &isValidScheme)) &&
isValidScheme);
rv = mEventSource->CheckInnerWindowCorrectness();
rv = mEventSource->CheckCurrentGlobalCorrectness();
if (NS_FAILED(rv) || !isValidScheme) {
DispatchFailConnection();
return NS_ERROR_DOM_SECURITY_ERR;
@ -842,7 +842,7 @@ EventSourceImpl::GetInterface(const nsIID& aIID, void** aResult) {
if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)) ||
aIID.Equals(NS_GET_IID(nsIAuthPrompt2))) {
nsresult rv = mEventSource->CheckInnerWindowCorrectness();
nsresult rv = mEventSource->CheckCurrentGlobalCorrectness();
NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIPromptFactory> wwatch =
@ -952,7 +952,7 @@ nsresult EventSourceImpl::InitChannelAndRequestEventSource() {
(NS_SUCCEEDED(mSrc->SchemeIs("http", &isValidScheme)) && isValidScheme) ||
(NS_SUCCEEDED(mSrc->SchemeIs("https", &isValidScheme)) && isValidScheme);
nsresult rv = mEventSource->CheckInnerWindowCorrectness();
nsresult rv = mEventSource->CheckCurrentGlobalCorrectness();
if (NS_FAILED(rv) || !isValidScheme) {
DispatchFailConnection();
return NS_ERROR_DOM_SECURITY_ERR;
@ -1039,7 +1039,7 @@ void EventSourceImpl::AnnounceConnection() {
SetReadyState(OPEN);
nsresult rv = mEventSource->CheckInnerWindowCorrectness();
nsresult rv = mEventSource->CheckCurrentGlobalCorrectness();
if (NS_FAILED(rv)) {
return;
}
@ -1120,7 +1120,7 @@ void EventSourceImpl::ReestablishConnection() {
return;
}
rv = mEventSource->CheckInnerWindowCorrectness();
rv = mEventSource->CheckCurrentGlobalCorrectness();
if (NS_FAILED(rv)) {
return;
}
@ -1252,7 +1252,7 @@ void EventSourceImpl::FailConnection() {
// When a user agent is to fail the connection, the user agent must set the
// readyState attribute to CLOSED and queue a task to fire a simple event
// named error at the EventSource object.
nsresult rv = mEventSource->CheckInnerWindowCorrectness();
nsresult rv = mEventSource->CheckCurrentGlobalCorrectness();
if (NS_SUCCEEDED(rv)) {
rv = mEventSource->CreateAndDispatchSimpleEvent(NS_LITERAL_STRING("error"));
if (NS_FAILED(rv)) {
@ -1370,7 +1370,7 @@ void EventSourceImpl::DispatchAllMessageEvents() {
return;
}
nsresult rv = mEventSource->CheckInnerWindowCorrectness();
nsresult rv = mEventSource->CheckCurrentGlobalCorrectness();
if (NS_FAILED(rv)) {
return;
}

Просмотреть файл

@ -100,7 +100,7 @@ nsresult nsDOMDataChannel::Init(nsPIDOMWindowInner* aDOMWindow) {
// Attempt to kill "ghost" DataChannel (if one can happen): but usually too
// early for check to fail
rv = CheckInnerWindowCorrectness();
rv = CheckCurrentGlobalCorrectness();
NS_ENSURE_SUCCESS(rv, rv);
rv = nsContentUtils::GetUTFOrigin(principal, mOrigin);
@ -261,7 +261,7 @@ nsresult nsDOMDataChannel::DoOnMessageAvailable(const nsACString& aData,
? ((mBinaryType == DC_BINARY_TYPE_BLOB) ? " (blob)" : " (binary)")
: ""));
nsresult rv = CheckInnerWindowCorrectness();
nsresult rv = CheckCurrentGlobalCorrectness();
if (NS_FAILED(rv)) {
return NS_OK;
}
@ -333,7 +333,7 @@ nsresult nsDOMDataChannel::OnSimpleEvent(nsISupports* aContext,
const nsAString& aName) {
MOZ_ASSERT(NS_IsMainThread());
nsresult rv = CheckInnerWindowCorrectness();
nsresult rv = CheckCurrentGlobalCorrectness();
if (NS_FAILED(rv)) {
return NS_OK;
}

Просмотреть файл

@ -43,9 +43,7 @@ mozilla::ipc::IPCResult BroadcastChannelChild::RecvNotify(
return IPC_OK();
}
// CheckInnerWindowCorrectness can be used also without a window when
// BroadcastChannel is running in a worker. In this case, it's a NOP.
if (NS_FAILED(mBC->CheckInnerWindowCorrectness())) {
if (NS_FAILED(mBC->CheckCurrentGlobalCorrectness())) {
return IPC_OK();
}

Просмотреть файл

@ -134,7 +134,7 @@ void DOMEventTargetHelper::DisconnectFromOwner() {
}
nsPIDOMWindowInner* DOMEventTargetHelper::GetWindowIfCurrent() const {
if (NS_FAILED(CheckInnerWindowCorrectness())) {
if (NS_FAILED(CheckCurrentGlobalCorrectness())) {
return nullptr;
}
@ -212,7 +212,7 @@ EventListenerManager* DOMEventTargetHelper::GetExistingListenerManager() const {
}
nsresult DOMEventTargetHelper::WantsUntrusted(bool* aRetVal) {
nsresult rv = CheckInnerWindowCorrectness();
nsresult rv = CheckCurrentGlobalCorrectness();
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<Document> doc = GetDocumentIfCurrent();
@ -253,7 +253,7 @@ void DOMEventTargetHelper::IgnoreKeepAliveIfHasListenersFor(nsAtom* aType) {
void DOMEventTargetHelper::MaybeUpdateKeepAlive() {
bool shouldBeKeptAlive = false;
if (NS_SUCCEEDED(CheckInnerWindowCorrectness())) {
if (NS_SUCCEEDED(CheckCurrentGlobalCorrectness())) {
if (!mKeepingAliveTypes.mAtoms.IsEmpty()) {
for (uint32_t i = 0; i < mKeepingAliveTypes.mAtoms.Length(); ++i) {
if (HasListenersFor(mKeepingAliveTypes.mAtoms[i])) {
@ -314,4 +314,23 @@ void DOMEventTargetHelper::BindToOwnerInternal(nsIGlobalObject* aOwner) {
}
}
nsresult DOMEventTargetHelper::CheckCurrentGlobalCorrectness() const {
NS_ENSURE_STATE(!mHasOrHasHadOwnerWindow || mOwnerWindow);
// Main-thread.
if (mOwnerWindow && !mOwnerWindow->IsCurrentInnerWindow()) {
return NS_ERROR_FAILURE;
}
if (NS_IsMainThread()) {
return NS_OK;
}
if (!mParentObject) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
} // namespace mozilla

Просмотреть файл

@ -131,13 +131,7 @@ class DOMEventTargetHelper : public dom::EventTarget,
return nsPIDOMWindowOuter::GetFromCurrentInner(GetOwner());
}
nsresult CheckInnerWindowCorrectness() const {
NS_ENSURE_STATE(!mHasOrHasHadOwnerWindow || mOwnerWindow);
if (mOwnerWindow && !mOwnerWindow->IsCurrentInnerWindow()) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult CheckCurrentGlobalCorrectness() const;
nsPIDOMWindowInner* GetOwner() const { return mOwnerWindow; }
// Like GetOwner, but only returns non-null if the window being returned is

Просмотреть файл

@ -51,7 +51,7 @@ already_AddRefed<IDBFileRequest> IDBFileRequest::Create(
void IDBFileRequest::FireProgressEvent(uint64_t aLoaded, uint64_t aTotal) {
AssertIsOnOwningThread();
if (NS_FAILED(CheckInnerWindowCorrectness())) {
if (NS_FAILED(CheckCurrentGlobalCorrectness())) {
return;
}

Просмотреть файл

@ -277,8 +277,8 @@ void IDBRequest::SetResultCallback(ResultCallback* aCallback) {
return;
}
// See if our window is still valid.
if (NS_WARN_IF(NS_FAILED(CheckInnerWindowCorrectness()))) {
// See this global is still valid.
if (NS_WARN_IF(NS_FAILED(CheckCurrentGlobalCorrectness()))) {
SetError(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
return;
}

Просмотреть файл

@ -164,7 +164,7 @@ NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
void MediaDevices::OnDeviceChange() {
MOZ_ASSERT(NS_IsMainThread());
nsresult rv = CheckInnerWindowCorrectness();
nsresult rv = CheckCurrentGlobalCorrectness();
if (NS_FAILED(rv)) {
MOZ_ASSERT(false);
return;

Просмотреть файл

@ -1586,7 +1586,7 @@ nsresult MediaRecorder::CreateAndDispatchBlobEvent(Blob* aBlob) {
void MediaRecorder::DispatchSimpleEvent(const nsAString& aStr) {
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
nsresult rv = CheckInnerWindowCorrectness();
nsresult rv = CheckCurrentGlobalCorrectness();
if (NS_FAILED(rv)) {
return;
}
@ -1602,7 +1602,7 @@ void MediaRecorder::DispatchSimpleEvent(const nsAString& aStr) {
void MediaRecorder::NotifyError(nsresult aRv) {
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
nsresult rv = CheckInnerWindowCorrectness();
nsresult rv = CheckCurrentGlobalCorrectness();
if (NS_FAILED(rv)) {
return;
}

Просмотреть файл

@ -161,7 +161,7 @@ nsresult ImageCapture::PostBlobEvent(Blob* aBlob) {
nsresult ImageCapture::PostErrorEvent(uint16_t aErrorCode, nsresult aReason) {
MOZ_ASSERT(NS_IsMainThread());
nsresult rv = CheckInnerWindowCorrectness();
nsresult rv = CheckCurrentGlobalCorrectness();
NS_ENSURE_SUCCESS(rv, rv);
nsString errorMsg;

Просмотреть файл

@ -570,7 +570,7 @@ void UDPSocket::HandleReceivedData(const nsACString& aRemoteAddress,
return;
}
if (NS_FAILED(CheckInnerWindowCorrectness())) {
if (NS_FAILED(CheckCurrentGlobalCorrectness())) {
return;
}

Просмотреть файл

@ -693,7 +693,7 @@ WebSocketImpl::OnStart(nsISupports* aContext) {
}
// Attempt to kill "ghost" websocket: but usually too early for check to fail
nsresult rv = mWebSocket->CheckInnerWindowCorrectness();
nsresult rv = mWebSocket->CheckCurrentGlobalCorrectness();
if (NS_FAILED(rv)) {
CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
return rv;
@ -1461,7 +1461,7 @@ nsresult WebSocketImpl::Init(JSContext* aCx, nsIPrincipal* aLoadingPrincipal,
RefPtr<WebSocketImpl> kungfuDeathGrip = this;
// Attempt to kill "ghost" websocket: but usually too early for check to fail
nsresult rv = mWebSocket->CheckInnerWindowCorrectness();
nsresult rv = mWebSocket->CheckCurrentGlobalCorrectness();
NS_ENSURE_SUCCESS(rv, rv);
// Shut down websocket if window is frozen or destroyed (only needed for
@ -1512,7 +1512,7 @@ nsresult WebSocketImpl::Init(JSContext* aCx, nsIPrincipal* aLoadingPrincipal,
nsCOMPtr<Document> originDoc = mWebSocket->GetDocumentIfCurrent();
if (!originDoc) {
rv = mWebSocket->CheckInnerWindowCorrectness();
rv = mWebSocket->CheckCurrentGlobalCorrectness();
NS_ENSURE_SUCCESS(rv, rv);
}
mOriginDocument = do_GetWeakReference(originDoc);
@ -1779,7 +1779,7 @@ nsresult WebSocket::CreateAndDispatchSimpleEvent(const nsAString& aName) {
MOZ_ASSERT(mImpl);
AssertIsOnTargetThread();
nsresult rv = CheckInnerWindowCorrectness();
nsresult rv = CheckCurrentGlobalCorrectness();
if (NS_FAILED(rv)) {
return NS_OK;
}
@ -1807,7 +1807,7 @@ nsresult WebSocket::CreateAndDispatchMessageEvent(const nsACString& aData,
JSContext* cx = jsapi.cx();
nsresult rv = CheckInnerWindowCorrectness();
nsresult rv = CheckCurrentGlobalCorrectness();
if (NS_FAILED(rv)) {
return NS_OK;
}
@ -1884,7 +1884,7 @@ nsresult WebSocket::CreateAndDispatchCloseEvent(bool aWasClean, uint16_t aCode,
aReason);
}
nsresult rv = CheckInnerWindowCorrectness();
nsresult rv = CheckCurrentGlobalCorrectness();
if (NS_FAILED(rv)) {
return NS_OK;
}

Просмотреть файл

@ -80,6 +80,10 @@ WorkerGlobalScope::WorkerGlobalScope(WorkerPrivate* aWorkerPrivate)
// We should always have an event target when the global is created.
MOZ_DIAGNOSTIC_ASSERT(mSerialEventTarget);
// In workers, each DETH must have an owner. Because the global scope doesn't
// have one, let's set it as owner of itself.
BindToOwner(static_cast<nsIGlobalObject*>(this));
}
WorkerGlobalScope::~WorkerGlobalScope() {
@ -781,6 +785,10 @@ WorkerDebuggerGlobalScope::WorkerDebuggerGlobalScope(
// We should always have an event target when the global is created.
MOZ_DIAGNOSTIC_ASSERT(mSerialEventTarget);
// In workers, each DETH must have an owner. Because the global scope doesn't
// have an owner, let's set it as owner of itself.
BindToOwner(static_cast<nsIGlobalObject*>(this));
}
WorkerDebuggerGlobalScope::~WorkerDebuggerGlobalScope() {

Просмотреть файл

@ -1206,7 +1206,7 @@ void XMLHttpRequestMainThread::DispatchProgressEvent(
int64_t aLoaded, int64_t aTotal) {
NS_ASSERTION(aTarget, "null target");
if (NS_FAILED(CheckInnerWindowCorrectness()) ||
if (NS_FAILED(CheckCurrentGlobalCorrectness()) ||
(!AllowUploadProgress() && aTarget == mUpload)) {
return;
}
@ -1266,7 +1266,7 @@ void XMLHttpRequestMainThread::DispatchOrStoreEvent(
MOZ_ASSERT(aTarget);
MOZ_ASSERT(aEvent);
if (NS_FAILED(CheckInnerWindowCorrectness())) {
if (NS_FAILED(CheckCurrentGlobalCorrectness())) {
return;
}
@ -1292,7 +1292,7 @@ void XMLHttpRequestMainThread::ResumeEventDispatching() {
nsTArray<PendingEvent> pendingEvents;
pendingEvents.SwapElements(mPendingEvents);
if (NS_FAILED(CheckInnerWindowCorrectness())) {
if (NS_FAILED(CheckCurrentGlobalCorrectness())) {
return;
}
@ -1364,7 +1364,7 @@ nsresult XMLHttpRequestMainThread::Open(const nsACString& aMethod,
if (!responsibleDocument) {
// This could be because we're no longer current or because we're in some
// non-window context...
nsresult rv = CheckInnerWindowCorrectness();
nsresult rv = CheckCurrentGlobalCorrectness();
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_DOM_INVALID_STATE_XHR_HAS_INVALID_CONTEXT;
}
@ -1417,7 +1417,7 @@ nsresult XMLHttpRequestMainThread::Open(const nsACString& aMethod,
}
return rv;
}
if (NS_WARN_IF(NS_FAILED(CheckInnerWindowCorrectness()))) {
if (NS_WARN_IF(NS_FAILED(CheckCurrentGlobalCorrectness()))) {
return NS_ERROR_DOM_INVALID_STATE_XHR_HAS_INVALID_CONTEXT;
}
@ -1966,7 +1966,7 @@ XMLHttpRequestMainThread::OnStartRequest(nsIRequest* request) {
} else {
// If we're no longer current, just kill the load, though it really should
// have been killed already.
if (NS_WARN_IF(NS_FAILED(CheckInnerWindowCorrectness()))) {
if (NS_WARN_IF(NS_FAILED(CheckCurrentGlobalCorrectness()))) {
return NS_ERROR_DOM_INVALID_STATE_XHR_HAS_INVALID_CONTEXT;
}
}
@ -2790,7 +2790,7 @@ nsresult XMLHttpRequestMainThread::SendInternal(const BodyExtractorBase* aBody,
return NS_ERROR_DOM_INVALID_STATE_XHR_MUST_NOT_BE_SENDING;
}
nsresult rv = CheckInnerWindowCorrectness();
nsresult rv = CheckCurrentGlobalCorrectness();
if (NS_FAILED(rv)) {
return NS_ERROR_DOM_INVALID_STATE_XHR_HAS_INVALID_CONTEXT;
}

Просмотреть файл

@ -0,0 +1,36 @@
<!DOCTYPE html>
<meta charset=utf-8>
<link rel="help" href="https://html.spec.whatwg.org/multipage/comms.html#messageevent">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
async_test(t => {
function workerCode() {
onmessage = function(e) {
close();
var mc = new MessageChannel();
mc.port1.onmessage = function() {
postMessage("message received!");
}
mc.port2.postMessage(42);
postMessage("done");
}
}
var workerBlob = new Blob([workerCode.toString() + ";workerCode();"], {type:"application/javascript"});
var w = new Worker(URL.createObjectURL(workerBlob));
w.postMessage('');
w.onmessage = function(e) {
if (e.data == "done") {
setTimeout(function() {
t.done();
}, 250);
} else {
assert_true(false, "A wrong message has been received!");
}
}
}, 'MessageChannel/MessagePort should not work after a worker self.close()');
</script>