diff --git a/dom/media/GraphDriver.h b/dom/media/GraphDriver.h index 34eb35f467..8c01a70e73 100644 --- a/dom/media/GraphDriver.h +++ b/dom/media/GraphDriver.h @@ -120,6 +120,11 @@ public: return mNextDriver || mPreviousDriver; } + GraphDriver* NextDriver() + { + return mNextDriver; + } + /** * If we are running a real time graph, get the current time stamp to schedule * video frames. This has to be reimplemented by real time drivers. diff --git a/dom/media/MediaStreamGraph.cpp b/dom/media/MediaStreamGraph.cpp index 54fbdc1345..edac40d06a 100644 --- a/dom/media/MediaStreamGraph.cpp +++ b/dom/media/MediaStreamGraph.cpp @@ -623,6 +623,7 @@ MediaStreamGraphImpl::UpdateStreamOrder() if (CurrentDriver()->AsAudioCallbackDriver()->IsStarted()) { if (mLifecycleState == LIFECYCLE_RUNNING) { SystemClockDriver* driver = new SystemClockDriver(this); + mMixer.RemoveCallback(CurrentDriver()->AsAudioCallbackDriver()); CurrentDriver()->SwitchAtNextIteration(driver); } } @@ -2357,6 +2358,7 @@ MediaStream::RunAfterPendingUpdates(nsCOMPtr aRunnable) // runnable will run in finite time. if (!(graph->mRealtime || graph->mNonRealtimeProcessing)) { aRunnable->Run(); + return; } class Message : public ControlMessage { @@ -3255,7 +3257,6 @@ MediaStreamGraph::NotifyWhenGraphStarted(AudioNodeStream* aStream) } virtual void RunDuringShutdown() { - MOZ_ASSERT(false, "We should be reviving the graph?"); } }; @@ -3395,15 +3396,21 @@ MediaStreamGraphImpl::ApplyAudioContextOperationImpl(AudioNodeStream* aStream, // If we have suspended the last AudioContext, and we don't have other // streams that have audio, this graph will automatically switch to a // SystemCallbackDriver, because it can't find a MediaStream that has an audio - // track. When resuming, force switching to an AudioCallbackDriver. It would - // have happened at the next iteration anyways, but doing this now save - // some time. + // track. When resuming, force switching to an AudioCallbackDriver (if we're + // not already switching). It would have happened at the next iteration + // anyways, but doing this now save some time. if (aOperation == AudioContextOperation::Resume) { if (!CurrentDriver()->AsAudioCallbackDriver()) { - AudioCallbackDriver* driver = new AudioCallbackDriver(this); + AudioCallbackDriver* driver; + if (CurrentDriver()->Switching()) { + MOZ_ASSERT(CurrentDriver()->NextDriver()->AsAudioCallbackDriver()); + driver = CurrentDriver()->NextDriver()->AsAudioCallbackDriver(); + } else { + driver = new AudioCallbackDriver(this); + mMixer.AddCallback(driver); + CurrentDriver()->SwitchAtNextIteration(driver); + } driver->EnqueueStreamAndPromiseForOperation(aStream, aPromise, aOperation); - mMixer.AddCallback(driver); - CurrentDriver()->SwitchAtNextIteration(driver); } else { // We are resuming a context, but we are already using an // AudioCallbackDriver, we can resolve the promise now. @@ -3431,8 +3438,14 @@ MediaStreamGraphImpl::ApplyAudioContextOperationImpl(AudioNodeStream* aStream, CurrentDriver()->AsAudioCallbackDriver()-> EnqueueStreamAndPromiseForOperation(aStream, aPromise, aOperation); - SystemClockDriver* driver = new SystemClockDriver(this); - CurrentDriver()->SwitchAtNextIteration(driver); + SystemClockDriver* driver; + if (CurrentDriver()->NextDriver()) { + MOZ_ASSERT(!CurrentDriver()->NextDriver()->AsAudioCallbackDriver()); + } else { + driver = new SystemClockDriver(this); + mMixer.RemoveCallback(CurrentDriver()->AsAudioCallbackDriver()); + CurrentDriver()->SwitchAtNextIteration(driver); + } } else { // We are closing or suspending an AudioContext, but something else is // using the audio stream, we can resolve the promise now. diff --git a/dom/media/test/crashtests/audiocontext-double-suspend.html b/dom/media/test/crashtests/audiocontext-double-suspend.html new file mode 100644 index 0000000000..98399549bd --- /dev/null +++ b/dom/media/test/crashtests/audiocontext-double-suspend.html @@ -0,0 +1,5 @@ + diff --git a/dom/media/test/crashtests/crashtests.list b/dom/media/test/crashtests/crashtests.list index 6b404d0f2c..985a9fcf76 100644 --- a/dom/media/test/crashtests/crashtests.list +++ b/dom/media/test/crashtests/crashtests.list @@ -77,6 +77,7 @@ load oscillator-ended-2.html load 1080986.html load 1122218.html load 1158427.html +load audiocontext-double-suspend.html include ../../mediasource/test/crashtests/crashtests.list # This needs to run at the end to avoid leaking busted state into other tests. diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 5c91fc49a9..8cbb074bcf 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -270,6 +270,21 @@ nsHttpChannel::Connect() LOG(("nsHttpChannel::Connect [this=%p]\n", this)); + // Note that we are only setting the "Upgrade-Insecure-Requests" request + // header for *all* navigational requests instead of all requests as + // defined in the spec, see: + // https://www.w3.org/TR/upgrade-insecure-requests/#preference + nsContentPolicyType type = mLoadInfo ? + mLoadInfo->GetExternalContentPolicyType() : + nsIContentPolicy::TYPE_OTHER; + + if (type == nsIContentPolicy::TYPE_DOCUMENT || + type == nsIContentPolicy::TYPE_SUBDOCUMENT) { + rv = SetRequestHeader(NS_LITERAL_CSTRING("Upgrade-Insecure-Requests"), + NS_LITERAL_CSTRING("1"), false); + NS_ENSURE_SUCCESS(rv, rv); + } + // Even if we're in private browsing mode, we still enforce existing STS // data (it is read-only). // if the connection is not using SSL and either the exact host matches or