@@ -98,8 +98,8 @@ class EventSourceImpl final : public nsIObserver,
98
98
nsresult GetBaseURI (nsIURI** aBaseURI);
99
99
100
100
void SetupHttpChannel ();
101
- nsresult SetupReferrerInfo ();
102
- nsresult InitChannelAndRequestEventSource ();
101
+ nsresult SetupReferrerInfo (const nsCOMPtr<Document>& aDocument );
102
+ nsresult InitChannelAndRequestEventSource (bool aEventTargetAccessAllowed );
103
103
nsresult ResetConnection ();
104
104
void ResetDecoder ();
105
105
nsresult SetReconnectionTimeout ();
@@ -554,7 +554,9 @@ class ConnectRunnable final : public WorkerMainThreadRunnable {
554
554
555
555
bool MainThreadRun () override {
556
556
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 );
558
560
// We want to ensure the shortest possible remaining lifetime
559
561
// and not depend on the Runnable's destruction.
560
562
mESImpl = nullptr ;
@@ -585,6 +587,10 @@ nsresult EventSourceImpl::ParseURL(const nsAString& aURL) {
585
587
rv = srcURI->GetSpec (spec);
586
588
NS_ENSURE_SUCCESS (rv, rv);
587
589
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.
588
594
mEventSource ->mOriginalURL = NS_ConvertUTF8toUTF16(spec);
589
595
mSrc = srcURI;
590
596
mOrigin = origin;
@@ -664,6 +670,7 @@ EventSourceImpl::Observe(nsISupports* aSubject, const char* aTopic,
664
670
}
665
671
666
672
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface (aSubject);
673
+ MOZ_ASSERT (mIsMainThread );
667
674
if (!mEventSource ->GetOwner () || window != mEventSource ->GetOwner ()) {
668
675
return NS_OK;
669
676
}
@@ -882,7 +889,7 @@ EventSourceImpl::AsyncOnChannelRedirect(
882
889
883
890
bool isValidScheme = newURI->SchemeIs (" http" ) || newURI->SchemeIs (" https" );
884
891
885
- rv = mEventSource ->CheckCurrentGlobalCorrectness ();
892
+ rv = mIsMainThread ? mEventSource ->CheckCurrentGlobalCorrectness () : NS_OK ;
886
893
if (NS_FAILED(rv) || !isValidScheme) {
887
894
DispatchFailConnection ();
888
895
return NS_ERROR_DOM_SECURITY_ERR;
@@ -927,21 +934,27 @@ EventSourceImpl::GetInterface(const nsIID& aIID, void** aResult) {
927
934
928
935
if (aIID.Equals (NS_GET_IID(nsIAuthPrompt)) ||
929
936
aIID.Equals (NS_GET_IID(nsIAuthPrompt2))) {
930
- nsresult rv = mEventSource ->CheckCurrentGlobalCorrectness ();
931
- NS_ENSURE_SUCCESS (rv, NS_ERROR_UNEXPECTED);
932
-
937
+ nsresult rv;
933
938
nsCOMPtr<nsIPromptFactory> wwatch =
934
939
do_GetService (NS_WINDOWWATCHER_CONTRACTID, &rv);
935
940
NS_ENSURE_SUCCESS (rv, rv);
936
941
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
-
940
942
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
+ }
943
953
}
944
954
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
+
945
958
return wwatch->GetPrompt (window, aIID, aResult);
946
959
}
947
960
@@ -967,7 +980,8 @@ nsresult EventSourceImpl::GetBaseURI(nsIURI** aBaseURI) {
967
980
nsCOMPtr<nsIURI> baseURI;
968
981
969
982
// first we try from document->GetBaseURI()
970
- nsCOMPtr<Document> doc = mEventSource ->GetDocumentIfCurrent ();
983
+ nsCOMPtr<Document> doc =
984
+ mIsMainThread ? mEventSource ->GetDocumentIfCurrent () : nullptr ;
971
985
if (doc) {
972
986
baseURI = doc->GetBaseURI ();
973
987
}
@@ -1013,28 +1027,33 @@ void EventSourceImpl::SetupHttpChannel() {
1013
1027
Unused << rv;
1014
1028
}
1015
1029
1016
- nsresult EventSourceImpl::SetupReferrerInfo () {
1030
+ nsresult EventSourceImpl::SetupReferrerInfo (
1031
+ const nsCOMPtr<Document>& aDocument) {
1017
1032
AssertIsOnMainThread ();
1018
1033
MOZ_ASSERT (!IsShutDown ());
1019
1034
1020
- if (nsCOMPtr<Document> doc = mEventSource -> GetDocumentIfCurrent () ) {
1021
- auto referrerInfo = MakeRefPtr<ReferrerInfo>(*doc );
1035
+ if (aDocument ) {
1036
+ auto referrerInfo = MakeRefPtr<ReferrerInfo>(*aDocument );
1022
1037
nsresult rv = mHttpChannel ->SetReferrerInfoWithoutClone (referrerInfo);
1023
1038
NS_ENSURE_SUCCESS (rv, rv);
1024
1039
}
1025
1040
1026
1041
return NS_OK;
1027
1042
}
1028
1043
1029
- nsresult EventSourceImpl::InitChannelAndRequestEventSource () {
1044
+ nsresult EventSourceImpl::InitChannelAndRequestEventSource (
1045
+ const bool aEventTargetAccessAllowed) {
1030
1046
AssertIsOnMainThread ();
1031
1047
if (IsClosed ()) {
1032
1048
return NS_ERROR_ABORT;
1033
1049
}
1034
1050
1035
1051
bool isValidScheme = mSrc ->SchemeIs (" http" ) || mSrc ->SchemeIs (" https" );
1036
1052
1037
- nsresult rv = mEventSource ->CheckCurrentGlobalCorrectness ();
1053
+ MOZ_ASSERT_IF (mIsMainThread , aEventTargetAccessAllowed);
1054
+ nsresult rv = aEventTargetAccessAllowed
1055
+ ? mEventSource ->CheckCurrentGlobalCorrectness ()
1056
+ : NS_OK;
1038
1057
if (NS_FAILED(rv) || !isValidScheme) {
1039
1058
DispatchFailConnection ();
1040
1059
return NS_ERROR_DOM_SECURITY_ERR;
@@ -1046,7 +1065,9 @@ nsresult EventSourceImpl::InitChannelAndRequestEventSource() {
1046
1065
loadFlags = nsIRequest::LOAD_BACKGROUND | nsIRequest::LOAD_BYPASS_CACHE |
1047
1066
nsIRequest::INHIBIT_CACHING;
1048
1067
1049
- nsCOMPtr<Document> doc = mEventSource ->GetDocumentIfCurrent ();
1068
+ const nsCOMPtr<Document> doc = aEventTargetAccessAllowed
1069
+ ? mEventSource ->GetDocumentIfCurrent ()
1070
+ : nullptr ;
1050
1071
1051
1072
nsSecurityFlags securityFlags =
1052
1073
nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT;
@@ -1084,7 +1105,7 @@ nsresult EventSourceImpl::InitChannelAndRequestEventSource() {
1084
1105
NS_ENSURE_TRUE (mHttpChannel , NS_ERROR_NO_INTERFACE);
1085
1106
1086
1107
SetupHttpChannel ();
1087
- rv = SetupReferrerInfo ();
1108
+ rv = SetupReferrerInfo (doc );
1088
1109
NS_ENSURE_SUCCESS (rv, rv);
1089
1110
1090
1111
#ifdef DEBUG
@@ -1360,7 +1381,7 @@ NS_IMETHODIMP EventSourceImpl::Notify(nsITimer* aTimer) {
1360
1381
MOZ_ASSERT (!mHttpChannel , " the channel hasn't been cancelled!!" );
1361
1382
1362
1383
if (!IsFrozen ()) {
1363
- nsresult rv = InitChannelAndRequestEventSource ();
1384
+ nsresult rv = InitChannelAndRequestEventSource (mIsMainThread );
1364
1385
if (NS_FAILED(rv)) {
1365
1386
NS_WARNING (" InitChannelAndRequestEventSource() failed" );
1366
1387
}
@@ -1390,7 +1411,7 @@ nsresult EventSourceImpl::Thaw() {
1390
1411
NS_ENSURE_SUCCESS (rv, rv);
1391
1412
}
1392
1413
1393
- rv = InitChannelAndRequestEventSource ();
1414
+ rv = InitChannelAndRequestEventSource (mIsMainThread );
1394
1415
NS_ENSURE_SUCCESS (rv, rv);
1395
1416
1396
1417
return NS_OK;
@@ -1961,7 +1982,7 @@ already_AddRefed<EventSource> EventSource::Constructor(
1961
1982
return nullptr ;
1962
1983
}
1963
1984
1964
- eventSource->mESImpl ->InitChannelAndRequestEventSource ();
1985
+ eventSource->mESImpl ->InitChannelAndRequestEventSource (true );
1965
1986
return eventSource.forget ();
1966
1987
}
1967
1988
0 commit comments