From a368c596cb4272ab0083ac2827ae3d4ac2b900fc Mon Sep 17 00:00:00 2001 From: Eugen Sawin Date: Wed, 8 Jun 2016 14:28:24 +0200 Subject: [PATCH 01/76] Bug 1214710 - [1.11] Implement ReaderQueue for simultaneous decoder limit enforcement. r=jya,jwwang --- dom/media/MediaDecoderReader.cpp | 156 +++++++++++++++++++++++++++++++ dom/media/MediaDecoderReader.h | 13 +++ dom/media/MediaFormatReader.cpp | 18 +++- dom/media/MediaFormatReader.h | 1 + dom/media/MediaPrefs.h | 1 + 5 files changed, 188 insertions(+), 1 deletion(-) diff --git a/dom/media/MediaDecoderReader.cpp b/dom/media/MediaDecoderReader.cpp index bc6ffcd34b6a..8d26320441a4 100644 --- a/dom/media/MediaDecoderReader.cpp +++ b/dom/media/MediaDecoderReader.cpp @@ -9,11 +9,14 @@ #include "MediaResource.h" #include "VideoUtils.h" #include "ImageContainer.h" +#include "MediaPrefs.h" #include "nsPrintfCString.h" #include "mozilla/mozalloc.h" +#include "mozilla/Mutex.h" #include #include +#include using namespace mozilla::media; @@ -62,6 +65,154 @@ public: size_t mSize; }; +// The ReaderQueue is used to keep track of the numer of active readers to +// enforce a given limit on the number of simultaneous active decoders. +// Readers are added/removed during construction/destruction and are +// suspended and resumed by the queue. The max number of active decoders is +// controlled by the "media.decoder.limit" pref. +class ReaderQueue +{ +public: + static ReaderQueue& Instance() + { + static StaticMutex sMutex; + StaticMutexAutoLock lock(sMutex); + + if (!sInstance) { + sInstance = new ReaderQueue; + sInstance->MaxNumActive(MediaPrefs::MediaDecoderLimit()); + ClearOnShutdown(&sInstance); + } + MOZ_ASSERT(sInstance); + return *sInstance; + } + + void MaxNumActive(int32_t aNumActive) + { + MutexAutoLock lock(mMutex); + + if (aNumActive < 0) { + mNumMaxActive = std::numeric_limits::max(); + } else { + mNumMaxActive = aNumActive; + } + } + + void Add(MediaDecoderReader* aReader) + { + MutexAutoLock lock(mMutex); + + if (mActive.Length() < mNumMaxActive) { + // Below active limit, resume the new reader. + mActive.AppendElement(aReader); + DispatchResume(aReader); + } else if (mActive.IsEmpty()) { + MOZ_ASSERT(mNumMaxActive == 0); + mSuspended.AppendElement(aReader); + } else { + // We're past the active limit, suspend an old reader and resume the new. + mActive.AppendElement(aReader); + MediaDecoderReader* suspendReader = mActive.ElementAt(0); + mSuspended.AppendElement(suspendReader); + mActive.RemoveElementAt(0); + DispatchSuspendResume(suspendReader, aReader); + } + } + + void Remove(MediaDecoderReader* aReader) + { + MutexAutoLock lock(mMutex); + + if (aReader->IsSuspended()) { + // Removing suspended readers has no immediate side-effects. + DebugOnly result = mSuspended.RemoveElement(aReader); + MOZ_ASSERT(result, "Suspended reader must be in mSuspended"); + } else { + // For each removed active reader, we resume a suspended one. + DebugOnly result = mActive.RemoveElement(aReader); + MOZ_ASSERT(result, "Non-suspended reader must be in mActive"); + if (mSuspended.IsEmpty()) { + return; + } + MediaDecoderReader* resumeReader = mSuspended.LastElement(); + mActive.AppendElement(resumeReader); + mSuspended.RemoveElementAt(mSuspended.Length() - 1); + DispatchResume(resumeReader); + } + } + +private: + ReaderQueue() + : mNumMaxActive(std::numeric_limits::max()) + , mMutex("ReaderQueue:mMutex") + { + } + + static void Resume(MediaDecoderReader* aReader) + { + if (!aReader->IsSuspended()) { + return; + } + aReader->SetIsSuspended(false); + } + + static void Suspend(MediaDecoderReader* aReader) + { + if (aReader->IsSuspended()) { + return; + } + aReader->SetIsSuspended(true); + + aReader->ReleaseMediaResources(); + } + + static void DispatchResume(MediaDecoderReader* aReader) + { + RefPtr reader = aReader; + + nsCOMPtr task = NS_NewRunnableFunction( + [reader]() { + Resume(reader); + }); + reader->OwnerThread()->Dispatch(task.forget()); + } + + static void DispatchSuspend(MediaDecoderReader* aReader) + { + RefPtr reader = aReader; + + nsCOMPtr task = NS_NewRunnableFunction( + [reader]() { + Suspend(reader); + }); + reader->OwnerThread()->Dispatch(task.forget()); + } + + static void DispatchSuspendResume(MediaDecoderReader* aSuspend, + MediaDecoderReader* aResume) + { + RefPtr suspend = aSuspend; + RefPtr resume = aResume; + + nsCOMPtr task = NS_NewRunnableFunction( + [suspend, resume] () { + Suspend(suspend); + DispatchResume(resume); + }); + suspend->OwnerThread()->Dispatch(task.forget()); + } + + static StaticAutoPtr sInstance; + + nsTArray> mActive; + nsTArray> mSuspended; + uint32_t mNumMaxActive; + + mutable Mutex mMutex; +}; + +StaticAutoPtr ReaderQueue::sInstance; + MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder) : mAudioCompactor(mAudioQueue) , mDecoder(aDecoder) @@ -75,6 +226,7 @@ MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder) , mShutdown(false) , mAudioDiscontinuity(false) , mVideoDiscontinuity(false) + , mIsSuspended(true) { MOZ_COUNT_CTOR(MediaDecoderReader); MOZ_ASSERT(NS_IsMainThread()); @@ -84,6 +236,8 @@ MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder) mTaskQueue, this, &MediaDecoderReader::NotifyDataArrived); } + ReaderQueue::Instance().Add(this); + // Dispatch initialization that needs to happen on that task queue. mTaskQueue->Dispatch(NewRunnableMethod(this, &MediaDecoderReader::InitializationTask)); } @@ -376,6 +530,8 @@ MediaDecoderReader::Shutdown() mDecoder = nullptr; + ReaderQueue::Instance().Remove(this); + return mTaskQueue->BeginShutdown(); } diff --git a/dom/media/MediaDecoderReader.h b/dom/media/MediaDecoderReader.h index ed03865576fe..45943a76a906 100644 --- a/dom/media/MediaDecoderReader.h +++ b/dom/media/MediaDecoderReader.h @@ -290,6 +290,18 @@ public: // Notified by the OggReader during playback when chained ogg is detected. MediaEventSource& OnMediaNotSeekable() { return mOnMediaNotSeekable; } + bool IsSuspended() const + { + MOZ_ASSERT(OnTaskQueue()); + return mIsSuspended; + } + + void SetIsSuspended(bool aState) + { + MOZ_ASSERT(OnTaskQueue()); + mIsSuspended = aState; + } + protected: virtual ~MediaDecoderReader(); @@ -435,6 +447,7 @@ private: // "discontinuity" in the stream. For example after a seek. bool mAudioDiscontinuity; bool mVideoDiscontinuity; + bool mIsSuspended; MediaEventListener mDataArrivedListener; }; diff --git a/dom/media/MediaFormatReader.cpp b/dom/media/MediaFormatReader.cpp index a01fce013456..a901982234ce 100644 --- a/dom/media/MediaFormatReader.cpp +++ b/dom/media/MediaFormatReader.cpp @@ -135,7 +135,6 @@ MediaFormatReader::Shutdown() MOZ_ASSERT(!mVideo.HasPromise()); mDemuxer = nullptr; - mPlatform = nullptr; return MediaDecoderReader::Shutdown(); @@ -459,6 +458,11 @@ MediaFormatReader::EnsureDecoderInitialized(TrackType aTrack) [self] (TrackType aTrack) { auto& decoder = self->GetDecoderData(aTrack); decoder.mInitPromise.Complete(); + + if (self->IsSuspended()) { + return; + } + decoder.mDecoderInitialized = true; MonitorAutoLock mon(decoder.mMonitor); decoder.mDescription = decoder.mDecoder->GetDescriptionName(); @@ -533,6 +537,10 @@ MediaFormatReader::RequestVideoData(bool aSkipToNextKeyframe, return MediaDataPromise::CreateAndReject(CANCELED, __func__); } + if (IsSuspended()) { + return MediaDataPromise::CreateAndReject(CANCELED, __func__); + } + media::TimeUnit timeThreshold{media::TimeUnit::FromMicroseconds(aTimeThreshold)}; // Ensure we have no pending seek going as ShouldSkip could return out of date // information. @@ -624,6 +632,10 @@ MediaFormatReader::RequestAudioData() return MediaDataPromise::CreateAndReject(DECODE_ERROR, __func__); } + if (IsSuspended()) { + return MediaDataPromise::CreateAndReject(CANCELED, __func__); + } + if (IsSeeking()) { LOG("called mid-seek. Rejecting."); return MediaDataPromise::CreateAndReject(CANCELED, __func__); @@ -918,6 +930,7 @@ MediaFormatReader::HandleDemuxedSamples(TrackType aTrack, AbstractMediaDecoder::AutoNotifyDecoded& aA) { MOZ_ASSERT(OnTaskQueue()); + auto& decoder = GetDecoderData(aTrack); if (decoder.mQueuedSamples.IsEmpty()) { @@ -1884,6 +1897,9 @@ void MediaFormatReader::ReleaseMediaResources() } mVideo.mInitPromise.DisconnectIfExists(); mVideo.ShutdownDecoder(); + + mAudio.mInitPromise.DisconnectIfExists(); + mAudio.ShutdownDecoder(); } bool diff --git a/dom/media/MediaFormatReader.h b/dom/media/MediaFormatReader.h index 816b28b14808..d08a4bebe966 100644 --- a/dom/media/MediaFormatReader.h +++ b/dom/media/MediaFormatReader.h @@ -101,6 +101,7 @@ public: void GetMozDebugReaderData(nsAString& aString); private: + bool HasVideo() { return mVideo.mTrackDemuxer; } bool HasAudio() { return mAudio.mTrackDemuxer; } diff --git a/dom/media/MediaPrefs.h b/dom/media/MediaPrefs.h index 812c66b25c8d..a6afae7e6737 100644 --- a/dom/media/MediaPrefs.h +++ b/dom/media/MediaPrefs.h @@ -120,6 +120,7 @@ private: DECL_MEDIA_PREF("media.webspeech.recognition.force_enable", WebSpeechRecognitionForceEnabled, bool, false); DECL_MEDIA_PREF("media.num-decode-threads", MediaThreadPoolDefaultCount, uint32_t, 4); + DECL_MEDIA_PREF("media.decoder.limit", MediaDecoderLimit, uint32_t, -1); public: // Manage the singleton: From 778760ed81832b217d2c6e87276f5b180be66805 Mon Sep 17 00:00:00 2001 From: Eugen Sawin Date: Wed, 8 Jun 2016 14:28:37 +0200 Subject: [PATCH 02/76] Bug 1214710 - [2.5] Recover decode seek position when resuming suspended playback. r=jwwang --- dom/media/MediaDecoderReader.cpp | 4 +- dom/media/MediaDecoderReader.h | 6 ++- dom/media/MediaDecoderReaderWrapper.h | 3 ++ dom/media/MediaDecoderStateMachine.cpp | 52 +++++++++++++++++++++----- dom/media/MediaDecoderStateMachine.h | 13 +++++-- 5 files changed, 62 insertions(+), 16 deletions(-) diff --git a/dom/media/MediaDecoderReader.cpp b/dom/media/MediaDecoderReader.cpp index 8d26320441a4..98c914fafde1 100644 --- a/dom/media/MediaDecoderReader.cpp +++ b/dom/media/MediaDecoderReader.cpp @@ -226,7 +226,8 @@ MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder) , mShutdown(false) , mAudioDiscontinuity(false) , mVideoDiscontinuity(false) - , mIsSuspended(true) + , mIsSuspended(mTaskQueue, true, + "MediaDecoderReader::mIsSuspended (Canonical)") { MOZ_COUNT_CTOR(MediaDecoderReader); MOZ_ASSERT(NS_IsMainThread()); @@ -522,6 +523,7 @@ MediaDecoderReader::Shutdown() ReleaseMediaResources(); mDuration.DisconnectIfConnected(); mBuffered.DisconnectAll(); + mIsSuspended.DisconnectAll(); // Shut down the watch manager before shutting down our task queue. mWatchManager.Shutdown(); diff --git a/dom/media/MediaDecoderReader.h b/dom/media/MediaDecoderReader.h index 45943a76a906..b8f3ecefb09b 100644 --- a/dom/media/MediaDecoderReader.h +++ b/dom/media/MediaDecoderReader.h @@ -302,6 +302,10 @@ public: mIsSuspended = aState; } + AbstractCanonical* CanonicalIsSuspended() { + return &mIsSuspended; + } + protected: virtual ~MediaDecoderReader(); @@ -447,7 +451,7 @@ private: // "discontinuity" in the stream. For example after a seek. bool mAudioDiscontinuity; bool mVideoDiscontinuity; - bool mIsSuspended; + Canonical mIsSuspended; MediaEventListener mDataArrivedListener; }; diff --git a/dom/media/MediaDecoderReaderWrapper.h b/dom/media/MediaDecoderReaderWrapper.h index 2813a19fb600..de170c4f4de1 100644 --- a/dom/media/MediaDecoderReaderWrapper.h +++ b/dom/media/MediaDecoderReaderWrapper.h @@ -415,6 +415,9 @@ public: AbstractCanonical* CanonicalBuffered() { return mReader->CanonicalBuffered(); } + AbstractCanonical* CanonicalIsSuspended() { + return mReader->CanonicalIsSuspended(); + } #ifdef MOZ_EME void SetCDMProxy(CDMProxy* aProxy) { mReader->SetCDMProxy(aProxy); } diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index b9049fd1477e..edd19f756f42 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -262,6 +262,8 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder, mAudioOffloading(false), mBuffered(mTaskQueue, TimeIntervals(), "MediaDecoderStateMachine::mBuffered (Mirror)"), + mIsReaderSuspended(mTaskQueue, true, + "MediaDecoderStateMachine::mIsReaderSuspended (Mirror)"), mEstimatedDuration(mTaskQueue, NullableTimeUnit(), "MediaDecoderStateMachine::mEstimatedDuration (Mirror)"), mExplicitDuration(mTaskQueue, Maybe(), @@ -339,6 +341,7 @@ MediaDecoderStateMachine::InitializationTask(MediaDecoder* aDecoder) // Connect mirrors. mBuffered.Connect(mReader->CanonicalBuffered()); + mIsReaderSuspended.Connect(mReader->CanonicalIsSuspended()); mEstimatedDuration.Connect(aDecoder->CanonicalEstimatedDuration()); mExplicitDuration.Connect(aDecoder->CanonicalExplicitDuration()); mPlayState.Connect(aDecoder->CanonicalPlayState()); @@ -357,6 +360,7 @@ MediaDecoderStateMachine::InitializationTask(MediaDecoder* aDecoder) // Initialize watchers. mWatchManager.Watch(mBuffered, &MediaDecoderStateMachine::BufferedRangeUpdated); + mWatchManager.Watch(mIsReaderSuspended, &MediaDecoderStateMachine::ReaderSuspendedChanged); mWatchManager.Watch(mState, &MediaDecoderStateMachine::UpdateNextFrameStatus); mWatchManager.Watch(mAudioCompleted, &MediaDecoderStateMachine::UpdateNextFrameStatus); mWatchManager.Watch(mVideoCompleted, &MediaDecoderStateMachine::UpdateNextFrameStatus); @@ -1342,8 +1346,9 @@ void MediaDecoderStateMachine::PlayStateChanged() void MediaDecoderStateMachine::VisibilityChanged() { MOZ_ASSERT(OnTaskQueue()); - DECODER_LOG("VisibilityChanged: is visible = %d, video decode suspended = %d", - mIsVisible.Ref(), mVideoDecodeSuspended); + DECODER_LOG("VisibilityChanged: is visible = %d, video decode suspended = %d, " + "reader suspended = %d", + mIsVisible.Ref(), mVideoDecodeSuspended, mIsReaderSuspended.Ref()); // Not suspending background videos so there's nothing to do. if (!MediaPrefs::MDSMSuspendBackgroundVideoEnabled()) { @@ -1378,6 +1383,10 @@ void MediaDecoderStateMachine::VisibilityChanged() if (mVideoDecodeSuspended) { mVideoDecodeSuspended = false; + if (mIsReaderSuspended) { + return; + } + // If an existing seek is in flight don't bother creating a new // one to catch up. if (mSeekTask || mQueuedSeek.Exists()) { @@ -1385,23 +1394,31 @@ void MediaDecoderStateMachine::VisibilityChanged() } // Start video-only seek to the current time... - InitiateVideoDecodeRecoverySeek(); + InitiateDecodeRecoverySeek(TrackSet(TrackInfo::kVideoTrack)); } } -// InitiateVideoDecodeRecoverySeek is responsible for setting up a video-only -// seek using the seek task. When suspension of decoding for videos that are in +// InitiateDecodeRecoverySeek is responsible for setting up a seek using the +// seek task for the following situations: +// 1. When suspension of decoding for videos that are in // background tabs (ie. invisible) is enabled, the audio keeps playing and when // switching back to decoding video, it is highly desirable to not cause the // audio to pause as the video is seeked else there be a noticeable audio glitch // as the tab becomes visible. -void MediaDecoderStateMachine::InitiateVideoDecodeRecoverySeek() +// 2. When there is a decoder limit set, suspended videos may be resumed and +// require the seek to recover the original seek position for both audio and +// video. +void MediaDecoderStateMachine::InitiateDecodeRecoverySeek(TrackSet aTracks) { MOZ_ASSERT(OnTaskQueue()); + DECODER_LOG("InitiateDecodeRecoverySeek"); + SeekJob seekJob; - seekJob.mTarget = SeekTarget(GetMediaTime(), - SeekTarget::Type::AccurateVideoOnly, + SeekTarget::Type seekTargetType = aTracks.contains(TrackInfo::kAudioTrack) + ? SeekTarget::Type::Accurate + : SeekTarget::Type::AccurateVideoOnly; + seekJob.mTarget = SeekTarget(GetMediaTime(), seekTargetType, MediaDecoderEventVisibility::Suppressed); SetState(DECODER_STATE_SEEKING); @@ -1423,7 +1440,7 @@ void MediaDecoderStateMachine::InitiateVideoDecodeRecoverySeek() // Reset our state machine and decoding pipeline before seeking. if (mSeekTask->NeedToResetMDSM()) { - Reset(TrackInfo::kVideoTrack); + Reset(aTracks); } // Do the seek. @@ -1456,6 +1473,19 @@ void MediaDecoderStateMachine::BufferedRangeUpdated() } } +void MediaDecoderStateMachine::ReaderSuspendedChanged() +{ + MOZ_ASSERT(OnTaskQueue()); + DECODER_LOG("ReaderSuspendedChanged: suspended = %d", mIsReaderSuspended.Ref()); + + if (!HasVideo() || mIsReaderSuspended || IsDecodingFirstFrame()) { + return; + } + + InitiateDecodeRecoverySeek(TrackSet(TrackInfo::kAudioTrack, + TrackInfo::kVideoTrack)); +} + void MediaDecoderStateMachine::ReadMetadata() { @@ -2222,6 +2252,7 @@ MediaDecoderStateMachine::FinishShutdown() // Disconnect canonicals and mirrors before shutting down our task queue. mBuffered.DisconnectIfConnected(); + mIsReaderSuspended.DisconnectIfConnected(); mEstimatedDuration.DisconnectIfConnected(); mExplicitDuration.DisconnectIfConnected(); mPlayState.DisconnectIfConnected(); @@ -2636,7 +2667,8 @@ bool MediaDecoderStateMachine::IsStateMachineScheduled() const bool MediaDecoderStateMachine::IsVideoDecodeSuspended() const { MOZ_ASSERT(OnTaskQueue()); - return MediaPrefs::MDSMSuspendBackgroundVideoEnabled() && mVideoDecodeSuspended; + return (MediaPrefs::MDSMSuspendBackgroundVideoEnabled() && mVideoDecodeSuspended) || + mIsReaderSuspended; } void diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h index 69854e82ae2c..e6aefa81478f 100644 --- a/dom/media/MediaDecoderStateMachine.h +++ b/dom/media/MediaDecoderStateMachine.h @@ -381,6 +381,8 @@ protected: void BufferedRangeUpdated(); + void ReaderSuspendedChanged(); + // Inserts MediaData* samples into their respective MediaQueues. // aSample must not be null. @@ -518,10 +520,11 @@ protected: // The decoder monitor must be held. void InitiateSeek(SeekJob aSeekJob); - // Clears any previous seeking state and initiates a video-only seek on the - // decoder to catch up the video to the current audio position, when recovering - // from video decoding being suspended in background. - void InitiateVideoDecodeRecoverySeek(); + // Clears any previous seeking state and initiates a seek on the decoder to + // resync the video and audio positions, when recovering from video decoding + // being suspended in background or from audio and video decoding being + // suspended due to the decoder limit. + void InitiateDecodeRecoverySeek(TrackSet aTracks); nsresult DispatchAudioDecodeTaskIfNeeded(); @@ -975,6 +978,8 @@ private: // The buffered range. Mirrored from the decoder thread. Mirror mBuffered; + Mirror mIsReaderSuspended; + // The duration according to the demuxer's current estimate, mirrored from the main thread. Mirror mEstimatedDuration; From bd5f8d5d32e911da1468b5154cf7b2b9f900af13 Mon Sep 17 00:00:00 2001 From: Mike Conley Date: Sun, 29 May 2016 12:00:50 -0400 Subject: [PATCH 03/76] Bug 1277644 - Make sure browser_Addons_sample test add-on tests CPOWs when it is supposed to. r=Yoric browser_Addons_sample is used by the browser_AddonWatcher.js test to make sure we can properly detect when an add-on consumes a bunch of CPU or does a lot of CPOW traffic. There's a race condition in the add-on where what is supposed to be a CPOW might not always be a CPOW, so when we try to cause a bunch of CPOW traffic, we don't get the expected performance warnings. This makes sure that when we try to simulate CPOW usage, we do it with an actual CPOW. Additionally, this commit also includes the unpacked source of the add-on, which before wasn't in the tree. I've also taken the liberty of bumping the add-on version and signing it. MozReview-Commit-ID: GICLYpi8Kon --HG-- extra : rebase_source : bc9537c701335806d4845113910b03fadadb5b77 --- .../tests/browser/browser_AddonWatcher.js | 10 +- .../tests/browser/browser_Addons_sample.xpi | Bin 6621 -> 7848 bytes .../browser_Addons_sample/bootstrap.js | 105 ++++++++++++++++++ .../browser/browser_Addons_sample/build.sh | 4 + .../browser_Addons_sample/chrome.manifest | 1 + .../content/framescript.js | 23 ++++ .../browser/browser_Addons_sample/install.rdf | 30 +++++ 7 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/bootstrap.js create mode 100644 toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/build.sh create mode 100644 toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/chrome.manifest create mode 100644 toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/content/framescript.js create mode 100644 toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/install.rdf diff --git a/toolkit/components/perfmonitoring/tests/browser/browser_AddonWatcher.js b/toolkit/components/perfmonitoring/tests/browser/browser_AddonWatcher.js index bfa796576e5d..e0bb14774542 100644 --- a/toolkit/components/perfmonitoring/tests/browser/browser_AddonWatcher.js +++ b/toolkit/components/perfmonitoring/tests/browser/browser_AddonWatcher.js @@ -20,15 +20,21 @@ add_task(function* init() { if (installer.error) { throw installer.error; } - let ready = new Promise((resolve, reject) => installer.addListener({ + let installed = new Promise((resolve, reject) => installer.addListener({ onInstallEnded: (_, addon) => resolve(addon), onInstallFailed: reject, onDownloadFailed: reject })); + + // We also need to wait for the add-on to report that it's ready + // to be used in the test. + let ready = TestUtils.topicObserved("test-addonwatcher-ready"); installer.install(); info("Waiting for installation to terminate"); - let addon = yield ready; + let addon = yield installed; + + yield ready; registerCleanupFunction(() => { info("Uninstalling test add-on"); diff --git a/toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample.xpi b/toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample.xpi index 99ea037b2b8cb17751a26eee8f97c04c78f86834..ae5bcc5ff3bdd42bb93c87bca7ea22131bf79f93 100644 GIT binary patch literal 7848 zcmb7p1yq||)^%`6k>XaoXmBl7q`12mm*8&2tw3?NLW>r6io3gO@dCx&?T5ZI)6Tq| z_06BG`y_c*?!G7I>~qfDxpI#!03I-1)GZdb^+w?C833S#3IIIal@?YKpc9u7 zVX(Az16x?=(c9VUEvUM3#@^wj4N`TXF`sv(;VhOJV=Ev;t&?Se@ucGQLOqDejU{Kr zpQ)D{1{=PRM2m`~it0;7TO}jdcGp?D8Y0>(vH!Tk_0V{61DZa0SG-x9z5`2D7=P&3 zO)4W=$l|j_Qj0Og0th%Ghkn+@2no015IrCVkMaUu_jVn6D4RG9fKf;94M{f~AlQNm zPhdf>{H_gM_j(*SP=k#zcSVLUK>%y=J~2iA5|HN6(lTTvc1p&{Z6MF}CK^A=|0Q}* zF%B-E(b~um`=;Hk?U0}^@lC^O@VqmB5*mRPLNPLxB2VuJ?{))5?*UIh?A@37bQ#l# z$3dWi_ii0=bW&(;-Gm)X+6zI3(sQrAD!`cgrF&S3&@?0E{dd`i^dk+gH!DH(-hgO? zOn53tiE^A!5V03TFZqXAzmNxiep9MIDBT-%o=hf$11TGl8h!Dmhif+(Zv&!{3Km>6 zUhQ5rU)nxj?~AU|-KsrN)n!Ugj6=~02&bSSgisvfZPLJ_?#rY|)4Qsu|SJ`AmT**M0J z%ZWv-w7Wo9*c$tpyZfbl%fU2Oc;+F2gN3@at&oAm#3gJcpyvD9@U2#WsyAwH)6Sg8 zMT2JA`Ad0l$4J@AOePZE6Nw@O zVqh|zce7Yh*dhC2v1O`WSMDCXw=j3Jwpe`Q_|p1-JeoP#allz1Aze9_l}AwOt5etq zp$M;4CG^1zl?6n($+$yp5+|o6k#)p@X+n`iN*eq)U_xZM>8SPz0gdqWv`Zy2vam|X zw0o=(*1jMGCdm9!2tHts{kmWa(f?%U#e2Gawki!@ThDD1e{`CYCd|bU=Fah%3EA2F zma8!(I~t*N9whIhbN0>evDJ$@GyNfRb8&I*e_4hay4+o`4c5r!?nGNX=6aMCC~XyMUh^o@jkKIRmN~&{C8c?- zFNQa=PyWkpSLMjv{3=`$b@unBN_iV3&4tkV@FSH5!60~!$-^iJ1Eo~$qqrJ;c6;iy zuoKFc6sOhH5{W$p7b_AFfm)f1fp)vS-OL;G?=hz|pQ}1<6NP2Y5#xO?UJY3oB0Y74Pfgj4xKMI8*Z{V-~Z{yc)U;$_v!ez&{1vTPpS zbGFjLM3<=16#y@6x2ryi|3x^8vN$MKfLsR5HL$fI?=vN~0{ zXsgZZS_}9RvC+i3q$p2rv|x}frLn!VNElKZhmS@Vd9$HuTYA56hQ#0>q$+H?+-&kX1OEA458``<#W)NGMU%}%wN`c<^wts}m^uAJpOF^3b*#{k- zxgIpD-jq(PPHs__=O14V)x1%-s|#4D03f;pKegm|F~5q%gudE|B|bOhIc)A*6$RX< zgNDRO(R$xCgxv#E477t@&!|E~wo~=?QTO!q?^hh~#XeBpHrFyg1h;}4?Mes_%cPm$ zIgD)95RIkDTzRY{K)Il5Zo~9@!io8w*@alsW_q20hvU8Wv8nyDekxFt9PO`|efK(65S2k$K3bm%*pVC|YuQe_*O z7+?p^HcLQyVLI5FvI;e^W0zs#HPgF;2?az_V?m>e*M};J`5xc^W#v7M@hyy`!HTYZ zlemU?Wd<0jWfwwoEzxXobfIrWd*2W8Yt>WBslf(3pAz_(+x*AE_nG|{r?DlA`y2P! zOy;io6k`XDS3R6d=aei4uIlPkr901FEYPIwKGV%C&DwJpXF%zv7+n>Jr*B$p^{xbS zPn4BobS6f%9bn9t&`}o1MLmb?i8CD2SurD7P2`7Z?wTB0;Nna zm``8iRoAVvjtoAX=0bd}#wweu*WmSM38{1Vz0v}vxf>5BS3VvcH0N-^y;Z!-%Rr`7 zJHD@&t&-B5ZyG;t%(R?Pmkx2vFY-a^60yu#Gp zNAzR$3)+Q`e9%^^6=Co_L$r<0)RFrRlw+N=mg+5`w&ZWAwSb^j3Nw(AHeYI6&x3 z0E;$sob0|}R+3GrF?`{+aaII#x98AGg*swe@Jf|$AO^OVK__>HPq1W`+>v)~bw}9_s~}0xp$B2yOgij%-*-#f}p&Fuc#e-o5wD2lP2C9<(O&o7hH7h!_601t{lZ-Q?DxCjdt>rHfO;2 zDZnyhN(+HZec3 zd+aN+DSor+#*G$HKtbffn{6E3V@je9X%8f?3Cepx;zS_Mk(Kyceez08r2&1)bRaB= zNZ<5?6JI|c7IIpGk^ojAkX~xmaQyAO!zQ;|L;ry#dwS-4Vmd2PyqSx6#lZK6;3FC4 z2u|A`9A{FgH4vOjl}$oc7WOFP?qiC&kjuF-rVn071A|l8_Ck$40C#KOhp-w{i7>pG z2Ab)5NT^WW+?yRtX=rs6)J$o)$$IR|%(DG{dDkUYvHvd4h}zyTPT+F4r~(Oc?S zfsKvq9h8+|08r7Ks;Z7IKmY{v83X|EQ)@{M4bzGb(#nfTiT4iE%7Vm)#OTK8#Odhe z#R7YN*h2t*trGO1Tg)Bqq>vZot~wUy@4Ir#)00<{^w%W zJbzm(AX?sho)NWs>5dw?!UrAi6~=iq9m-2XMzQ2l!_cufm8jwB5IWo~rI-Nsi!^*n z#_CZxvZbs0=K6=;E!67l^U|_bYX77`)Fus8s7?17-b_+rpb{x+-JIXxl5h51QGrAo z*Dg&FDNdUpEh}NkvT#ck4)8MG585c@PPpPNKP@kgWF%Nt<^WO;wkRhWSb4x$TbyWX z0!0OG*%ve8d*(|{6`U-dJe9lHR!3@N+_#_r(asvOy8N80G~?19W6)xubRrVl$6-BS zV@4j0`_$SKSB2A17mMa}3w8lmf4Dk3edG<{${13~Rtg*%m?}sY-}?YTKVmlK$eZB*TMlg%XeP>J8&WoNqchy zODz53sim{da9fr{nPQufTJdx#A}QZOy3~>HoR)~Cau263&Mqb`nr3;d4yI1JXSbcW zn-|igTv=zsmhh_#8$pc02)tp29M-hraX&=z%l6*jOCMnpgx{u?oVwrze|UH1>m|+l z<6d~{4Vkq$!I@POexget(+=h@w(LH#g(Be1Vihz1p!z7|pFOfg-`d*2-oZ}K=ARq^ z@&1h?A5}H&SJ^Q~uR=QqN%3Z?<@g0i}n0s~LAUIK|r)?Ua&-V<7(iTf4JV<)#Z7XdgC0K8aU*r9` z$F7xnI$vP8%Xzwev;U@d?{J?`m_RyiAI-p3U1NU;*jq1QSc$&@Gv|Rq@R~p*WS#HF zr4xJI#}@_~x~y6UwtCEXT6eWX;le>GmN`};<6FxSqY$}a1s+{VR=eM1n|Qp^o}u!k zYAp>u18Iq!A_5zs*!q0?#);#}GihQ$(`r0xou!AkSo~(wQA)vrfg(br;K<-FVtI%; zN==L)97yKwb}WPKtaE*&kZs)lFI22EW`s&6Sw`9BjRMl5{6W`E=8Z85Na8dbfsr|?+E$yXPeVxQMa(P$95PX)_ zEijynUa}&gPu?q22O`8y7sweB&bOR2wyi>g&~W2;H9Ki7cu2TJ>TLlXvkl(exhH0_ zU{bbyt(A#uEzm;Dwf~CMFen}vXunyFHd3V9+@@YKO^d`|bRXq$3*X$5OWDEVx8%V7 z@PlVf7tgX}XYGC8#rJac^i2AceK%m(A*nPIZ~c$*?zzkPDI43(RSq@t+I#|rI7^by zan$5An1rUOBVpnAdYyS!08MtJ$EB;Z4u{uK3A=qt7+fQV6??L#$=*unK*~qAweqZL zUcK2^Y*$QK7I^()cLx(5(FtIjm9mp{LJd!lc>Wj1BY?y0a^p(zTB~%{;#*{MOl96` zL!LGlra6%VW)>EvRTvqHQNcQ7N(Kl@4iZs`b8!m>ClzxwQwI*XMB!;GMGrT%M- zuV4M87;EfaFn3dINitz;#KkYFmeGf3UIfa2&kgm;l`kquzA*Fl2nc&EM@y&zwNE&> zfytI6uuWhizOg0$Ln%VdYvXb0( zK(JZL^92mW36jTtzuh}8S80+_wDI(SN>EH*mQ!75wFlPaIo%2iTdZInH#H;Nwtzm? z2-d0%sA&{+eOsLi%+`u*zK70d{ckOV0>jCpuA|5wRk1ba3 zvBd%(XM?Tm9rP?L=+!ELiz6;sg%YBKn$0N&pk7p=~L;fHMax3ZG5C z-bYp=e>J+`D5ovh6eMg=xnp?2Z(y20G@cqAKMC1K1OpTFO4X9PJWB5^)jy@C-Wu zgN^+vnMyZ#y}+tM>lkBS2<}tWFy!k}^MyuxF`Pn`j)DA;Q3CvWQS1mc3XW(uGrqMhL zz%eG3p2~bC->&hfXIb`^98dIQzspSc5_R0?oDmgd$BN(w6byVpDm(I==!V`PuWxP8 z@1V=JOOTjK{?a|Wuf@AN9QTk#XI;U4nk9>vqC;WN2k|Rx0X21EZBi`5(~m)i#sL5j z9>YfeMo~x6!P?H~XV9o?MgMc>wU@|?*v5|v6TcpYjjHV&`@u>$j>&1T8f6!T8zh&^h)B~k6Y`(OD5{Q^F z_rRvzNG%Cqpodhy*5mBt9Uk|wigCn6T}9XWZNKRBNam>)AFrrKue3gnr&Q2)1X~!= z+nfG$ip}4d>=<5#+{XCq&4p*cR-1o?vrq;a8RU7srIgw8RVrKX)--xq#kbS_g;7p~ z2~|Af^LRf$lHO=)M^W>a-{~((ejrTu1gWXwi*l0lvwFR13Gp1;CiiiYvnx4_{4OQ{ z!(0z2M3Ty9;^+e18oKv(EncWGj>C5QP{na4kUJ5^Efo^k$FI|Gs9f*mV=yPITmye) zw(nz*|B=)`U!H>euQQ3CzlZGaLH@;&rz4H#PQ>l>$JEApOznR^()h6OtDh@rRL+5ELCz*h0~#X3vki#WA7S7bFsxQRGeZiS0P_T~4FidRL>%4GR$m zM1h72VikUlsh)}*7s27VF*DfxB~f0}9=&t!)#A>N{EftUza)ATC<9ASZ0~EgNXBFX z>Id`7asf1lYoq;E*VD422+3Tn>Xxc&FfoH6?OK-uXPAH9{nMSj)W; zumKUnoQP?w-Y+7#> zxQ-K!uGa@J+cOqZJ>ugbqCeNp@fH;q>Y`Y@3Ucb$r$fP^ z?tJ)0e2{0DD^sygCs<@DLf?3}{d(aOr!ns33?;`F2m0gq7a#t4MrCgd9FiKA1X0sTOd?6r(F_d?S12$}uq+=tGEF-6O3BjE zkDf^n^h-f87h*)mRMLig>_em*us=ojKyq&=|0Z$v!qT$VmzMyEDXu=(m^1JiCZ2l( zXHyO98UxEjq{b*NE^zDS)tsH}lTw3##DMzm2WUT8`*`twWZ)l6eLPNkLLmGH!k;wd z)4Zq2Sw0L%fd5rt{to&l3Hb{&?g{k&OHlrf{U^ck3%eZ!@IT3qzYza>FMmP=08jyY z0(Fm`{-?D+)Bg|Z`gi;O)Z3r1{&MK$BijGa>3;|OQ`dO{e0pU0lwbk=?;i9!+@H$z z6VzY!bz(pI@Bb*?zx(b_)$$4LFW<#JHpzeG%73q&|IX+Cte$_tJ@I+`cesE41yCGIyM`A_aJOI^BoKl_(BQ${-C-B^4eqdbaDoH~?(XjHP6+NH5Fog7;Ygix z&;3u`f2MkCc5C|CuKB+A?e1?Bq~YLk0RR9ZU?W0Tf)ug0<_;AA(7^-%o_>`TRS{y4 zloMmJwskYNvNB|Ja5P*}cjbz^BjN}%+^;;0tzc{R&rqn2N|nhL4QH80Gu|hEAFGs& z86rVcX|hr&BGDi8)=6_v=@T=sgye^Z{>s%TaHq^Mb&uzv<>H2Z?!>)xr{T-qv)8=m z%=OqaiH!qDMlhy|E;0b*NOD4W;VL*g!YWn*c>2L%`0@t_Sdb!@9sqaS$p@Bp)XzuA zfEhJF6_42lj_ctRw&D<8wB}9%wgTFD*7R5kXla+2(5+W6D(yIJ@ z0uimjZd)y|dl){$ryHKMtfh$T%}i;;z~;@DY<|W!-?E@&^F1m-Ds2wC+NsyU2RhNgv9+ssW^$9c!0ZF zz_U?2tKJ)|kZ*?)t36M0=Mc)CTBI3H1JUcuYqAyK+N#1EQaJn3=M}W4=FB=3c~L^O z;Cz%Qh^&m17mdJiI-x9vg6e;ZJ>7JGC_^g0zD(@A(map<)q{$uX9ujDb!fl|LNg5#R0aQ>v4)v6${F zPrqgNjP2=Vf)&SiBQ%8PRR^4r+JWO?&8s~tU@h$c);c$nJby1JlitSg+QgYz#;jM{Qz?OdB8`k~-7-n140qrTZdUcs zxTSGRT)G#Cys%4#gJj6rWjAP(dbg+^?kSEnz}_QJ3L$V_yO=3SO2RMvOb6qOgFHJX zTG@v)Onnkrf(tHqCsvJ?!=O{cR%0)F`7CKxQq77nTU8=R(PcDQXh5&XB7=lwU8a+e#N1>@Z^&V((<;;lG7KznASU))Q;TG4Gbsd$%FlF<48v z11{Yz9ObcgMbSA<$>6UzikW*ybNec7=)}#O&3z3ua(&+*NW)A70+hn)kiXEJs3T@pK`dXGL|cIt-V{ z%RgkQd6G(m(eTp|*DQ6xNgatXrJ zdhgK!=2|q-XaiUxB4{<%aIoZ!NfH3a`*ec7qqimwh!{ARWy+lu?>E*SRPhsFsk|!d zUxr9f9UgJ~V6uuhp}sfJM@{#gRhw(iw=6s?FS}-(zNNWsYhZnd?r35UEb6|HsURml z2wrvEsYnpLi^Ww}#{bd)CiD*bUP`cUR&Vd6%%*R2Bx^025!6FTGZdKK014}37-ZU= zv?s|zA`W8PXXcd8y2m& zY`O%5+V-&q7HGTbue(wPpl%wF)sb%I?nxoBR>ML+h<&yl)_rVV-MALid-#rFey3&W9AO$?(hqZ&lD@Q5q2 zGv-uQ^g0=)PER7<06TFSIwT<=(W72Dwz(}}6>#D?&*V0`)swg7*1V_ji9|Dbk$TA|&ON@;D#X$DrAfEB=|T8M zIHhpGYtg+ocWa!XU0Sh*9Fbz*uP1A_U!H!aHWEq3OMMNx%ossL2yC~iaeSSA2S5mb z;c^O8^1~QJ6%mx%nhd^8SMU)JlH?vWpcxlXun3*9n`dFQ1p8mFTgz%s1GU=o3qIV5$c&Iy~vU+-MkgfFM(KEkMBcKMeieI?x$&bjM>~BmG z?DFbRpYFE|dgj|@or0E`x>DT+&DF@`XGF*MBAaZB728~O%@ksyZo_M=kZ>0`+u_Kc z4QYb4q{p9`(yPlaDWACDa%o=QBx$7siF}^9p$<&ZW=nr+Uk*-VJjzIxywJm%8Sp0-{>G!;1JGnJ&)Go*whA z=J+{vPxnqPv6@JNgM2MFM8Ck`a2-3UB|dk{`Ri4LdHp=&BzFiLC0jHD%yZW>aeWUWz2-XcSGO0gaV49v z96_^Z5w!-+SYL3yc!iOnU^dkeq{~f{1x%#hCf*+Ja3W{-Z6vV*c=Jq130nZf2Pt@=2h|Cf^)~upvxBw)Qoz*^vgo1R^SaSr zXwTBgE%-fjJIyL=eODrJuj{4|a(t2sfpHwh+1Ds1Ow9{seF7WcDvQ?)$;L8?ivkZF zn=+~!j+C`uV~)0|%C7d7w$ymXXy#H86;Uj>;4|IclQI3QSNp~T|K->>=n zD{f`SSN+%Yfs)#3eRqPFBk(VW$|R^cyyXxNTJuAByBbN3wLhiV9d50|z=IYml6KY{ zb9AhfCx1+PWQ)NxDC!%wk37Ti-q9MF@9n_NuF@CU%AY(-t7;Lg z#pkb)uwb7JsE~`8{V{2zH#}mKKT{~%584^6yVotxJUQ2RLvm6pC9Va3_}cb?p+-cP z580AniJ%3T(lN>0XjpDXU-t1AhQe>#CD_O95~ZT6I4_Vtwh0aZI79*fPyvJhBU@XD zBgDbbj?uzVRRsY6SLvpz_Q3@O00Vyp0|3B3?x+AcYSy;vT$uN1`YfRb*>TW-WpOt? zQczQ#6p9M85a^~l$3^YJSwXqr>xA`i*BgSPH%KaRfw15t*{l*Fz4V<% znY9tM39Fi7EQ}&CieCQ3aE@P64Bg1Ir9ecE3q>GfB66GM*a^yrAaPH@uQJ}qOc2~& z=aI^VfkL%!u81WVqZ&A@hQZ^o71Jm)q@c20I1l*Df1b< zB27JhXS7%$GYizq^OkA+P<-`r_pMTCgiv4B?oTtf2+NRp#0_D)z`(j#$%nE997T;4 zKE`@;SQn4W>+7wI$fJ&~rMv0Q@4^|x`-^1LL}4j=W~CCnZ&i6YzoHTMq$6^xsU)?l z%M1xCT9PZ$51Qy?%ZTITej<72<1=haX?#lQe{pC)8?J72pmNrCd$*?q;ik=eIduAr*!S5Cw2dpF4;S(gh zf<{+UrehqPNTl{-R(9ILb=*&KR0Op)#DLl3^;-fYgCTppsGAdEg{~aHf@Rz@f^so& z4zV=E0=uuJYgb!?1J&e%>6>g3hOal@)aToBNj069YuS-x8x+BiKEEMlY+AC}0$7}k z-A>V5;(56X@zz~_tow!DSx8v^v9we#I7`Y%s(N?NSxA?`uPSN3vHoh#$R6g?S8-`} zufnVb^U+zg`DLvD$q)+JGC5Fnj*(Byo`8Y%bQ7Hl$m+Ra82mK&8H{_;-U|XvGLMB^ zbQ#(Lx1*ut7VCTbl|eac4(sn^0rMKm&$RXA28yGn{XSc8l1Ua>*+(~dBzMHJks5Jr zyvY0{gAf7!c{ef_$SuiE_nsGqRGQi=7(o?+{xuRf!u!G0NzqT+jH zI{AHYs*iD27Rka!oL-Nc@s3*&(@G_QU+ zbLpdD>KVLiW3zy0IHsS@;U2dsOWTWkR7Cb=d+_@C@0cd=%U+rqJ2}Ve;XZrE5HaFo zl%!LMV|*0dDQ*Z9U*%mzx&|Ik&X*TgP5PT~w`Neu>Xu$2u*Y1suTA-_fGZZ28M-C6 zyaB(9|EX3oBBv|iXmyMB;ZfCwj|PD9D1LJrM~I=76{CX*_&4oOLZ|=G{`r&kpUNqz zu}e07%!Gks4ak0`(o%GZwD9)Sy(nJ~*OW5M>h7az(d$4L{KYT38mwNJdUyh_`4wX3 zBiJsWuVr%*-QELT8L^Uv3pC_gnigIqx>QZu$L#e?mShRbw|ry)p&F{Hdf{Cwm8>y` zQUt>i!V7L8jF)w;l4828av$7R8pyarZXJJQ4g3iQ8z2^S#K(6uNhF0YVjB7>w{&Yg zelfYAPL;wYJrUWO+1STe2qp6))FS*SahrD3k@k&MC7NRU^pN^baMC6cZ$N~g@t4_S zr;--u2qgcR#XRQd!u(wVj#`@qI3_#ox(Yj z<5p9b?0>M-3^Yc_azPLidU%b8G394PF#zvopZp#X7ny^-Iw$UJ)Qp9Rbu@V7AfJN$`jGUM zL;84(zsAp_WzG|)I*m2y4GR7nevQtOGDM)q_w<^t2?7Ji-S3I~6uwh<+*QwCt(01$ zoqNvnd^UiVRCPx)9?|uIT1S6X1p1!!^%0DDg>{IO6R0ps*@2i;4DBZK+k23do77&c zcw$%*w&HF;4E?a)QuN6xLdIGgf#^_Hl%Hyw8hDbG-zg1YwKa8KNiJ34?Ysa1FP$EC zwHv!>VG3K{~{7bsbBQGYk~B z@UtCLLbWi)%5zfgqFND`d_BkW=jxljSiH|-iN2o;vI4jDHJ!QL@p6nNHo1;yuluJh zY3nT0T_66K2753RXVv8@KH-rmD;RRE|B(^p~o=>WSW32mp-~w*@{Nky$s!_Kb!1)+e;A2$( zcWw2L++(x`$Bz%$_zB`ZTji7QNbB#>hIS+PA*$g{`$2-3+h2E$Cn-+nmF1Sm?)M&y z4qU}P4B2lWgMBL10Ep1~Nf*&LZW}Vn^k3zf^o-Kc*)L2xZ}F#wNO1a*Mc9|w-ERkH z@eX*ZTMvlZQZx!(Bl3U9bSxAwXo8j`?(O=QVlGtr2n!lNR>otIa6p4*om}+PWjD|= z*W}%mFvERtwMX~4sjbSLoUPYexdstxdkEcy_a{NT zS$V!1>KiKgqM`IHc{%vOS5Rbn5jKosU(j}+m{1h|1}@|qwAnprgW1xdp*6q7m>s!M zi7X|CZu1X`|5?PAJ@n7Fcod)OW5aoD|EGxU2u2x|8Iz``WssUdlV*4`Iy_dT#5~Qm zdi;T9=EH!DJOkszne6b83><4Qu1;swWYKW5zfAZEJvLuwrz7&xlGKp3b%P%t2^vd$ zlj?2)D1f*Dzu}r2%KeI`>GP*t6|w9fHJ7ag2m2>qfPuw@`}Yd_A0`3tdCZLeFx1C- z`xAlek??Pe&ZmA)owI$J&;b9{67)~vzs+QS5$Ul2|INJiC-7;A|H)+k0Bp##u|2ynoPw_u_>=Wzvrx^G*+JEP`Pb2+%jQ^?hC-&3f1EYiY t_Za`B`+pMtnZm#Ke {try { + gBurnContentCPU() + } catch (ex) { + dump(`test-addon error: ${ex}\n`); + }}, 0); +} +let gBurnContentCPU = null; + +let gTab = null; +let gTabBrowser = null; + +function startup() { + Services.obs.addObserver(burnCPU, TOPIC_BURNCPU, false); + Services.obs.addObserver(burnCPOW, TOPIC_BURNCPOW, false); + Services.obs.addObserver(burnContentCPU, TOPIC_BURNCONTENTCPU, false); + + let windows = Services.wm.getEnumerator("navigator:browser"); + let win = windows.getNext(); + gTabBrowser = win.gBrowser; + gTab = gTabBrowser.addTab("about:robots"); + gBurnContentCPU = function() { + gTab.linkedBrowser.messageManager.sendAsyncMessage("test-addonwatcher-burn-some-content-cpu", {}); + } + + gTab.linkedBrowser.messageManager.loadFrameScript(URL_FRAMESCRIPT, false); + globalMM.loadFrameScript(URL_FRAMESCRIPT, false); + + if (Services.appinfo.browserTabsRemoteAutostart) { + // This profile has e10s enabled, which means we'll want to + // test CPOW traffic. + globalMM.addMessageListener("test-addonwatcher-cpow:init", function waitForCPOW(msg) { + if (Components.utils.isCrossProcessWrapper(msg.objects.burnCPOW)) { + gBurnCPOW = msg.objects.burnCPOW; + globalMM.removeMessageListener("test-addonwatcher-cpow:init", waitForCPOW); + Services.obs.notifyObservers(null, TOPIC_READY, null); + } else { + Cu.reportError("test-addonwatcher-cpow:init didn't give us a CPOW! Expect timeouts."); + } + }); + } else { + // e10s is not enabled, so a CPOW is not necessary - we can report ready + // right away. + Services.obs.notifyObservers(null, TOPIC_READY, null); + } +} + +function shutdown() { + Services.obs.removeObserver(burnCPU, TOPIC_BURNCPU); + Services.obs.removeObserver(burnCPOW, TOPIC_BURNCPOW); + Services.obs.removeObserver(burnContentCPU, TOPIC_BURNCONTENTCPU); + gTabBrowser.removeTab(gTab); +} + +function install() { + // Nothing to do +} + +function uninstall() { + // Nothing to do +} diff --git a/toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/build.sh b/toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/build.sh new file mode 100644 index 000000000000..28d52ea3a836 --- /dev/null +++ b/toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/build.sh @@ -0,0 +1,4 @@ +echo "Rebuilding browser_Addons_sample.xpi..." +zip -r ../browser_Addons_sample.xpi . +echo " +Done! Don't forget to sign it: https://wiki.mozilla.org/EngineeringProductivity/HowTo/SignExtensions" \ No newline at end of file diff --git a/toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/chrome.manifest b/toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/chrome.manifest new file mode 100644 index 000000000000..9f53da861bfd --- /dev/null +++ b/toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/chrome.manifest @@ -0,0 +1 @@ +content addonwatcher-test content/ diff --git a/toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/content/framescript.js b/toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/content/framescript.js new file mode 100644 index 000000000000..e7ebc2a616ef --- /dev/null +++ b/toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/content/framescript.js @@ -0,0 +1,23 @@ +/* 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/. */ + +"use strict"; + +Components.utils.import("resource://gre/modules/Services.jsm"); + +function burnCPOW(msg) { + dump(`Addon: content burnCPU start ${Math.sin(Math.random())}\n`); + let start = content.performance.now(); + let ignored = []; + while (content.performance.now() - start < 5000) { + ignored[ignored.length % 2] = ignored.length; + } + dump(`Addon: content burnCPU done: ${content.performance.now() - start}\n`); +} + +if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) { + sendAsyncMessage("test-addonwatcher-cpow:init", {}, {burnCPOW}); +} + +addMessageListener("test-addonwatcher-burn-some-content-cpu", burnCPOW); diff --git a/toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/install.rdf b/toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/install.rdf new file mode 100644 index 000000000000..cae10ace66fa --- /dev/null +++ b/toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/install.rdf @@ -0,0 +1,30 @@ + + + + + addonwatcher-test@mozilla.com + 1.1 + + + + {ec8030f7-c20a-464f-9b0e-13a3a9e97384} + 0.3 + * + + + + + + toolkit@mozilla.org + 1 + * + + + + true + + Sample for browser_AddonWatcher.js + + + From af016de2cb87b611c7274b19e6c292f0c2b509e2 Mon Sep 17 00:00:00 2001 From: Andrew Sutherland Date: Mon, 16 May 2016 23:20:52 -0400 Subject: [PATCH 04/76] Bug 1272436 - P0: Implement "only-if-cached" RequestCache mode. r=mayhemer, r=bkelly, r=bzbarsky for WebIDL change The fetch spec has re-introduced "only-if-cached" mode which loads only from the cache. There are privacy implications to this so for the time being it is required that "same-origin" mode is used. --- dom/bindings/Errors.msg | 1 + dom/cache/DBSchema.cpp | 3 ++- dom/fetch/Request.cpp | 8 ++++++++ dom/webidl/Request.webidl | 2 +- dom/workers/ServiceWorkerManager.cpp | 4 +++- netwerk/protocol/http/HttpBaseChannel.cpp | 11 +++++++++++ netwerk/protocol/http/nsIHttpChannelInternal.idl | 1 + 7 files changed, 27 insertions(+), 3 deletions(-) diff --git a/dom/bindings/Errors.msg b/dom/bindings/Errors.msg index fb55f176765a..3cbebb6a90ec 100644 --- a/dom/bindings/Errors.msg +++ b/dom/bindings/Errors.msg @@ -98,3 +98,4 @@ MSG_DEF(MSG_INVALID_EASING_ERROR, 1, JSEXN_TYPEERR, "Invalid easing '{0}'.") MSG_DEF(MSG_USELESS_SETTIMEOUT, 1, JSEXN_TYPEERR, "Useless {0} call (missing quotes around argument?)") MSG_DEF(MSG_TOKENLIST_NO_SUPPORTED_TOKENS, 2, JSEXN_TYPEERR, "{0} attribute of <{1}> does not define any supported tokens") MSG_DEF(MSG_CACHE_STREAM_CLOSED, 0, JSEXN_TYPEERR, "Response body is a cache file stream that has already been closed.") +MSG_DEF(MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN, 1, JSEXN_TYPEERR, "Request mode '{0}' was used, but request cache mode 'only-if-cached' can only be used with request mode 'same-origin'.") diff --git a/dom/cache/DBSchema.cpp b/dom/cache/DBSchema.cpp index 369d39cb8e9b..e80bce1c5082 100644 --- a/dom/cache/DBSchema.cpp +++ b/dom/cache/DBSchema.cpp @@ -220,7 +220,8 @@ static_assert(int(RequestCache::Default) == 0 && int(RequestCache::Reload) == 2 && int(RequestCache::No_cache) == 3 && int(RequestCache::Force_cache) == 4 && - int(RequestCache::EndGuard_) == 5, + int(RequestCache::Only_if_cached) == 5 && + int(RequestCache::EndGuard_) == 6, "RequestCache values are as expected"); static_assert(int(RequestRedirect::Follow) == 0 && int(RequestRedirect::Error) == 1 && diff --git a/dom/fetch/Request.cpp b/dom/fetch/Request.cpp index 766378c526fd..82c1b0169846 100644 --- a/dom/fetch/Request.cpp +++ b/dom/fetch/Request.cpp @@ -428,6 +428,14 @@ Request::Constructor(const GlobalObject& aGlobal, RequestCache cache = aInit.mCache.WasPassed() ? aInit.mCache.Value() : fallbackCache; if (cache != RequestCache::EndGuard_) { + if (cache == RequestCache::Only_if_cached && + request->Mode() != RequestMode::Same_origin) { + uint32_t t = static_cast(request->Mode()); + NS_ConvertASCIItoUTF16 modeString(RequestModeValues::strings[t].value, + RequestModeValues::strings[t].length); + aRv.ThrowTypeError(modeString); + return nullptr; + } request->ClearCreatedByFetchEvent(); request->SetCacheMode(cache); } diff --git a/dom/webidl/Request.webidl b/dom/webidl/Request.webidl index 02ebece9baee..1b4af67312dc 100644 --- a/dom/webidl/Request.webidl +++ b/dom/webidl/Request.webidl @@ -59,6 +59,6 @@ enum RequestContext { enum RequestMode { "same-origin", "no-cors", "cors", "navigate" }; enum RequestCredentials { "omit", "same-origin", "include" }; -enum RequestCache { "default", "no-store", "reload", "no-cache", "force-cache" }; +enum RequestCache { "default", "no-store", "reload", "no-cache", "force-cache", "only-if-cached" }; enum RequestRedirect { "follow", "error", "manual" }; enum ReferrerPolicy { "", "no-referrer", "no-referrer-when-downgrade", "origin", "origin-when-cross-origin", "unsafe-url" }; diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp index 08529bb7c5ba..fd95a75a115b 100644 --- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -126,7 +126,9 @@ static_assert(nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_CACHE == static_cast(RequestCache::Force_cache), "RequestCache enumeration value should match Necko Cache mode value."); -static_assert(5 == static_cast(RequestCache::EndGuard_), +static_assert(nsIHttpChannelInternal::FETCH_CACHE_MODE_ONLY_IF_CACHED == static_cast(RequestCache::Only_if_cached), + "RequestCache enumeration value should match Necko Cache mode value."); +static_assert(6 == static_cast(RequestCache::EndGuard_), "RequestCache enumeration value should match Necko Cache mode value."); static StaticRefPtr gInstance; diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index 899b0e45e42d..a6e2e7e29746 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -2414,6 +2414,8 @@ HttpBaseChannel::GetFetchCacheMode(uint32_t* aFetchCacheMode) *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_RELOAD; } else if (mLoadFlags & VALIDATE_ALWAYS) { *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_NO_CACHE; + } else if (mLoadFlags & (LOAD_FROM_CACHE | nsICachingChannel::LOAD_ONLY_FROM_CACHE)) { + *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_ONLY_IF_CACHED; } else if (mLoadFlags & LOAD_FROM_CACHE) { *aFetchCacheMode = nsIHttpChannelInternal::FETCH_CACHE_MODE_FORCE_CACHE; } else { @@ -2452,6 +2454,15 @@ HttpBaseChannel::SetFetchCacheMode(uint32_t aFetchCacheMode) // force-cache means don't validate unless if the response would vary. mLoadFlags |= LOAD_FROM_CACHE; break; + case nsIHttpChannelInternal::FETCH_CACHE_MODE_ONLY_IF_CACHED: + // only-if-cached means only from cache, no network, no validation, generate + // a network error if the document was't in the cache. + // The privacy implications of these flags (making it fast/easy to check if + // the user has things in their cache without any network traffic side + // effects) are addressed in the Request constructor which enforces/requires + // same-origin request mode. + mLoadFlags |= LOAD_FROM_CACHE | nsICachingChannel::LOAD_ONLY_FROM_CACHE; + break; } return NS_OK; diff --git a/netwerk/protocol/http/nsIHttpChannelInternal.idl b/netwerk/protocol/http/nsIHttpChannelInternal.idl index 84d0ffc00f0f..e25e7225ff57 100644 --- a/netwerk/protocol/http/nsIHttpChannelInternal.idl +++ b/netwerk/protocol/http/nsIHttpChannelInternal.idl @@ -247,6 +247,7 @@ interface nsIHttpChannelInternal : nsISupports const unsigned long FETCH_CACHE_MODE_RELOAD = 2; const unsigned long FETCH_CACHE_MODE_NO_CACHE = 3; const unsigned long FETCH_CACHE_MODE_FORCE_CACHE = 4; + const unsigned long FETCH_CACHE_MODE_ONLY_IF_CACHED = 5; /** * Set to indicate Request.cache mode, which simulates the fetch API * semantics, and is also used for exposing this value to the Web page From ad3240027a5cf912bab74beef08b792bc039878b Mon Sep 17 00:00:00 2001 From: Andrew Sutherland Date: Wed, 18 May 2016 04:21:37 -0400 Subject: [PATCH 05/76] Bug 1272436 - P1 Fetch "only-if-cached" cache mode tests. r=bkelly request-error.html: - Add test verifying we enforce only-if-cached requires same-origin mode. request-cache.html (only-if-cached does not hit network): - Add comment block explaining the test dictionary arguments. - Eliminate duplicated code in populate_cache which seems to have existed only for historical reasons and is now moot. - Add `response` optional test dictionary array for cases where a network error is expected as the result of the fetch. Normalize server results to handle this case since test cases may no longer talk to the server at all. - Add only-if-cached tests that verify the network is not touched in any of the fresh cached, stale cached, and not cached cases. request-cache.html (cross-origin redirects in the cache are not traversed): - Tests added to request/request-cache.html instead of under redirect/ because redirect/ and redirect.py explicitly disable caching. Also, the issue is about cache behavior, not the redirect-following logic. - Enhance cache.py to accept a "redirect" parameter that generates a 302 redirect using a Location header when received. - Make the "error" handling generate a test failure if we don't fail when expected. - Add "redirect" argument to request-cache.html test info dicts to tell cache.py to generate a redirect. - Add test cases for "only-if-cached" to first prime with redirect, expecting success on same-origin redirects and failure on cross-origin redirects. --- .../fetch/api/request/request-cache.html | 176 +++++++++++++++--- .../fetch/api/request/request-error.html | 6 + .../fetch/api/request/resources/cache.py | 13 +- .../request/resources/get-host-info.sub.js | 32 ++++ .../service-worker/fetch-event.https.html | 11 +- 5 files changed, 209 insertions(+), 29 deletions(-) create mode 100644 testing/web-platform/tests/fetch/api/request/resources/get-host-info.sub.js diff --git a/testing/web-platform/tests/fetch/api/request/request-cache.html b/testing/web-platform/tests/fetch/api/request/request-cache.html index 9cc64cdf8d68..9e9b8f4ed8dd 100644 --- a/testing/web-platform/tests/fetch/api/request/request-cache.html +++ b/testing/web-platform/tests/fetch/api/request/request-cache.html @@ -8,10 +8,58 @@ + + + + + + + + + + + + + diff --git a/toolkit/components/extensions/test/xpcshell/test_native_messaging.js b/toolkit/components/extensions/test/xpcshell/test_native_messaging.js index ce620a28443d..bd73392815f7 100644 --- a/toolkit/components/extensions/test/xpcshell/test_native_messaging.js +++ b/toolkit/components/extensions/test/xpcshell/test_native_messaging.js @@ -1,15 +1,14 @@ "use strict"; -Cu.import("resource://gre/modules/Services.jsm"); +/* global OS, HostManifestManager, NativeApp */ +Cu.import("resource://gre/modules/AsyncShutdown.jsm"); Cu.import("resource://gre/modules/FileUtils.jsm"); - -/* global OS */ +Cu.import("resource://gre/modules/Schemas.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); +const {Subprocess, SubprocessImpl} = Cu.import("resource://gre/modules/Subprocess.jsm"); +Cu.import("resource://gre/modules/NativeMessaging.jsm"); Cu.import("resource://gre/modules/osfile.jsm"); -/* global HostManifestManager */ -Cu.import("resource://gre/modules/NativeMessaging.jsm"); - -Components.utils.import("resource://gre/modules/Schemas.jsm"); const BASE_SCHEMA = "chrome://extensions/content/schemas/manifest.json"; let dir = FileUtils.getDir("TmpD", ["NativeMessaging"]); @@ -48,16 +47,24 @@ function writeManifest(path, manifest) { return OS.File.writeAtomic(path, manifest); } +let PYTHON; add_task(function* setup() { yield Schemas.load(BASE_SCHEMA); + + PYTHON = yield Subprocess.pathSearch("python2.7"); + if (PYTHON == null) { + PYTHON = yield Subprocess.pathSearch("python"); + } + notEqual(PYTHON, null, "Found a suitable python interpreter"); }); // Test of HostManifestManager.lookupApplication() begin here... - let context = { url: null, logError() {}, preprocessors: {}, + callOnClose: () => {}, + forgetOnClose: () => {}, }; let templateManifest = { @@ -163,3 +170,65 @@ add_task(function* test_user_dir_precedence() { deepEqual(result.manifest, templateManifest, "lookupApplication returns user-specific manifest contents with user-specific and system-wide entries both exist"); }); +// Test shutdown handling in NativeApp +add_task(function* test_native_app_shutdown() { + const SCRIPT = String.raw`#!${PYTHON} -u +import signal +import struct +import sys + +signal.signal(signal.SIGTERM, signal.SIG_IGN) + +while True: + rawlen = sys.stdin.read(4) + if len(rawlen) == 0: + signal.pause() + msglen = struct.unpack('@I', rawlen)[0] + msg = sys.stdin.read(msglen) + + sys.stdout.write(struct.pack('@I', msglen)) + sys.stdout.write(msg) +`; + + let scriptPath = OS.Path.join(userDir.path, "wontdie.py"); + yield OS.File.writeAtomic(scriptPath, SCRIPT); + yield OS.File.setPermissions(scriptPath, {unixMode: 0o755}); + + const ID = "native@tests.mozilla.org"; + const MANIFEST = { + name: "wontdie", + description: "test async shutdown of native apps", + path: scriptPath, + type: "stdio", + allowed_extensions: [ID], + }; + yield writeManifest(OS.Path.join(userDir.path, "wontdie.json"), MANIFEST); + + let extension = {id: ID}; + let app = new NativeApp(extension, context, "wontdie"); + + // send a message and wait for the reply to make sure the app is running + let MSG = "test"; + let recvPromise = new Promise(resolve => { + let listener = (what, msg) => { + equal(msg, MSG, "Received test message"); + app.off("message", listener); + resolve(); + }; + app.on("message", listener); + }); + + app.send(MSG); + yield recvPromise; + + app._cleanup(); + + do_print("waiting for async shutdown"); + Services.prefs.setBoolPref("toolkit.asyncshutdown.testing", true); + AsyncShutdown.profileBeforeChange._trigger(); + Services.prefs.clearUserPref("toolkit.asyncshutdown.testing"); + + let procs = yield SubprocessImpl.Process.getWorker().call("getProcesses", []); + equal(procs.size, 0, "native process exited"); +}); + From 42f36f97883bd9e0a021d682c7aec6845dd8c75a Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Tue, 31 May 2016 10:59:44 +1200 Subject: [PATCH 42/76] Bug 1276132 - Rename media.gmp-*.forcevisible to media.gmp-*.visible, and set it when keysystems are enabled. r=spohl Repurpose the media.gmp-*.forcevisible pref to control whether the corresponding GMP is visible in the addons manager UI. The pref has to be true for the GMP to be usable. The pref is enabled and not hidden when the corresponding EME keysystem is enabled in the mozconfig. This means users can turn on EME without needing to recompile their build; they just need to create a hidden pref. This will be useful for CDM developers, and users on platforms where we've not enabled EME yet but users want to test it (Linux). We also need to change the GMPUtils.isPluginHidden() accessor so that plugins are considered hidden if the "visible" pref is false OR we're on an unsupported platform. This ensures that we must be on a supported OS and the visibility pref is true before GMPs appear in the addon list. A consequence of the isPluginHidden() change is that we also need to add a "force-supported" pref to override the checks that refuse to load the GMPs on various platform versions, so that the unit tests pass. MozReview-Commit-ID: h6CwLDkvFW --HG-- extra : rebase_source : 2c077e577352e356aceeda000d873bad1439f242 --- browser/app/profile/firefox.js | 10 +++++++ toolkit/modules/GMPUtils.jsm | 30 ++++++++++++++----- .../test/browser/browser_gmpProvider.js | 8 ++--- .../test/xpcshell/test_gmpProvider.js | 4 ++- 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index a375301328e6..ad272261cfe7 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1285,11 +1285,21 @@ pref("media.gmp.decoder.h264", 2); // decode H.264. pref("media.gmp.trial-create.enabled", true); +// Note: when media.gmp-*.visible is true, provided we're running on a +// supported platform/OS version, the corresponding CDM appears in the +// plugins list, Firefox will download the GMP/CDM if enabled, and our +// UI to re-enable EME prompts the user to re-enable EME if it's disabled +// and script requests EME. If *.visible is false, we won't show the UI +// to enable the CDM if its disabled; it's as if the keysystem is completely +// unsupported. + #ifdef MOZ_ADOBE_EME +pref("media.gmp-eme-adobe.visible", true); pref("media.gmp-eme-adobe.enabled", true); #endif #ifdef MOZ_WIDEVINE_EME +pref("media.gmp-widevinecdm.visible", true); pref("media.gmp-widevinecdm.enabled", true); #endif diff --git a/toolkit/modules/GMPUtils.jsm b/toolkit/modules/GMPUtils.jsm index 53356f34e391..b1d2b8e8d0a3 100644 --- a/toolkit/modules/GMPUtils.jsm +++ b/toolkit/modules/GMPUtils.jsm @@ -46,8 +46,8 @@ this.GMPUtils = { return false; } - if (!this._isPluginSupported(aPlugin) && - !this._isPluginForcedVisible(aPlugin)) { + if (!this._isPluginSupported(aPlugin) || + !this._isPluginVisible(aPlugin)) { this.maybeReportTelemetry(aPlugin.id, "VIDEO_EME_ADOBE_HIDDEN_REASON", GMPPluginHiddenReason.UNSUPPORTED); @@ -70,6 +70,9 @@ this.GMPUtils = { * The plugin to check. */ _isPluginSupported: function(aPlugin) { + if (this._isPluginForceSupported(aPlugin)) { + return true; + } if (aPlugin.id == EME_ADOBE_ID) { if (Services.appinfo.OS != "WINNT") { // Non-Windows OSes currently unsupported by Adobe EME @@ -92,13 +95,25 @@ this.GMPUtils = { }, /** - * Checks whether or not a given plugin is forced visible. This can be used - * to test plugins that aren't yet supported by default on a particular OS. + * Checks whether or not a given plugin is visible in the addons manager + * UI and the "enable DRM" notification box. This can be used to test + * plugins that aren't yet turned on in the mozconfig. * @param aPlugin * The plugin to check. */ - _isPluginForcedVisible: function(aPlugin) { - return GMPPrefs.get(GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, false, aPlugin.id); + _isPluginVisible: function(aPlugin) { + return GMPPrefs.get(GMPPrefs.KEY_PLUGIN_VISIBLE, false, aPlugin.id); + }, + + /** + * Checks whether or not a given plugin is forced-supported. This is used + * in automated tests to override the checks that prevent GMPs running on an + * unsupported platform. + * @param aPlugin + * The plugin to check. + */ + _isPluginForceSupported: function(aPlugin) { + return GMPPrefs.get(GMPPrefs.KEY_PLUGIN_FORCE_SUPPORTED, false, aPlugin.id); }, /** @@ -136,8 +151,9 @@ this.GMPPrefs = { KEY_PLUGIN_LAST_UPDATE: "media.{0}.lastUpdate", KEY_PLUGIN_VERSION: "media.{0}.version", KEY_PLUGIN_AUTOUPDATE: "media.{0}.autoupdate", - KEY_PLUGIN_FORCEVISIBLE: "media.{0}.forcevisible", + KEY_PLUGIN_VISIBLE: "media.{0}.visible", KEY_PLUGIN_ABI: "media.{0}.abi", + KEY_PLUGIN_FORCE_SUPPORTED: "media.{0}.forceSupported", KEY_URL: "media.gmp-manager.url", KEY_URL_OVERRIDE: "media.gmp-manager.url.override", KEY_CERT_CHECKATTRS: "media.gmp-manager.cert.checkAttributes", diff --git a/toolkit/mozapps/extensions/test/browser/browser_gmpProvider.js b/toolkit/mozapps/extensions/test/browser/browser_gmpProvider.js index 37825b0652a9..5921fc5b6aa1 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_gmpProvider.js +++ b/toolkit/mozapps/extensions/test/browser/browser_gmpProvider.js @@ -102,7 +102,7 @@ add_task(function* initializeState() { gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_LAST_UPDATE, addon.id)); gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_AUTOUPDATE, addon.id)); gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id)); - gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id)); + gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VISIBLE, addon.id)); } gPrefs.clearUserPref(GMPScope.GMPPrefs.KEY_LOGGING_DUMP); gPrefs.clearUserPref(GMPScope.GMPPrefs.KEY_LOGGING_LEVEL); @@ -125,7 +125,7 @@ add_task(function* initializeState() { gPrefs.setIntPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_LAST_UPDATE, addon.id), 0); gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_AUTOUPDATE, addon.id), false); gPrefs.setCharPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id), ""); - gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id), + gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VISIBLE, addon.id), true); } yield GMPScope.GMPProvider.shutdown(); @@ -370,7 +370,7 @@ add_task(function* testUpdateButton() { add_task(function* testEmeSupport() { for (let addon of gMockAddons) { - gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id)); + gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VISIBLE, addon.id)); } yield GMPScope.GMPProvider.shutdown(); GMPScope.GMPProvider.startup(); @@ -400,7 +400,7 @@ add_task(function* testEmeSupport() { } for (let addon of gMockAddons) { - gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id), + gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VISIBLE, addon.id), true); } yield GMPScope.GMPProvider.shutdown(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gmpProvider.js b/toolkit/mozapps/extensions/test/xpcshell/test_gmpProvider.js index 48d9c0557639..88140bd11af4 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gmpProvider.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gmpProvider.js @@ -59,7 +59,9 @@ function run_test() { gPrefs.setIntPref(GMPScope.GMPPrefs.KEY_LOGGING_LEVEL, 0); gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_EME_ENABLED, true); for (let addon of gMockAddons.values()) { - gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id), + gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_VISIBLE, addon.id), + true); + gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCE_SUPPORTED, addon.id), true); } GMPScope.GMPProvider.shutdown(); From 64f7e2a1c9a3aeb3bb0807868a1717f797c29f60 Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Tue, 31 May 2016 11:00:55 +1200 Subject: [PATCH 43/76] Bug 1276132 - Remove use of #ifdef MOZ_{KEYSYSTEM}_EME in dom/media code. r=jwwang Instead of controlling visibility of EME keysystems by build config, do it by preference. This means keysystems can be turned on easier. MozReview-Commit-ID: Ky1zrHPubOJ --HG-- extra : rebase_source : 7d68ad8389afdac8fcfffd2c505f8467107c05a5 --- dom/media/eme/MediaKeySystemAccess.cpp | 66 +++++++++++++------------- dom/media/eme/moz.build | 3 -- dom/media/gmp/GMPChild.cpp | 16 +------ dom/media/gmp/GMPParent.cpp | 8 ---- dom/media/gmp/GMPParent.h | 2 - dom/media/gmp/moz.build | 9 +--- 6 files changed, 36 insertions(+), 68 deletions(-) diff --git a/dom/media/eme/MediaKeySystemAccess.cpp b/dom/media/eme/MediaKeySystemAccess.cpp index eea37525580d..66e5f3d0da3e 100644 --- a/dom/media/eme/MediaKeySystemAccess.cpp +++ b/dom/media/eme/MediaKeySystemAccess.cpp @@ -278,51 +278,51 @@ MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem, return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, aOutMessage, aOutCdmVersion); } -#ifdef MOZ_ADOBE_EME - if (aKeySystem.EqualsLiteral("com.adobe.primetime")) { - if (!Preferences::GetBool("media.gmp-eme-adobe.enabled", false)) { - aOutMessage = NS_LITERAL_CSTRING("Adobe EME disabled"); - return MediaKeySystemStatus::Cdm_disabled; - } + if (Preferences::GetBool("media.gmp-eme-adobe.visible", false)) { + if (aKeySystem.EqualsLiteral("com.adobe.primetime")) { + if (!Preferences::GetBool("media.gmp-eme-adobe.enabled", false)) { + aOutMessage = NS_LITERAL_CSTRING("Adobe EME disabled"); + return MediaKeySystemStatus::Cdm_disabled; + } #ifdef XP_WIN - // Win Vista and later only. - if (!IsVistaOrLater()) { - aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version (Vista) not met for Adobe EME"); - return MediaKeySystemStatus::Cdm_not_supported; - } + // Win Vista and later only. + if (!IsVistaOrLater()) { + aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version (Vista) not met for Adobe EME"); + return MediaKeySystemStatus::Cdm_not_supported; + } #endif #ifdef XP_MACOSX - if (!nsCocoaFeatures::OnLionOrLater()) { - aOutMessage = NS_LITERAL_CSTRING("Minimum MacOSX version (10.7) not met for Adobe EME"); - return MediaKeySystemStatus::Cdm_not_supported; + if (!nsCocoaFeatures::OnLionOrLater()) { + aOutMessage = NS_LITERAL_CSTRING("Minimum MacOSX version (10.7) not met for Adobe EME"); + return MediaKeySystemStatus::Cdm_not_supported; + } +#endif + return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, aOutMessage, aOutCdmVersion); } -#endif - return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, aOutMessage, aOutCdmVersion); } -#endif -#ifdef MOZ_WIDEVINE_EME - if (aKeySystem.EqualsLiteral("com.widevine.alpha")) { + if (Preferences::GetBool("media.gmp-widevinecdm.visible", false)) { + if (aKeySystem.EqualsLiteral("com.widevine.alpha")) { #ifdef XP_WIN - // Win Vista and later only. - if (!IsVistaOrLater()) { - aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version (Vista) not met for Widevine EME"); - return MediaKeySystemStatus::Cdm_not_supported; - } + // Win Vista and later only. + if (!IsVistaOrLater()) { + aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version (Vista) not met for Widevine EME"); + return MediaKeySystemStatus::Cdm_not_supported; + } #endif #ifdef XP_MACOSX - if (!nsCocoaFeatures::OnLionOrLater()) { - aOutMessage = NS_LITERAL_CSTRING("Minimum MacOSX version (10.7) not met for Widevine EME"); - return MediaKeySystemStatus::Cdm_not_supported; - } + if (!nsCocoaFeatures::OnLionOrLater()) { + aOutMessage = NS_LITERAL_CSTRING("Minimum MacOSX version (10.7) not met for Widevine EME"); + return MediaKeySystemStatus::Cdm_not_supported; + } #endif - if (!Preferences::GetBool("media.gmp-widevinecdm.enabled", false)) { - aOutMessage = NS_LITERAL_CSTRING("Widevine EME disabled"); - return MediaKeySystemStatus::Cdm_disabled; + if (!Preferences::GetBool("media.gmp-widevinecdm.enabled", false)) { + aOutMessage = NS_LITERAL_CSTRING("Widevine EME disabled"); + return MediaKeySystemStatus::Cdm_disabled; + } + return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, aOutMessage, aOutCdmVersion); } - return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, aOutMessage, aOutCdmVersion); } -#endif return MediaKeySystemStatus::Cdm_not_supported; } diff --git a/dom/media/eme/moz.build b/dom/media/eme/moz.build index 8270d9b9ed2e..a7af0577d5c1 100644 --- a/dom/media/eme/moz.build +++ b/dom/media/eme/moz.build @@ -4,9 +4,6 @@ # 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/. -for cdm in CONFIG['MOZ_EME_MODULES']: - DEFINES['MOZ_%s_EME' % cdm.upper()] = True - EXPORTS.mozilla.dom += [ 'MediaEncryptedEvent.h', 'MediaKeyError.h', diff --git a/dom/media/gmp/GMPChild.cpp b/dom/media/gmp/GMPChild.cpp index bc4584aedc80..9cc31369349c 100644 --- a/dom/media/gmp/GMPChild.cpp +++ b/dom/media/gmp/GMPChild.cpp @@ -23,9 +23,7 @@ #include "GMPUtils.h" #include "prio.h" #include "base/task.h" -#ifdef MOZ_WIDEVINE_EME #include "widevine-adapter/WidevineAdapter.h" -#endif using namespace mozilla::ipc; using mozilla::dom::CrashReporterChild; @@ -376,17 +374,12 @@ GMPChild::AnswerStartPlugin(const nsString& aAdapter) return false; } -#ifdef MOZ_WIDEVINE_EME bool isWidevine = aAdapter.EqualsLiteral("widevine"); -#endif - #if defined(MOZ_GMP_SANDBOX) && defined(XP_MACOSX) MacSandboxPluginType pluginType = MacSandboxPluginType_GMPlugin_Default; -#ifdef MOZ_WIDEVINE_EME if (isWidevine) { - pluginType = MacSandboxPluginType_GMPlugin_EME_Widevine; + pluginType = MacSandboxPluginType_GMPlugin_EME_Widevine; } -#endif if (!SetMacSandboxInfo(pluginType)) { NS_WARNING("Failed to set Mac GMP sandbox info"); delete platformAPI; @@ -394,12 +387,7 @@ GMPChild::AnswerStartPlugin(const nsString& aAdapter) } #endif - GMPAdapter* adapter = nullptr; -#ifdef MOZ_WIDEVINE_EME - if (isWidevine) { - adapter = new WidevineAdapter(); - } -#endif + GMPAdapter* adapter = (isWidevine) ? new WidevineAdapter() : nullptr; if (!mGMPLoader->Load(libPath.get(), libPath.Length(), mNodeId.BeginWriting(), diff --git a/dom/media/gmp/GMPParent.cpp b/dom/media/gmp/GMPParent.cpp index d5bebfa19605..7239ef0884ea 100644 --- a/dom/media/gmp/GMPParent.cpp +++ b/dom/media/gmp/GMPParent.cpp @@ -40,10 +40,8 @@ using CrashReporter::GetIDFromMinidump; #include "WMFDecoderModule.h" #endif -#ifdef MOZ_WIDEVINE_EME #include "mozilla/dom/WidevineCDMManifestBinding.h" #include "widevine-adapter/WidevineAdapter.h" -#endif namespace mozilla { @@ -809,7 +807,6 @@ GMPParent::ReadGMPMetaData() return ReadGMPInfoFile(infoFile); } -#ifdef MOZ_WIDEVINE_EME // Maybe this is the Widevine adapted plugin? nsCOMPtr manifestFile; rv = mDirectory->Clone(getter_AddRefs(manifestFile)); @@ -818,9 +815,6 @@ GMPParent::ReadGMPMetaData() } manifestFile->AppendRelativePath(NS_LITERAL_STRING("manifest.json")); return ReadChromiumManifestFile(manifestFile); -#else - return GenericPromise::CreateAndReject(rv, __func__); -#endif } RefPtr @@ -915,7 +909,6 @@ GMPParent::ReadGMPInfoFile(nsIFile* aFile) return GenericPromise::CreateAndResolve(true, __func__); } -#ifdef MOZ_WIDEVINE_EME RefPtr GMPParent::ReadChromiumManifestFile(nsIFile* aFile) { @@ -968,7 +961,6 @@ GMPParent::ParseChromiumManifest(nsString aJSON) return GenericPromise::CreateAndResolve(true, __func__); } -#endif bool GMPParent::CanBeSharedCrossNodeIds() const diff --git a/dom/media/gmp/GMPParent.h b/dom/media/gmp/GMPParent.h index f36cbd19ccc6..67355faeee63 100644 --- a/dom/media/gmp/GMPParent.h +++ b/dom/media/gmp/GMPParent.h @@ -167,10 +167,8 @@ private: bool EnsureProcessLoaded(); RefPtr ReadGMPMetaData(); RefPtr ReadGMPInfoFile(nsIFile* aFile); -#ifdef MOZ_WIDEVINE_EME RefPtr ParseChromiumManifest(nsString aJSON); // Main thread. RefPtr ReadChromiumManifestFile(nsIFile* aFile); // GMP thread. -#endif #ifdef MOZ_CRASHREPORTER void WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes); void GetCrashID(nsString& aResult); diff --git a/dom/media/gmp/moz.build b/dom/media/gmp/moz.build index 77b51ff927a2..d05b5937b321 100644 --- a/dom/media/gmp/moz.build +++ b/dom/media/gmp/moz.build @@ -4,9 +4,6 @@ # 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/. -for cdm in CONFIG['MOZ_EME_MODULES']: - DEFINES['MOZ_%s_EME' % cdm.upper()] = True - XPIDL_MODULE = 'content_geckomediaplugins' XPIDL_SOURCES += [ @@ -120,13 +117,9 @@ UNIFIED_SOURCES += [ DIRS += [ 'rlz', + 'widevine-adapter', ] -if 'widevine' in CONFIG['MOZ_EME_MODULES']: - DIRS += [ - 'widevine-adapter', - ] - IPDL_SOURCES += [ 'GMPTypes.ipdlh', 'PGMP.ipdl', From b48e2e7ea4833a86a9726ade116ae5c4b1e4c486 Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Tue, 31 May 2016 12:04:12 +1200 Subject: [PATCH 44/76] Bug 1276132 - Don't show EME 'enable' UI for non-visible keysystems. r=gijs This means we'll only show the EME UI for keysystems that are explicitly turned on in the build config, or those that are enabled after the build via prefs. MozReview-Commit-ID: 7VTp1BJSZFy --HG-- extra : rebase_source : 4f243a70cdfc45f40a07d034dfa30f34cb1baaf7 --- browser/base/content/browser-media.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/browser/base/content/browser-media.js b/browser/base/content/browser-media.js index 7c915112a550..b9ce5ad3a4d2 100644 --- a/browser/base/content/browser-media.js +++ b/browser/base/content/browser-media.js @@ -31,6 +31,20 @@ var gEMEHandler = { } browser.reload(); }, + isKeySystemVisible: function(keySystem) { + if (!keySystem) { + return false; + } + if (keySystem.startsWith("com.adobe") && + Services.prefs.getPrefType("media.gmp-eme-adobe.visible")) { + return Services.prefs.getBoolPref("media.gmp-eme-adobe.visible"); + } + if (keySystem == "com.widevine.alpha" && + Services.prefs.getPrefType("media.gmp-widevinecdm.visible")) { + return Services.prefs.getBoolPref("media.gmp-widevinecdm.visible"); + } + return true; + }, getLearnMoreLink: function(msgId) { let text = gNavigatorBundle.getString("emeNotifications." + msgId + ".learnMoreLabel"); let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL"); @@ -46,8 +60,8 @@ var gEMEHandler = { return; } let {status: status, keySystem: keySystem} = parsedData; - // Don't need to show if disabled - if (!this.uiEnabled) { + // Don't need to show if disabled or keysystem not visible. + if (!this.uiEnabled || !this.isKeySystemVisible(keySystem)) { return; } From 57fa47069254fb27a5a47ab910f54f7e722720af Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Tue, 31 May 2016 12:05:24 +1200 Subject: [PATCH 45/76] Bug 1276132 - Make more Widevine class constructors explicit to keep gcc happy. r=jwwang Fixes compile errors on Linux when Widevine is compiled. MozReview-Commit-ID: 19qQw02CqdQ --HG-- extra : rebase_source : ebb98b25738e0438d873834f07c72be1f4eb71db --- dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp | 2 +- dom/media/gmp/widevine-adapter/WidevineUtils.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp b/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp index 5d16e6092e67..28c4fbab977e 100644 --- a/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp +++ b/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp @@ -193,7 +193,7 @@ WidevineDecryptor::DecryptingComplete() class WidevineBuffer : public cdm::Buffer { public: - WidevineBuffer(size_t aSize) { + explicit WidevineBuffer(size_t aSize) { Log("WidevineBuffer(size=" PRIuSIZE ") created", aSize); mBuffer.SetLength(aSize); } diff --git a/dom/media/gmp/widevine-adapter/WidevineUtils.h b/dom/media/gmp/widevine-adapter/WidevineUtils.h index 9eb039673afb..e5d20fe9c624 100644 --- a/dom/media/gmp/widevine-adapter/WidevineUtils.h +++ b/dom/media/gmp/widevine-adapter/WidevineUtils.h @@ -46,7 +46,7 @@ class CDMWrapper { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CDMWrapper) - CDMWrapper(cdm::ContentDecryptionModule_8* aCDM) + explicit CDMWrapper(cdm::ContentDecryptionModule_8* aCDM) : mCDM(aCDM) { MOZ_ASSERT(mCDM); From 5aaca3d44eb773b7a739decac50a7520a66a71b3 Mon Sep 17 00:00:00 2001 From: Brian Birtles Date: Thu, 9 Jun 2016 08:12:52 +0900 Subject: [PATCH 46/76] Bug 1276688 part 1 - Handle entries arrays where we don't have a property value at the 0.0/1.0 offset; r=heycam MozReview-Commit-ID: GCCF4taOC6z --HG-- extra : rebase_source : b2238ce7aa1fde865810ca70774d51cd1f5b7c8b --- dom/animation/KeyframeUtils.cpp | 64 +++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/dom/animation/KeyframeUtils.cpp b/dom/animation/KeyframeUtils.cpp index 52c94aeb193f..d346566aad9c 100644 --- a/dom/animation/KeyframeUtils.cpp +++ b/dom/animation/KeyframeUtils.cpp @@ -957,9 +957,6 @@ BuildSegmentsFromValueEntries(nsStyleContext* aStyleContext, std::stable_sort(aEntries.begin(), aEntries.end(), &KeyframeValueEntry::PropertyOffsetComparator::LessThan); - MOZ_ASSERT(aEntries[0].mOffset == 0.0f); - MOZ_ASSERT(aEntries.LastElement().mOffset == 1.0f); - // For a given index i, we want to generate a segment from aEntries[i] // to aEntries[j], if: // @@ -974,13 +971,56 @@ BuildSegmentsFromValueEntries(nsStyleContext* aStyleContext, // offset 1, if we have multiple values for a given property at that offset, // since we need to retain the very first and very last value so they can // be used for reverse and forward filling. + // + // Typically, for each property in |aEntries|, we expect there to be at least + // one KeyframeValueEntry with offset 0.0, and at least one with offset 1.0. + // However, since it is possible that when building |aEntries|, the call to + // StyleAnimationValue::ComputeValues might fail, this can't be guaranteed. + // Furthermore, since we don't yet implement additive animation and hence + // don't have sensible fallback behavior when these values are missing, the + // following loop takes care to identify properties that lack a value at + // offset 0.0/1.0 and drops those properties from |aResult|. nsCSSProperty lastProperty = eCSSProperty_UNKNOWN; AnimationProperty* animationProperty = nullptr; size_t i = 0, n = aEntries.Length(); - while (i + 1 < n) { + while (i < n) { + // Check that the last property ends with an entry at offset 1. + if (i + 1 == n) { + if (aEntries[i].mOffset != 1.0f && animationProperty) { + aResult.RemoveElementAt(aResult.Length() - 1); + animationProperty = nullptr; + } + break; + } + + MOZ_ASSERT(aEntries[i].mProperty != eCSSProperty_UNKNOWN && + aEntries[i + 1].mProperty != eCSSProperty_UNKNOWN, + "Each entry should specify a valid property"); + + // Skip properties that don't have an entry with offset 0. + if (aEntries[i].mProperty != lastProperty && + aEntries[i].mOffset != 0.0f) { + // Since the entries are sorted by offset for a given property, and + // since we don't update |lastProperty|, we will keep hitting this + // condition until we change property. + ++i; + continue; + } + + // Drop properties that don't end with an entry with offset 1. + if (aEntries[i].mProperty != aEntries[i + 1].mProperty && + aEntries[i].mOffset != 1.0f) { + if (animationProperty) { + aResult.RemoveElementAt(aResult.Length() - 1); + animationProperty = nullptr; + } + ++i; + continue; + } + // Starting from i, determine the next [i, j] interval from which to // generate a segment. size_t j; @@ -988,23 +1028,24 @@ BuildSegmentsFromValueEntries(nsStyleContext* aStyleContext, // We need to generate an initial zero-length segment. MOZ_ASSERT(aEntries[i].mProperty == aEntries[i + 1].mProperty); j = i + 1; - while (aEntries[j + 1].mOffset == 0.0f) { - MOZ_ASSERT(aEntries[j].mProperty == aEntries[j + 1].mProperty); + while (aEntries[j + 1].mOffset == 0.0f && + aEntries[j + 1].mProperty == aEntries[j].mProperty) { ++j; } } else if (aEntries[i].mOffset == 1.0f) { - if (aEntries[i + 1].mOffset == 1.0f) { + if (aEntries[i + 1].mOffset == 1.0f && + aEntries[i + 1].mProperty == aEntries[i].mProperty) { // We need to generate a final zero-length segment. - MOZ_ASSERT(aEntries[i].mProperty == aEntries[i].mProperty); j = i + 1; - while (j + 1 < n && aEntries[j + 1].mOffset == 1.0f) { - MOZ_ASSERT(aEntries[j].mProperty == aEntries[j + 1].mProperty); + while (j + 1 < n && + aEntries[j + 1].mOffset == 1.0f && + aEntries[j + 1].mProperty == aEntries[j].mProperty) { ++j; } } else { // New property. - MOZ_ASSERT(aEntries[i + 1].mOffset == 0.0f); MOZ_ASSERT(aEntries[i].mProperty != aEntries[i + 1].mProperty); + animationProperty = nullptr; ++i; continue; } @@ -1020,6 +1061,7 @@ BuildSegmentsFromValueEntries(nsStyleContext* aStyleContext, // to insert segments into. if (aEntries[i].mProperty != lastProperty) { MOZ_ASSERT(aEntries[i].mOffset == 0.0f); + MOZ_ASSERT(!animationProperty); animationProperty = aResult.AppendElement(); animationProperty->mProperty = aEntries[i].mProperty; lastProperty = aEntries[i].mProperty; From 618e68471e4c8e2d0423e040071b92fb660cc621 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Tue, 7 Jun 2016 12:13:24 -0700 Subject: [PATCH 47/76] Bug 1278647 [stylo] Add font family bindings for Servo r=heycam MozReview-Commit-ID: IlEB0f1xrKF --HG-- extra : rebase_source : aa9cd08f0abf281dcf149435fbb2e39fc37c8367 --- gfx/thebes/gfxFontFamilyList.h | 2 +- layout/style/ServoBindings.cpp | 28 ++++++++++++++++++++++++++++ layout/style/ServoBindings.h | 15 ++++++++++++++- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/gfx/thebes/gfxFontFamilyList.h b/gfx/thebes/gfxFontFamilyList.h index 6e5e93f63146..e240102e0910 100644 --- a/gfx/thebes/gfxFontFamilyList.h +++ b/gfx/thebes/gfxFontFamilyList.h @@ -21,7 +21,7 @@ namespace mozilla { * between unquoted and quoted names for serializaiton */ -enum FontFamilyType { +enum FontFamilyType : uint32_t { eFamily_none = 0, // used when finding generics // explicitly named font family (e.g. Helvetica) diff --git a/layout/style/ServoBindings.cpp b/layout/style/ServoBindings.cpp index 4f148ffcb044..13dd4edac808 100644 --- a/layout/style/ServoBindings.cpp +++ b/layout/style/ServoBindings.cpp @@ -6,6 +6,7 @@ #include "mozilla/ServoBindings.h" +#include "gfxFontFamilyList.h" #include "nsAttrValueInlines.h" #include "nsCSSRuleProcessor.h" #include "nsContentUtils.h" @@ -286,6 +287,33 @@ Gecko_AtomEqualsUTF8IgnoreCase(nsIAtom* aAtom, const char* aString, uint32_t aLe return nsContentUtils::EqualsIgnoreASCIICase(atomStr, inStr); } +void +Gecko_FontFamilyList_Clear(FontFamilyList* aList) { + aList->Clear(); +} + +void +Gecko_FontFamilyList_AppendNamed(FontFamilyList* aList, nsIAtom* aName) +{ + // Servo doesn't record whether the name was quoted or unquoted, so just + // assume unquoted for now. + FontFamilyName family; + aName->ToString(family.mName); + aList->Append(family); +} + +void +Gecko_FontFamilyList_AppendGeneric(FontFamilyList* aList, FontFamilyType aType) +{ + aList->Append(FontFamilyName(aType)); +} + +void +Gecko_CopyFontFamilyFrom(nsFont* dst, const nsFont* src) +{ + dst->fontlist = src->fontlist; +} + void Gecko_SetListStyleType(nsStyleList* style_struct, uint32_t type) { diff --git a/layout/style/ServoBindings.h b/layout/style/ServoBindings.h index eb48746d8a77..abaac0e08f86 100644 --- a/layout/style/ServoBindings.h +++ b/layout/style/ServoBindings.h @@ -25,7 +25,14 @@ class nsINode; typedef nsINode RawGeckoNode; class nsIPrincipal; class nsIURI; -namespace mozilla { namespace dom { class Element; } } +struct nsFont; +namespace mozilla { + class FontFamilyList; + enum FontFamilyType : uint32_t; + namespace dom { class Element; } +} +using mozilla::FontFamilyList; +using mozilla::FontFamilyType; using mozilla::dom::Element; typedef mozilla::dom::Element RawGeckoElement; class nsIDocument; @@ -121,6 +128,12 @@ const uint16_t* Gecko_GetAtomAsUTF16(nsIAtom* aAtom, uint32_t* aLength); bool Gecko_AtomEqualsUTF8(nsIAtom* aAtom, const char* aString, uint32_t aLength); bool Gecko_AtomEqualsUTF8IgnoreCase(nsIAtom* aAtom, const char* aString, uint32_t aLength); +// Font style +void Gecko_FontFamilyList_Clear(FontFamilyList* aList); +void Gecko_FontFamilyList_AppendNamed(FontFamilyList* aList, nsIAtom* aName); +void Gecko_FontFamilyList_AppendGeneric(FontFamilyList* list, FontFamilyType familyType); +void Gecko_CopyFontFamilyFrom(nsFont* dst, const nsFont* src); + // Counter style. void Gecko_SetListStyleType(nsStyleList* style_struct, uint32_t type); void Gecko_CopyListStyleTypeFrom(nsStyleList* dst, const nsStyleList* src); From 8a50416d83da017d6d619cea42094818e8fb95bf Mon Sep 17 00:00:00 2001 From: "Kearwood (Kip) Gilbert" Date: Tue, 31 May 2016 17:22:30 -0700 Subject: [PATCH 48/76] Bug 1111689 - Part 1: Let EXT_shader_texture_lod play when ARB_shader_texture_lod can play. r=jgilbert --- dom/canvas/WebGLContextExtensions.cpp | 2 +- gfx/gl/GLContext.cpp | 1 + gfx/gl/GLContext.h | 2 ++ gfx/gl/GLContextFeatures.cpp | 11 +++++++++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/dom/canvas/WebGLContextExtensions.cpp b/dom/canvas/WebGLContextExtensions.cpp index 8527c02600b9..6059cb0fcdb3 100644 --- a/dom/canvas/WebGLContextExtensions.cpp +++ b/dom/canvas/WebGLContextExtensions.cpp @@ -172,7 +172,7 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const case WebGLExtensionID::EXT_frag_depth: return WebGLExtensionFragDepth::IsSupported(this); case WebGLExtensionID::EXT_shader_texture_lod: - return gl->IsExtensionSupported(gl::GLContext::EXT_shader_texture_lod); + return gl->IsSupported(gl::GLFeature::shader_texture_lod); case WebGLExtensionID::EXT_sRGB: return WebGLExtensionSRGB::IsSupported(this); diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index 9142aeba894a..4cebe310e377 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -100,6 +100,7 @@ static const char* const sExtensionNames[] = { "GL_ARB_robustness", "GL_ARB_sampler_objects", "GL_ARB_seamless_cube_map", + "GL_ARB_shader_texture_lod", "GL_ARB_sync", "GL_ARB_texture_compression", "GL_ARB_texture_float", diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h index 7e81aeed7a90..95a641938468 100644 --- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -128,6 +128,7 @@ enum class GLFeature { sRGB_texture, sampler_objects, seamless_cube_map_opt_in, + shader_texture_lod, split_framebuffer, standard_derivatives, sync, @@ -423,6 +424,7 @@ public: ARB_robustness, ARB_sampler_objects, ARB_seamless_cube_map, + ARB_shader_texture_lod, ARB_sync, ARB_texture_compression, ARB_texture_float, diff --git a/gfx/gl/GLContextFeatures.cpp b/gfx/gl/GLContextFeatures.cpp index b0177eb96024..691d697d263d 100644 --- a/gfx/gl/GLContextFeatures.cpp +++ b/gfx/gl/GLContextFeatures.cpp @@ -567,6 +567,17 @@ static const FeatureInfo sFeatureInfoArr[] = { GLContext::Extensions_End } }, + { + "shader_texture_lod", + GLVersion::NONE, + GLESVersion::NONE, + GLContext::Extension_None, + { + GLContext::ARB_shader_texture_lod, + GLContext::EXT_shader_texture_lod, + GLContext::Extensions_End + } + }, { // Do we have separate DRAW and READ framebuffer bind points? "split_framebuffer", From 9b588f7bc7ebedbd324d0ad16a0f5cab7680ebfe Mon Sep 17 00:00:00 2001 From: "Kearwood (Kip) Gilbert" Date: Tue, 31 May 2016 17:28:35 -0700 Subject: [PATCH 49/76] Bug 1111689 - Suppress ASAN leak reports for libglsl.so. - r=jgilbert --- build/sanitizers/lsan_suppressions.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/build/sanitizers/lsan_suppressions.txt b/build/sanitizers/lsan_suppressions.txt index d6f63009926b..18b4479e80c0 100644 --- a/build/sanitizers/lsan_suppressions.txt +++ b/build/sanitizers/lsan_suppressions.txt @@ -96,6 +96,7 @@ leak:libdricore.so leak:libdricore9.2.1.so leak:libGL.so leak:libglib-2.0.so +leak:libglsl.so leak:libp11-kit.so leak:libpixman-1.so leak:libpulse.so From cc716a2cf989bfc9f351bef1a5c0122af3ebfdd6 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Mon, 6 Jun 2016 17:56:10 -0700 Subject: [PATCH 50/76] Bug 1111689 - Remark failures. MozReview-Commit-ID: 6SsnoDXPdvO --- dom/canvas/test/webgl-mochitest/mochitest.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/canvas/test/webgl-mochitest/mochitest.ini b/dom/canvas/test/webgl-mochitest/mochitest.ini index 06de3131740d..76f5e57b91ee 100644 --- a/dom/canvas/test/webgl-mochitest/mochitest.ini +++ b/dom/canvas/test/webgl-mochitest/mochitest.ini @@ -21,7 +21,7 @@ fail-if = (os == 'android') [ensure-exts/test_EXT_sRGB.html] fail-if = (os == 'android') || (os == 'mac' && os_version == '10.6') || (os == 'win') [ensure-exts/test_EXT_shader_texture_lod.html] -fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') +fail-if = (os == 'android') [ensure-exts/test_EXT_texture_filter_anisotropic.html] fail-if = (os == 'android') || (os == 'linux') [ensure-exts/test_OES_standard_derivatives.html] From e0b7bbc6beaff8ffa0e6220c477ae80c9374d994 Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Thu, 26 May 2016 12:09:46 -0700 Subject: [PATCH 51/76] Bug 1272851 - Allow temporary directory to be specified to xpcshell test harness; r=ted A subsequent commit will change where the temporary directory is located in certain test invocations. To do this, we need to teach the xpcshell harness to use an alternate temporary directory instead of using the system default (likely specified from TEMP* environment variables). MozReview-Commit-ID: IUUlYaLBiEC --HG-- extra : rebase_source : 389144dedb8cce62c1d10c65a37be7fb632c2317 --- testing/xpcshell/runxpcshelltests.py | 13 +++++++++---- testing/xpcshell/xpcshellcommandline.py | 3 +++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/testing/xpcshell/runxpcshelltests.py b/testing/xpcshell/runxpcshelltests.py index c107d48fa806..68c6eaa70b30 100755 --- a/testing/xpcshell/runxpcshelltests.py +++ b/testing/xpcshell/runxpcshelltests.py @@ -17,6 +17,7 @@ import re import shutil import signal import sys +import tempfile import time import traceback @@ -132,6 +133,7 @@ class XPCShellTestThread(Thread): self.xpcsRunArgs = kwargs.get('xpcsRunArgs') self.failureManifest = kwargs.get('failureManifest') self.stack_fixer_function = kwargs.get('stack_fixer_function') + self._rootTempDir = kwargs.get('tempDir') self.app_dir_key = app_dir_key self.interactive = interactive @@ -321,7 +323,7 @@ class XPCShellTestThread(Thread): name.replace('\\', '/')] def setupTempDir(self): - tempDir = mkdtemp(prefix='xpc-other-') + tempDir = mkdtemp(prefix='xpc-other-', dir=self._rootTempDir) self.env["XPCSHELL_TEST_TEMP_DIR"] = tempDir if self.interactive: self.log.info("temp dir is %s" % tempDir) @@ -331,7 +333,7 @@ class XPCShellTestThread(Thread): if not os.path.isdir(self.pluginsPath): return None - pluginsDir = mkdtemp(prefix='xpc-plugins-') + pluginsDir = mkdtemp(prefix='xpc-plugins-', dir=self._rootTempDir) # shutil.copytree requires dst to not exist. Deleting the tempdir # would make a race condition possible in a concurrent environment, # so we are using dir_utils.copy_tree which accepts an existing dst @@ -357,7 +359,7 @@ class XPCShellTestThread(Thread): pass os.makedirs(profileDir) else: - profileDir = mkdtemp(prefix='xpc-profile-') + profileDir = mkdtemp(prefix='xpc-profile-', dir=self._rootTempDir) self.env["XPCSHELL_TEST_PROFILE_DIR"] = profileDir if self.interactive or self.singleFile: self.log.info("profile dir is %s" % profileDir) @@ -1070,7 +1072,7 @@ class XPCShellTests(object): return path def runTests(self, xpcshell=None, xrePath=None, appPath=None, symbolsPath=None, - manifest=None, testPaths=None, mobileArgs=None, + manifest=None, testPaths=None, mobileArgs=None, tempDir=None, interactive=False, verbose=False, keepGoing=False, logfiles=True, thisChunk=1, totalChunks=1, debugger=None, debuggerArgs=None, debuggerInteractive=False, @@ -1110,6 +1112,7 @@ class XPCShellTests(object): |shuffle|, if True, execute tests in random order. |testingModulesDir|, if provided, specifies where JS modules reside. xpcshell will register a resource handler mapping this path. + |tempDir|, if provided, specifies a temporary directory to use. |otherOptions| may be present for the convenience of subclasses """ @@ -1163,6 +1166,7 @@ class XPCShellTests(object): self.xrePath = xrePath self.appPath = appPath self.symbolsPath = symbolsPath + self.tempDir = os.path.normpath(tempDir or tempfile.gettempdir()) self.manifest = manifest self.dump_tests = dump_tests self.interactive = interactive @@ -1249,6 +1253,7 @@ class XPCShellTests(object): 'httpdManifest': self.httpdManifest, 'httpdJSPath': self.httpdJSPath, 'headJSPath': self.headJSPath, + 'tempDir': self.tempDir, 'testharnessdir': self.testharnessdir, 'profileName': self.profileName, 'singleFile': self.singleFile, diff --git a/testing/xpcshell/xpcshellcommandline.py b/testing/xpcshell/xpcshellcommandline.py index f17efe474f55..ef48c97011f1 100644 --- a/testing/xpcshell/xpcshellcommandline.py +++ b/testing/xpcshell/xpcshellcommandline.py @@ -29,6 +29,9 @@ def add_common_arguments(parser): parser.add_argument("--sequential", action="store_true", dest="sequential", default=False, help="Run all tests sequentially") + parser.add_argument("--temp-dir", + dest="tempDir", default=None, + help="Directory to use for temporary files") parser.add_argument("--testing-modules-dir", dest="testingModulesDir", default=None, help="Directory where testing modules are located.") From 7fd974e58a80a6e2d3119f7a3b86f683a735e235 Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Thu, 26 May 2016 11:56:20 -0700 Subject: [PATCH 52/76] Bug 1272851 - Use objdir for temporary directory for `mach xpcshell-test`; r=ted When running xpcshell tests on my i7-6700K, the Windows Defender MsMpEng.exe process regularly consumes up to 50% CPU - 2 whole cores. This is because it is canning the thousands of files we create in the temporary directory. (We create a profile for every xpcshell.exe process.) This commit changes the behavior of `mach xpcshell-test` to use a temporary directory under the topobjdir. We encourage people to disable file indexing and A/V scanning in the source and object directories because this can add overhead. So by putting temporary files in the object directory, we should minimize the chances of file scanning slowing down test execution. On my machine (which has Windows Defender disabled in my source and objdirs), `mach xpcshell-test` execution time drops from ~13:40 to ~7:30. Seriously. I'm told we have Windows Defender disabled in automation, so this hack shouldn't need to be investigated there. i.e. this is a pure local development win. MozReview-Commit-ID: BMcSAZ16Yei --HG-- extra : rebase_source : 5490be35b59ff675639180b928ee77dcc70de485 --- testing/xpcshell/mach_commands.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/testing/xpcshell/mach_commands.py b/testing/xpcshell/mach_commands.py index 1544e039768e..932e4b02d2f2 100644 --- a/testing/xpcshell/mach_commands.py +++ b/testing/xpcshell/mach_commands.py @@ -7,6 +7,7 @@ from __future__ import absolute_import, unicode_literals, print_function import argparse +import errno import os import shutil import sys @@ -122,6 +123,18 @@ class XPCShellRunner(MozbuildObject): if kwargs["failure_manifest"] is None: kwargs["failure_manifest"] = os.path.join(self.statedir, 'xpcshell.failures.ini') + # Use the object directory for the temp directory to minimize the chance + # of file scanning. The overhead from e.g. search indexers and anti-virus + # scanners like Windows Defender can add tons of overhead to test execution. + # We encourage people to disable these things in the object directory. + temp_dir = os.path.join(self.topobjdir, 'temp') + try: + os.mkdir(temp_dir) + except OSError as e: + if e.errno != errno.EEXIST: + raise + kwargs['tempDir'] = temp_dir + # Python through 2.7.2 has issues with unicode in some of the # arguments. Work around that. filtered_args = {} From 8cf45849efac072928aa0aab74834b66442b5df6 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Mon, 6 Jun 2016 21:07:24 +0900 Subject: [PATCH 53/76] Bug 1278084 part.1 Don't release TSF objects during handling a key message r=m_kato While TIP is handling a key message, TSFTextStore shouldn't release any TSF objects since it may cause hitting a bug of TIPs. Actually, MS-IME for Japanese on Windows 10 crashes when TSFTextStore is destroyed during composition because probably it accesses some destroyed objects to request to commit composition or query contents. MozReview-Commit-ID: 9CTjHhAvG04 --HG-- extra : rebase_source : c34041962927795fe0d288aed10a96cf064b6243 --- widget/windows/TSFTextStore.cpp | 49 +++++++++++++++++++++++++++++---- widget/windows/TSFTextStore.h | 16 +++++++++++ 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/widget/windows/TSFTextStore.cpp b/widget/windows/TSFTextStore.cpp index 65f1c8af9b6f..66ade4e57057 100644 --- a/widget/windows/TSFTextStore.cpp +++ b/widget/windows/TSFTextStore.cpp @@ -1182,6 +1182,7 @@ TSFTextStore::TSFTextStore() , mSinkMask(0) , mLock(0) , mLockQueued(0) + , mHandlingKeyMessage(0) , mLockedContent(mComposition, mSelection) , mRequestedAttrValues(false) , mIsRecordingActionsWithoutLock(false) @@ -1288,9 +1289,10 @@ TSFTextStore::Destroy() { MOZ_LOG(sTextStoreLog, LogLevel::Info, ("TSF: 0x%p TSFTextStore::Destroy(), mLock=%s, " - "mComposition.IsComposing()=%s", + "mComposition.IsComposing()=%s, mHandlingKeyMessage=%u", this, GetLockFlagNameStr(mLock).get(), - GetBoolName(mComposition.IsComposing()))); + GetBoolName(mComposition.IsComposing()), + mHandlingKeyMessage)); mDestroyed = true; @@ -1319,6 +1321,27 @@ TSFTextStore::Destroy() mLockedContent.Clear(); mSelection.MarkDirty(); + // If this is called during handling a keydown or keyup message, we should + // put off to release TSF objects until it completely finishes since + // MS-IME for Japanese refers some objects without grabbing them. + if (!mHandlingKeyMessage) { + ReleaseTSFObjects(); + } + + MOZ_LOG(sTextStoreLog, LogLevel::Info, + ("TSF: 0x%p TSFTextStore::Destroy() succeeded", this)); + + return true; +} + +void +TSFTextStore::ReleaseTSFObjects() +{ + MOZ_ASSERT(!mHandlingKeyMessage); + + MOZ_LOG(sTextStoreLog, LogLevel::Info, + ("TSF: 0x%p TSFTextStore::ReleaseTSFObjects()", this)); + mContext = nullptr; if (mDocumentMgr) { mDocumentMgr->Pop(TF_POPF_ALL); @@ -1330,14 +1353,14 @@ TSFTextStore::Destroy() if (!mMouseTrackers.IsEmpty()) { MOZ_LOG(sTextStoreLog, LogLevel::Debug, - ("TSF: 0x%p TSFTextStore::Destroy(), removing a mouse tracker...", + ("TSF: 0x%p TSFTextStore::ReleaseTSFObjects(), " + "removing a mouse tracker...", this)); mMouseTrackers.Clear(); } - MOZ_LOG(sTextStoreLog, LogLevel::Info, - ("TSF: 0x%p TSFTextStore::Destroy() succeeded", this)); - return true; + MOZ_LOG(sTextStoreLog, LogLevel::Debug, + ("TSF: 0x%p TSFTextStore::ReleaseTSFObjects() completed", this)); } STDMETHODIMP @@ -5470,7 +5493,14 @@ TSFTextStore::ProcessRawKeyMessage(const MSG& aMsg) if (FAILED(hr) || !eaten) { return false; } + RefPtr textStore(sEnabledTextStore); + if (textStore) { + textStore->OnStartToHandleKeyMessage(); + } hr = sKeystrokeMgr->KeyDown(aMsg.wParam, aMsg.lParam, &eaten); + if (textStore) { + textStore->OnEndHandlingKeyMessage(); + } return SUCCEEDED(hr) && eaten; } if (aMsg.message == WM_KEYUP) { @@ -5479,7 +5509,14 @@ TSFTextStore::ProcessRawKeyMessage(const MSG& aMsg) if (FAILED(hr) || !eaten) { return false; } + RefPtr textStore(sEnabledTextStore); + if (textStore) { + textStore->OnStartToHandleKeyMessage(); + } hr = sKeystrokeMgr->KeyUp(aMsg.wParam, aMsg.lParam, &eaten); + if (textStore) { + textStore->OnEndHandlingKeyMessage(); + } return SUCCEEDED(hr) && eaten; } return false; diff --git a/widget/windows/TSFTextStore.h b/widget/windows/TSFTextStore.h index b4d7f8545c30..f3ed35556003 100644 --- a/widget/windows/TSFTextStore.h +++ b/widget/windows/TSFTextStore.h @@ -248,6 +248,7 @@ protected: bool Init(nsWindowBase* aWidget); bool Destroy(); + void ReleaseTSFObjects(); bool IsReadLock(DWORD aLock) const { @@ -348,6 +349,21 @@ protected: // 0 if no lock is queued, otherwise TS_LF_* indicating the queue lock DWORD mLockQueued; + uint32_t mHandlingKeyMessage; + void OnStartToHandleKeyMessage() { ++mHandlingKeyMessage; } + void OnEndHandlingKeyMessage() + { + MOZ_ASSERT(mHandlingKeyMessage); + if (--mHandlingKeyMessage) { + return; + } + // If TSFTextStore instance is destroyed during handling key message(s), + // release all TSF objects when all nested key messages have been handled. + if (mDestroyed) { + ReleaseTSFObjects(); + } + } + class Composition final { public: From c3611a1825e63ab8f0e1afb164ea2e1250378681 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Wed, 8 Jun 2016 19:12:07 +0900 Subject: [PATCH 54/76] Bug 1278084 part.2 TSFTextStore should allow TSF to lock the document even during destroying r=m_kato While a TSFTextStore instance is being destroyed, TSFTextStore::Destroy() tries to commit remaining composition and notify TSF of destroying the view. At this moment, TSF/TIP may try to commit the composition or retrieve the contents with calling ITextStoreACP::RequestLock() but currently TSFTextStore disallows the requests to lock of them. This means that TSFTextStore never sends composition commit events asynchronously. Therefore, TextComposition may keep waiting remaining composition events but this causes odd behavior because they won't be fired. For avoiding this issue, TSFTextStore should behave as normal even while it's being destroyed. Fortunately, if there is a composition, it always has mLockedContent and mSelection. So, it can compute expected results of TSF/TIP with them. MozReview-Commit-ID: 2DSCGXXkLx1 --HG-- extra : rebase_source : 1dc5d08186bc50e7c3f1d9c5fe885ed855db8319 --- widget/windows/TSFTextStore.cpp | 158 +++++++++++++++++++++++++++----- widget/windows/TSFTextStore.h | 5 +- 2 files changed, 137 insertions(+), 26 deletions(-) diff --git a/widget/windows/TSFTextStore.cpp b/widget/windows/TSFTextStore.cpp index 66ade4e57057..faeb9c0158ca 100644 --- a/widget/windows/TSFTextStore.cpp +++ b/widget/windows/TSFTextStore.cpp @@ -12,6 +12,7 @@ #include "nsWindow.h" #include "nsPrintfCString.h" #include "WinUtils.h" +#include "mozilla/AutoRestore.h" #include "mozilla/Preferences.h" #include "mozilla/TextEventDispatcher.h" #include "mozilla/TextEvents.h" @@ -1196,6 +1197,7 @@ TSFTextStore::TSFTextStore() , mDeferCommittingComposition(false) , mDeferCancellingComposition(false) , mDestroyed(false) + , mBeingDestroyed(false) { for (int32_t i = 0; i < NUM_OF_SUPPORTED_ATTRS; i++) { mRequestedAttrs[i] = false; @@ -1284,9 +1286,13 @@ TSFTextStore::Init(nsWindowBase* aWidget) return true; } -bool +void TSFTextStore::Destroy() { + if (mBeingDestroyed) { + return; + } + MOZ_LOG(sTextStoreLog, LogLevel::Info, ("TSF: 0x%p TSFTextStore::Destroy(), mLock=%s, " "mComposition.IsComposing()=%s, mHandlingKeyMessage=%u", @@ -1296,20 +1302,25 @@ TSFTextStore::Destroy() mDestroyed = true; + // Destroy native caret first because it's not directly related to TSF and + // there may be another textstore which gets focus. So, we should avoid + // to destroy caret after the new one recreates caret. + MaybeDestroyNativeCaret(); + if (mLock) { mPendingDestroy = true; - return true; + return; } + AutoRestore savedBeingDestroyed(mBeingDestroyed); + mBeingDestroyed = true; + // If there is composition, TSF keeps the composition even after the text // store destroyed. So, we should clear the composition here. if (mComposition.IsComposing()) { - NS_WARNING("Composition is still alive at destroying the text store"); CommitCompositionInternal(false); } - MaybeDestroyNativeCaret(); - if (mSink) { MOZ_LOG(sTextStoreLog, LogLevel::Debug, ("TSF: 0x%p TSFTextStore::Destroy(), calling " @@ -1318,9 +1329,6 @@ TSFTextStore::Destroy() mSink->OnLayoutChange(TS_LC_DESTROY, TEXTSTORE_DEFAULT_VIEW); } - mLockedContent.Clear(); - mSelection.MarkDirty(); - // If this is called during handling a keydown or keyup message, we should // put off to release TSF objects until it completely finishes since // MS-IME for Japanese refers some objects without grabbing them. @@ -1330,8 +1338,6 @@ TSFTextStore::Destroy() MOZ_LOG(sTextStoreLog, LogLevel::Info, ("TSF: 0x%p TSFTextStore::Destroy() succeeded", this)); - - return true; } void @@ -1488,10 +1494,11 @@ TSFTextStore::RequestLock(DWORD dwLockFlags, "any sink not stored", this)); return E_FAIL; } - if (mDestroyed) { + if (mDestroyed && + (!mLockedContent.IsInitialized() || mSelection.IsDirty())) { MOZ_LOG(sTextStoreLog, LogLevel::Error, ("TSF: 0x%p TSFTextStore::RequestLock() FAILED due to " - "being destroyed", this)); + "being destroyed and no information of the contents", this)); return E_FAIL; } if (!phrSession) { @@ -1579,7 +1586,7 @@ TSFTextStore::DidLockGranted() } // If the widget has gone, we don't need to notify anything. - if (!mWidget || mWidget->Destroyed()) { + if (mDestroyed || !mWidget || mWidget->Destroyed()) { mPendingOnSelectionChange = false; mHasReturnedNoLayoutError = false; } @@ -1603,8 +1610,10 @@ void TSFTextStore::FlushPendingActions() { if (!mWidget || mWidget->Destroyed()) { + // Note that don't clear the locked contents because TIP may try to commit + // composition with a document lock. In such case, TSFTextStore needs to + // behave as expected by TIP. mPendingActions.Clear(); - mLockedContent.Clear(); mPendingOnSelectionChange = false; mHasReturnedNoLayoutError = false; return; @@ -1625,8 +1634,17 @@ TSFTextStore::FlushPendingActions() MOZ_LOG(sTextStoreLog, LogLevel::Debug, ("TSF: 0x%p TSFTextStore::FlushPendingActions() " "flushing COMPOSITION_START={ mSelectionStart=%d, " - "mSelectionLength=%d }", - this, action.mSelectionStart, action.mSelectionLength)); + "mSelectionLength=%d }, mDestroyed=%s", + this, action.mSelectionStart, action.mSelectionLength, + GetBoolName(mDestroyed))); + + if (mDestroyed) { + MOZ_LOG(sTextStoreLog, LogLevel::Warning, + ("TSF: 0x%p TSFTextStore::FlushPendingActions() " + "IGNORED pending compositionstart due to already destroyed", + this)); + break; + } if (action.mAdjustSelection) { // Select composition range so the new composition replaces the range @@ -1734,9 +1752,19 @@ TSFTextStore::FlushPendingActions() MOZ_LOG(sTextStoreLog, LogLevel::Debug, ("TSF: 0x%p TSFTextStore::FlushPendingActions() " "flushing SET_SELECTION={ mSelectionStart=%d, " - "mSelectionLength=%d, mSelectionReversed=%s }", + "mSelectionLength=%d, mSelectionReversed=%s }, " + "mDestroyed=%s", this, action.mSelectionStart, action.mSelectionLength, - GetBoolName(action.mSelectionReversed))); + GetBoolName(action.mSelectionReversed), + GetBoolName(mDestroyed))); + + if (mDestroyed) { + MOZ_LOG(sTextStoreLog, LogLevel::Warning, + ("TSF: 0x%p TSFTextStore::FlushPendingActions() " + "IGNORED pending selectionset due to already destroyed", + this)); + break; + } WidgetSelectionEvent selectionSet(true, eSetSelection, mWidget); selectionSet.mOffset = @@ -1800,6 +1828,15 @@ TSFTextStore::MaybeFlushPendingNotifications() return; } + if (mDestroyed) { + // If it's already been destroyed completely, this shouldn't notify TSF of + // anything anymore. + MOZ_LOG(sTextStoreLog, LogLevel::Debug, + ("TSF: 0x%p TSFTextStore::MaybeFlushPendingNotifications(), " + "does nothing because this has already destroyed completely...", this)); + return; + } + if (!mDeferClearingLockedContent && mLockedContent.IsInitialized()) { mLockedContent.Clear(); MOZ_LOG(sTextStoreLog, LogLevel::Debug, @@ -2006,6 +2043,7 @@ TSFTextStore::GetCurrentText(nsAString& aTextContent) return true; } + MOZ_ASSERT(!mDestroyed); MOZ_ASSERT(mWidget && !mWidget->Destroyed()); MOZ_LOG(sTextStoreLog, LogLevel::Debug, @@ -2032,6 +2070,7 @@ TSFTextStore::Selection& TSFTextStore::CurrentSelection() { if (mSelection.IsDirty()) { + MOZ_ASSERT(!mDestroyed); // If the window has never been available, we should crash since working // with broken values may make TIP confused. if (!mWidget || mWidget->Destroyed()) { @@ -3286,7 +3325,7 @@ TSFTextStore::GetACPFromPoint(TsViewCookie vcView, mWaitingQueryLayout = false; - if (mLockedContent.IsLayoutChanged()) { + if (mDestroyed || mLockedContent.IsLayoutChanged()) { MOZ_LOG(sTextStoreLog, LogLevel::Error, ("TSF: 0x%p TSFTextStore::GetACPFromPoint() returned " "TS_E_NOLAYOUT", this)); @@ -3533,6 +3572,15 @@ TSFTextStore::GetTextExt(TsViewCookie vcView, return TS_E_NOLAYOUT; } + if (mDestroyed) { + MOZ_LOG(sTextStoreLog, LogLevel::Error, + ("TSF: 0x%p TSFTextStore::GetTextExt() returned TS_E_NOLAYOUT " + "(acpEnd=%d) because this has already been destroyed", + this, acpEnd)); + mHasReturnedNoLayoutError = true; + return TS_E_NOLAYOUT; + } + // use eQueryTextRect to get rect in system, screen coordinates WidgetQueryContentEvent event(true, eQueryTextRect, mWidget); mWidget->InitEvent(event); @@ -3624,6 +3672,14 @@ TSFTextStore::GetScreenExt(TsViewCookie vcView, return E_INVALIDARG; } + if (mDestroyed) { + MOZ_LOG(sTextStoreLog, LogLevel::Error, + ("TSF: 0x%p TSFTextStore::GetScreenExt() returns empty rect " + "due to already destroyed", this)); + prc->left = prc->top = prc->right = prc->left = 0; + return S_OK; + } + if (!GetScreenExtInternal(*prc)) { MOZ_LOG(sTextStoreLog, LogLevel::Error, ("TSF: 0x%p TSFTextStore::GetScreenExt() FAILED due to " @@ -3644,6 +3700,8 @@ TSFTextStore::GetScreenExtInternal(RECT& aScreenExt) MOZ_LOG(sTextStoreLog, LogLevel::Debug, ("TSF: 0x%p TSFTextStore::GetScreenExtInternal()", this)); + MOZ_ASSERT(!mDestroyed); + // use NS_QUERY_EDITOR_RECT to get rect in system, screen coordinates WidgetQueryContentEvent event(true, eQueryEditorRect, mWidget); mWidget->InitEvent(event); @@ -3718,7 +3776,7 @@ TSFTextStore::GetWnd(TsViewCookie vcView, return E_INVALIDARG; } - *phwnd = mWidget->GetWindowHandle(); + *phwnd = mWidget ? mWidget->GetWindowHandle() : nullptr; MOZ_LOG(sTextStoreLog, LogLevel::Info, ("TSF: 0x%p TSFTextStore::GetWnd() succeeded: *phwnd=0x%p", @@ -4503,7 +4561,8 @@ TSFTextStore::OnTextChangeInternal(const IMENotification& aIMENotification) "mCausedOnlyByComposition=%s, " "mIncludingChangesDuringComposition=%s, " "mIncludingChangesWithoutComposition=%s }), " - "mSink=0x%p, mSinkMask=%s, mComposition.IsComposing()=%s", + "mDestroyed=%s, mSink=0x%p, mSinkMask=%s, " + "mComposition.IsComposing()=%s", this, aIMENotification.mMessage, textChangeData.mStartOffset, textChangeData.mRemovedEndOffset, @@ -4511,10 +4570,17 @@ TSFTextStore::OnTextChangeInternal(const IMENotification& aIMENotification) GetBoolName(textChangeData.mCausedOnlyByComposition), GetBoolName(textChangeData.mIncludingChangesDuringComposition), GetBoolName(textChangeData.mIncludingChangesWithoutComposition), + GetBoolName(mDestroyed), mSink.get(), GetSinkMaskNameStr(mSinkMask).get(), GetBoolName(mComposition.IsComposing()))); + if (mDestroyed) { + // If this instance is already destroyed, we shouldn't notify TSF of any + // changes. + return NS_OK; + } + if (textChangeData.mCausedOnlyByComposition) { // Ignore text change notifications caused only by composition since it's // already been handled internally. @@ -4569,6 +4635,8 @@ TSFTextStore::OnTextChangeInternal(const IMENotification& aIMENotification) void TSFTextStore::NotifyTSFOfTextChange(const TS_TEXTCHANGE& aTextChange) { + MOZ_ASSERT(!mDestroyed); + // XXX We need to cache the text change ranges and notify TSF of that // the document is unlocked. if (NS_WARN_IF(IsReadLocked())) { @@ -4605,7 +4673,7 @@ TSFTextStore::OnSelectionChangeInternal(const IMENotification& aIMENotification) "aIMENotification={ mSelectionChangeData={ mOffset=%lu, " "Length()=%lu, mReversed=%s, mWritingMode=%s, " "mCausedByComposition=%s, mCausedBySelectionEvent=%s, " - "mOccurredDuringComposition=%s } }), " + "mOccurredDuringComposition=%s } }), mDestroyed=%s, " "mSink=0x%p, mSinkMask=%s, mIsRecordingActionsWithoutLock=%s, " "mComposition.IsComposing()=%s", this, selectionChangeData.mOffset, selectionChangeData.Length(), @@ -4614,10 +4682,17 @@ TSFTextStore::OnSelectionChangeInternal(const IMENotification& aIMENotification) GetBoolName(selectionChangeData.mCausedByComposition), GetBoolName(selectionChangeData.mCausedBySelectionEvent), GetBoolName(selectionChangeData.mOccurredDuringComposition), + GetBoolName(mDestroyed), mSink.get(), GetSinkMaskNameStr(mSinkMask).get(), GetBoolName(mIsRecordingActionsWithoutLock), GetBoolName(mComposition.IsComposing()))); + if (mDestroyed) { + // If this instance is already destroyed, we shouldn't notify TSF of any + // changes. + return NS_OK; + } + if (selectionChangeData.mCausedByComposition) { // Ignore selection change notifications caused by composition since it's // already been handled internally. @@ -4684,6 +4759,8 @@ TSFTextStore::OnSelectionChangeInternal(const IMENotification& aIMENotification) void TSFTextStore::NotifyTSFOfSelectionChange() { + MOZ_ASSERT(!mDestroyed); + if (NS_WARN_IF(IsReadLocked())) { return; } @@ -4715,6 +4792,12 @@ TSFTextStore::NotifyTSFOfSelectionChange() nsresult TSFTextStore::OnLayoutChangeInternal() { + if (mDestroyed) { + // If this instance is already destroyed, we shouldn't notify TSF of any + // changes. + return NS_OK; + } + NS_ENSURE_TRUE(mContext, NS_ERROR_FAILURE); NS_ENSURE_TRUE(mSink, NS_ERROR_FAILURE); @@ -4743,6 +4826,8 @@ TSFTextStore::OnLayoutChangeInternal() bool TSFTextStore::NotifyTSFOfLayoutChange() { + MOZ_ASSERT(!mDestroyed); + // If we're waiting a query of layout information from TIP, it means that // we've returned TS_E_NOLAYOUT error. bool returnedNoLayoutError = @@ -4848,6 +4933,12 @@ TSFTextStore::NotifyTSFOfLayoutChange() void TSFTextStore::NotifyTSFOfLayoutChangeAgain() { + // Don't notify TSF of layout change after destroyed. + if (mDestroyed) { + mWaitingQueryLayout = false; + return; + } + // Before preforming this method, TIP has accessed our layout information by // itself. In such case, we don't need to call OnLayoutChange() anymore. if (!mWaitingQueryLayout) { @@ -4882,8 +4973,13 @@ TSFTextStore::OnUpdateCompositionInternal() { MOZ_LOG(sTextStoreLog, LogLevel::Debug, ("TSF: 0x%p TSFTextStore::OnUpdateCompositionInternal(), " - "mDeferNotifyingTSF=%s", - this, GetBoolName(mDeferNotifyingTSF))); + "mDestroyed=%s, mDeferNotifyingTSF=%s", + this, GetBoolName(mDestroyed), GetBoolName(mDeferNotifyingTSF))); + + // There are nothing to do after destroyed. + if (mDestroyed) { + return NS_OK; + } // Now, all sent composition events are handled by the content even in // e10s mode. @@ -4897,6 +4993,12 @@ nsresult TSFTextStore::OnMouseButtonEventInternal( const IMENotification& aIMENotification) { + if (mDestroyed) { + // If this instance is already destroyed, we shouldn't notify TSF of any + // events. + return NS_OK; + } + if (mMouseTrackers.IsEmpty()) { return NS_OK; } @@ -4972,6 +5074,11 @@ TSFTextStore::CreateNativeCaret() { MaybeDestroyNativeCaret(); + // Don't create native caret after destroyed. + if (mDestroyed) { + return; + } + MOZ_LOG(sTextStoreLog, LogLevel::Debug, ("TSF: 0x%p TSFTextStore::CreateNativeCaret(), " "mComposition.IsComposing()=%s", @@ -5081,7 +5188,8 @@ TSFTextStore::CommitCompositionInternal(bool aDiscard) if (mComposition.IsComposing() && aDiscard) { LONG endOffset = mComposition.EndOffset(); mComposition.mString.Truncate(0); - if (mSink) { + // Note that don't notify TSF of text change after this is destroyed. + if (mSink && !mDestroyed) { TS_TEXTCHANGE textChange; textChange.acpStart = mComposition.mStart; textChange.acpOldEnd = endOffset; diff --git a/widget/windows/TSFTextStore.h b/widget/windows/TSFTextStore.h index f3ed35556003..6ec61102f70f 100644 --- a/widget/windows/TSFTextStore.h +++ b/widget/windows/TSFTextStore.h @@ -247,7 +247,7 @@ protected: static void MarkContextAsEmpty(ITfContext* aContext); bool Init(nsWindowBase* aWidget); - bool Destroy(); + void Destroy(); void ReleaseTSFObjects(); bool IsReadLock(DWORD aLock) const @@ -904,6 +904,9 @@ protected: // Immediately after a call of Destroy(), mDestroyed becomes true. If this // is true, the instance shouldn't grant any requests from the TIP anymore. bool mDestroyed; + // While the instance is being destroyed, this is set to true for avoiding + // recursive Destroy() calls. + bool mBeingDestroyed; // TSF thread manager object for the current application From 77f6ee4369bdc8c0a7c4162a012e7e02f2d36896 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 7 Jun 2016 21:25:24 +0900 Subject: [PATCH 55/76] Bug 1278084 part.3 TextComposition shouldn't decide composition string which is only an ideographic space as a placeholder r=m_kato Currently, when TextComposition tries to forcibly commit composition synchronously, it cancels the composition if there is only an ideographic space since legacy Chinese IMEs for Windows were used an ideographic space as a placeholder and shows actual composition string in its owning window (called reading window). However, Japanese TIPs basically use composition to input an ideographic space. Unfortunately, this intentional input of an ideographic space is always canceled if an editor commits to composition at every input event in TSF mode because TSF cannot commit during a call of ITextStore::RequestLock(). Additionally, we will enable e10s mode, then, on all platforms, requesting commit composition is handled asynchronously. Therefore, we should make the hack disabled in default settings now. If we'll find a way to distinguish if an ideographic space is a placeholder, we should recover this hack. Note that such input fields cannot handle such legacy IMEs, so, disabling the hack in default settings must be fine. MozReview-Commit-ID: IdBcfBxeJum --HG-- extra : rebase_source : 18ca5cd1083ade8813703cec05c020dc03f09f63 --- dom/events/TextComposition.cpp | 9 ++++++--- modules/libpref/init/all.js | 6 ++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/dom/events/TextComposition.cpp b/dom/events/TextComposition.cpp index 796376429713..35cc68fd9948 100644 --- a/dom/events/TextComposition.cpp +++ b/dom/events/TextComposition.cpp @@ -267,10 +267,13 @@ TextComposition::DispatchCompositionEvent( aCompositionEvent->mRanges = nullptr; NS_ASSERTION(aCompositionEvent->mData.IsEmpty(), "mData of eCompositionCommitAsIs should be empty string"); - if (mLastData == IDEOGRAPHIC_SPACE) { - // If the last data is an ideographic space (FullWidth space), it must be + bool removePlaceholderCharacter = + Preferences::GetBool("intl.ime.remove_placeholder_character_at_commit", + false); + if (removePlaceholderCharacter && mLastData == IDEOGRAPHIC_SPACE) { + // If the last data is an ideographic space (FullWidth space), it might be // a placeholder character of some Chinese IME. So, committing with - // this data must not be expected by users. Let's use empty string. + // this data might not be expected by users. Let's use empty string. aCompositionEvent->mData.Truncate(); } else { aCompositionEvent->mData = mLastData; diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index d61c626719bb..8b3d510b8de8 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1980,6 +1980,12 @@ pref("intl.ime.hack.on_ime_unaware_apps.fire_key_events_for_composition", true); pref("intl.ime.hack.on_ime_unaware_apps.fire_key_events_for_composition", false); #endif +// If you use legacy Chinese IME which puts an ideographic space to composition +// string as placeholder, this pref might be useful. If this is true and when +// web contents forcibly commits composition (e.g., moving focus), the +// ideographic space will be ignored (i.e., commits with empty string). +pref("intl.ime.remove_placeholder_character_at_commit", false); + // these locales have right-to-left UI pref("intl.uidirection.ar", "rtl"); pref("intl.uidirection.he", "rtl"); From 62b8fa4250bbf19f1be653705bc60c2f0db05b7e Mon Sep 17 00:00:00 2001 From: Makoto Kato Date: Wed, 11 May 2016 20:05:25 +0900 Subject: [PATCH 56/76] Bug 1271886 - Move netapi32 to delay load DLLs. r=ted netapi32's API isn't used at startup and browsing page. So netapi32 should move to delay load DLLs. MozReview-Commit-ID: 1g25lnuwbfY --HG-- extra : rebase_source : 7893ff80d10d3f0fd25aabe5c5fbaebe167e89fe --- browser/components/build/moz.build | 2 ++ old-configure.in | 4 ++-- toolkit/library/moz.build | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/browser/components/build/moz.build b/browser/components/build/moz.build index b8eda2d4fc0b..5bc4858d7ea0 100644 --- a/browser/components/build/moz.build +++ b/browser/components/build/moz.build @@ -25,6 +25,7 @@ LOCAL_INCLUDES += [ if CONFIG['OS_ARCH'] == 'WINNT': OS_LIBS += [ 'esent', + 'netapi32', 'ole32', 'shell32', 'shlwapi', @@ -32,6 +33,7 @@ if CONFIG['OS_ARCH'] == 'WINNT': ] DELAYLOAD_DLLS += [ 'esent.dll', + 'netapi32.dll', ] # Mac: Need to link with CoreFoundation for Mac Migrators (PList reading code) diff --git a/old-configure.in b/old-configure.in index 92a6b665f5be..d12ca2ef9713 100644 --- a/old-configure.in +++ b/old-configure.in @@ -1328,7 +1328,7 @@ case "$target" in # Use temp file for windres (bug 213281) RCFLAGS='-O coff --use-temp-file' # mingw doesn't require kernel32, user32, and advapi32 explicitly - LIBS="$LIBS -luuid -lgdi32 -lwinmm -lwsock32 -luserenv -lsecur32 -lnetapi32" + LIBS="$LIBS -luuid -lgdi32 -lwinmm -lwsock32 -luserenv -lsecur32" MOZ_FIX_LINK_PATHS= DLL_PREFIX= IMPORT_LIB_SUFFIX=a @@ -1484,7 +1484,7 @@ case "$target" in # make 'foo == bar;' error out CFLAGS="$CFLAGS -we4553" CXXFLAGS="$CXXFLAGS -we4553" - LIBS="$LIBS kernel32.lib user32.lib gdi32.lib winmm.lib wsock32.lib advapi32.lib secur32.lib netapi32.lib" + LIBS="$LIBS kernel32.lib user32.lib gdi32.lib winmm.lib wsock32.lib advapi32.lib secur32.lib" MOZ_DEBUG_LDFLAGS='-DEBUG -DEBUGTYPE:CV' WARNINGS_AS_ERRORS='-WX' MOZ_OPTIMIZE_FLAGS='-O1 -Oi' diff --git a/toolkit/library/moz.build b/toolkit/library/moz.build index 15967d4ac07d..15b7607185d2 100644 --- a/toolkit/library/moz.build +++ b/toolkit/library/moz.build @@ -18,6 +18,7 @@ def Libxul(name): DELAYLOAD_DLLS += [ 'comdlg32.dll', 'dbghelp.dll', + 'netapi32.dll', 'PowrProf.dll', 'psapi.dll', 'rasapi32.dll', @@ -337,6 +338,7 @@ if CONFIG['OS_ARCH'] == 'WINNT': 'comdlg32', 'imm32', 'msimg32', + 'netapi32', 'shlwapi', 'psapi', 'ws2_32', From 26ebe8e651305da70ee45522ab101be87493ef47 Mon Sep 17 00:00:00 2001 From: Justin D'Arcangelo Date: Wed, 8 Jun 2016 21:37:06 -0400 Subject: [PATCH 57/76] Bug 1272102 - FlyWeb Android UI. r=sebastian --HG-- extra : amend_source : b1bac8800988d31790a64a293403336375e5effd --- .../java/org/mozilla/gecko/BrowserApp.java | 2 + .../gecko/preferences/GeckoPreferences.java | 1 + .../gecko/updater/PostUpdateHandler.java | 154 ++++++++++++++++++ mobile/android/base/moz.build | 1 + mobile/android/chrome/content/aboutAddons.js | 4 + mobile/android/extensions/flyweb/bootstrap.js | 151 +++++++++++++++++ .../extensions/flyweb/content/aboutFlyWeb.css | 29 ++++ .../extensions/flyweb/content/aboutFlyWeb.js | 73 +++++++++ .../flyweb/content/aboutFlyWeb.xhtml | 47 ++++++ .../extensions/flyweb/content/icon-64.png | Bin 0 -> 1311 bytes .../android/extensions/flyweb/install.rdf.in | 31 ++++ mobile/android/extensions/flyweb/jar.mn | 10 ++ .../flyweb/locale/en-US/aboutFlyWeb.dtd | 7 + .../flyweb/locale/en-US/flyweb.properties | 5 + mobile/android/extensions/flyweb/moz.build | 17 ++ mobile/android/extensions/moz.build | 11 ++ mobile/android/installer/package-manifest.in | 3 + mobile/android/moz.build | 1 + .../mozbuild/action/package_fennec_apk.py | 9 + toolkit/mozapps/installer/upload-files-APK.mk | 1 + 20 files changed, 557 insertions(+) create mode 100644 mobile/android/base/java/org/mozilla/gecko/updater/PostUpdateHandler.java create mode 100644 mobile/android/extensions/flyweb/bootstrap.js create mode 100644 mobile/android/extensions/flyweb/content/aboutFlyWeb.css create mode 100644 mobile/android/extensions/flyweb/content/aboutFlyWeb.js create mode 100644 mobile/android/extensions/flyweb/content/aboutFlyWeb.xhtml create mode 100644 mobile/android/extensions/flyweb/content/icon-64.png create mode 100644 mobile/android/extensions/flyweb/install.rdf.in create mode 100644 mobile/android/extensions/flyweb/jar.mn create mode 100644 mobile/android/extensions/flyweb/locale/en-US/aboutFlyWeb.dtd create mode 100644 mobile/android/extensions/flyweb/locale/en-US/flyweb.properties create mode 100644 mobile/android/extensions/flyweb/moz.build create mode 100644 mobile/android/extensions/moz.build diff --git a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java index 0e260304fd61..ce03e294fc40 100644 --- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java +++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java @@ -85,6 +85,7 @@ import org.mozilla.gecko.toolbar.BrowserToolbar; import org.mozilla.gecko.toolbar.BrowserToolbar.TabEditingState; import org.mozilla.gecko.toolbar.ToolbarProgressView; import org.mozilla.gecko.trackingprotection.TrackingProtectionPrompt; +import org.mozilla.gecko.updater.PostUpdateHandler; import org.mozilla.gecko.updater.UpdateServiceHelper; import org.mozilla.gecko.util.ActivityUtils; import org.mozilla.gecko.util.Clipboard; @@ -310,6 +311,7 @@ public class BrowserApp extends GeckoApp (BrowserAppDelegate) new BookmarkStateChangeDelegate(), (BrowserAppDelegate) new ReaderViewBookmarkPromotion(), (BrowserAppDelegate) new ContentNotificationsDelegate(), + (BrowserAppDelegate) new PostUpdateHandler(), new TelemetryCorePingDelegate() )); diff --git a/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java b/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java index 443acc9bf2ff..172abeb80f0a 100644 --- a/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java +++ b/mobile/android/base/java/org/mozilla/gecko/preferences/GeckoPreferences.java @@ -159,6 +159,7 @@ OnSharedPreferenceChangeListener public static final String PREFS_NOTIFICATIONS_CONTENT = NON_PREF_PREFIX + "notifications.content"; public static final String PREFS_NOTIFICATIONS_CONTENT_LEARN_MORE = NON_PREF_PREFIX + "notifications.content.learn_more"; public static final String PREFS_NOTIFICATIONS_WHATS_NEW = NON_PREF_PREFIX + "notifications.whats_new"; + public static final String PREFS_APP_UPDATE_LAST_BUILD_ID = "app.update.last_build_id"; private static final String ACTION_STUMBLER_UPLOAD_PREF = AppConstants.ANDROID_PACKAGE_NAME + ".STUMBLER_PREF"; diff --git a/mobile/android/base/java/org/mozilla/gecko/updater/PostUpdateHandler.java b/mobile/android/base/java/org/mozilla/gecko/updater/PostUpdateHandler.java new file mode 100644 index 000000000000..2601acb0376c --- /dev/null +++ b/mobile/android/base/java/org/mozilla/gecko/updater/PostUpdateHandler.java @@ -0,0 +1,154 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- + * 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/. */ + +package org.mozilla.gecko.updater; + +import android.content.Context; +import android.content.SharedPreferences; +import android.util.Log; + +import com.keepsafe.switchboard.SwitchBoard; + +import org.mozilla.gecko.AppConstants; +import org.mozilla.gecko.BrowserApp; +import org.mozilla.gecko.delegates.BrowserAppDelegateWithReference; +import org.mozilla.gecko.GeckoSharedPrefs; +import org.mozilla.gecko.preferences.GeckoPreferences; +import org.mozilla.gecko.util.ThreadUtils; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Enumeration; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +/** + * Perform tasks in the background after the app has been installed/updated. + */ +public class PostUpdateHandler extends BrowserAppDelegateWithReference { + private static final String LOGTAG = "PostUpdateHandler"; + + @Override + public void onStart(BrowserApp browserApp) { + final SharedPreferences prefs = GeckoSharedPrefs.forApp(browserApp); + + // Check if this is a new installation or if the app has been updated since the last start. + if (!AppConstants.MOZ_APP_BUILDID.equals(prefs.getString(GeckoPreferences.PREFS_APP_UPDATE_LAST_BUILD_ID, null))) { + Log.d(LOGTAG, "Build ID changed since last start: '" + AppConstants.MOZ_APP_BUILDID + "', '" + prefs.getString(GeckoPreferences.PREFS_APP_UPDATE_LAST_BUILD_ID, null) + "'"); + + // Copy the bundled system add-ons from the APK to the data directory. + copyFeaturesFromAPK(); + } + } + + /** + * Copies the /assets/features folder out of the APK and into the app's data directory. + */ + private void copyFeaturesFromAPK() { + final BrowserApp browserApp = getBrowserApp(); + if (browserApp == null) { + return; + } + + final String dataDir = browserApp.getApplicationInfo().dataDir; + final String sourceDir = browserApp.getApplicationInfo().sourceDir; + final File applicationPackage = new File(sourceDir); + + final String assetsPrefix = "assets/"; + final String fullPrefix = assetsPrefix + "features/"; + + final SharedPreferences prefs = GeckoSharedPrefs.forApp(browserApp); + + ThreadUtils.postToBackgroundThread(new Runnable() { + @Override + public void run() { + Log.d(LOGTAG, "Copying system add-ons from APK to dataDir"); + + try { + final ZipFile zip = new ZipFile(applicationPackage); + final Enumeration zipEntries = zip.entries(); + + final byte[] buffer = new byte[1024]; + + while (zipEntries.hasMoreElements()) { + final ZipEntry fileEntry = zipEntries.nextElement(); + final String name = fileEntry.getName(); + + if (fileEntry.isDirectory()) { + // We'll let getDataFile deal with creating the directory hierarchy. + continue; + } + + // Read from "assets/features/**". + if (!name.startsWith(fullPrefix)) { + continue; + } + + // Write to "features/**". + final String nameWithoutPrefix = name.substring(assetsPrefix.length()); + final File outFile = getDataFile(dataDir, nameWithoutPrefix); + if (outFile == null) { + continue; + } + + final InputStream fileStream = zip.getInputStream(fileEntry); + try { + writeStream(fileStream, outFile, fileEntry.getTime(), buffer); + } finally { + fileStream.close(); + } + } + + zip.close(); + } catch (IOException e) { + Log.e(LOGTAG, "Error copying system add-ons from APK.", e); + } + + // Save the Build ID so we don't perform post-update operations again until the app is updated. + prefs.edit().putString(GeckoPreferences.PREFS_APP_UPDATE_LAST_BUILD_ID, AppConstants.MOZ_APP_BUILDID).apply(); + } + }); + } + + /** + * Return a File instance in the data directory, ensuring + * that the parent exists. + * + * @return null if the parents could not be created. + */ + private File getDataFile(final String dataDir, final String name) { + File outFile = new File(dataDir, name); + File dir = outFile.getParentFile(); + + if (!dir.exists()) { + Log.d(LOGTAG, "Creating " + dir.getAbsolutePath()); + if (!dir.mkdirs()) { + Log.e(LOGTAG, "Unable to create directories: " + dir.getAbsolutePath()); + return null; + } + } + + return outFile; + } + + private void writeStream(InputStream fileStream, File outFile, final long modifiedTime, byte[] buffer) + throws FileNotFoundException, IOException { + final OutputStream outStream = new FileOutputStream(outFile); + try { + int count; + while ((count = fileStream.read(buffer)) > 0) { + outStream.write(buffer, 0, count); + } + + outFile.setLastModified(modifiedTime); + } finally { + outStream.close(); + } + } +} diff --git a/mobile/android/base/moz.build b/mobile/android/base/moz.build index 0a6c0d24a6c1..1634497a14a8 100644 --- a/mobile/android/base/moz.build +++ b/mobile/android/base/moz.build @@ -624,6 +624,7 @@ gbjar.sources += ['java/org/mozilla/gecko/' + x for x in [ 'toolbar/ToolbarProgressView.java', 'TouchEventInterceptor.java', 'trackingprotection/TrackingProtectionPrompt.java', + 'updater/PostUpdateHandler.java', 'updater/UpdateService.java', 'updater/UpdateServiceHelper.java', 'util/Experiments.java', diff --git a/mobile/android/chrome/content/aboutAddons.js b/mobile/android/chrome/content/aboutAddons.js index 2b837c533bc7..0c190d537dee 100644 --- a/mobile/android/chrome/content/aboutAddons.js +++ b/mobile/android/chrome/content/aboutAddons.js @@ -266,6 +266,10 @@ var Addons = { return a.name.localeCompare(b.name); }); for (let i=0; i a { + color: inherit; + text-decoration: none; +} + +.details { + -moz-margin-start: calc(var(--icon-size) + var(--icon-margin) * 2 - 1em); + padding: 1em; +} + +#flyweb-item-template { + display: none; +} + +#flyweb-list-empty { + display: none; +} + +#flyweb-list:empty + #flyweb-list-empty { + display: block; + text-align: center; + padding-top: 3.9em; +} diff --git a/mobile/android/extensions/flyweb/content/aboutFlyWeb.js b/mobile/android/extensions/flyweb/content/aboutFlyWeb.js new file mode 100644 index 000000000000..48b7ea4b7e6a --- /dev/null +++ b/mobile/android/extensions/flyweb/content/aboutFlyWeb.js @@ -0,0 +1,73 @@ +/* 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/. */ +"use strict"; + +const {classes: Cc, interfaces: Ci, utils: Cu} = Components; + +Cu.import("resource://gre/modules/Console.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm"); + +XPCOMUtils.defineLazyGetter(this, "gFlyWebBundle", function() { + return Services.strings.createBundle("chrome://flyweb/locale/flyweb.properties"); +}); + +let discoveryManager = new FlyWebDiscoveryManager(); + +let discoveryCallback = { + onDiscoveredServicesChanged(services) { + if (!this.id) { + return; + } + + let list = document.getElementById("flyweb-list"); + while (list.firstChild) { + list.firstChild.remove(); + } + + let template = document.getElementById("flyweb-item-template"); + + for (let service of services) { + let item = template.cloneNode(true); + item.removeAttribute("id"); + + item.setAttribute("data-service-id", service.serviceId); + item.querySelector(".title").setAttribute("value", service.displayName); + item.querySelector(".icon").src = "chrome://flyweb/content/icon-64.png"; + + list.appendChild(item); + } + }, + start() { + this.id = discoveryManager.startDiscovery(this); + }, + stop() { + discoveryManager.stopDiscovery(this.id); + this.id = undefined; + } +}; + +window.addEventListener("DOMContentLoaded", () => { + let list = document.getElementById("flyweb-list"); + list.addEventListener("click", (evt) => { + let serviceId = evt.target.closest("[data-service-id]").getAttribute("data-service-id"); + + discoveryManager.pairWithService(serviceId, { + pairingSucceeded(service) { + window.open(service.uiUrl, "FlyWebWindow_" + serviceId); + }, + + pairingFailed(error) { + console.error("FlyWeb failed to connect to service " + serviceId, error); + } + }); + }); + + discoveryCallback.start(); +}); + +window.addEventListener("unload", () => { + discoveryCallback.stop(); +}); diff --git a/mobile/android/extensions/flyweb/content/aboutFlyWeb.xhtml b/mobile/android/extensions/flyweb/content/aboutFlyWeb.xhtml new file mode 100644 index 000000000000..85e92ddf8fa1 --- /dev/null +++ b/mobile/android/extensions/flyweb/content/aboutFlyWeb.xhtml @@ -0,0 +1,47 @@ + + + +%brandDTD; + +%globalDTD; + +%flywebDTD; +]> + + + + + + &aboutFlyWeb.title; + + + + + + + + +
  • + +
    +
    + + +
    +
    +
  • + + +
    +
    &aboutFlyWeb.header;
    +
    +
      + &aboutFlyWeb.empty; + - - - - - - - - - - - - diff --git a/toolkit/components/extensions/test/xpcshell/test_native_messaging.js b/toolkit/components/extensions/test/xpcshell/test_native_messaging.js index bd73392815f7..ce620a28443d 100644 --- a/toolkit/components/extensions/test/xpcshell/test_native_messaging.js +++ b/toolkit/components/extensions/test/xpcshell/test_native_messaging.js @@ -1,14 +1,15 @@ "use strict"; -/* global OS, HostManifestManager, NativeApp */ -Cu.import("resource://gre/modules/AsyncShutdown.jsm"); -Cu.import("resource://gre/modules/FileUtils.jsm"); -Cu.import("resource://gre/modules/Schemas.jsm"); Cu.import("resource://gre/modules/Services.jsm"); -const {Subprocess, SubprocessImpl} = Cu.import("resource://gre/modules/Subprocess.jsm"); -Cu.import("resource://gre/modules/NativeMessaging.jsm"); +Cu.import("resource://gre/modules/FileUtils.jsm"); + +/* global OS */ Cu.import("resource://gre/modules/osfile.jsm"); +/* global HostManifestManager */ +Cu.import("resource://gre/modules/NativeMessaging.jsm"); + +Components.utils.import("resource://gre/modules/Schemas.jsm"); const BASE_SCHEMA = "chrome://extensions/content/schemas/manifest.json"; let dir = FileUtils.getDir("TmpD", ["NativeMessaging"]); @@ -47,24 +48,16 @@ function writeManifest(path, manifest) { return OS.File.writeAtomic(path, manifest); } -let PYTHON; add_task(function* setup() { yield Schemas.load(BASE_SCHEMA); - - PYTHON = yield Subprocess.pathSearch("python2.7"); - if (PYTHON == null) { - PYTHON = yield Subprocess.pathSearch("python"); - } - notEqual(PYTHON, null, "Found a suitable python interpreter"); }); // Test of HostManifestManager.lookupApplication() begin here... + let context = { url: null, logError() {}, preprocessors: {}, - callOnClose: () => {}, - forgetOnClose: () => {}, }; let templateManifest = { @@ -170,65 +163,3 @@ add_task(function* test_user_dir_precedence() { deepEqual(result.manifest, templateManifest, "lookupApplication returns user-specific manifest contents with user-specific and system-wide entries both exist"); }); -// Test shutdown handling in NativeApp -add_task(function* test_native_app_shutdown() { - const SCRIPT = String.raw`#!${PYTHON} -u -import signal -import struct -import sys - -signal.signal(signal.SIGTERM, signal.SIG_IGN) - -while True: - rawlen = sys.stdin.read(4) - if len(rawlen) == 0: - signal.pause() - msglen = struct.unpack('@I', rawlen)[0] - msg = sys.stdin.read(msglen) - - sys.stdout.write(struct.pack('@I', msglen)) - sys.stdout.write(msg) -`; - - let scriptPath = OS.Path.join(userDir.path, "wontdie.py"); - yield OS.File.writeAtomic(scriptPath, SCRIPT); - yield OS.File.setPermissions(scriptPath, {unixMode: 0o755}); - - const ID = "native@tests.mozilla.org"; - const MANIFEST = { - name: "wontdie", - description: "test async shutdown of native apps", - path: scriptPath, - type: "stdio", - allowed_extensions: [ID], - }; - yield writeManifest(OS.Path.join(userDir.path, "wontdie.json"), MANIFEST); - - let extension = {id: ID}; - let app = new NativeApp(extension, context, "wontdie"); - - // send a message and wait for the reply to make sure the app is running - let MSG = "test"; - let recvPromise = new Promise(resolve => { - let listener = (what, msg) => { - equal(msg, MSG, "Received test message"); - app.off("message", listener); - resolve(); - }; - app.on("message", listener); - }); - - app.send(MSG); - yield recvPromise; - - app._cleanup(); - - do_print("waiting for async shutdown"); - Services.prefs.setBoolPref("toolkit.asyncshutdown.testing", true); - AsyncShutdown.profileBeforeChange._trigger(); - Services.prefs.clearUserPref("toolkit.asyncshutdown.testing"); - - let procs = yield SubprocessImpl.Process.getWorker().call("getProcesses", []); - equal(procs.size, 0, "native process exited"); -}); - diff --git a/toolkit/modules/subprocess/subprocess_worker_common.js b/toolkit/modules/subprocess/subprocess_worker_common.js index 877ba834bf23..bda7c014d02c 100644 --- a/toolkit/modules/subprocess/subprocess_worker_common.js +++ b/toolkit/modules/subprocess/subprocess_worker_common.js @@ -149,10 +149,6 @@ let requests = { proc => [proc.id, proc.pid])); return {data}; }, - - waitForNoProcesses() { - return Promise.all(Array.from(io.processes.values(), proc => proc.exitPromise)); - }, }; onmessage = event => { From 7270ed519a7b87160f6977548bfd7eeed00d2f49 Mon Sep 17 00:00:00 2001 From: Phil Ringnalda Date: Wed, 8 Jun 2016 20:36:22 -0700 Subject: [PATCH 61/76] Back out 4 changesets (bug 1276132) for browser_gmpProvider.js failures CLOSED TREE Backed out changeset 511a2389ca48 (bug 1276132) Backed out changeset 91b3cdd0640a (bug 1276132) Backed out changeset 09b9972e36f9 (bug 1276132) Backed out changeset 69052d4e3dbb (bug 1276132) --- browser/app/profile/firefox.js | 10 --- browser/base/content/browser-media.js | 18 +---- dom/media/eme/MediaKeySystemAccess.cpp | 68 +++++++++---------- dom/media/eme/moz.build | 3 + dom/media/gmp/GMPChild.cpp | 16 ++++- dom/media/gmp/GMPParent.cpp | 8 +++ dom/media/gmp/GMPParent.h | 2 + dom/media/gmp/moz.build | 9 ++- .../widevine-adapter/WidevineDecryptor.cpp | 2 +- .../gmp/widevine-adapter/WidevineUtils.h | 2 +- toolkit/modules/GMPUtils.jsm | 30 ++------ .../test/browser/browser_gmpProvider.js | 8 +-- .../test/xpcshell/test_gmpProvider.js | 4 +- 13 files changed, 85 insertions(+), 95 deletions(-) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index ad272261cfe7..a375301328e6 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1285,21 +1285,11 @@ pref("media.gmp.decoder.h264", 2); // decode H.264. pref("media.gmp.trial-create.enabled", true); -// Note: when media.gmp-*.visible is true, provided we're running on a -// supported platform/OS version, the corresponding CDM appears in the -// plugins list, Firefox will download the GMP/CDM if enabled, and our -// UI to re-enable EME prompts the user to re-enable EME if it's disabled -// and script requests EME. If *.visible is false, we won't show the UI -// to enable the CDM if its disabled; it's as if the keysystem is completely -// unsupported. - #ifdef MOZ_ADOBE_EME -pref("media.gmp-eme-adobe.visible", true); pref("media.gmp-eme-adobe.enabled", true); #endif #ifdef MOZ_WIDEVINE_EME -pref("media.gmp-widevinecdm.visible", true); pref("media.gmp-widevinecdm.enabled", true); #endif diff --git a/browser/base/content/browser-media.js b/browser/base/content/browser-media.js index b9ce5ad3a4d2..7c915112a550 100644 --- a/browser/base/content/browser-media.js +++ b/browser/base/content/browser-media.js @@ -31,20 +31,6 @@ var gEMEHandler = { } browser.reload(); }, - isKeySystemVisible: function(keySystem) { - if (!keySystem) { - return false; - } - if (keySystem.startsWith("com.adobe") && - Services.prefs.getPrefType("media.gmp-eme-adobe.visible")) { - return Services.prefs.getBoolPref("media.gmp-eme-adobe.visible"); - } - if (keySystem == "com.widevine.alpha" && - Services.prefs.getPrefType("media.gmp-widevinecdm.visible")) { - return Services.prefs.getBoolPref("media.gmp-widevinecdm.visible"); - } - return true; - }, getLearnMoreLink: function(msgId) { let text = gNavigatorBundle.getString("emeNotifications." + msgId + ".learnMoreLabel"); let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL"); @@ -60,8 +46,8 @@ var gEMEHandler = { return; } let {status: status, keySystem: keySystem} = parsedData; - // Don't need to show if disabled or keysystem not visible. - if (!this.uiEnabled || !this.isKeySystemVisible(keySystem)) { + // Don't need to show if disabled + if (!this.uiEnabled) { return; } diff --git a/dom/media/eme/MediaKeySystemAccess.cpp b/dom/media/eme/MediaKeySystemAccess.cpp index 66e5f3d0da3e..eea37525580d 100644 --- a/dom/media/eme/MediaKeySystemAccess.cpp +++ b/dom/media/eme/MediaKeySystemAccess.cpp @@ -278,51 +278,51 @@ MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem, return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, aOutMessage, aOutCdmVersion); } - if (Preferences::GetBool("media.gmp-eme-adobe.visible", false)) { - if (aKeySystem.EqualsLiteral("com.adobe.primetime")) { - if (!Preferences::GetBool("media.gmp-eme-adobe.enabled", false)) { - aOutMessage = NS_LITERAL_CSTRING("Adobe EME disabled"); - return MediaKeySystemStatus::Cdm_disabled; - } +#ifdef MOZ_ADOBE_EME + if (aKeySystem.EqualsLiteral("com.adobe.primetime")) { + if (!Preferences::GetBool("media.gmp-eme-adobe.enabled", false)) { + aOutMessage = NS_LITERAL_CSTRING("Adobe EME disabled"); + return MediaKeySystemStatus::Cdm_disabled; + } #ifdef XP_WIN - // Win Vista and later only. - if (!IsVistaOrLater()) { - aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version (Vista) not met for Adobe EME"); - return MediaKeySystemStatus::Cdm_not_supported; - } + // Win Vista and later only. + if (!IsVistaOrLater()) { + aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version (Vista) not met for Adobe EME"); + return MediaKeySystemStatus::Cdm_not_supported; + } #endif #ifdef XP_MACOSX - if (!nsCocoaFeatures::OnLionOrLater()) { - aOutMessage = NS_LITERAL_CSTRING("Minimum MacOSX version (10.7) not met for Adobe EME"); - return MediaKeySystemStatus::Cdm_not_supported; - } -#endif - return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, aOutMessage, aOutCdmVersion); + if (!nsCocoaFeatures::OnLionOrLater()) { + aOutMessage = NS_LITERAL_CSTRING("Minimum MacOSX version (10.7) not met for Adobe EME"); + return MediaKeySystemStatus::Cdm_not_supported; } +#endif + return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, aOutMessage, aOutCdmVersion); } +#endif - if (Preferences::GetBool("media.gmp-widevinecdm.visible", false)) { - if (aKeySystem.EqualsLiteral("com.widevine.alpha")) { +#ifdef MOZ_WIDEVINE_EME + if (aKeySystem.EqualsLiteral("com.widevine.alpha")) { #ifdef XP_WIN - // Win Vista and later only. - if (!IsVistaOrLater()) { - aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version (Vista) not met for Widevine EME"); - return MediaKeySystemStatus::Cdm_not_supported; - } + // Win Vista and later only. + if (!IsVistaOrLater()) { + aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version (Vista) not met for Widevine EME"); + return MediaKeySystemStatus::Cdm_not_supported; + } #endif #ifdef XP_MACOSX - if (!nsCocoaFeatures::OnLionOrLater()) { - aOutMessage = NS_LITERAL_CSTRING("Minimum MacOSX version (10.7) not met for Widevine EME"); - return MediaKeySystemStatus::Cdm_not_supported; - } -#endif - if (!Preferences::GetBool("media.gmp-widevinecdm.enabled", false)) { - aOutMessage = NS_LITERAL_CSTRING("Widevine EME disabled"); - return MediaKeySystemStatus::Cdm_disabled; - } - return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, aOutMessage, aOutCdmVersion); + if (!nsCocoaFeatures::OnLionOrLater()) { + aOutMessage = NS_LITERAL_CSTRING("Minimum MacOSX version (10.7) not met for Widevine EME"); + return MediaKeySystemStatus::Cdm_not_supported; } +#endif + if (!Preferences::GetBool("media.gmp-widevinecdm.enabled", false)) { + aOutMessage = NS_LITERAL_CSTRING("Widevine EME disabled"); + return MediaKeySystemStatus::Cdm_disabled; + } + return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, aOutMessage, aOutCdmVersion); } +#endif return MediaKeySystemStatus::Cdm_not_supported; } diff --git a/dom/media/eme/moz.build b/dom/media/eme/moz.build index a7af0577d5c1..8270d9b9ed2e 100644 --- a/dom/media/eme/moz.build +++ b/dom/media/eme/moz.build @@ -4,6 +4,9 @@ # 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/. +for cdm in CONFIG['MOZ_EME_MODULES']: + DEFINES['MOZ_%s_EME' % cdm.upper()] = True + EXPORTS.mozilla.dom += [ 'MediaEncryptedEvent.h', 'MediaKeyError.h', diff --git a/dom/media/gmp/GMPChild.cpp b/dom/media/gmp/GMPChild.cpp index 9cc31369349c..bc4584aedc80 100644 --- a/dom/media/gmp/GMPChild.cpp +++ b/dom/media/gmp/GMPChild.cpp @@ -23,7 +23,9 @@ #include "GMPUtils.h" #include "prio.h" #include "base/task.h" +#ifdef MOZ_WIDEVINE_EME #include "widevine-adapter/WidevineAdapter.h" +#endif using namespace mozilla::ipc; using mozilla::dom::CrashReporterChild; @@ -374,12 +376,17 @@ GMPChild::AnswerStartPlugin(const nsString& aAdapter) return false; } +#ifdef MOZ_WIDEVINE_EME bool isWidevine = aAdapter.EqualsLiteral("widevine"); +#endif + #if defined(MOZ_GMP_SANDBOX) && defined(XP_MACOSX) MacSandboxPluginType pluginType = MacSandboxPluginType_GMPlugin_Default; +#ifdef MOZ_WIDEVINE_EME if (isWidevine) { - pluginType = MacSandboxPluginType_GMPlugin_EME_Widevine; + pluginType = MacSandboxPluginType_GMPlugin_EME_Widevine; } +#endif if (!SetMacSandboxInfo(pluginType)) { NS_WARNING("Failed to set Mac GMP sandbox info"); delete platformAPI; @@ -387,7 +394,12 @@ GMPChild::AnswerStartPlugin(const nsString& aAdapter) } #endif - GMPAdapter* adapter = (isWidevine) ? new WidevineAdapter() : nullptr; + GMPAdapter* adapter = nullptr; +#ifdef MOZ_WIDEVINE_EME + if (isWidevine) { + adapter = new WidevineAdapter(); + } +#endif if (!mGMPLoader->Load(libPath.get(), libPath.Length(), mNodeId.BeginWriting(), diff --git a/dom/media/gmp/GMPParent.cpp b/dom/media/gmp/GMPParent.cpp index 7239ef0884ea..d5bebfa19605 100644 --- a/dom/media/gmp/GMPParent.cpp +++ b/dom/media/gmp/GMPParent.cpp @@ -40,8 +40,10 @@ using CrashReporter::GetIDFromMinidump; #include "WMFDecoderModule.h" #endif +#ifdef MOZ_WIDEVINE_EME #include "mozilla/dom/WidevineCDMManifestBinding.h" #include "widevine-adapter/WidevineAdapter.h" +#endif namespace mozilla { @@ -807,6 +809,7 @@ GMPParent::ReadGMPMetaData() return ReadGMPInfoFile(infoFile); } +#ifdef MOZ_WIDEVINE_EME // Maybe this is the Widevine adapted plugin? nsCOMPtr manifestFile; rv = mDirectory->Clone(getter_AddRefs(manifestFile)); @@ -815,6 +818,9 @@ GMPParent::ReadGMPMetaData() } manifestFile->AppendRelativePath(NS_LITERAL_STRING("manifest.json")); return ReadChromiumManifestFile(manifestFile); +#else + return GenericPromise::CreateAndReject(rv, __func__); +#endif } RefPtr @@ -909,6 +915,7 @@ GMPParent::ReadGMPInfoFile(nsIFile* aFile) return GenericPromise::CreateAndResolve(true, __func__); } +#ifdef MOZ_WIDEVINE_EME RefPtr GMPParent::ReadChromiumManifestFile(nsIFile* aFile) { @@ -961,6 +968,7 @@ GMPParent::ParseChromiumManifest(nsString aJSON) return GenericPromise::CreateAndResolve(true, __func__); } +#endif bool GMPParent::CanBeSharedCrossNodeIds() const diff --git a/dom/media/gmp/GMPParent.h b/dom/media/gmp/GMPParent.h index 67355faeee63..f36cbd19ccc6 100644 --- a/dom/media/gmp/GMPParent.h +++ b/dom/media/gmp/GMPParent.h @@ -167,8 +167,10 @@ private: bool EnsureProcessLoaded(); RefPtr ReadGMPMetaData(); RefPtr ReadGMPInfoFile(nsIFile* aFile); +#ifdef MOZ_WIDEVINE_EME RefPtr ParseChromiumManifest(nsString aJSON); // Main thread. RefPtr ReadChromiumManifestFile(nsIFile* aFile); // GMP thread. +#endif #ifdef MOZ_CRASHREPORTER void WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes); void GetCrashID(nsString& aResult); diff --git a/dom/media/gmp/moz.build b/dom/media/gmp/moz.build index d05b5937b321..77b51ff927a2 100644 --- a/dom/media/gmp/moz.build +++ b/dom/media/gmp/moz.build @@ -4,6 +4,9 @@ # 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/. +for cdm in CONFIG['MOZ_EME_MODULES']: + DEFINES['MOZ_%s_EME' % cdm.upper()] = True + XPIDL_MODULE = 'content_geckomediaplugins' XPIDL_SOURCES += [ @@ -117,9 +120,13 @@ UNIFIED_SOURCES += [ DIRS += [ 'rlz', - 'widevine-adapter', ] +if 'widevine' in CONFIG['MOZ_EME_MODULES']: + DIRS += [ + 'widevine-adapter', + ] + IPDL_SOURCES += [ 'GMPTypes.ipdlh', 'PGMP.ipdl', diff --git a/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp b/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp index 28c4fbab977e..5d16e6092e67 100644 --- a/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp +++ b/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp @@ -193,7 +193,7 @@ WidevineDecryptor::DecryptingComplete() class WidevineBuffer : public cdm::Buffer { public: - explicit WidevineBuffer(size_t aSize) { + WidevineBuffer(size_t aSize) { Log("WidevineBuffer(size=" PRIuSIZE ") created", aSize); mBuffer.SetLength(aSize); } diff --git a/dom/media/gmp/widevine-adapter/WidevineUtils.h b/dom/media/gmp/widevine-adapter/WidevineUtils.h index e5d20fe9c624..9eb039673afb 100644 --- a/dom/media/gmp/widevine-adapter/WidevineUtils.h +++ b/dom/media/gmp/widevine-adapter/WidevineUtils.h @@ -46,7 +46,7 @@ class CDMWrapper { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CDMWrapper) - explicit CDMWrapper(cdm::ContentDecryptionModule_8* aCDM) + CDMWrapper(cdm::ContentDecryptionModule_8* aCDM) : mCDM(aCDM) { MOZ_ASSERT(mCDM); diff --git a/toolkit/modules/GMPUtils.jsm b/toolkit/modules/GMPUtils.jsm index b1d2b8e8d0a3..53356f34e391 100644 --- a/toolkit/modules/GMPUtils.jsm +++ b/toolkit/modules/GMPUtils.jsm @@ -46,8 +46,8 @@ this.GMPUtils = { return false; } - if (!this._isPluginSupported(aPlugin) || - !this._isPluginVisible(aPlugin)) { + if (!this._isPluginSupported(aPlugin) && + !this._isPluginForcedVisible(aPlugin)) { this.maybeReportTelemetry(aPlugin.id, "VIDEO_EME_ADOBE_HIDDEN_REASON", GMPPluginHiddenReason.UNSUPPORTED); @@ -70,9 +70,6 @@ this.GMPUtils = { * The plugin to check. */ _isPluginSupported: function(aPlugin) { - if (this._isPluginForceSupported(aPlugin)) { - return true; - } if (aPlugin.id == EME_ADOBE_ID) { if (Services.appinfo.OS != "WINNT") { // Non-Windows OSes currently unsupported by Adobe EME @@ -95,25 +92,13 @@ this.GMPUtils = { }, /** - * Checks whether or not a given plugin is visible in the addons manager - * UI and the "enable DRM" notification box. This can be used to test - * plugins that aren't yet turned on in the mozconfig. + * Checks whether or not a given plugin is forced visible. This can be used + * to test plugins that aren't yet supported by default on a particular OS. * @param aPlugin * The plugin to check. */ - _isPluginVisible: function(aPlugin) { - return GMPPrefs.get(GMPPrefs.KEY_PLUGIN_VISIBLE, false, aPlugin.id); - }, - - /** - * Checks whether or not a given plugin is forced-supported. This is used - * in automated tests to override the checks that prevent GMPs running on an - * unsupported platform. - * @param aPlugin - * The plugin to check. - */ - _isPluginForceSupported: function(aPlugin) { - return GMPPrefs.get(GMPPrefs.KEY_PLUGIN_FORCE_SUPPORTED, false, aPlugin.id); + _isPluginForcedVisible: function(aPlugin) { + return GMPPrefs.get(GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, false, aPlugin.id); }, /** @@ -151,9 +136,8 @@ this.GMPPrefs = { KEY_PLUGIN_LAST_UPDATE: "media.{0}.lastUpdate", KEY_PLUGIN_VERSION: "media.{0}.version", KEY_PLUGIN_AUTOUPDATE: "media.{0}.autoupdate", - KEY_PLUGIN_VISIBLE: "media.{0}.visible", + KEY_PLUGIN_FORCEVISIBLE: "media.{0}.forcevisible", KEY_PLUGIN_ABI: "media.{0}.abi", - KEY_PLUGIN_FORCE_SUPPORTED: "media.{0}.forceSupported", KEY_URL: "media.gmp-manager.url", KEY_URL_OVERRIDE: "media.gmp-manager.url.override", KEY_CERT_CHECKATTRS: "media.gmp-manager.cert.checkAttributes", diff --git a/toolkit/mozapps/extensions/test/browser/browser_gmpProvider.js b/toolkit/mozapps/extensions/test/browser/browser_gmpProvider.js index 5921fc5b6aa1..37825b0652a9 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_gmpProvider.js +++ b/toolkit/mozapps/extensions/test/browser/browser_gmpProvider.js @@ -102,7 +102,7 @@ add_task(function* initializeState() { gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_LAST_UPDATE, addon.id)); gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_AUTOUPDATE, addon.id)); gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id)); - gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VISIBLE, addon.id)); + gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id)); } gPrefs.clearUserPref(GMPScope.GMPPrefs.KEY_LOGGING_DUMP); gPrefs.clearUserPref(GMPScope.GMPPrefs.KEY_LOGGING_LEVEL); @@ -125,7 +125,7 @@ add_task(function* initializeState() { gPrefs.setIntPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_LAST_UPDATE, addon.id), 0); gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_AUTOUPDATE, addon.id), false); gPrefs.setCharPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id), ""); - gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VISIBLE, addon.id), + gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id), true); } yield GMPScope.GMPProvider.shutdown(); @@ -370,7 +370,7 @@ add_task(function* testUpdateButton() { add_task(function* testEmeSupport() { for (let addon of gMockAddons) { - gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VISIBLE, addon.id)); + gPrefs.clearUserPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id)); } yield GMPScope.GMPProvider.shutdown(); GMPScope.GMPProvider.startup(); @@ -400,7 +400,7 @@ add_task(function* testEmeSupport() { } for (let addon of gMockAddons) { - gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VISIBLE, addon.id), + gPrefs.setBoolPref(getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id), true); } yield GMPScope.GMPProvider.shutdown(); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_gmpProvider.js b/toolkit/mozapps/extensions/test/xpcshell/test_gmpProvider.js index 88140bd11af4..48d9c0557639 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_gmpProvider.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_gmpProvider.js @@ -59,9 +59,7 @@ function run_test() { gPrefs.setIntPref(GMPScope.GMPPrefs.KEY_LOGGING_LEVEL, 0); gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_EME_ENABLED, true); for (let addon of gMockAddons.values()) { - gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_VISIBLE, addon.id), - true); - gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCE_SUPPORTED, addon.id), + gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCEVISIBLE, addon.id), true); } GMPScope.GMPProvider.shutdown(); From 591bde5c07d780fa90b2c7b8dc85952e64bdee91 Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Wed, 8 Jun 2016 21:01:00 -0700 Subject: [PATCH 62/76] Bug 1269711 - Disallow JS interrupt callback function to affect exception state of interrupted JS. (r=jimb) --- js/src/shell/js.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 32cbe119b39b..77b7ba68c474 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -458,14 +458,27 @@ ShellInterruptCallback(JSContext* cx) bool result; if (sr->haveInterruptFunc) { + bool wasAlreadyThrowing = cx->isExceptionPending(); JS::AutoSaveExceptionState savedExc(cx); JSAutoCompartment ac(cx, &sr->interruptFunc.toObject()); RootedValue rval(cx); - if (!JS_CallFunctionValue(cx, nullptr, sr->interruptFunc, - JS::HandleValueArray::empty(), &rval)) + + // Report any exceptions thrown by the JS interrupt callback, but do + // *not* keep it on the cx. The interrupt handler is invoked at points + // that are not expected to throw catchable exceptions, like at + // JSOP_RETRVAL. + // + // If the interrupted JS code was already throwing, any exceptions + // thrown by the interrupt handler are silently swallowed. { - return false; + Maybe are; + if (!wasAlreadyThrowing) + are.emplace(cx); + result = JS_CallFunctionValue(cx, nullptr, sr->interruptFunc, + JS::HandleValueArray::empty(), &rval); } + savedExc.restore(); + if (rval.isBoolean()) result = rval.toBoolean(); else From aa82814823ceeeacca5e06b71349233024eb6cb5 Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Wed, 8 Jun 2016 21:01:00 -0700 Subject: [PATCH 63/76] Bug 1269711 - Update futex shell test. (r=lth) --- js/src/tests/shell/futex.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/js/src/tests/shell/futex.js b/js/src/tests/shell/futex.js index 3800a396d186..b0951f12ec77 100644 --- a/js/src/tests/shell/futex.js +++ b/js/src/tests/shell/futex.js @@ -134,18 +134,20 @@ dprint("Woke up as I should have in " + (Date.now() - then)/1000 + "s"); // the interrupt handler we will execute a wait. This is // explicitly prohibited (for now), so there should be a catchable exception. +var exn = false; timeout(2, function () { dprint("In the interrupt, starting inner wait with timeout 2s"); - Atomics.wait(mem, 0, 42); // Should throw and propagate all the way out + try { + Atomics.wait(mem, 0, 42); // Should throw + } catch (e) { + dprint("Got the interrupt exception!"); + exn = true; + } + return true; }); -var exn = false; try { dprint("Starting outer wait"); - assertEq(Atomics.wait(mem, 0, 42, 5000), "ok"); -} -catch (e) { - dprint("Got the timeout exception!"); - exn = true; + assertEq(Atomics.wait(mem, 0, 42, 5000), "timed-out"); } finally { timeout(-1); From 77a0b3ec78f30b9d77fe5b4b6d6d919eaaef232c Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Wed, 8 Jun 2016 21:01:01 -0700 Subject: [PATCH 64/76] Bug 1275001 - Fix RematerializedFrame::locals() when there's arguments underflow. (r=jandem) --- js/src/jit-test/tests/debug/bug1275001.js | 30 +++++++++++++++++++++++ js/src/jit/RematerializedFrame.h | 7 +++++- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 js/src/jit-test/tests/debug/bug1275001.js diff --git a/js/src/jit-test/tests/debug/bug1275001.js b/js/src/jit-test/tests/debug/bug1275001.js new file mode 100644 index 000000000000..b8bdc5556079 --- /dev/null +++ b/js/src/jit-test/tests/debug/bug1275001.js @@ -0,0 +1,30 @@ + +g = newGlobal(); +g.parent = this; +g.eval("(" + function() { + Debugger(parent).onExceptionUnwind = function(frame) { + frame.older + } +} + ")()") +function check_one(expected, f, err) { + try { + f() + } catch (ex) { + s = ex.toString() + assertEq(s.slice(11, -err.length), expected) + } +} +ieval = eval +function check(expr, expected = expr) { + var end, err + for ([end, err] of[[".random_prop", " is undefined" ]]) + statement = "o = {};" + expr + end; + cases = [ + function() ieval("var undef;" + statement), + Function(statement) + ] + for (f of cases) + check_one(expected, f, err) +} +check("undef"); +check("o.b"); diff --git a/js/src/jit/RematerializedFrame.h b/js/src/jit/RematerializedFrame.h index 4d3cce19cfa4..e63a1e0b8dc7 100644 --- a/js/src/jit/RematerializedFrame.h +++ b/js/src/jit/RematerializedFrame.h @@ -7,6 +7,8 @@ #ifndef jit_RematerializedFrame_h #define jit_RematerializedFrame_h +#include + #include "jsfun.h" #include "jit/JitFrameIterator.h" @@ -180,12 +182,15 @@ class RematerializedFrame unsigned numActualArgs() const { return numActualArgs_; } + unsigned numArgSlots() const { + return std::max(numFormalArgs(), numActualArgs()); + } Value* argv() { return slots_; } Value* locals() { - return slots_ + numActualArgs_ + isConstructing_; + return slots_ + numArgSlots() + isConstructing_; } Value& unaliasedLocal(unsigned i) { From 3dd770634ac4831a68d2e27ed20ed024c9fbadb8 Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Wed, 8 Jun 2016 21:24:46 -0700 Subject: [PATCH 65/76] Bug 1275001 - Fix Windows bustage. (r=me) --- js/src/jit/RematerializedFrame.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/jit/RematerializedFrame.h b/js/src/jit/RematerializedFrame.h index e63a1e0b8dc7..088bd37279e9 100644 --- a/js/src/jit/RematerializedFrame.h +++ b/js/src/jit/RematerializedFrame.h @@ -183,7 +183,7 @@ class RematerializedFrame return numActualArgs_; } unsigned numArgSlots() const { - return std::max(numFormalArgs(), numActualArgs()); + return (std::max)(numFormalArgs(), numActualArgs()); } Value* argv() { From e7758d8a8c675c9b8b16367bec694207e9d66068 Mon Sep 17 00:00:00 2001 From: Honza Bambas Date: Wed, 8 Jun 2016 04:24:00 +0200 Subject: [PATCH 66/76] Bug 1188387 - On failure of nsHttpChannel::ProcessNotModified redirect to reload from network, r=michal --HG-- extra : rebase_source : f714c545a6a1b7fba0691ee5032257f291a558be --- netwerk/protocol/http/nsHttpChannel.cpp | 58 ++++++++++++++++++------- netwerk/protocol/http/nsHttpChannel.h | 1 + 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 7ddb2aa98531..d39155e9c662 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -1815,14 +1815,32 @@ nsHttpChannel::ContinueProcessResponse1(nsresult rv) } break; case 304: - rv = ProcessNotModified(); - if (NS_FAILED(rv)) { + if (!ShouldBypassProcessNotModified()) { + rv = ProcessNotModified(); + if (NS_SUCCEEDED(rv)) { + successfulReval = true; + break; + } + LOG(("ProcessNotModified failed [rv=%x]\n", rv)); + + // We cannot read from the cache entry, it might be in an + // incosistent state. Doom it and redirect the channel + // to the same URI to reload from the network. mCacheInputStream.CloseAndRelease(); - rv = ProcessNormal(); + if (mCacheEntry) { + mCacheEntry->AsyncDoom(nullptr); + mCacheEntry = nullptr; + } + + rv = StartRedirectChannelToURI(mURI, nsIChannelEventSink::REDIRECT_INTERNAL); + if (NS_SUCCEEDED(rv)) { + return NS_OK; + } } - else { - successfulReval = true; + + if (ShouldBypassProcessNotModified() || NS_FAILED(rv)) { + rv = ProcessNormal(); } break; case 401: @@ -2821,6 +2839,23 @@ nsHttpChannel::OnDoneReadingPartialCacheEntry(bool *streamDone) // nsHttpChannel //----------------------------------------------------------------------------- +bool +nsHttpChannel::ShouldBypassProcessNotModified() +{ + if (mCustomConditionalRequest) { + LOG(("Bypassing ProcessNotModified due to custom conditional headers")); + return true; + } + + if (!mDidReval) { + LOG(("Server returned a 304 response even though we did not send a " + "conditional request")); + return true; + } + + return false; +} + nsresult nsHttpChannel::ProcessNotModified() { @@ -2828,16 +2863,9 @@ nsHttpChannel::ProcessNotModified() LOG(("nsHttpChannel::ProcessNotModified [this=%p]\n", this)); - if (mCustomConditionalRequest) { - LOG(("Bypassing ProcessNotModified due to custom conditional headers")); - return NS_ERROR_FAILURE; - } - - if (!mDidReval) { - LOG(("Server returned a 304 response even though we did not send a " - "conditional request")); - return NS_ERROR_FAILURE; - } + // Assert ShouldBypassProcessNotModified() has been checked before call to + // ProcessNotModified(). + MOZ_ASSERT(!ShouldBypassProcessNotModified()); MOZ_ASSERT(mCachedResponseHead); MOZ_ASSERT(mCacheEntry); diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h index 993cdd6d7d2a..5e823f1e0817 100644 --- a/netwerk/protocol/http/nsHttpChannel.h +++ b/netwerk/protocol/http/nsHttpChannel.h @@ -279,6 +279,7 @@ private: nsresult ProcessNormal(); nsresult ContinueProcessNormal(nsresult); void ProcessAltService(); + bool ShouldBypassProcessNotModified(); nsresult ProcessNotModified(); nsresult AsyncProcessRedirection(uint32_t httpStatus); nsresult ContinueProcessRedirection(nsresult); From 7c273b3eb3c052fb59790b1e3e4fa1d6dace8382 Mon Sep 17 00:00:00 2001 From: James Andreou Date: Tue, 7 Jun 2016 13:50:00 +0200 Subject: [PATCH 67/76] Bug 1276328 - Remove private browsing flags r=baku --HG-- extra : rebase_source : e13f6b834ae22986776ca7cc3dd0cee3fc945992 --- dom/broadcastchannel/BroadcastChannel.cpp | 29 ++++------------------- dom/broadcastchannel/BroadcastChannel.h | 4 +--- ipc/glue/BackgroundChildImpl.cpp | 3 +-- ipc/glue/BackgroundChildImpl.h | 3 +-- ipc/glue/BackgroundParentImpl.cpp | 14 ++++------- ipc/glue/BackgroundParentImpl.h | 6 ++--- ipc/glue/PBackground.ipdl | 3 +-- 7 files changed, 15 insertions(+), 47 deletions(-) diff --git a/dom/broadcastchannel/BroadcastChannel.cpp b/dom/broadcastchannel/BroadcastChannel.cpp index a77df35f9a55..22979398bfc2 100644 --- a/dom/broadcastchannel/BroadcastChannel.cpp +++ b/dom/broadcastchannel/BroadcastChannel.cpp @@ -71,14 +71,12 @@ class InitializeRunnable final : public WorkerMainThreadRunnable { public: InitializeRunnable(WorkerPrivate* aWorkerPrivate, nsACString& aOrigin, - PrincipalInfo& aPrincipalInfo, bool& aPrivateBrowsing, - ErrorResult& aRv) + PrincipalInfo& aPrincipalInfo, ErrorResult& aRv) : WorkerMainThreadRunnable(aWorkerPrivate, NS_LITERAL_CSTRING("BroadcastChannel :: Initialize")) , mWorkerPrivate(GetCurrentThreadWorkerPrivate()) , mOrigin(aOrigin) , mPrincipalInfo(aPrincipalInfo) - , mPrivateBrowsing(aPrivateBrowsing) , mRv(aRv) { MOZ_ASSERT(mWorkerPrivate); @@ -127,11 +125,6 @@ public: return true; } - nsIDocument* doc = window->GetExtantDoc(); - if (doc) { - mPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc); - } - return true; } @@ -139,7 +132,6 @@ private: WorkerPrivate* mWorkerPrivate; nsACString& mOrigin; PrincipalInfo& mPrincipalInfo; - bool& mPrivateBrowsing; ErrorResult& mRv; }; @@ -306,14 +298,12 @@ private: BroadcastChannel::BroadcastChannel(nsPIDOMWindowInner* aWindow, const PrincipalInfo& aPrincipalInfo, const nsACString& aOrigin, - const nsAString& aChannel, - bool aPrivateBrowsing) + const nsAString& aChannel) : DOMEventTargetHelper(aWindow) , mWorkerFeature(nullptr) , mPrincipalInfo(new PrincipalInfo(aPrincipalInfo)) , mOrigin(aOrigin) , mChannel(aChannel) - , mPrivateBrowsing(aPrivateBrowsing) , mIsKeptAlive(false) , mInnerID(0) , mState(StateActive) @@ -344,7 +334,6 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal, nsAutoCString origin; PrincipalInfo principalInfo; - bool privateBrowsing = false; WorkerPrivate* workerPrivate = nullptr; if (NS_IsMainThread()) { @@ -381,19 +370,13 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal, if (NS_WARN_IF(aRv.Failed())) { return nullptr; } - - nsIDocument* doc = window->GetExtantDoc(); - if (doc) { - privateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc); - } } else { JSContext* cx = aGlobal.Context(); workerPrivate = GetWorkerPrivateFromContext(cx); MOZ_ASSERT(workerPrivate); RefPtr runnable = - new InitializeRunnable(workerPrivate, origin, principalInfo, - privateBrowsing, aRv); + new InitializeRunnable(workerPrivate, origin, principalInfo, aRv); runnable->Dispatch(aRv); } @@ -402,8 +385,7 @@ BroadcastChannel::Constructor(const GlobalObject& aGlobal, } RefPtr bc = - new BroadcastChannel(window, principalInfo, origin, aChannel, - privateBrowsing); + new BroadcastChannel(window, principalInfo, origin, aChannel); // Register this component to PBackground. PBackgroundChild* actor = BackgroundChild::GetForCurrentThread(); @@ -522,8 +504,7 @@ BroadcastChannel::ActorCreated(PBackgroundChild* aActor) } PBroadcastChannelChild* actor = - aActor->SendPBroadcastChannelConstructor(*mPrincipalInfo, mOrigin, mChannel, - mPrivateBrowsing); + aActor->SendPBroadcastChannelConstructor(*mPrincipalInfo, mOrigin, mChannel); mActor = static_cast(actor); MOZ_ASSERT(mActor); diff --git a/dom/broadcastchannel/BroadcastChannel.h b/dom/broadcastchannel/BroadcastChannel.h index 5ada71aeae99..9cdb5bbdc82c 100644 --- a/dom/broadcastchannel/BroadcastChannel.h +++ b/dom/broadcastchannel/BroadcastChannel.h @@ -88,8 +88,7 @@ private: BroadcastChannel(nsPIDOMWindowInner* aWindow, const PrincipalInfo& aPrincipalInfo, const nsACString& aOrigin, - const nsAString& aChannel, - bool aPrivateBrowsing); + const nsAString& aChannel); ~BroadcastChannel(); @@ -116,7 +115,6 @@ private: nsCString mOrigin; nsString mChannel; - bool mPrivateBrowsing; bool mIsKeptAlive; diff --git a/ipc/glue/BackgroundChildImpl.cpp b/ipc/glue/BackgroundChildImpl.cpp index 824d11adb7d3..d66336e10e3f 100644 --- a/ipc/glue/BackgroundChildImpl.cpp +++ b/ipc/glue/BackgroundChildImpl.cpp @@ -276,8 +276,7 @@ BackgroundChildImpl::DeallocPUDPSocketChild(PUDPSocketChild* child) dom::PBroadcastChannelChild* BackgroundChildImpl::AllocPBroadcastChannelChild(const PrincipalInfo& aPrincipalInfo, const nsCString& aOrigin, - const nsString& aChannel, - const bool& aPrivateBrowsing) + const nsString& aChannel) { RefPtr agent = new dom::BroadcastChannelChild(aOrigin); diff --git a/ipc/glue/BackgroundChildImpl.h b/ipc/glue/BackgroundChildImpl.h index fe60002e307b..cff95fb2fb06 100644 --- a/ipc/glue/BackgroundChildImpl.h +++ b/ipc/glue/BackgroundChildImpl.h @@ -104,8 +104,7 @@ protected: virtual PBroadcastChannelChild* AllocPBroadcastChannelChild(const PrincipalInfo& aPrincipalInfo, const nsCString& aOrigin, - const nsString& aChannel, - const bool& aPrivateBrowsing) override; + const nsString& aChannel) override; virtual bool DeallocPBroadcastChannelChild(PBroadcastChannelChild* aActor) override; diff --git a/ipc/glue/BackgroundParentImpl.cpp b/ipc/glue/BackgroundParentImpl.cpp index bb780e9a0c84..81d4382fd7bf 100644 --- a/ipc/glue/BackgroundParentImpl.cpp +++ b/ipc/glue/BackgroundParentImpl.cpp @@ -467,8 +467,7 @@ mozilla::dom::PBroadcastChannelParent* BackgroundParentImpl::AllocPBroadcastChannelParent( const PrincipalInfo& aPrincipalInfo, const nsCString& aOrigin, - const nsString& aChannel, - const bool& aPrivateBrowsing) + const nsString& aChannel) { AssertIsInMainProcess(); AssertIsOnBackgroundThread(); @@ -476,15 +475,11 @@ BackgroundParentImpl::AllocPBroadcastChannelParent( nsString originChannelKey; // The format of originChannelKey is: - // |pb={true,false}| + // | originChannelKey.Assign(aChannel); - if (aPrivateBrowsing) { - originChannelKey.AppendLiteral("|pb=true|"); - } else { - originChannelKey.AppendLiteral("|pb=false|"); - } + originChannelKey.AppendLiteral("|"); originChannelKey.Append(NS_ConvertUTF8toUTF16(aOrigin)); @@ -648,8 +643,7 @@ BackgroundParentImpl::RecvPBroadcastChannelConstructor( PBroadcastChannelParent* actor, const PrincipalInfo& aPrincipalInfo, const nsCString& aOrigin, - const nsString& aChannel, - const bool& aPrivateBrowsing) + const nsString& aChannel) { AssertIsInMainProcess(); AssertIsOnBackgroundThread(); diff --git a/ipc/glue/BackgroundParentImpl.h b/ipc/glue/BackgroundParentImpl.h index bfb1ece56d9d..8df37f279540 100644 --- a/ipc/glue/BackgroundParentImpl.h +++ b/ipc/glue/BackgroundParentImpl.h @@ -90,15 +90,13 @@ protected: virtual PBroadcastChannelParent* AllocPBroadcastChannelParent(const PrincipalInfo& aPrincipalInfo, const nsCString& aOrigin, - const nsString& aChannel, - const bool& aPrivateBrowsing) override; + const nsString& aChannel) override; virtual bool RecvPBroadcastChannelConstructor(PBroadcastChannelParent* actor, const PrincipalInfo& aPrincipalInfo, const nsCString& origin, - const nsString& channel, - const bool& aPrivateBrowsing) override; + const nsString& channel) override; virtual bool DeallocPBroadcastChannelParent(PBroadcastChannelParent* aActor) override; diff --git a/ipc/glue/PBackground.ipdl b/ipc/glue/PBackground.ipdl index 8d23f84ad15b..9e8cb55c18ee 100644 --- a/ipc/glue/PBackground.ipdl +++ b/ipc/glue/PBackground.ipdl @@ -79,8 +79,7 @@ parent: async PCameras(); async PUDPSocket(OptionalPrincipalInfo pInfo, nsCString filter); - async PBroadcastChannel(PrincipalInfo pInfo, nsCString origin, nsString channel, - bool privateBrowsing); + async PBroadcastChannel(PrincipalInfo pInfo, nsCString origin, nsString channel); async PServiceWorkerManager(); From 112a78c7a371b56187c93725305b741ae9733e25 Mon Sep 17 00:00:00 2001 From: Jim Mathies Date: Tue, 7 Jun 2016 15:58:42 -0500 Subject: [PATCH 68/76] Bug 1278568 - Enable e10s with accessibility in Nightly and local builds. r=tbsaunde MozReview-Commit-ID: Gu9zRuJImYb --- toolkit/xre/nsAppRunner.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 66c12ff8ea9d..adff9f2ebe28 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -4785,7 +4785,14 @@ MultiprocessBlockPolicy() { } } - if (disabledForA11y) { + // For linux nightly and aurora builds skip accessibility + // checks. + bool doAccessibilityCheck = true; +#if defined(MOZ_WIDGET_GTK) && !defined(RELEASE_BUILD) + doAccessibilityCheck = false; +#endif + + if (doAccessibilityCheck && disabledForA11y) { gMultiprocessBlockPolicy = kE10sDisabledForAccessibility; return gMultiprocessBlockPolicy; } From 695c044db935e0224a37b7af74b1c45aa8fb5076 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Thu, 9 Jun 2016 16:36:12 +1200 Subject: [PATCH 69/76] Bug 1275694 - Use the presence of checkerboarding to decide when to override the clip rect rather than always using the client side visible rect. r=botond --HG-- extra : rebase_source : 3d1785095b265bc3e2b51cf6ebb18f2538e3e62c --- gfx/layers/Layers.cpp | 9 +++------ gfx/layers/Layers.h | 4 ++++ gfx/layers/composite/ContainerLayerComposite.cpp | 11 +++++++++++ gfx/layers/composite/ContainerLayerComposite.h | 4 ++++ 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index 969a89a10fe5..49594442249e 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -804,15 +804,12 @@ Layer::CalculateScissorRect(const RenderTargetIntRect& aCurrentScissorRect) return currentClip; } - if (GetVisibleRegion().IsEmpty()) { + if (GetLocalVisibleRegion().IsEmpty() && !NeedToDrawCheckerboarding()) { // When our visible region is empty, our parent may not have created the // intermediate surface that we would require for correct clipping; however, // this does not matter since we are invisible. - // Note that we do not use GetLocalVisibleRegion(), because that can be - // empty for a layer whose rendered contents have been async-scrolled - // completely offscreen, but for which we still need to draw a - // checkerboarding backround color, and calculating an empty scissor rect - // for such a layer would prevent that (see bug 1247452 comment 10). + // Make sure we still compute a clip rect if we want to draw checkboarding + // for this layer, since we want to do this even if the layer is invisible. return RenderTargetIntRect(currentClip.TopLeft(), RenderTargetIntSize(0, 0)); } diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index c20a09956d8b..c2e6653b1f91 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -1556,6 +1556,10 @@ public: return !GetLocalVisibleRegion().IsEmpty() || Extend3DContext(); } + virtual bool NeedToDrawCheckerboarding(gfx::Color* aOutCheckerboardingColor = nullptr) { + return false; + } + /** * Return true if current layer content is opaque. * It does not guarantee that layer content is always opaque. diff --git a/gfx/layers/composite/ContainerLayerComposite.cpp b/gfx/layers/composite/ContainerLayerComposite.cpp index e0d75753e910..6f819c746ad8 100755 --- a/gfx/layers/composite/ContainerLayerComposite.cpp +++ b/gfx/layers/composite/ContainerLayerComposite.cpp @@ -905,6 +905,12 @@ ContainerLayerComposite::Prepare(const RenderTargetIntRect& aClipRect) ContainerPrepare(this, mCompositeManager, aClipRect); } +bool +ContainerLayerComposite::NeedToDrawCheckerboarding(Color* aOutCheckerboardingColor) +{ + return NeedToDrawCheckerboardingForLayer(this, aOutCheckerboardingColor); +} + void ContainerLayerComposite::CleanupResources() { @@ -956,6 +962,11 @@ RefLayerComposite::Prepare(const RenderTargetIntRect& aClipRect) ContainerPrepare(this, mCompositeManager, aClipRect); } +bool +RefLayerComposite::NeedToDrawCheckerboarding(Color* aOutCheckerboardingColor) +{ + return NeedToDrawCheckerboardingForLayer(this, aOutCheckerboardingColor); +} void RefLayerComposite::CleanupResources() diff --git a/gfx/layers/composite/ContainerLayerComposite.h b/gfx/layers/composite/ContainerLayerComposite.h index ec1e01cfd131..03df1f4b2c00 100644 --- a/gfx/layers/composite/ContainerLayerComposite.h +++ b/gfx/layers/composite/ContainerLayerComposite.h @@ -88,6 +88,8 @@ public: DefaultComputeEffectiveTransforms(aTransformToSurface); } + virtual bool NeedToDrawCheckerboarding(gfx::Color* aOutCheckerboardingColor = nullptr) override; + virtual void CleanupResources() override; virtual LayerComposite* AsLayerComposite() override { return this; } @@ -173,6 +175,8 @@ public: DefaultComputeEffectiveTransforms(aTransformToSurface); } + virtual bool NeedToDrawCheckerboarding(gfx::Color* aOutCheckerboardingColor = nullptr) override; + virtual void CleanupResources() override; virtual LayerComposite* AsLayerComposite() override { return this; } From 5592622f0957cbcadf9bf50406dfc8e9c4967c7e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 9 Jun 2016 13:09:58 +1000 Subject: [PATCH 70/76] Bug 1277104 - Add strings to high-frequency MOZ_CRASH() occurrences. mccr8. Some of these are guesses; it's not always clear from a crash report stack trace which MOZ_CRASH() was hit. --- caps/nsScriptSecurityManager.cpp | 2 +- js/xpconnect/src/XPCJSContextStack.cpp | 3 +-- js/xpconnect/src/XPCWrappedJS.cpp | 16 ++++++++-------- xpcom/base/CycleCollectedJSRuntime.cpp | 2 +- xpcom/base/nsDebugImpl.cpp | 2 +- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/caps/nsScriptSecurityManager.cpp b/caps/nsScriptSecurityManager.cpp index 18776533ea18..935b3070da31 100644 --- a/caps/nsScriptSecurityManager.cpp +++ b/caps/nsScriptSecurityManager.cpp @@ -1436,7 +1436,7 @@ nsScriptSecurityManager::InitStatics() RefPtr ssManager = new nsScriptSecurityManager(); nsresult rv = ssManager->Init(); if (NS_FAILED(rv)) { - MOZ_CRASH(); + MOZ_CRASH("ssManager->Init() failed"); } ClearOnShutdown(&gScriptSecMan); diff --git a/js/xpconnect/src/XPCJSContextStack.cpp b/js/xpconnect/src/XPCJSContextStack.cpp index 412c2632d56c..6c98526afeff 100644 --- a/js/xpconnect/src/XPCJSContextStack.cpp +++ b/js/xpconnect/src/XPCJSContextStack.cpp @@ -64,7 +64,6 @@ XPCJSContextStack::InitSafeJSContext() { MOZ_ASSERT(!mSafeJSContext); mSafeJSContext = JS_NewContext(XPCJSRuntime::Get()->Runtime(), 8192); - if (!mSafeJSContext) - MOZ_CRASH(); + MOZ_RELEASE_ASSERT(mSafeJSContext, "JS_NewContext failed"); return mSafeJSContext; } diff --git a/js/xpconnect/src/XPCWrappedJS.cpp b/js/xpconnect/src/XPCWrappedJS.cpp index 0bd0eb2b2e26..c2f90e7e6199 100644 --- a/js/xpconnect/src/XPCWrappedJS.cpp +++ b/js/xpconnect/src/XPCWrappedJS.cpp @@ -228,8 +228,8 @@ nsXPCWrappedJS::QueryInterface(REFNSIID aIID, void** aInstancePtr) MozExternalRefCountType nsXPCWrappedJS::AddRef(void) { - if (!MOZ_LIKELY(NS_IsMainThread())) - MOZ_CRASH(); + MOZ_RELEASE_ASSERT(NS_IsMainThread(), + "nsXPCWrappedJS::AddRef called off main thread"); MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); nsISupports* base = NS_CYCLE_COLLECTION_CLASSNAME(nsXPCWrappedJS)::Upcast(this); @@ -247,8 +247,8 @@ nsXPCWrappedJS::AddRef(void) MozExternalRefCountType nsXPCWrappedJS::Release(void) { - if (!MOZ_LIKELY(NS_IsMainThread())) - MOZ_CRASH(); + MOZ_RELEASE_ASSERT(NS_IsMainThread(), + "nsXPCWrappedJS::Release called off main thread"); MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); NS_ASSERT_OWNINGTHREAD(nsXPCWrappedJS); @@ -319,8 +319,8 @@ nsXPCWrappedJS::GetNewOrUsed(JS::HandleObject jsObj, nsXPCWrappedJS** wrapperResult) { // Do a release-mode assert against accessing nsXPCWrappedJS off-main-thread. - if (!MOZ_LIKELY(NS_IsMainThread())) - MOZ_CRASH(); + MOZ_RELEASE_ASSERT(NS_IsMainThread(), + "nsXPCWrappedJS::GetNewOrUsed called off main thread"); AutoJSContext cx; @@ -594,8 +594,8 @@ nsXPCWrappedJS::CallMethod(uint16_t methodIndex, nsXPTCMiniVariant* params) { // Do a release-mode assert against accessing nsXPCWrappedJS off-main-thread. - if (!MOZ_LIKELY(NS_IsMainThread())) - MOZ_CRASH(); + MOZ_RELEASE_ASSERT(NS_IsMainThread(), + "nsXPCWrappedJS::CallMethod called off main thread"); if (!IsValid()) return NS_ERROR_UNEXPECTED; diff --git a/xpcom/base/CycleCollectedJSRuntime.cpp b/xpcom/base/CycleCollectedJSRuntime.cpp index ce33b5c6a619..f3394bd32706 100644 --- a/xpcom/base/CycleCollectedJSRuntime.cpp +++ b/xpcom/base/CycleCollectedJSRuntime.cpp @@ -505,7 +505,7 @@ CycleCollectedJSRuntime::Initialize(JSRuntime* aParentRuntime, } if (!JS_AddExtraGCRootsTracer(mJSRuntime, TraceBlackJS, this)) { - MOZ_CRASH(); + MOZ_CRASH("JS_AddExtraGCRootsTracer failed"); } JS_SetGrayGCRootsTracer(mJSRuntime, TraceGrayJS, this); JS_SetGCCallback(mJSRuntime, GCCallback, this); diff --git a/xpcom/base/nsDebugImpl.cpp b/xpcom/base/nsDebugImpl.cpp index a2b39f2fcffa..1fead566e260 100644 --- a/xpcom/base/nsDebugImpl.cpp +++ b/xpcom/base/nsDebugImpl.cpp @@ -601,5 +601,5 @@ NS_ABORT_OOM(size_t aSize) #if defined(MOZ_CRASHREPORTER) CrashReporter::AnnotateOOMAllocationSize(aSize); #endif - MOZ_CRASH(); + MOZ_CRASH("OOM"); } From 4c22980cdc873a6da69c43cae25165fa9cc85196 Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Fri, 3 Jun 2016 17:22:08 -0700 Subject: [PATCH 71/76] Bug 1268559 - Wait to finish nested event loops before shutdown (r=bsmedberg) --- dom/ipc/ContentChild.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index d574872dd6d5..0ff686296ac5 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -3075,6 +3075,24 @@ ContentChild::ForceKillTimerCallback(nsITimer* aTimer, void* aClosure) bool ContentChild::RecvShutdown() { + // If we receive the shutdown message from within a nested event loop, we want + // to wait for that event loop to finish. Otherwise we could prematurely + // terminate an "unload" or "pagehide" event handler (which might be doing a + // sync XHR, for example). + nsCOMPtr thread; + nsresult rv = NS_GetMainThread(getter_AddRefs(thread)); + if (NS_SUCCEEDED(rv) && thread) { + RefPtr mainThread(thread.forget().downcast()); + if (mainThread->RecursionDepth() > 1) { + // We're in a nested event loop. Let's delay for an arbitrary period of + // time (100ms) in the hopes that the event loop will have finished by + // then. + MessageLoop::current()->PostDelayedTask( + NewRunnableMethod(this, &ContentChild::RecvShutdown), 100); + return true; + } + } + if (mPolicy) { mPolicy->Deactivate(); mPolicy = nullptr; From cadf9d8f777d10912f737f03aa31ec95625d991c Mon Sep 17 00:00:00 2001 From: Makoto Kato Date: Fri, 3 Jun 2016 18:56:04 +0900 Subject: [PATCH 72/76] Bug 1257731 - Part 1. Send HaveBidiKeyboards information to content process. r=masayuki MozReview-Commit-ID: 87J4hE79e3n --HG-- extra : rebase_source : fbfb473ebfd28a0f19b81b8030a0dfe60bc310a9 extra : histedit_source : e8b2ab1c0da578be8170ed5380d43cb4503ab299 --- dom/ipc/ContentChild.cpp | 12 +++++++----- dom/ipc/ContentChild.h | 3 ++- dom/ipc/ContentParent.cpp | 3 +++ dom/ipc/ContentParent.h | 1 + dom/ipc/PContent.ipdl | 5 +++-- widget/PuppetBidiKeyboard.cpp | 8 +++++--- widget/PuppetBidiKeyboard.h | 3 ++- widget/WidgetUtils.cpp | 4 +++- 8 files changed, 26 insertions(+), 13 deletions(-) diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 0ff686296ac5..94e8816f08aa 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -1037,18 +1037,19 @@ ContentChild::InitXPCOM() if (NS_FAILED(svc->RegisterListener(mConsoleListener))) NS_WARNING("Couldn't register console listener for child process"); - bool isOffline, isLangRTL; + bool isOffline, isLangRTL, haveBidiKeyboards; bool isConnected; ClipboardCapabilities clipboardCaps; DomainPolicyClone domainPolicy; StructuredCloneData initialData; SendGetXPCOMProcessAttributes(&isOffline, &isConnected, - &isLangRTL, &mAvailableDictionaries, + &isLangRTL, &haveBidiKeyboards, + &mAvailableDictionaries, &clipboardCaps, &domainPolicy, &initialData); RecvSetOffline(isOffline); RecvSetConnectivity(isConnected); - RecvBidiKeyboardNotify(isLangRTL); + RecvBidiKeyboardNotify(isLangRTL, haveBidiKeyboards); // Create the CPOW manager as soon as possible. SendPJavaScriptConstructor(); @@ -1511,13 +1512,14 @@ ContentChild::RecvSpeakerManagerNotify() } bool -ContentChild::RecvBidiKeyboardNotify(const bool& aIsLangRTL) +ContentChild::RecvBidiKeyboardNotify(const bool& aIsLangRTL, + const bool& aHaveBidiKeyboards) { // bidi is always of type PuppetBidiKeyboard* (because in the child, the only // possible implementation of nsIBidiKeyboard is PuppetBidiKeyboard). PuppetBidiKeyboard* bidi = static_cast(nsContentUtils::GetBidiKeyboard()); if (bidi) { - bidi->SetIsLangRTL(aIsLangRTL); + bidi->SetBidiKeyboardInfo(aIsLangRTL, aHaveBidiKeyboards); } return true; } diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 3ca080d45596..e785a16937b3 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -401,7 +401,8 @@ public: virtual bool RecvSpeakerManagerNotify() override; - virtual bool RecvBidiKeyboardNotify(const bool& isLangRTL) override; + virtual bool RecvBidiKeyboardNotify(const bool& isLangRTL, + const bool& haveBidiKeyboards) override; virtual bool RecvNotifyVisited(const URIParams& aURI) override; diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index f120fc633305..8efbdd91d8e7 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -3388,6 +3388,7 @@ bool ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline, bool* aIsConnected, bool* aIsLangRTL, + bool* aHaveBidiKeyboards, InfallibleTArray* dictionaries, ClipboardCapabilities* clipboardCaps, DomainPolicyClone* domainPolicy, @@ -3404,8 +3405,10 @@ ContentParent::RecvGetXPCOMProcessAttributes(bool* aIsOffline, nsIBidiKeyboard* bidi = nsContentUtils::GetBidiKeyboard(); *aIsLangRTL = false; + *aHaveBidiKeyboards = false; if (bidi) { bidi->IsLangRTL(aIsLangRTL); + bidi->GetHaveBidiKeyboards(aHaveBidiKeyboards); } nsCOMPtr spellChecker(do_GetService(NS_SPELLCHECKER_CONTRACTID)); diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 140e11404077..a36e62446ed8 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -707,6 +707,7 @@ private: RecvGetXPCOMProcessAttributes(bool* aIsOffline, bool* aIsConnected, bool* aIsLangRTL, + bool* aHaveBidiKeyboards, InfallibleTArray* dictionaries, ClipboardCapabilities* clipboardCaps, DomainPolicyClone* domainPolicy, diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 073f17208ebc..99cfd0902060 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -494,7 +494,7 @@ child: * Communication between the PuppetBidiKeyboard and the actual * BidiKeyboard hosted by the parent */ - async BidiKeyboardNotify(bool isLangRTL); + async BidiKeyboardNotify(bool isLangRTL, bool haveBidiKeyboards); /** * Dump this process's GC and CC logs to the provided files. @@ -702,7 +702,8 @@ parent: sync GetProcessAttributes() returns (ContentParentId cpId, bool isForApp, bool isForBrowser); sync GetXPCOMProcessAttributes() - returns (bool isOffline, bool isConnected, bool isLangRTL, nsString[] dictionaries, + returns (bool isOffline, bool isConnected, bool isLangRTL, + bool haveBidiKeyboards, nsString[] dictionaries, ClipboardCapabilities clipboardCaps, DomainPolicyClone domainPolicy, StructuredCloneData initialData); diff --git a/widget/PuppetBidiKeyboard.cpp b/widget/PuppetBidiKeyboard.cpp index 54d7c9397286..94d371631aa5 100644 --- a/widget/PuppetBidiKeyboard.cpp +++ b/widget/PuppetBidiKeyboard.cpp @@ -33,14 +33,16 @@ PuppetBidiKeyboard::IsLangRTL(bool* aIsRTL) } void -PuppetBidiKeyboard::SetIsLangRTL(bool aIsLangRTL) +PuppetBidiKeyboard::SetBidiKeyboardInfo(bool aIsLangRTL, + bool aHaveBidiKeyboards) { mIsLangRTL = aIsLangRTL; + mHaveBidiKeyboards = aHaveBidiKeyboards; } NS_IMETHODIMP PuppetBidiKeyboard::GetHaveBidiKeyboards(bool* aResult) { - // not implemented yet - return NS_ERROR_NOT_IMPLEMENTED; + *aResult = mHaveBidiKeyboards; + return NS_OK; } diff --git a/widget/PuppetBidiKeyboard.h b/widget/PuppetBidiKeyboard.h index 54c68582aa31..403b3248adf3 100644 --- a/widget/PuppetBidiKeyboard.h +++ b/widget/PuppetBidiKeyboard.h @@ -21,12 +21,13 @@ public: PuppetBidiKeyboard(); - void SetIsLangRTL(bool aIsLangRTL); + void SetBidiKeyboardInfo(bool aIsLangRTL, bool aHaveBidiKeyboards); private: ~PuppetBidiKeyboard(); bool mIsLangRTL; + bool mHaveBidiKeyboards; }; } // namespace widget diff --git a/widget/WidgetUtils.cpp b/widget/WidgetUtils.cpp index c174548f6897..bc0c0bbc99da 100644 --- a/widget/WidgetUtils.cpp +++ b/widget/WidgetUtils.cpp @@ -127,11 +127,13 @@ WidgetUtils::SendBidiKeyboardInfoToContent() if (NS_FAILED(bidiKeyboard->IsLangRTL(&rtl))) { return; } + bool bidiKeyboards = false; + bidiKeyboard->GetHaveBidiKeyboards(&bidiKeyboards); nsTArray children; dom::ContentParent::GetAll(children); for (uint32_t i = 0; i < children.Length(); i++) { - Unused << children[i]->SendBidiKeyboardNotify(rtl); + Unused << children[i]->SendBidiKeyboardNotify(rtl, bidiKeyboards); } } From 4616a049e9cafe518ae915f1ceef6c9f65ae9952 Mon Sep 17 00:00:00 2001 From: Makoto Kato Date: Wed, 8 Jun 2016 13:23:11 +0900 Subject: [PATCH 73/76] Bug 1257731 - Part 2. Don't use Win32 API on content process. r=masayuki On content sandbox process, GetKeyboardState() API doesn't return current keyboard state. So we shouldn't use it. MozReview-Commit-ID: 4phnJf0sJFZ --HG-- extra : rebase_source : ea52839d427431a2ba7624ef199f9842fe12f8ef extra : histedit_source : f7905715eb4e09a0234b9f7717cec6161150a7f3 --- editor/libeditor/TypeInState.h | 5 +++ editor/libeditor/nsEditorEventListener.cpp | 48 +++++++--------------- editor/libeditor/nsHTMLEditRules.cpp | 5 +++ 3 files changed, 24 insertions(+), 34 deletions(-) diff --git a/editor/libeditor/TypeInState.h b/editor/libeditor/TypeInState.h index 77466289a9be..51316adac707 100644 --- a/editor/libeditor/TypeInState.h +++ b/editor/libeditor/TypeInState.h @@ -14,6 +14,11 @@ #include "nsTArray.h" #include "nscore.h" +// Workaround for windows headers +#ifdef SetProp +#undef SetProp +#endif + class nsIAtom; class nsIDOMNode; namespace mozilla { diff --git a/editor/libeditor/nsEditorEventListener.cpp b/editor/libeditor/nsEditorEventListener.cpp index e932e6097be8..8c22040cd411 100644 --- a/editor/libeditor/nsEditorEventListener.cpp +++ b/editor/libeditor/nsEditorEventListener.cpp @@ -498,25 +498,11 @@ nsEditorEventListener::HandleEvent(nsIDOMEvent* aEvent) } #ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH -#include -// Undo the windows.h damage -#undef GetMessage -#undef CreateEvent -#undef GetClassName -#undef GetBinaryType -#undef RemoveDirectory -#undef SetProp - namespace { // This function is borrowed from Chromium's ImeInput::IsCtrlShiftPressed -bool IsCtrlShiftPressed(bool& isRTL) +bool IsCtrlShiftPressed(nsIDOMKeyEvent* aEvent, bool& isRTL) { - BYTE keystate[256]; - if (!::GetKeyboardState(keystate)) { - return false; - } - // To check if a user is pressing only a control key and a right-shift key // (or a left-shift key), we use the steps below: // 1. Check if a user is pressing a control key and a right-shift key (or @@ -525,16 +511,19 @@ bool IsCtrlShiftPressed(bool& isRTL) // keys pressed at the same time. // To ignore the keys checked in 1, we set their status to 0 before // checking the key status. - const int kKeyDownMask = 0x80; - if ((keystate[VK_CONTROL] & kKeyDownMask) == 0) { + WidgetKeyboardEvent* keyboardEvent = + aEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent(); + MOZ_ASSERT(keyboardEvent, + "DOM key event's internal event must be WidgetKeyboardEvent"); + + if (!keyboardEvent->IsControl()) { return false; } - if (keystate[VK_RSHIFT] & kKeyDownMask) { - keystate[VK_RSHIFT] = 0; + uint32_t location = keyboardEvent->mLocation; + if (location == nsIDOMKeyEvent::DOM_KEY_LOCATION_RIGHT) { isRTL = true; - } else if (keystate[VK_LSHIFT] & kKeyDownMask) { - keystate[VK_LSHIFT] = 0; + } else if (location == nsIDOMKeyEvent::DOM_KEY_LOCATION_LEFT) { isRTL = false; } else { return false; @@ -542,19 +531,10 @@ bool IsCtrlShiftPressed(bool& isRTL) // Scan the key status to find pressed keys. We should abandon changing the // text direction when there are other pressed keys. - // This code is executed only when a user is pressing a control key and a - // right-shift key (or a left-shift key), i.e. we should ignore the status of - // the keys: VK_SHIFT, VK_CONTROL, VK_RCONTROL, and VK_LCONTROL. - // So, we reset their status to 0 and ignore them. - keystate[VK_SHIFT] = 0; - keystate[VK_CONTROL] = 0; - keystate[VK_RCONTROL] = 0; - keystate[VK_LCONTROL] = 0; - for (int i = 0; i <= VK_PACKET; ++i) { - if (keystate[i] & kKeyDownMask) { - return false; - } + if (keyboardEvent->IsAlt() || keyboardEvent->IsOS()) { + return false; } + return true; } @@ -598,7 +578,7 @@ nsEditorEventListener::KeyDown(nsIDOMKeyEvent* aKeyEvent) aKeyEvent->GetKeyCode(&keyCode); if (keyCode == nsIDOMKeyEvent::DOM_VK_SHIFT) { bool switchToRTL; - if (IsCtrlShiftPressed(switchToRTL)) { + if (IsCtrlShiftPressed(aKeyEvent, switchToRTL)) { mShouldSwitchTextDirection = true; mSwitchToRTL = switchToRTL; } diff --git a/editor/libeditor/nsHTMLEditRules.cpp b/editor/libeditor/nsHTMLEditRules.cpp index b5d50d30e1a8..77b7a5886c01 100644 --- a/editor/libeditor/nsHTMLEditRules.cpp +++ b/editor/libeditor/nsHTMLEditRules.cpp @@ -54,6 +54,11 @@ #include "nsWSRunObject.h" #include +// Workaround for windows headers +#ifdef SetProp +#undef SetProp +#endif + class nsISupports; class nsRulesInfo; From 12bac0f7570cb87884e34c7232f126135e04d48a Mon Sep 17 00:00:00 2001 From: Andi-Bogdan Postelnicu Date: Thu, 9 Jun 2016 09:32:11 +0300 Subject: [PATCH 74/76] Bug 525063 - add attribute to mark member variables that should be skipped by clang plugin initialization checker. r=nfroyd MozReview-Commit-ID: 4V1YcK2thiF --- mfbt/Attributes.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mfbt/Attributes.h b/mfbt/Attributes.h index 43a9f674bf08..58a5a92f76d2 100644 --- a/mfbt/Attributes.h +++ b/mfbt/Attributes.h @@ -527,6 +527,12 @@ * declarations where an instance of the template should be considered, for * static analysis purposes, to inherit any type annotations (such as * MOZ_MUST_USE_TYPE and MOZ_STACK_CLASS) from its template arguments. + * MOZ_IGNORE_INITIALIZATION: Applies to class member declarations. Occasionally + * there are class members that are not initialized in the constructor, but logic + * elsewhere in the class ensures they are initialized prior to use. Using this + * attribute on a member disables the check that this member must be initialized + * in constructors via list-initialization, in the constructor body, or via functions + * called from the constructor body. * MOZ_NON_AUTOABLE: Applies to class declarations. Makes it a compile time error to * use `auto` in place of this type in variable declarations. This is intended to * be used with types which are intended to be implicitly constructed into other @@ -560,6 +566,8 @@ # define MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS \ __attribute__((annotate("moz_inherit_type_annotations_from_template_args"))) # define MOZ_NON_AUTOABLE __attribute__((annotate("moz_non_autoable"))) +# define MOZ_INITIALIZED_OUTSIDE_CONSTRUCTOR \ + __attribute__((annotate("moz_ignore_ctor_initialization"))) /* * It turns out that clang doesn't like void func() __attribute__ {} without a * warning, so use pragmas to disable the warning. This code won't work on GCC @@ -591,6 +599,7 @@ # define MOZ_NEEDS_MEMMOVABLE_TYPE /* nothing */ # define MOZ_NEEDS_MEMMOVABLE_MEMBERS /* nothing */ # define MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS /* nothing */ +# define MOZ_INITIALIZED_OUTSIDE_CONSTRUCTOR /* nothing */ # define MOZ_NON_AUTOABLE /* nothing */ #endif /* MOZ_CLANG_PLUGIN */ From dda722b328dd696ad53b147fec7833f9c678f5c8 Mon Sep 17 00:00:00 2001 From: "Nils Ohlmeier [:drno]" Date: Wed, 8 Jun 2016 11:44:46 -0700 Subject: [PATCH 75/76] Bug 1279004: do RTCP decryption after filtering. r=jesup MozReview-Commit-ID: 2VIgy6czdNp --HG-- extra : rebase_source : 2e92f947bc802fc87db3c3f990aa86623f19ac61 --- .../src/mediapipeline/MediaPipeline.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp index aebd1011f07b..5298ac0dbacb 100644 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp @@ -994,6 +994,16 @@ void MediaPipeline::RtcpPacketReceived(TransportLayer *layer, return; } + // We do not filter RTCP for send pipelines, since the webrtc.org code for + // senders already has logic to ignore RRs that do not apply. + // TODO bug 1279153: remove SR check for reduced size RTCP + if (filter_ && direction_ == RECEIVE) { + if (!filter_->FilterSenderReport(data, len)) { + MOZ_MTLOG(ML_NOTICE, "Dropping incoming RTCP packet; filtered out"); + return; + } + } + // Make a copy rather than cast away constness auto inner_data = MakeUnique(len); memcpy(inner_data.get(), data, len); @@ -1007,15 +1017,6 @@ void MediaPipeline::RtcpPacketReceived(TransportLayer *layer, if (!NS_SUCCEEDED(res)) return; - // We do not filter RTCP for send pipelines, since the webrtc.org code for - // senders already has logic to ignore RRs that do not apply. - if (filter_ && direction_ == RECEIVE) { - if (!filter_->FilterSenderReport(inner_data.get(), out_len)) { - MOZ_MTLOG(ML_NOTICE, "Dropping rtcp packet"); - return; - } - } - MOZ_MTLOG(ML_DEBUG, description_ << " received RTCP packet."); increment_rtcp_packets_received(); From ffd9e007e61a0833a86d3166bb11510b24467468 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Thu, 9 Jun 2016 08:54:34 +0200 Subject: [PATCH 76/76] Backed out changeset 1b8e6e22a983 (bug 1275694) for test failures in checkerboard-3.html --- gfx/layers/Layers.cpp | 9 ++++++--- gfx/layers/Layers.h | 4 ---- gfx/layers/composite/ContainerLayerComposite.cpp | 11 ----------- gfx/layers/composite/ContainerLayerComposite.h | 4 ---- 4 files changed, 6 insertions(+), 22 deletions(-) diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index 49594442249e..969a89a10fe5 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -804,12 +804,15 @@ Layer::CalculateScissorRect(const RenderTargetIntRect& aCurrentScissorRect) return currentClip; } - if (GetLocalVisibleRegion().IsEmpty() && !NeedToDrawCheckerboarding()) { + if (GetVisibleRegion().IsEmpty()) { // When our visible region is empty, our parent may not have created the // intermediate surface that we would require for correct clipping; however, // this does not matter since we are invisible. - // Make sure we still compute a clip rect if we want to draw checkboarding - // for this layer, since we want to do this even if the layer is invisible. + // Note that we do not use GetLocalVisibleRegion(), because that can be + // empty for a layer whose rendered contents have been async-scrolled + // completely offscreen, but for which we still need to draw a + // checkerboarding backround color, and calculating an empty scissor rect + // for such a layer would prevent that (see bug 1247452 comment 10). return RenderTargetIntRect(currentClip.TopLeft(), RenderTargetIntSize(0, 0)); } diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index c2e6653b1f91..c20a09956d8b 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -1556,10 +1556,6 @@ public: return !GetLocalVisibleRegion().IsEmpty() || Extend3DContext(); } - virtual bool NeedToDrawCheckerboarding(gfx::Color* aOutCheckerboardingColor = nullptr) { - return false; - } - /** * Return true if current layer content is opaque. * It does not guarantee that layer content is always opaque. diff --git a/gfx/layers/composite/ContainerLayerComposite.cpp b/gfx/layers/composite/ContainerLayerComposite.cpp index 6f819c746ad8..e0d75753e910 100755 --- a/gfx/layers/composite/ContainerLayerComposite.cpp +++ b/gfx/layers/composite/ContainerLayerComposite.cpp @@ -905,12 +905,6 @@ ContainerLayerComposite::Prepare(const RenderTargetIntRect& aClipRect) ContainerPrepare(this, mCompositeManager, aClipRect); } -bool -ContainerLayerComposite::NeedToDrawCheckerboarding(Color* aOutCheckerboardingColor) -{ - return NeedToDrawCheckerboardingForLayer(this, aOutCheckerboardingColor); -} - void ContainerLayerComposite::CleanupResources() { @@ -962,11 +956,6 @@ RefLayerComposite::Prepare(const RenderTargetIntRect& aClipRect) ContainerPrepare(this, mCompositeManager, aClipRect); } -bool -RefLayerComposite::NeedToDrawCheckerboarding(Color* aOutCheckerboardingColor) -{ - return NeedToDrawCheckerboardingForLayer(this, aOutCheckerboardingColor); -} void RefLayerComposite::CleanupResources() diff --git a/gfx/layers/composite/ContainerLayerComposite.h b/gfx/layers/composite/ContainerLayerComposite.h index 03df1f4b2c00..ec1e01cfd131 100644 --- a/gfx/layers/composite/ContainerLayerComposite.h +++ b/gfx/layers/composite/ContainerLayerComposite.h @@ -88,8 +88,6 @@ public: DefaultComputeEffectiveTransforms(aTransformToSurface); } - virtual bool NeedToDrawCheckerboarding(gfx::Color* aOutCheckerboardingColor = nullptr) override; - virtual void CleanupResources() override; virtual LayerComposite* AsLayerComposite() override { return this; } @@ -175,8 +173,6 @@ public: DefaultComputeEffectiveTransforms(aTransformToSurface); } - virtual bool NeedToDrawCheckerboarding(gfx::Color* aOutCheckerboardingColor = nullptr) override; - virtual void CleanupResources() override; virtual LayerComposite* AsLayerComposite() override { return this; }