Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit c20eddf

Browse files
committed
Bug 1682928 - Remove some potential data races. r=asuth,dom-workers-and-storage-reviewers, a=tjr
Differential Revision: https://phabricator.services.mozilla.com/D101163
1 parent 3824b2d commit c20eddf

File tree

1 file changed

+44
-23
lines changed

1 file changed

+44
-23
lines changed

dom/base/EventSource.cpp

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ class EventSourceImpl final : public nsIObserver,
9898
nsresult GetBaseURI(nsIURI** aBaseURI);
9999

100100
void SetupHttpChannel();
101-
nsresult SetupReferrerInfo();
102-
nsresult InitChannelAndRequestEventSource();
101+
nsresult SetupReferrerInfo(const nsCOMPtr<Document>& aDocument);
102+
nsresult InitChannelAndRequestEventSource(bool aEventTargetAccessAllowed);
103103
nsresult ResetConnection();
104104
void ResetDecoder();
105105
nsresult SetReconnectionTimeout();
@@ -554,7 +554,9 @@ class ConnectRunnable final : public WorkerMainThreadRunnable {
554554

555555
bool MainThreadRun() override {
556556
MOZ_ASSERT(mESImpl);
557-
mESImpl->InitChannelAndRequestEventSource();
557+
// We are allowed to access the event target since this runnable is
558+
// synchronized with the thread the event target lives on.
559+
mESImpl->InitChannelAndRequestEventSource(true);
558560
// We want to ensure the shortest possible remaining lifetime
559561
// and not depend on the Runnable's destruction.
560562
mESImpl = nullptr;
@@ -585,6 +587,10 @@ nsresult EventSourceImpl::ParseURL(const nsAString& aURL) {
585587
rv = srcURI->GetSpec(spec);
586588
NS_ENSURE_SUCCESS(rv, rv);
587589

590+
// This assignment doesn't require extra synchronization because this function
591+
// is only ever called from EventSourceImpl::Init(), which is either called
592+
// directly if mEventSource was created on the main thread, or via a
593+
// synchronous runnable if it was created on a worker thread.
588594
mEventSource->mOriginalURL = NS_ConvertUTF8toUTF16(spec);
589595
mSrc = srcURI;
590596
mOrigin = origin;
@@ -664,6 +670,7 @@ EventSourceImpl::Observe(nsISupports* aSubject, const char* aTopic,
664670
}
665671

666672
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aSubject);
673+
MOZ_ASSERT(mIsMainThread);
667674
if (!mEventSource->GetOwner() || window != mEventSource->GetOwner()) {
668675
return NS_OK;
669676
}
@@ -882,7 +889,7 @@ EventSourceImpl::AsyncOnChannelRedirect(
882889

883890
bool isValidScheme = newURI->SchemeIs("http") || newURI->SchemeIs("https");
884891

885-
rv = mEventSource->CheckCurrentGlobalCorrectness();
892+
rv = mIsMainThread ? mEventSource->CheckCurrentGlobalCorrectness() : NS_OK;
886893
if (NS_FAILED(rv) || !isValidScheme) {
887894
DispatchFailConnection();
888895
return NS_ERROR_DOM_SECURITY_ERR;
@@ -927,21 +934,27 @@ EventSourceImpl::GetInterface(const nsIID& aIID, void** aResult) {
927934

928935
if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)) ||
929936
aIID.Equals(NS_GET_IID(nsIAuthPrompt2))) {
930-
nsresult rv = mEventSource->CheckCurrentGlobalCorrectness();
931-
NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
932-
937+
nsresult rv;
933938
nsCOMPtr<nsIPromptFactory> wwatch =
934939
do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
935940
NS_ENSURE_SUCCESS(rv, rv);
936941

937-
// Get the an auth prompter for our window so that the parenting
938-
// of the dialogs works as it should when using tabs.
939-
940942
nsCOMPtr<nsPIDOMWindowOuter> window;
941-
if (mEventSource->GetOwner()) {
942-
window = mEventSource->GetOwner()->GetOuterWindow();
943+
944+
// To avoid a data race we may only access the event target if it lives on
945+
// the main thread.
946+
if (mIsMainThread) {
947+
rv = mEventSource->CheckCurrentGlobalCorrectness();
948+
NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
949+
950+
if (mEventSource->GetOwner()) {
951+
window = mEventSource->GetOwner()->GetOuterWindow();
952+
}
943953
}
944954

955+
// Get the an auth prompter for our window so that the parenting
956+
// of the dialogs works as it should when using tabs.
957+
945958
return wwatch->GetPrompt(window, aIID, aResult);
946959
}
947960

@@ -967,7 +980,8 @@ nsresult EventSourceImpl::GetBaseURI(nsIURI** aBaseURI) {
967980
nsCOMPtr<nsIURI> baseURI;
968981

969982
// first we try from document->GetBaseURI()
970-
nsCOMPtr<Document> doc = mEventSource->GetDocumentIfCurrent();
983+
nsCOMPtr<Document> doc =
984+
mIsMainThread ? mEventSource->GetDocumentIfCurrent() : nullptr;
971985
if (doc) {
972986
baseURI = doc->GetBaseURI();
973987
}
@@ -1013,28 +1027,33 @@ void EventSourceImpl::SetupHttpChannel() {
10131027
Unused << rv;
10141028
}
10151029

1016-
nsresult EventSourceImpl::SetupReferrerInfo() {
1030+
nsresult EventSourceImpl::SetupReferrerInfo(
1031+
const nsCOMPtr<Document>& aDocument) {
10171032
AssertIsOnMainThread();
10181033
MOZ_ASSERT(!IsShutDown());
10191034

1020-
if (nsCOMPtr<Document> doc = mEventSource->GetDocumentIfCurrent()) {
1021-
auto referrerInfo = MakeRefPtr<ReferrerInfo>(*doc);
1035+
if (aDocument) {
1036+
auto referrerInfo = MakeRefPtr<ReferrerInfo>(*aDocument);
10221037
nsresult rv = mHttpChannel->SetReferrerInfoWithoutClone(referrerInfo);
10231038
NS_ENSURE_SUCCESS(rv, rv);
10241039
}
10251040

10261041
return NS_OK;
10271042
}
10281043

1029-
nsresult EventSourceImpl::InitChannelAndRequestEventSource() {
1044+
nsresult EventSourceImpl::InitChannelAndRequestEventSource(
1045+
const bool aEventTargetAccessAllowed) {
10301046
AssertIsOnMainThread();
10311047
if (IsClosed()) {
10321048
return NS_ERROR_ABORT;
10331049
}
10341050

10351051
bool isValidScheme = mSrc->SchemeIs("http") || mSrc->SchemeIs("https");
10361052

1037-
nsresult rv = mEventSource->CheckCurrentGlobalCorrectness();
1053+
MOZ_ASSERT_IF(mIsMainThread, aEventTargetAccessAllowed);
1054+
nsresult rv = aEventTargetAccessAllowed
1055+
? mEventSource->CheckCurrentGlobalCorrectness()
1056+
: NS_OK;
10381057
if (NS_FAILED(rv) || !isValidScheme) {
10391058
DispatchFailConnection();
10401059
return NS_ERROR_DOM_SECURITY_ERR;
@@ -1046,7 +1065,9 @@ nsresult EventSourceImpl::InitChannelAndRequestEventSource() {
10461065
loadFlags = nsIRequest::LOAD_BACKGROUND | nsIRequest::LOAD_BYPASS_CACHE |
10471066
nsIRequest::INHIBIT_CACHING;
10481067

1049-
nsCOMPtr<Document> doc = mEventSource->GetDocumentIfCurrent();
1068+
const nsCOMPtr<Document> doc = aEventTargetAccessAllowed
1069+
? mEventSource->GetDocumentIfCurrent()
1070+
: nullptr;
10501071

10511072
nsSecurityFlags securityFlags =
10521073
nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT;
@@ -1084,7 +1105,7 @@ nsresult EventSourceImpl::InitChannelAndRequestEventSource() {
10841105
NS_ENSURE_TRUE(mHttpChannel, NS_ERROR_NO_INTERFACE);
10851106

10861107
SetupHttpChannel();
1087-
rv = SetupReferrerInfo();
1108+
rv = SetupReferrerInfo(doc);
10881109
NS_ENSURE_SUCCESS(rv, rv);
10891110

10901111
#ifdef DEBUG
@@ -1360,7 +1381,7 @@ NS_IMETHODIMP EventSourceImpl::Notify(nsITimer* aTimer) {
13601381
MOZ_ASSERT(!mHttpChannel, "the channel hasn't been cancelled!!");
13611382

13621383
if (!IsFrozen()) {
1363-
nsresult rv = InitChannelAndRequestEventSource();
1384+
nsresult rv = InitChannelAndRequestEventSource(mIsMainThread);
13641385
if (NS_FAILED(rv)) {
13651386
NS_WARNING("InitChannelAndRequestEventSource() failed");
13661387
}
@@ -1390,7 +1411,7 @@ nsresult EventSourceImpl::Thaw() {
13901411
NS_ENSURE_SUCCESS(rv, rv);
13911412
}
13921413

1393-
rv = InitChannelAndRequestEventSource();
1414+
rv = InitChannelAndRequestEventSource(mIsMainThread);
13941415
NS_ENSURE_SUCCESS(rv, rv);
13951416

13961417
return NS_OK;
@@ -1961,7 +1982,7 @@ already_AddRefed<EventSource> EventSource::Constructor(
19611982
return nullptr;
19621983
}
19631984

1964-
eventSource->mESImpl->InitChannelAndRequestEventSource();
1985+
eventSource->mESImpl->InitChannelAndRequestEventSource(true);
19651986
return eventSource.forget();
19661987
}
19671988

0 commit comments

Comments
 (0)