From f2da3665257e768abd10b112bcc93b07e1adf7e7 Mon Sep 17 00:00:00 2001 From: Heiher Date: Mon, 21 Sep 2015 21:48:53 +0800 Subject: [PATCH 001/133] Bug 1205917 - IonMonkey: MIPS32: Use rshiftPtrArithmetic in clampIntToUint8. r=arai --- js/src/jit/mips32/MacroAssembler-mips32.cpp | 25 +++++++++++++++++++++++++ js/src/jit/mips32/MacroAssembler-mips32.h | 23 +---------------------- 2 files changed, 26 insertions(+), 22 deletions(-) --- js/src/jit/mips32/MacroAssembler-mips32.cpp | 25 +++++++++++++++++++++ js/src/jit/mips32/MacroAssembler-mips32.h | 23 +------------------ 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/js/src/jit/mips32/MacroAssembler-mips32.cpp b/js/src/jit/mips32/MacroAssembler-mips32.cpp index 976aa7db86e4..a084e42bea4a 100644 --- a/js/src/jit/mips32/MacroAssembler-mips32.cpp +++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp @@ -1921,6 +1921,31 @@ MacroAssemblerMIPSCompat::storePtr(Register src, AbsoluteAddress dest) storePtr(src, Address(ScratchRegister, 0)); } +void +MacroAssemblerMIPSCompat::clampIntToUint8(Register reg) +{ + // look at (reg >> 8) if it is 0, then src shouldn't be clamped + // if it is <0, then we want to clamp to 0, + // otherwise, we wish to clamp to 255 + Label done; + ma_move(ScratchRegister, reg); + asMasm().rshiftPtrArithmetic(Imm32(8), ScratchRegister); + ma_b(ScratchRegister, ScratchRegister, &done, Assembler::Zero, ShortJump); + { + Label negative; + ma_b(ScratchRegister, ScratchRegister, &negative, Assembler::Signed, ShortJump); + { + ma_li(reg, Imm32(255)); + ma_b(&done, ShortJump); + } + bind(&negative); + { + ma_move(reg, zero); + } + } + bind(&done); +} + // Note: this function clobbers the input register. void MacroAssembler::clampDoubleToUint8(FloatRegister input, Register output) diff --git a/js/src/jit/mips32/MacroAssembler-mips32.h b/js/src/jit/mips32/MacroAssembler-mips32.h index 05143518634d..bcb1073e3b68 100644 --- a/js/src/jit/mips32/MacroAssembler-mips32.h +++ b/js/src/jit/mips32/MacroAssembler-mips32.h @@ -1287,28 +1287,7 @@ class MacroAssemblerMIPSCompat : public MacroAssemblerMIPS moveToDoubleHi(zero, reg); } - void clampIntToUint8(Register reg) { - // look at (reg >> 8) if it is 0, then src shouldn't be clamped - // if it is <0, then we want to clamp to 0, - // otherwise, we wish to clamp to 255 - Label done; - ma_move(ScratchRegister, reg); - as_sra(ScratchRegister, ScratchRegister, 8); - ma_b(ScratchRegister, ScratchRegister, &done, Assembler::Zero, ShortJump); - { - Label negative; - ma_b(ScratchRegister, ScratchRegister, &negative, Assembler::Signed, ShortJump); - { - ma_li(reg, Imm32(255)); - ma_b(&done, ShortJump); - } - bind(&negative); - { - ma_move(reg, zero); - } - } - bind(&done); - } + void clampIntToUint8(Register reg); void subPtr(Imm32 imm, const Register dest); void subPtr(const Address& addr, const Register dest); From c22dac30b840f2ea8872190d7697a9b042cfcc58 Mon Sep 17 00:00:00 2001 From: JW Wang Date: Mon, 21 Sep 2015 13:48:39 +0800 Subject: [PATCH 002/133] Bug 1204430. Part 1 - dispatch AbstractMediaDecoder::SetMediaSeekable() to the main thread. r=kinetik. --- dom/media/AbstractMediaDecoder.h | 7 +++++++ dom/media/MediaDecoder.cpp | 1 + dom/media/MediaDecoderStateMachine.cpp | 2 +- dom/media/ogg/OggReader.cpp | 5 +---- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/dom/media/AbstractMediaDecoder.h b/dom/media/AbstractMediaDecoder.h index 230056fc48c0..a2f9b0118205 100644 --- a/dom/media/AbstractMediaDecoder.h +++ b/dom/media/AbstractMediaDecoder.h @@ -93,6 +93,13 @@ public: // Set the media as being seekable or not. virtual void SetMediaSeekable(bool aMediaSeekable) = 0; + void DispatchSetMediaSeekable(bool aMediaSeekable) + { + nsCOMPtr r = NS_NewRunnableMethodWithArg( + this, &AbstractMediaDecoder::SetMediaSeekable, aMediaSeekable); + NS_DispatchToMainThread(r); + } + virtual VideoFrameContainer* GetVideoFrameContainer() = 0; virtual mozilla::layers::ImageContainer* GetImageContainer() = 0; diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp index 69fbf1d80609..3510228e3734 100644 --- a/dom/media/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -1110,6 +1110,7 @@ void MediaDecoder::UpdateEstimatedMediaDuration(int64_t aDuration) } void MediaDecoder::SetMediaSeekable(bool aMediaSeekable) { + MOZ_ASSERT(NS_IsMainThread()); ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); mMediaSeekable = aMediaSeekable; } diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index 6f74403f4855..eb402c7ffa7d 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -1932,7 +1932,7 @@ MediaDecoderStateMachine::OnMetadataRead(MetadataHolder* aMetadata) // Set mode to PLAYBACK after reading metadata. mResource->SetReadMode(MediaCacheStream::MODE_PLAYBACK); - mDecoder->SetMediaSeekable(mReader->IsMediaSeekable()); + mDecoder->DispatchSetMediaSeekable(mReader->IsMediaSeekable()); mInfo = aMetadata->mInfo; mMetadataTags = aMetadata->mTags.forget(); nsRefPtr self = this; diff --git a/dom/media/ogg/OggReader.cpp b/dom/media/ogg/OggReader.cpp index 64ee37186131..61b908ed55d8 100644 --- a/dom/media/ogg/OggReader.cpp +++ b/dom/media/ogg/OggReader.cpp @@ -720,10 +720,7 @@ void OggReader::SetChained(bool aIsChained) { ReentrantMonitorAutoEnter mon(mMonitor); mIsChained = aIsChained; } - { - ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); - mDecoder->SetMediaSeekable(false); - } + mDecoder->DispatchSetMediaSeekable(false); } bool OggReader::ReadOggChain() From 9fd579e930fb402f38521c4cd7ca275eaeb6ca77 Mon Sep 17 00:00:00 2001 From: JW Wang Date: Mon, 21 Sep 2015 13:49:01 +0800 Subject: [PATCH 003/133] Bug 1204430. Part 2 - mirror MediaDecoder::mMediaSeekable. r=kinetik. --- dom/media/MediaDecoder.cpp | 7 ++++--- dom/media/MediaDecoder.h | 9 ++++++--- dom/media/MediaDecoderStateMachine.cpp | 8 ++++++-- dom/media/MediaDecoderStateMachine.h | 3 +++ 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp index 3510228e3734..9b2b31652cf9 100644 --- a/dom/media/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -351,7 +351,6 @@ MediaDecoder::MediaDecoder() : mDormantSupported(false), mLogicalPosition(0.0), mDuration(std::numeric_limits::quiet_NaN()), - mMediaSeekable(true), mReentrantMonitor("media.decoder"), mIgnoreProgressData(false), mInfiniteStream(false), @@ -407,7 +406,9 @@ MediaDecoder::MediaDecoder() : mPlaybackRateReliable(AbstractThread::MainThread(), true, "MediaDecoder::mPlaybackRateReliable (Canonical)"), mDecoderPosition(AbstractThread::MainThread(), 0, - "MediaDecoder::mDecoderPosition (Canonical)") + "MediaDecoder::mDecoderPosition (Canonical)"), + mMediaSeekable(AbstractThread::MainThread(), true, + "MediaDecoder::mMediaSeekable (Canonical)") { MOZ_COUNT_CTOR(MediaDecoder); MOZ_ASSERT(NS_IsMainThread()); @@ -1124,8 +1125,8 @@ MediaDecoder::IsTransportSeekable() bool MediaDecoder::IsMediaSeekable() { + MOZ_ASSERT(NS_IsMainThread()); NS_ENSURE_TRUE(GetStateMachine(), false); - ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); return mMediaSeekable; } diff --git a/dom/media/MediaDecoder.h b/dom/media/MediaDecoder.h index 7d5e23bb94f7..3ee120275004 100644 --- a/dom/media/MediaDecoder.h +++ b/dom/media/MediaDecoder.h @@ -801,9 +801,6 @@ protected: // Official duration of the media resource as observed by script. double mDuration; - // True if the media is seekable (i.e. supports random access). - bool mMediaSeekable; - /****** * The following member variables can be accessed from any thread. ******/ @@ -1001,6 +998,9 @@ protected: // back again. Canonical mDecoderPosition; + // True if the media is seekable (i.e. supports random access). + Canonical mMediaSeekable; + public: AbstractCanonical* CanonicalDurationOrNull() override; AbstractCanonical* CanonicalVolume() { @@ -1039,6 +1039,9 @@ public: AbstractCanonical* CanonicalDecoderPosition() { return &mDecoderPosition; } + AbstractCanonical* CanonicalMediaSeekable() { + return &mMediaSeekable; + } }; } // namespace mozilla diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index eb402c7ffa7d..b23034025c05 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -249,6 +249,8 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder, "MediaDecoderStateMachine::mPlaybackRateReliable (Mirror)"), mDecoderPosition(mTaskQueue, 0, "MediaDecoderStateMachine::mDecoderPosition (Mirror)"), + mMediaSeekable(mTaskQueue, true, + "MediaDecoderStateMachine::mMediaSeekable (Mirror)"), mDuration(mTaskQueue, NullableTimeUnit(), "MediaDecoderStateMachine::mDuration (Canonical"), mIsShutdown(mTaskQueue, false, @@ -334,6 +336,7 @@ MediaDecoderStateMachine::InitializationTask() mPlaybackBytesPerSecond.Connect(mDecoder->CanonicalPlaybackBytesPerSecond()); mPlaybackRateReliable.Connect(mDecoder->CanonicalPlaybackRateReliable()); mDecoderPosition.Connect(mDecoder->CanonicalDecoderPosition()); + mMediaSeekable.Connect(mDecoder->CanonicalMediaSeekable()); // Initialize watchers. mWatchManager.Watch(mBuffered, &MediaDecoderStateMachine::BufferedRangeUpdated); @@ -1483,7 +1486,7 @@ MediaDecoderStateMachine::Seek(SeekTarget aTarget) // We need to be able to seek both at a transport level and at a media level // to seek. - if (!mDecoder->IsMediaSeekable()) { + if (!mMediaSeekable) { DECODER_WARN("Seek() function should not be called on a non-seekable state machine"); return MediaDecoder::SeekPromise::CreateAndReject(/* aIgnored = */ true, __func__); } @@ -2067,7 +2070,7 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame() DECODER_LOG("Media duration %lld, " "transportSeekable=%d, mediaSeekable=%d", - Duration().ToMicroseconds(), mResource->IsTransportSeekable(), mDecoder->IsMediaSeekable()); + Duration().ToMicroseconds(), mResource->IsTransportSeekable(), mMediaSeekable.Ref()); if (HasAudio() && !HasVideo() && !mSentFirstFrameLoadedEvent) { // We're playing audio only. We don't need to worry about slow video @@ -2236,6 +2239,7 @@ MediaDecoderStateMachine::FinishShutdown() mPlaybackBytesPerSecond.DisconnectIfConnected(); mPlaybackRateReliable.DisconnectIfConnected(); mDecoderPosition.DisconnectIfConnected(); + mMediaSeekable.DisconnectIfConnected(); mDuration.DisconnectAll(); mIsShutdown.DisconnectAll(); diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h index 772af393487e..297fa29d876b 100644 --- a/dom/media/MediaDecoderStateMachine.h +++ b/dom/media/MediaDecoderStateMachine.h @@ -1299,6 +1299,9 @@ private: // Current decoding position in the stream. Mirror mDecoderPosition; + // True if the media is seekable (i.e. supports random access). + Mirror mMediaSeekable; + // Duration of the media. This is guaranteed to be non-null after we finish // decoding the first frame. Canonical mDuration; From 5d35a74e159db166c5db70de0515973beb50de87 Mon Sep 17 00:00:00 2001 From: JW Wang Date: Mon, 21 Sep 2015 14:01:45 +0800 Subject: [PATCH 004/133] Bug 1206576 - Dispatch some MDSM functions to hide its internal thread model. r=jya. --- dom/media/MediaDecoder.cpp | 26 +++++----------------- dom/media/MediaDecoderStateMachine.cpp | 29 +++++++++++++++++++++++-- dom/media/MediaDecoderStateMachine.h | 17 ++++++++++----- dom/media/omx/MediaOmxCommonDecoder.cpp | 21 +++--------------- 4 files changed, 46 insertions(+), 47 deletions(-) diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp index 9b2b31652cf9..b0c12111cebf 100644 --- a/dom/media/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -217,13 +217,7 @@ void MediaDecoder::UpdateDormantState(bool aDormantTimeout, bool aActivity) if (mIsDormant) { DECODER_LOG("UpdateDormantState() entering DORMANT state"); // enter dormant state - RefPtr event = - NS_NewRunnableMethodWithArg( - mDecoderStateMachine, - &MediaDecoderStateMachine::SetDormant, - true); - mDecoderStateMachine->OwnerThread()->Dispatch(event.forget()); - + mDecoderStateMachine->DispatchSetDormant(true); if (IsEnded()) { mWasEndedWhenEnteredDormant = true; } @@ -232,13 +226,7 @@ void MediaDecoder::UpdateDormantState(bool aDormantTimeout, bool aActivity) } else { DECODER_LOG("UpdateDormantState() leaving DORMANT state"); // exit dormant state - // trigger to state machine. - RefPtr event = - NS_NewRunnableMethodWithArg( - mDecoderStateMachine, - &MediaDecoderStateMachine::SetDormant, - false); - mDecoderStateMachine->OwnerThread()->Dispatch(event.forget()); + mDecoderStateMachine->DispatchSetDormant(false); } } @@ -618,9 +606,8 @@ void MediaDecoder::CallSeek(const SeekTarget& aTarget) { MOZ_ASSERT(NS_IsMainThread()); mSeekRequest.DisconnectIfExists(); - mSeekRequest.Begin(InvokeAsync(mDecoderStateMachine->OwnerThread(), - mDecoderStateMachine.get(), __func__, - &MediaDecoderStateMachine::Seek, aTarget) + mSeekRequest.Begin( + mDecoderStateMachine->InvokeSeek(aTarget) ->Then(AbstractThread::MainThread(), __func__, this, &MediaDecoder::OnSeekResolved, &MediaDecoder::OnSeekRejected)); } @@ -1311,10 +1298,7 @@ void MediaDecoder::NotifyWaitingForResourcesStatusChanged() { if (mDecoderStateMachine) { - RefPtr task = - NS_NewRunnableMethod(mDecoderStateMachine, - &MediaDecoderStateMachine::NotifyWaitingForResourcesStatusChanged); - mDecoderStateMachine->OwnerThread()->Dispatch(task.forget()); + mDecoderStateMachine->DispatchWaitingForResourcesStatusChanged(); } } diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index b23034025c05..c861ad59040c 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -1234,7 +1234,16 @@ void MediaDecoderStateMachine::RecomputeDuration() mDuration = Some(duration); } -void MediaDecoderStateMachine::SetDormant(bool aDormant) +void +MediaDecoderStateMachine::DispatchSetDormant(bool aDormant) +{ + nsCOMPtr r = NS_NewRunnableMethodWithArg( + this, &MediaDecoderStateMachine::SetDormant, aDormant); + OwnerThread()->Dispatch(r.forget()); +} + +void +MediaDecoderStateMachine::SetDormant(bool aDormant) { MOZ_ASSERT(OnTaskQueue()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); @@ -1382,7 +1391,16 @@ void MediaDecoderStateMachine::StartDecoding() ScheduleStateMachine(); } -void MediaDecoderStateMachine::NotifyWaitingForResourcesStatusChanged() +void +MediaDecoderStateMachine::DispatchWaitingForResourcesStatusChanged() +{ + nsCOMPtr r = NS_NewRunnableMethod( + this, &MediaDecoderStateMachine::NotifyWaitingForResourcesStatusChanged); + OwnerThread()->Dispatch(r.forget()); +} + +void +MediaDecoderStateMachine::NotifyWaitingForResourcesStatusChanged() { MOZ_ASSERT(OnTaskQueue()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); @@ -1512,6 +1530,13 @@ MediaDecoderStateMachine::Seek(SeekTarget aTarget) return mPendingSeek.mPromise.Ensure(__func__); } +nsRefPtr +MediaDecoderStateMachine::InvokeSeek(SeekTarget aTarget) +{ + return InvokeAsync(OwnerThread(), this, __func__, + &MediaDecoderStateMachine::Seek, aTarget); +} + void MediaDecoderStateMachine::StopMediaSink() { MOZ_ASSERT(OnTaskQueue()); diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h index 297fa29d876b..906450186b7d 100644 --- a/dom/media/MediaDecoderStateMachine.h +++ b/dom/media/MediaDecoderStateMachine.h @@ -156,7 +156,7 @@ public: void RemoveOutputStream(MediaStream* aStream); // Set/Unset dormant state. - void SetDormant(bool aDormant); + void DispatchSetDormant(bool aDormant); TimedMetadataEventSource& TimedMetadataEvent() { return mMetadataManager.TimedMetadataEvent(); @@ -168,11 +168,17 @@ private: // constructor immediately after the task queue is created. void InitializationTask(); + void SetDormant(bool aDormant); + void SetAudioCaptured(bool aCaptured); - void Shutdown(); -public: + void NotifyWaitingForResourcesStatusChanged(); + nsRefPtr Seek(SeekTarget aTarget); + + void Shutdown(); + +public: void DispatchShutdown(); void FinishShutdown(); @@ -186,8 +192,7 @@ public: bool OnTaskQueue() const; // Seeks to the decoder to aTarget asynchronously. - // Must be called on the state machine thread. - nsRefPtr Seek(SeekTarget aTarget); + nsRefPtr InvokeSeek(SeekTarget aTarget); // Clear the flag indicating that a playback position change event // is currently queued. This is called from the main thread and must @@ -341,7 +346,7 @@ public: // Called when the reader may have acquired the hardware resources required // to begin decoding. - void NotifyWaitingForResourcesStatusChanged(); + void DispatchWaitingForResourcesStatusChanged(); // Notifies the state machine that should minimize the number of samples // decoded we preroll, until playback starts. The first time playback starts diff --git a/dom/media/omx/MediaOmxCommonDecoder.cpp b/dom/media/omx/MediaOmxCommonDecoder.cpp index d67458372ff6..f0128d48ab5b 100644 --- a/dom/media/omx/MediaOmxCommonDecoder.cpp +++ b/dom/media/omx/MediaOmxCommonDecoder.cpp @@ -116,12 +116,7 @@ MediaOmxCommonDecoder::PauseStateMachine() return; } // enter dormant state - RefPtr event = - NS_NewRunnableMethodWithArg( - GetStateMachine(), - &MediaDecoderStateMachine::SetDormant, - true); - GetStateMachine()->OwnerThread()->Dispatch(event.forget()); + GetStateMachine()->DispatchSetDormant(true); } void @@ -145,22 +140,12 @@ MediaOmxCommonDecoder::ResumeStateMachine() SeekTarget::Accurate, MediaDecoderEventVisibility::Suppressed); // Call Seek of MediaDecoderStateMachine to suppress seek events. - RefPtr event = - NS_NewRunnableMethodWithArg( - GetStateMachine(), - &MediaDecoderStateMachine::Seek, - target); - GetStateMachine()->OwnerThread()->Dispatch(event.forget()); + GetStateMachine()->InvokeSeek(target); mNextState = mPlayState; ChangeState(PLAY_STATE_LOADING); // exit dormant state - event = - NS_NewRunnableMethodWithArg( - GetStateMachine(), - &MediaDecoderStateMachine::SetDormant, - false); - GetStateMachine()->OwnerThread()->Dispatch(event.forget()); + GetStateMachine()->DispatchSetDormant(false); UpdateLogicalPosition(); } From cba6cef20c69717a33c28b49f995731ebe077d55 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Mon, 31 Aug 2015 17:34:49 -0700 Subject: [PATCH 005/133] Bug 1200482: Make Debugger respect 'enabled' flag when setting allocation tracking hook on debuggee compartments, and check that it does. r=fitzgen --HG-- extra : rebase_source : cc98909c59452b5934e93f72dd930d4557386b2f extra : amend_source : aaa340168608d79713e68e77613b53bab3337e6f --- js/src/vm/Debugger.cpp | 6 +++--- js/src/vm/SavedStacks.cpp | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index bdbc92ebab77..f710c81f7bbc 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -2302,7 +2302,7 @@ Debugger::isObservedByDebuggerTrackingAllocations(const GlobalObject& debuggee) if (auto* v = debuggee.getDebuggers()) { Debugger** p; for (p = v->begin(); p != v->end(); p++) { - if ((*p)->trackingAllocationSites) { + if ((*p)->trackingAllocationSites && (*p)->enabled) { return true; } } @@ -3415,10 +3415,10 @@ Debugger::addDebuggeeGlobal(JSContext* cx, Handle global) }); // (5) - if (trackingAllocationSites && !Debugger::addAllocationsTracking(cx, *global)) + if (trackingAllocationSites && enabled && !Debugger::addAllocationsTracking(cx, *global)) return false; auto allocationsTrackingGuard = MakeScopeExit([&] { - if (trackingAllocationSites) + if (trackingAllocationSites && enabled) Debugger::removeAllocationsTracking(*global); }); diff --git a/js/src/vm/SavedStacks.cpp b/js/src/vm/SavedStacks.cpp index b68b139cca5d..502c9d0fbd84 100644 --- a/js/src/vm/SavedStacks.cpp +++ b/js/src/vm/SavedStacks.cpp @@ -1312,6 +1312,7 @@ SavedStacks::chooseSamplingProbability(JSContext* cx) return; mozilla::DebugOnly begin = dbgs->begin(); + mozilla::DebugOnly foundAnyDebuggers = false; allocationSamplingProbability = 0; for (Debugger** dbgp = dbgs->begin(); dbgp < dbgs->end(); dbgp++) { @@ -1320,10 +1321,12 @@ SavedStacks::chooseSamplingProbability(JSContext* cx) MOZ_ASSERT(dbgs->begin() == begin); if ((*dbgp)->trackingAllocationSites && (*dbgp)->enabled) { + foundAnyDebuggers = true; allocationSamplingProbability = std::max((*dbgp)->allocationSamplingProbability, allocationSamplingProbability); } } + MOZ_ASSERT(foundAnyDebuggers); } JSObject* From b6bc8043cf8c1ccd93778026f45215f9724c2176 Mon Sep 17 00:00:00 2001 From: Victor Carlquist Date: Thu, 17 Sep 2015 09:24:36 -0300 Subject: [PATCH 006/133] Bug 984018 - Fixed build on Arm64; r=nbp --- js/src/jit/arm64/vixl/MozSimulator-vixl.cpp | 2 ++ js/src/jit/shared/Lowering-shared-inl.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp b/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp index c78b5660450b..08389d2d1d8f 100644 --- a/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp +++ b/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp @@ -120,7 +120,9 @@ void Simulator::init(Decoder* decoder, FILE* stream) { lock_ = PR_NewLock(); if (!lock_) MOZ_CRASH("Could not allocate simulator lock."); +#ifdef DEBUG lockOwner_ = nullptr; +#endif redirection_ = nullptr; } diff --git a/js/src/jit/shared/Lowering-shared-inl.h b/js/src/jit/shared/Lowering-shared-inl.h index c151d17efa76..95e109da6ac4 100644 --- a/js/src/jit/shared/Lowering-shared-inl.h +++ b/js/src/jit/shared/Lowering-shared-inl.h @@ -185,7 +185,7 @@ LIRGeneratorShared::defineSinCos(LInstructionHelper<2, Ops, Temps> *lir, MDefini uint32_t vreg = getVirtualRegister(); lir->setDef(0, LDefinition(vreg, LDefinition::DOUBLE, LFloatReg(ReturnDoubleReg))); #if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) - lir->setDef(1, LDefinition(vreg + VREG_INCREMENT, LDefinition::DOUBLE, LFloatReg(d1))); + lir->setDef(1, LDefinition(vreg + VREG_INCREMENT, LDefinition::DOUBLE, LFloatReg(FloatRegisters::d1))); #elif defined(JS_CODEGEN_MIPS32) lir->setDef(1, LDefinition(vreg + VREG_INCREMENT, LDefinition::DOUBLE, LFloatReg(f2))); #elif defined(JS_CODEGEN_NONE) From cc9dd45d70f601e59f89f1e3ac074d99d80ddef9 Mon Sep 17 00:00:00 2001 From: Sean Lin Date: Mon, 21 Sep 2015 10:27:19 +0800 Subject: [PATCH 007/133] Bug 1205233 - Make Presentation API available for browser chrome code. r=smaug r=fabrice --- .../tests/mochitest/test_presentation_receiver.html | 1 - .../tests/mochitest/test_presentation_receiver_oop.html | 1 - .../test_presentation_receiver_start_session_error.html | 1 - .../test_presentation_receiver_start_session_timeout.html | 1 - dom/presentation/tests/mochitest/test_presentation_sender.html | 1 - .../mochitest/test_presentation_sender_default_request.html | 1 - .../tests/mochitest/test_presentation_sender_disconnect.html | 1 - .../test_presentation_sender_start_session_error.html | 1 - dom/webidl/Navigator.webidl | 2 +- dom/webidl/Presentation.webidl | 3 +-- dom/webidl/PresentationAvailability.webidl | 3 +-- dom/webidl/PresentationRequest.webidl | 3 +-- dom/webidl/PresentationSession.webidl | 3 +-- dom/webidl/PresentationSessionConnectEvent.webidl | 3 +-- 14 files changed, 6 insertions(+), 19 deletions(-) diff --git a/dom/presentation/tests/mochitest/test_presentation_receiver.html b/dom/presentation/tests/mochitest/test_presentation_receiver.html index 36b8ba974ca7..c19cf2ce4df1 100644 --- a/dom/presentation/tests/mochitest/test_presentation_receiver.html +++ b/dom/presentation/tests/mochitest/test_presentation_receiver.html @@ -133,7 +133,6 @@ SpecialPowers.pushPermissions([ {type: 'presentation', allow: true, context: document}, ], function() { SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true], - ["dom.ignore_webidl_scope_checks", true], ["dom.presentation.test.enabled", true], ["dom.presentation.test.stage", 0]]}, runTests); diff --git a/dom/presentation/tests/mochitest/test_presentation_receiver_oop.html b/dom/presentation/tests/mochitest/test_presentation_receiver_oop.html index 842c7579ec80..5aea51351cc6 100644 --- a/dom/presentation/tests/mochitest/test_presentation_receiver_oop.html +++ b/dom/presentation/tests/mochitest/test_presentation_receiver_oop.html @@ -171,7 +171,6 @@ SpecialPowers.pushPermissions([ {type: 'browser', allow: true, context: document}, ], function() { SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true], - ["dom.ignore_webidl_scope_checks", true], ["dom.presentation.test.enabled", true], ["dom.presentation.test.stage", 0], ["dom.mozBrowserFramesEnabled", true], diff --git a/dom/presentation/tests/mochitest/test_presentation_receiver_start_session_error.html b/dom/presentation/tests/mochitest/test_presentation_receiver_start_session_error.html index e192a0e14408..f4dcc48111ed 100644 --- a/dom/presentation/tests/mochitest/test_presentation_receiver_start_session_error.html +++ b/dom/presentation/tests/mochitest/test_presentation_receiver_start_session_error.html @@ -99,7 +99,6 @@ SpecialPowers.pushPermissions([ {type: 'presentation', allow: true, context: document}, ], function() { SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true], - ["dom.ignore_webidl_scope_checks", true], ["dom.presentation.test.enabled", true], ["dom.presentation.test.stage", 0]]}, runTests); diff --git a/dom/presentation/tests/mochitest/test_presentation_receiver_start_session_timeout.html b/dom/presentation/tests/mochitest/test_presentation_receiver_start_session_timeout.html index ae8a59721e35..f0a4b0433f9b 100644 --- a/dom/presentation/tests/mochitest/test_presentation_receiver_start_session_timeout.html +++ b/dom/presentation/tests/mochitest/test_presentation_receiver_start_session_timeout.html @@ -72,7 +72,6 @@ SpecialPowers.pushPermissions([ {type: 'presentation', allow: true, context: document}, ], function() { SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true], - ["dom.ignore_webidl_scope_checks", true], ["dom.presentation.test.enabled", true], ["dom.presentation.test.stage", 0], ["presentation.receiver.loading.timeout", 10]]}, diff --git a/dom/presentation/tests/mochitest/test_presentation_sender.html b/dom/presentation/tests/mochitest/test_presentation_sender.html index 9d24e6d6beb4..cd20395096c7 100644 --- a/dom/presentation/tests/mochitest/test_presentation_sender.html +++ b/dom/presentation/tests/mochitest/test_presentation_sender.html @@ -193,7 +193,6 @@ SpecialPowers.pushPermissions([ {type: 'presentation', allow: true, context: document}, ], function() { SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true], - ["dom.ignore_webidl_scope_checks", true], ["dom.presentation.test.enabled", true], ["dom.presentation.test.stage", 0]]}, runTests); diff --git a/dom/presentation/tests/mochitest/test_presentation_sender_default_request.html b/dom/presentation/tests/mochitest/test_presentation_sender_default_request.html index db11063d416a..a857b288ce6d 100644 --- a/dom/presentation/tests/mochitest/test_presentation_sender_default_request.html +++ b/dom/presentation/tests/mochitest/test_presentation_sender_default_request.html @@ -139,7 +139,6 @@ SpecialPowers.pushPermissions([ {type: 'presentation', allow: true, context: document}, ], function() { SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true], - ["dom.ignore_webidl_scope_checks", true], ["dom.presentation.test.enabled", true], ["dom.presentation.test.stage", 0]]}, runTests); diff --git a/dom/presentation/tests/mochitest/test_presentation_sender_disconnect.html b/dom/presentation/tests/mochitest/test_presentation_sender_disconnect.html index 8338d038223e..5f20bc9146ff 100644 --- a/dom/presentation/tests/mochitest/test_presentation_sender_disconnect.html +++ b/dom/presentation/tests/mochitest/test_presentation_sender_disconnect.html @@ -160,7 +160,6 @@ SpecialPowers.pushPermissions([ {type: 'presentation', allow: true, context: document}, ], function() { SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true], - ["dom.ignore_webidl_scope_checks", true], ["dom.presentation.test.enabled", true], ["dom.presentation.test.stage", 0]]}, runTests); diff --git a/dom/presentation/tests/mochitest/test_presentation_sender_start_session_error.html b/dom/presentation/tests/mochitest/test_presentation_sender_start_session_error.html index a17a4b63b097..178fa530b0f6 100644 --- a/dom/presentation/tests/mochitest/test_presentation_sender_start_session_error.html +++ b/dom/presentation/tests/mochitest/test_presentation_sender_start_session_error.html @@ -252,7 +252,6 @@ SpecialPowers.pushPermissions([ {type: 'presentation', allow: true, context: document}, ], function() { SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true], - ["dom.ignore_webidl_scope_checks", true], ["dom.presentation.test.enabled", true], ["dom.presentation.test.stage", 0]]}, runTests); diff --git a/dom/webidl/Navigator.webidl b/dom/webidl/Navigator.webidl index 3df098b8df05..d59f9bfd1341 100644 --- a/dom/webidl/Navigator.webidl +++ b/dom/webidl/Navigator.webidl @@ -432,7 +432,7 @@ partial interface Navigator { }; partial interface Navigator { - [Throws, Pref="dom.presentation.enabled", CheckAnyPermissions="presentation", AvailableIn="PrivilegedApps", SameObject] + [Throws, Pref="dom.presentation.enabled", CheckAnyPermissions="presentation", SameObject] readonly attribute Presentation? presentation; }; diff --git a/dom/webidl/Presentation.webidl b/dom/webidl/Presentation.webidl index c093a52e9ee0..38f2232d0964 100644 --- a/dom/webidl/Presentation.webidl +++ b/dom/webidl/Presentation.webidl @@ -5,8 +5,7 @@ */ [Pref="dom.presentation.enabled", - CheckAnyPermissions="presentation", - AvailableIn="PrivilegedApps"] + CheckAnyPermissions="presentation"] interface Presentation : EventTarget { /* * This should be used by the UA as the default presentation request for the diff --git a/dom/webidl/PresentationAvailability.webidl b/dom/webidl/PresentationAvailability.webidl index a02bfc0a7fe6..8765875ece95 100644 --- a/dom/webidl/PresentationAvailability.webidl +++ b/dom/webidl/PresentationAvailability.webidl @@ -5,8 +5,7 @@ */ [Pref="dom.presentation.enabled", - CheckAnyPermissions="presentation", - AvailableIn="PrivilegedApps"] + CheckAnyPermissions="presentation"] interface PresentationAvailability : EventTarget { /* * If there is at least one device discovered by UA, the value is |true|. diff --git a/dom/webidl/PresentationRequest.webidl b/dom/webidl/PresentationRequest.webidl index 180db154f0ce..79862c4130f9 100644 --- a/dom/webidl/PresentationRequest.webidl +++ b/dom/webidl/PresentationRequest.webidl @@ -6,8 +6,7 @@ [Constructor(DOMString url), Pref="dom.presentation.enabled", - CheckAnyPermissions="presentation", - AvailableIn="PrivilegedApps"] + CheckAnyPermissions="presentation"] interface PresentationRequest : EventTarget { /* * A requesting page use start() to start a new session, and the session will diff --git a/dom/webidl/PresentationSession.webidl b/dom/webidl/PresentationSession.webidl index 97d40dfce479..df1d3295bf6e 100644 --- a/dom/webidl/PresentationSession.webidl +++ b/dom/webidl/PresentationSession.webidl @@ -18,8 +18,7 @@ enum PresentationSessionState }; [Pref="dom.presentation.enabled", - CheckAnyPermissions="presentation", - AvailableIn="PrivilegedApps"] + CheckAnyPermissions="presentation"] interface PresentationSession : EventTarget { /* * Unique id for all existing sessions. diff --git a/dom/webidl/PresentationSessionConnectEvent.webidl b/dom/webidl/PresentationSessionConnectEvent.webidl index cc8fb518288e..9196b8921cab 100644 --- a/dom/webidl/PresentationSessionConnectEvent.webidl +++ b/dom/webidl/PresentationSessionConnectEvent.webidl @@ -7,8 +7,7 @@ [Constructor(DOMString type, optional PresentationSessionConnectEventInit eventInitDict), Pref="dom.presentation.enabled", - CheckAnyPermissions="presentation", - AvailableIn="PrivilegedApps"] + CheckAnyPermissions="presentation"] interface PresentationSessionConnectEvent : Event { [SameObject] From b4177a8a7586b62c8685c1c8459e0902d2231ee9 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Fri, 18 Sep 2015 09:16:00 +0200 Subject: [PATCH 008/133] Bug 1205424 - Use swap instead of NS_RELEASE in UnbindFromTree. r=baku --- dom/base/Element.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index a30463ba84b5..c46aa53c1d81 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -1744,9 +1744,8 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent) } if (GetParent()) { - nsINode* p = mParent; - mParent = nullptr; - NS_RELEASE(p); + nsRefPtr p; + p.swap(mParent); } else { mParent = nullptr; } From 0bd5f800f7301fbb4729dd80f4968e6282763c2c Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Mon, 21 Sep 2015 08:54:53 +0200 Subject: [PATCH 009/133] Backed out 1 changesets (bug 984018) for bustage Backed out changeset 7cbb158c2c9b (bug 984018) --- js/src/jit/arm64/vixl/MozSimulator-vixl.cpp | 2 -- js/src/jit/shared/Lowering-shared-inl.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp b/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp index 08389d2d1d8f..c78b5660450b 100644 --- a/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp +++ b/js/src/jit/arm64/vixl/MozSimulator-vixl.cpp @@ -120,9 +120,7 @@ void Simulator::init(Decoder* decoder, FILE* stream) { lock_ = PR_NewLock(); if (!lock_) MOZ_CRASH("Could not allocate simulator lock."); -#ifdef DEBUG lockOwner_ = nullptr; -#endif redirection_ = nullptr; } diff --git a/js/src/jit/shared/Lowering-shared-inl.h b/js/src/jit/shared/Lowering-shared-inl.h index 95e109da6ac4..c151d17efa76 100644 --- a/js/src/jit/shared/Lowering-shared-inl.h +++ b/js/src/jit/shared/Lowering-shared-inl.h @@ -185,7 +185,7 @@ LIRGeneratorShared::defineSinCos(LInstructionHelper<2, Ops, Temps> *lir, MDefini uint32_t vreg = getVirtualRegister(); lir->setDef(0, LDefinition(vreg, LDefinition::DOUBLE, LFloatReg(ReturnDoubleReg))); #if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) - lir->setDef(1, LDefinition(vreg + VREG_INCREMENT, LDefinition::DOUBLE, LFloatReg(FloatRegisters::d1))); + lir->setDef(1, LDefinition(vreg + VREG_INCREMENT, LDefinition::DOUBLE, LFloatReg(d1))); #elif defined(JS_CODEGEN_MIPS32) lir->setDef(1, LDefinition(vreg + VREG_INCREMENT, LDefinition::DOUBLE, LFloatReg(f2))); #elif defined(JS_CODEGEN_NONE) From 673f245950d9bc4ca54e32d9e1aabb3f9e1a481b Mon Sep 17 00:00:00 2001 From: John Dai Date: Wed, 16 Sep 2015 01:59:00 +0200 Subject: [PATCH 010/133] Bug 1204800 - Add tooltool dependencies to phone builds. r=wcosta --- b2g/config/aries/releng-aries.tt | 14 +++++++------- b2g/config/flame-kk/releng-flame-kk.tt | 14 +++++++------- b2g/config/flame/releng-flame.tt | 5 ----- .../taskcluster/scripts/phone-builder/pre-build.sh | 3 +++ .../tasks/builds/b2g_aries_spark_debug.yml | 1 + .../tasks/builds/b2g_aries_spark_eng.yml | 1 + .../tasks/builds/b2g_aries_spark_opt.yml | 1 + .../tasks/builds/b2g_flame_kk_debug.yml | 1 + .../taskcluster/tasks/builds/b2g_flame_kk_eng.yml | 1 + .../taskcluster/tasks/builds/b2g_flame_kk_opt.yml | 1 + .../tasks/builds/b2g_phone_eng_base.yml | 4 ++++ testing/taskcluster/tasks/phone_build.yml | 2 ++ 12 files changed, 29 insertions(+), 19 deletions(-) diff --git a/b2g/config/aries/releng-aries.tt b/b2g/config/aries/releng-aries.tt index 74b32b01f17b..55f67c82c1fe 100644 --- a/b2g/config/aries/releng-aries.tt +++ b/b2g/config/aries/releng-aries.tt @@ -1,16 +1,16 @@ [ { -"size": 135359412, -"digest": "45e677c9606cc4eec44ef4761df47ff431df1ffad17a5c6d21ce700a1c47f79e87a4aa9f30ae47ff060bd64f5b775d995780d88211f9a759ffa0d076beb4816b", -"algorithm": "sha512", -"filename": "backup-aries.tar.xz", -"comment": "v18D" -}, -{ "size": 80458572, "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", "algorithm": "sha512", "filename": "gcc.tar.xz", "unpack": "True" +}, +{ +"size": 12057960, +"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e", +"algorithm": "sha512", +"filename": "gtk3.tar.xz", +"unpack": true } ] diff --git a/b2g/config/flame-kk/releng-flame-kk.tt b/b2g/config/flame-kk/releng-flame-kk.tt index d0e0c584aa85..55f67c82c1fe 100644 --- a/b2g/config/flame-kk/releng-flame-kk.tt +++ b/b2g/config/flame-kk/releng-flame-kk.tt @@ -1,16 +1,16 @@ [ { -"size": 135359412, -"digest": "45e677c9606cc4eec44ef4761df47ff431df1ffad17a5c6d21ce700a1c47f79e87a4aa9f30ae47ff060bd64f5b775d995780d88211f9a759ffa0d076beb4816b", -"algorithm": "sha512", -"filename": "backup-flame.tar.xz", -"comment": "v18D" -}, -{ "size": 80458572, "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", "algorithm": "sha512", "filename": "gcc.tar.xz", "unpack": "True" +}, +{ +"size": 12057960, +"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e", +"algorithm": "sha512", +"filename": "gtk3.tar.xz", +"unpack": true } ] diff --git a/b2g/config/flame/releng-flame.tt b/b2g/config/flame/releng-flame.tt index 65f9871b6796..1af12208b9da 100644 --- a/b2g/config/flame/releng-flame.tt +++ b/b2g/config/flame/releng-flame.tt @@ -1,9 +1,4 @@ [ -{"size": 149922032, -"digest": "8d1a71552ffee561e93b5b3f1bb47866592ab958f908007c75561156430eb1b85a265bfc4dc2038e58dda0264daa9854877a84ef3b591c9ac2f1ab97c098e61e", -"filename": "backup-flame.tar.xz", -"algorithm": "sha512" -}, { "size": 80458572, "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", diff --git a/testing/taskcluster/scripts/phone-builder/pre-build.sh b/testing/taskcluster/scripts/phone-builder/pre-build.sh index 99f0718a87cb..47357131ef39 100755 --- a/testing/taskcluster/scripts/phone-builder/pre-build.sh +++ b/testing/taskcluster/scripts/phone-builder/pre-build.sh @@ -26,6 +26,9 @@ tc-vcs repo-checkout $WORKSPACE/B2G https://git.mozilla.org/b2g/B2G.git $MANIFES rm -f $WORKSPACE/B2G/gecko ln -s $WORKSPACE/gecko $WORKSPACE/B2G/gecko +### Install package dependencies +. ../builder/install-packages.sh $WORKSPACE/gecko + debug_flag="" if [ 0$B2G_DEBUG -ne 0 ]; then debug_flag='--debug' diff --git a/testing/taskcluster/tasks/builds/b2g_aries_spark_debug.yml b/testing/taskcluster/tasks/builds/b2g_aries_spark_debug.yml index 0c751a811aa1..b3e946cc5fc7 100644 --- a/testing/taskcluster/tasks/builds/b2g_aries_spark_debug.yml +++ b/testing/taskcluster/tasks/builds/b2g_aries_spark_debug.yml @@ -22,6 +22,7 @@ task: GAIA_OPTIMIZE: '1' B2G_SYSTEM_APPS: '1' MOZHARNESS_CONFIG: b2g/taskcluster-spark.py + TOOLTOOL_MANIFEST: 'b2g/config/aries/releng-aries.tt' command: - > checkout-gecko workspace && diff --git a/testing/taskcluster/tasks/builds/b2g_aries_spark_eng.yml b/testing/taskcluster/tasks/builds/b2g_aries_spark_eng.yml index 7c3e71fc05c4..f138a3475740 100644 --- a/testing/taskcluster/tasks/builds/b2g_aries_spark_eng.yml +++ b/testing/taskcluster/tasks/builds/b2g_aries_spark_eng.yml @@ -17,6 +17,7 @@ task: env: TARGET: 'aries' MOZHARNESS_CONFIG: b2g/taskcluster-spark.py + TOOLTOOL_MANIFEST: 'b2g/config/aries/releng-aries.tt' extra: treeherderEnv: - production diff --git a/testing/taskcluster/tasks/builds/b2g_aries_spark_opt.yml b/testing/taskcluster/tasks/builds/b2g_aries_spark_opt.yml index 9207c05a7e62..c2aa962fa5c5 100644 --- a/testing/taskcluster/tasks/builds/b2g_aries_spark_opt.yml +++ b/testing/taskcluster/tasks/builds/b2g_aries_spark_opt.yml @@ -22,6 +22,7 @@ task: GAIA_OPTIMIZE: '1' B2G_SYSTEM_APPS: '1' MOZHARNESS_CONFIG: b2g/taskcluster-spark.py + TOOLTOOL_MANIFEST: 'b2g/config/aries/releng-aries.tt' command: - > checkout-gecko workspace && diff --git a/testing/taskcluster/tasks/builds/b2g_flame_kk_debug.yml b/testing/taskcluster/tasks/builds/b2g_flame_kk_debug.yml index 42fc7744d197..61c9ce96308b 100644 --- a/testing/taskcluster/tasks/builds/b2g_flame_kk_debug.yml +++ b/testing/taskcluster/tasks/builds/b2g_flame_kk_debug.yml @@ -19,6 +19,7 @@ task: TARGET: 'flame-kk' DEBUG: 0 VARIANT: userdebug + TOOLTOOL_MANIFEST: 'b2g/config/flame-kk/releng-flame-kk.tt' command: - > checkout-gecko workspace && diff --git a/testing/taskcluster/tasks/builds/b2g_flame_kk_eng.yml b/testing/taskcluster/tasks/builds/b2g_flame_kk_eng.yml index 7d8f1cfe8cff..1b1c7452c173 100644 --- a/testing/taskcluster/tasks/builds/b2g_flame_kk_eng.yml +++ b/testing/taskcluster/tasks/builds/b2g_flame_kk_eng.yml @@ -16,6 +16,7 @@ task: build-flame-kk-eng-objdir-gecko-{{project}}: /home/worker/objdir-gecko env: TARGET: 'flame-kk' + TOOLTOOL_MANIFEST: 'b2g/config/flame-kk/releng-flame-kk.tt' extra: treeherderEnv: - production diff --git a/testing/taskcluster/tasks/builds/b2g_flame_kk_opt.yml b/testing/taskcluster/tasks/builds/b2g_flame_kk_opt.yml index e007d5bbcc63..0e06f93d1733 100644 --- a/testing/taskcluster/tasks/builds/b2g_flame_kk_opt.yml +++ b/testing/taskcluster/tasks/builds/b2g_flame_kk_opt.yml @@ -18,6 +18,7 @@ task: env: TARGET: 'flame-kk' DEBUG: 0 + TOOLTOOL_MANIFEST: 'b2g/config/flame-kk/releng-flame-kk.tt' command: - > checkout-gecko workspace && diff --git a/testing/taskcluster/tasks/builds/b2g_phone_eng_base.yml b/testing/taskcluster/tasks/builds/b2g_phone_eng_base.yml index 20268158e66d..768a4f643c64 100644 --- a/testing/taskcluster/tasks/builds/b2g_phone_eng_base.yml +++ b/testing/taskcluster/tasks/builds/b2g_phone_eng_base.yml @@ -1,9 +1,13 @@ $inherits: from: 'tasks/builds/b2g_phone_base.yml' task: + scopes: + - 'docker-worker:cache:tooltool-cache' workerType: flame-kk payload: + cache: + tooltool-cache: '/home/worker/tooltool-cache' env: DEBUG: 0 VARIANT: eng diff --git a/testing/taskcluster/tasks/phone_build.yml b/testing/taskcluster/tasks/phone_build.yml index 9ef39d34611c..08b9f518b7b1 100644 --- a/testing/taskcluster/tasks/phone_build.yml +++ b/testing/taskcluster/tasks/phone_build.yml @@ -54,6 +54,8 @@ task: GECKO_HEAD_REPOSITORY: '{{head_repository}}' GECKO_HEAD_REV: '{{head_rev}}' GECKO_HEAD_REF: '{{head_ref}}' + TOOLTOOL_REPO: 'https://git.mozilla.org/build/tooltool.git' + TOOLTOOL_REV: 'master' extra: build_product: 'b2g' From bb38d89dd93ef58faca8a47cc3a60daa2c402577 Mon Sep 17 00:00:00 2001 From: John Dai Date: Thu, 17 Sep 2015 19:28:00 +0200 Subject: [PATCH 011/133] Bug 1204822 - Add LD_LIBRARY_PATH in build script. r=dustin, r=jlund --- .../mozilla/building/buildb2gbase.py | 19 +++++++++++++++++++ testing/mozharness/scripts/b2g_build.py | 18 ------------------ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/testing/mozharness/mozharness/mozilla/building/buildb2gbase.py b/testing/mozharness/mozharness/mozilla/building/buildb2gbase.py index 8b6f8848f304..6c90873edc8b 100644 --- a/testing/mozharness/mozharness/mozilla/building/buildb2gbase.py +++ b/testing/mozharness/mozharness/mozilla/building/buildb2gbase.py @@ -264,6 +264,18 @@ class B2GBuildBaseScript(BuildbotMixin, MockMixin, self.gecko_config = self.query_remote_gecko_config() return self.gecko_config + def symlink_gtk3(self): + dirs = self.query_abs_dirs() + gtk3_path = os.path.join(dirs['abs_work_dir'], 'gtk3') + gtk3_symlink_path = os.path.join(dirs['abs_work_dir'], 'gecko', 'gtk3') + + if os.path.isdir(gtk3_path): + cmd = ["ln", "-s", gtk3_path, gtk3_symlink_path] + retval = self.run_command(cmd) + if retval != 0: + self.error("failed to create symlink") + self.return_code = 2 + def query_build_env(self): """Retrieves the environment for building""" dirs = self.query_abs_dirs() @@ -285,6 +297,13 @@ class B2GBuildBaseScript(BuildbotMixin, MockMixin, if self.buildbot_config and 'buildid' in self.buildbot_config.get('properties', {}): env['MOZ_BUILD_DATE'] = self.buildbot_config['properties']['buildid'] + self.symlink_gtk3() + env['LD_LIBRARY_PATH'] = os.environ.get('LD_LIBRARY_PATH') + if env['LD_LIBRARY_PATH'] is None: + env['LD_LIBRARY_PATH'] = os.path.join(dirs['abs_work_dir'], 'gecko', 'gtk3', 'usr', 'local', 'lib') + else: + env['LD_LIBRARY_PATH'] += ':%s' % os.path.join(dirs['abs_work_dir'], 'gecko', 'gtk3', 'usr', 'local', 'lib') + return env def query_hgweb_url(self, repo, rev, filename=None): diff --git a/testing/mozharness/scripts/b2g_build.py b/testing/mozharness/scripts/b2g_build.py index ce5dd5bbcb8d..cba6cb7fab5f 100755 --- a/testing/mozharness/scripts/b2g_build.py +++ b/testing/mozharness/scripts/b2g_build.py @@ -541,18 +541,6 @@ class B2GBuild(LocalesMixin, PurgeMixin, cmd.append(target) return cmd - def symlink_gtk3(self): - dirs = self.query_abs_dirs() - gtk3_path = os.path.join(dirs['abs_work_dir'], 'gtk3') - gtk3_symlink_path = os.path.join(dirs['abs_work_dir'], 'gecko', 'gtk3') - - if os.path.isdir(gtk3_path): - cmd = ["ln", "-s", gtk3_path, gtk3_symlink_path] - retval = self.run_command(cmd) - if retval != 0: - self.error("failed to create symlink") - self.return_code = 2 - def build(self): dirs = self.query_abs_dirs() gecko_config = self.load_gecko_config() @@ -563,13 +551,7 @@ class B2GBuild(LocalesMixin, PurgeMixin, else: cmds = [self.generate_build_command(t) for t in build_targets] - self.symlink_gtk3() env = self.query_build_env() - env['LD_LIBRARY_PATH'] = os.environ.get('LD_LIBRARY_PATH') - if env['LD_LIBRARY_PATH'] is None: - env['LD_LIBRARY_PATH'] = os.path.join(dirs['abs_work_dir'], 'gecko', 'gtk3', 'usr', 'local', 'lib') - else: - env['LD_LIBRARY_PATH'] += ':%s' % os.path.join(dirs['abs_work_dir'], 'gecko', 'gtk3', 'usr', 'local', 'lib') if self.config.get('gaia_languages_file'): env['LOCALE_BASEDIR'] = dirs['gaia_l10n_base_dir'] env['LOCALES_FILE'] = os.path.join(dirs['abs_work_dir'], 'gaia', self.config['gaia_languages_file']) From c781ec5bbccecc2ba54d8bf28a80c8ec8603c39f Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Mon, 21 Sep 2015 10:06:38 +0200 Subject: [PATCH 012/133] Backed out 1 changesets (bug 1204800) for b2g build bustages Backed out changeset e244ce56e745 (bug 1204800) --- b2g/config/aries/releng-aries.tt | 14 +++++++------- b2g/config/flame-kk/releng-flame-kk.tt | 14 +++++++------- b2g/config/flame/releng-flame.tt | 5 +++++ .../taskcluster/scripts/phone-builder/pre-build.sh | 3 --- .../tasks/builds/b2g_aries_spark_debug.yml | 1 - .../tasks/builds/b2g_aries_spark_eng.yml | 1 - .../tasks/builds/b2g_aries_spark_opt.yml | 1 - .../tasks/builds/b2g_flame_kk_debug.yml | 1 - .../taskcluster/tasks/builds/b2g_flame_kk_eng.yml | 1 - .../taskcluster/tasks/builds/b2g_flame_kk_opt.yml | 1 - .../tasks/builds/b2g_phone_eng_base.yml | 4 ---- testing/taskcluster/tasks/phone_build.yml | 2 -- 12 files changed, 19 insertions(+), 29 deletions(-) diff --git a/b2g/config/aries/releng-aries.tt b/b2g/config/aries/releng-aries.tt index 55f67c82c1fe..74b32b01f17b 100644 --- a/b2g/config/aries/releng-aries.tt +++ b/b2g/config/aries/releng-aries.tt @@ -1,16 +1,16 @@ [ { +"size": 135359412, +"digest": "45e677c9606cc4eec44ef4761df47ff431df1ffad17a5c6d21ce700a1c47f79e87a4aa9f30ae47ff060bd64f5b775d995780d88211f9a759ffa0d076beb4816b", +"algorithm": "sha512", +"filename": "backup-aries.tar.xz", +"comment": "v18D" +}, +{ "size": 80458572, "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", "algorithm": "sha512", "filename": "gcc.tar.xz", "unpack": "True" -}, -{ -"size": 12057960, -"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e", -"algorithm": "sha512", -"filename": "gtk3.tar.xz", -"unpack": true } ] diff --git a/b2g/config/flame-kk/releng-flame-kk.tt b/b2g/config/flame-kk/releng-flame-kk.tt index 55f67c82c1fe..d0e0c584aa85 100644 --- a/b2g/config/flame-kk/releng-flame-kk.tt +++ b/b2g/config/flame-kk/releng-flame-kk.tt @@ -1,16 +1,16 @@ [ { +"size": 135359412, +"digest": "45e677c9606cc4eec44ef4761df47ff431df1ffad17a5c6d21ce700a1c47f79e87a4aa9f30ae47ff060bd64f5b775d995780d88211f9a759ffa0d076beb4816b", +"algorithm": "sha512", +"filename": "backup-flame.tar.xz", +"comment": "v18D" +}, +{ "size": 80458572, "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", "algorithm": "sha512", "filename": "gcc.tar.xz", "unpack": "True" -}, -{ -"size": 12057960, -"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e", -"algorithm": "sha512", -"filename": "gtk3.tar.xz", -"unpack": true } ] diff --git a/b2g/config/flame/releng-flame.tt b/b2g/config/flame/releng-flame.tt index 1af12208b9da..65f9871b6796 100644 --- a/b2g/config/flame/releng-flame.tt +++ b/b2g/config/flame/releng-flame.tt @@ -1,4 +1,9 @@ [ +{"size": 149922032, +"digest": "8d1a71552ffee561e93b5b3f1bb47866592ab958f908007c75561156430eb1b85a265bfc4dc2038e58dda0264daa9854877a84ef3b591c9ac2f1ab97c098e61e", +"filename": "backup-flame.tar.xz", +"algorithm": "sha512" +}, { "size": 80458572, "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", diff --git a/testing/taskcluster/scripts/phone-builder/pre-build.sh b/testing/taskcluster/scripts/phone-builder/pre-build.sh index 47357131ef39..99f0718a87cb 100755 --- a/testing/taskcluster/scripts/phone-builder/pre-build.sh +++ b/testing/taskcluster/scripts/phone-builder/pre-build.sh @@ -26,9 +26,6 @@ tc-vcs repo-checkout $WORKSPACE/B2G https://git.mozilla.org/b2g/B2G.git $MANIFES rm -f $WORKSPACE/B2G/gecko ln -s $WORKSPACE/gecko $WORKSPACE/B2G/gecko -### Install package dependencies -. ../builder/install-packages.sh $WORKSPACE/gecko - debug_flag="" if [ 0$B2G_DEBUG -ne 0 ]; then debug_flag='--debug' diff --git a/testing/taskcluster/tasks/builds/b2g_aries_spark_debug.yml b/testing/taskcluster/tasks/builds/b2g_aries_spark_debug.yml index b3e946cc5fc7..0c751a811aa1 100644 --- a/testing/taskcluster/tasks/builds/b2g_aries_spark_debug.yml +++ b/testing/taskcluster/tasks/builds/b2g_aries_spark_debug.yml @@ -22,7 +22,6 @@ task: GAIA_OPTIMIZE: '1' B2G_SYSTEM_APPS: '1' MOZHARNESS_CONFIG: b2g/taskcluster-spark.py - TOOLTOOL_MANIFEST: 'b2g/config/aries/releng-aries.tt' command: - > checkout-gecko workspace && diff --git a/testing/taskcluster/tasks/builds/b2g_aries_spark_eng.yml b/testing/taskcluster/tasks/builds/b2g_aries_spark_eng.yml index f138a3475740..7c3e71fc05c4 100644 --- a/testing/taskcluster/tasks/builds/b2g_aries_spark_eng.yml +++ b/testing/taskcluster/tasks/builds/b2g_aries_spark_eng.yml @@ -17,7 +17,6 @@ task: env: TARGET: 'aries' MOZHARNESS_CONFIG: b2g/taskcluster-spark.py - TOOLTOOL_MANIFEST: 'b2g/config/aries/releng-aries.tt' extra: treeherderEnv: - production diff --git a/testing/taskcluster/tasks/builds/b2g_aries_spark_opt.yml b/testing/taskcluster/tasks/builds/b2g_aries_spark_opt.yml index c2aa962fa5c5..9207c05a7e62 100644 --- a/testing/taskcluster/tasks/builds/b2g_aries_spark_opt.yml +++ b/testing/taskcluster/tasks/builds/b2g_aries_spark_opt.yml @@ -22,7 +22,6 @@ task: GAIA_OPTIMIZE: '1' B2G_SYSTEM_APPS: '1' MOZHARNESS_CONFIG: b2g/taskcluster-spark.py - TOOLTOOL_MANIFEST: 'b2g/config/aries/releng-aries.tt' command: - > checkout-gecko workspace && diff --git a/testing/taskcluster/tasks/builds/b2g_flame_kk_debug.yml b/testing/taskcluster/tasks/builds/b2g_flame_kk_debug.yml index 61c9ce96308b..42fc7744d197 100644 --- a/testing/taskcluster/tasks/builds/b2g_flame_kk_debug.yml +++ b/testing/taskcluster/tasks/builds/b2g_flame_kk_debug.yml @@ -19,7 +19,6 @@ task: TARGET: 'flame-kk' DEBUG: 0 VARIANT: userdebug - TOOLTOOL_MANIFEST: 'b2g/config/flame-kk/releng-flame-kk.tt' command: - > checkout-gecko workspace && diff --git a/testing/taskcluster/tasks/builds/b2g_flame_kk_eng.yml b/testing/taskcluster/tasks/builds/b2g_flame_kk_eng.yml index 1b1c7452c173..7d8f1cfe8cff 100644 --- a/testing/taskcluster/tasks/builds/b2g_flame_kk_eng.yml +++ b/testing/taskcluster/tasks/builds/b2g_flame_kk_eng.yml @@ -16,7 +16,6 @@ task: build-flame-kk-eng-objdir-gecko-{{project}}: /home/worker/objdir-gecko env: TARGET: 'flame-kk' - TOOLTOOL_MANIFEST: 'b2g/config/flame-kk/releng-flame-kk.tt' extra: treeherderEnv: - production diff --git a/testing/taskcluster/tasks/builds/b2g_flame_kk_opt.yml b/testing/taskcluster/tasks/builds/b2g_flame_kk_opt.yml index 0e06f93d1733..e007d5bbcc63 100644 --- a/testing/taskcluster/tasks/builds/b2g_flame_kk_opt.yml +++ b/testing/taskcluster/tasks/builds/b2g_flame_kk_opt.yml @@ -18,7 +18,6 @@ task: env: TARGET: 'flame-kk' DEBUG: 0 - TOOLTOOL_MANIFEST: 'b2g/config/flame-kk/releng-flame-kk.tt' command: - > checkout-gecko workspace && diff --git a/testing/taskcluster/tasks/builds/b2g_phone_eng_base.yml b/testing/taskcluster/tasks/builds/b2g_phone_eng_base.yml index 768a4f643c64..20268158e66d 100644 --- a/testing/taskcluster/tasks/builds/b2g_phone_eng_base.yml +++ b/testing/taskcluster/tasks/builds/b2g_phone_eng_base.yml @@ -1,13 +1,9 @@ $inherits: from: 'tasks/builds/b2g_phone_base.yml' task: - scopes: - - 'docker-worker:cache:tooltool-cache' workerType: flame-kk payload: - cache: - tooltool-cache: '/home/worker/tooltool-cache' env: DEBUG: 0 VARIANT: eng diff --git a/testing/taskcluster/tasks/phone_build.yml b/testing/taskcluster/tasks/phone_build.yml index 08b9f518b7b1..9ef39d34611c 100644 --- a/testing/taskcluster/tasks/phone_build.yml +++ b/testing/taskcluster/tasks/phone_build.yml @@ -54,8 +54,6 @@ task: GECKO_HEAD_REPOSITORY: '{{head_repository}}' GECKO_HEAD_REV: '{{head_rev}}' GECKO_HEAD_REF: '{{head_ref}}' - TOOLTOOL_REPO: 'https://git.mozilla.org/build/tooltool.git' - TOOLTOOL_REV: 'master' extra: build_product: 'b2g' From 71bccbbdcbd8c624bbaa8bcf06ed28aa91122195 Mon Sep 17 00:00:00 2001 From: Heiher Date: Tue, 22 Sep 2015 00:32:09 +0800 Subject: [PATCH 013/133] Bug 1205921 - IonMonkey: MIPS32: Fix scratch register in MacroAssembler::memIntToValue. r=evilpie --- js/src/jit/mips32/MacroAssembler-mips32.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) --- js/src/jit/mips32/MacroAssembler-mips32.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/jit/mips32/MacroAssembler-mips32.h b/js/src/jit/mips32/MacroAssembler-mips32.h index bcb1073e3b68..7bc35741bf7b 100644 --- a/js/src/jit/mips32/MacroAssembler-mips32.h +++ b/js/src/jit/mips32/MacroAssembler-mips32.h @@ -1353,8 +1353,8 @@ class MacroAssemblerMIPSCompat : public MacroAssemblerMIPS } void memIntToValue(Address Source, Address Dest) { - load32(Source, SecondScratchReg); - storeValue(JSVAL_TYPE_INT32, SecondScratchReg, Dest); + load32(Source, ScratchRegister); + storeValue(JSVAL_TYPE_INT32, ScratchRegister, Dest); } void lea(Operand addr, Register dest) { From e8d3447c5700f8e5e6ed904cd54b261073a4ad54 Mon Sep 17 00:00:00 2001 From: Heiher Date: Tue, 22 Sep 2015 00:32:17 +0800 Subject: [PATCH 014/133] Bug 1206591 - IonMonkey: MIPS32: Move LIRGeneratorMIPS::visitRandom to architecture-specific. r=arai --- js/src/jit/mips-shared/Lowering-mips-shared.cpp | 11 ----------- js/src/jit/mips-shared/Lowering-mips-shared.h | 1 - js/src/jit/mips32/Lowering-mips32.h | 1 + 3 files changed, 1 insertion(+), 12 deletions(-) --- js/src/jit/mips-shared/Lowering-mips-shared.cpp | 11 ----------- js/src/jit/mips-shared/Lowering-mips-shared.h | 1 - js/src/jit/mips32/Lowering-mips32.h | 1 + 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/js/src/jit/mips-shared/Lowering-mips-shared.cpp b/js/src/jit/mips-shared/Lowering-mips-shared.cpp index 45b26a824539..4d52e0a515a8 100644 --- a/js/src/jit/mips-shared/Lowering-mips-shared.cpp +++ b/js/src/jit/mips-shared/Lowering-mips-shared.cpp @@ -411,14 +411,3 @@ LIRGeneratorMIPSShared::visitAtomicTypedArrayElementBinop(MAtomicTypedArrayEleme { MOZ_CRASH("NYI"); } - -void -LIRGeneratorMIPSShared::visitRandom(MRandom* ins) -{ - LRandom *lir = new(alloc()) LRandom(temp(), - temp(), - temp(), - temp(), - temp()); - defineFixed(lir, ins, LFloatReg(ReturnDoubleReg)); -} diff --git a/js/src/jit/mips-shared/Lowering-mips-shared.h b/js/src/jit/mips-shared/Lowering-mips-shared.h index adc1c857838b..847cb672bd1f 100644 --- a/js/src/jit/mips-shared/Lowering-mips-shared.h +++ b/js/src/jit/mips-shared/Lowering-mips-shared.h @@ -89,7 +89,6 @@ class LIRGeneratorMIPSShared : public LIRGeneratorShared void visitAtomicExchangeTypedArrayElement(MAtomicExchangeTypedArrayElement* ins); void visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop* ins); void visitSubstr(MSubstr* ins); - void visitRandom(MRandom* ins); }; } // namespace jit diff --git a/js/src/jit/mips32/Lowering-mips32.h b/js/src/jit/mips32/Lowering-mips32.h index eced5aaf7a18..2871e83624f2 100644 --- a/js/src/jit/mips32/Lowering-mips32.h +++ b/js/src/jit/mips32/Lowering-mips32.h @@ -39,6 +39,7 @@ class LIRGeneratorMIPS : public LIRGeneratorMIPSShared void visitBox(MBox* box); void visitUnbox(MUnbox* unbox); void visitReturn(MReturn* ret); + void visitRandom(MRandom* ins); }; typedef LIRGeneratorMIPS LIRGeneratorSpecific; From ccfa972c4c043aa64effa30e74cc33347fe16ec5 Mon Sep 17 00:00:00 2001 From: Paul Adenot Date: Mon, 21 Sep 2015 10:14:59 +0200 Subject: [PATCH 015/133] Bug 1203836 - Properly handle silent chunks in AudioNodeExternalInputStream. r=karlt --HG-- extra : rebase_source : 272b220adf13ec2a62d048ccaab2f9d70af58987 --- dom/media/webaudio/AudioNodeExternalInputStream.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dom/media/webaudio/AudioNodeExternalInputStream.cpp b/dom/media/webaudio/AudioNodeExternalInputStream.cpp index 39a9c7dce47a..c9fee08ca459 100644 --- a/dom/media/webaudio/AudioNodeExternalInputStream.cpp +++ b/dom/media/webaudio/AudioNodeExternalInputStream.cpp @@ -109,8 +109,12 @@ static void ConvertSegmentToAudioBlock(AudioSegment* aSegment, CopyChunkToBlock(*ci, aBlock, duration); break; } - case AUDIO_FORMAT_SILENCE: + case AUDIO_FORMAT_SILENCE: { + // The actual type of the sample does not matter here, but we still need + // to send some audio to the graph. + CopyChunkToBlock(*ci, aBlock, duration); break; + } } duration += ci->GetDuration(); } From 945decca4ee345bf5261d8973ae0fde6bbcf7eba Mon Sep 17 00:00:00 2001 From: Paul Adenot Date: Mon, 21 Sep 2015 11:00:12 +0200 Subject: [PATCH 016/133] Bug 1203836 - Test that MediaElementAudioSourceNode pipes correct data to an AudioContext. r=karlt --HG-- extra : rebase_source : a7e55c894e665dcd57f69c730ec8aebc2af9152b --- dom/media/webaudio/test/mochitest.ini | 2 + ...t_mediaElementAudioSourceNodeFidelity.html | 135 ++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 dom/media/webaudio/test/test_mediaElementAudioSourceNodeFidelity.html diff --git a/dom/media/webaudio/test/mochitest.ini b/dom/media/webaudio/test/mochitest.ini index 68cad91c98f6..fe621905b427 100644 --- a/dom/media/webaudio/test/mochitest.ini +++ b/dom/media/webaudio/test/mochitest.ini @@ -121,6 +121,8 @@ skip-if = toolkit == 'android' # bug 1056706 [test_mediaDecoding.html] [test_mediaElementAudioSourceNode.html] tags=capturestream +[test_mediaElementAudioSourceNodeFidelity.html] +tags=capturestream [test_mediaElementAudioSourceNodePassThrough.html] tags=capturestream skip-if = toolkit == 'android' # bug 1145816 diff --git a/dom/media/webaudio/test/test_mediaElementAudioSourceNodeFidelity.html b/dom/media/webaudio/test/test_mediaElementAudioSourceNodeFidelity.html new file mode 100644 index 000000000000..a75e8c4ca237 --- /dev/null +++ b/dom/media/webaudio/test/test_mediaElementAudioSourceNodeFidelity.html @@ -0,0 +1,135 @@ + + + + + Test MediaStreamAudioSourceNode doesn't get data from cross-origin media resources + + + + +
+

From 5b5c5fef6751a4a1308891743212aeffe2a5b903 Mon Sep 17 00:00:00 2001
From: Rail Aliiev 
Date: Mon, 21 Sep 2015 06:40:27 -0400
Subject: [PATCH 017/133] Bug 1190766 - Tracking bug for Sep-21-2015 migration
 work. r=jlund DONTBUILD

---
 .../configs/merge_day/aurora_to_beta.py          |  8 +++++++-
 .../configs/merge_day/beta_to_release.py         |  7 +++++++
 .../configs/merge_day/central_to_aurora.py       |  7 ++++++-
 .../configs/merge_day/release_to_esr.py          |  6 ++++++
 .../scripts/merge_day/gecko_migration.py         | 16 ++++------------
 5 files changed, 30 insertions(+), 14 deletions(-)

diff --git a/testing/mozharness/configs/merge_day/aurora_to_beta.py b/testing/mozharness/configs/merge_day/aurora_to_beta.py
index ee5e8891c18d..2b974cffeba5 100644
--- a/testing/mozharness/configs/merge_day/aurora_to_beta.py
+++ b/testing/mozharness/configs/merge_day/aurora_to_beta.py
@@ -1,6 +1,12 @@
 config = {
     "log_name": "aurora_to_beta",
-
+    "version_files": [
+        "browser/config/version.txt",
+        "browser/config/version_display.txt",
+        "config/milestone.txt",
+        "mobile/android/confvars.sh",  # TODO: remove this line before gecko 43 merge
+        "b2g/confvars.sh",
+    ],
     "replacements": [
         # File, from, to
         ("{}/{}".format(d, f),
diff --git a/testing/mozharness/configs/merge_day/beta_to_release.py b/testing/mozharness/configs/merge_day/beta_to_release.py
index 63bd79ad5039..1b76d344dbae 100644
--- a/testing/mozharness/configs/merge_day/beta_to_release.py
+++ b/testing/mozharness/configs/merge_day/beta_to_release.py
@@ -1,5 +1,12 @@
 config = {
     "log_name": "beta_to_release",
+    "version_files": [
+        "browser/config/version.txt",
+        "browser/config/version_display.txt",
+        "config/milestone.txt",
+        "mobile/android/confvars.sh",  # TODO: remove this line before gecko 43 merge
+        "b2g/confvars.sh",
+    ],
     "replacements": [
         # File, from, to
         ("{}/{}".format(d, f),
diff --git a/testing/mozharness/configs/merge_day/central_to_aurora.py b/testing/mozharness/configs/merge_day/central_to_aurora.py
index d8eb9d5db97d..de370e1dcae3 100644
--- a/testing/mozharness/configs/merge_day/central_to_aurora.py
+++ b/testing/mozharness/configs/merge_day/central_to_aurora.py
@@ -1,6 +1,11 @@
 config = {
     "log_name": "central_to_aurora",
-
+    "version_files": [
+        "browser/config/version.txt",
+        "browser/config/version_display.txt",
+        "config/milestone.txt",
+        "b2g/confvars.sh",
+    ],
     "replacements": [
         # File, from, to
         ("{}/{}".format(d, f),
diff --git a/testing/mozharness/configs/merge_day/release_to_esr.py b/testing/mozharness/configs/merge_day/release_to_esr.py
index d1a934f9667c..e303c74c53b5 100644
--- a/testing/mozharness/configs/merge_day/release_to_esr.py
+++ b/testing/mozharness/configs/merge_day/release_to_esr.py
@@ -4,6 +4,12 @@ OLD_ESR_CHANGESET = "16351963d75c"
 
 config = {
     "log_name": "relese_to_esr",
+    "version_files": [
+        "browser/config/version.txt",
+        "browser/config/version_display.txt",
+        "config/milestone.txt",
+        "b2g/confvars.sh",
+    ],
     "replacements": [
         # File, from, to
         ("browser/confvars.sh",
diff --git a/testing/mozharness/scripts/merge_day/gecko_migration.py b/testing/mozharness/scripts/merge_day/gecko_migration.py
index 877044b31bb9..f02123548a8d 100755
--- a/testing/mozharness/scripts/merge_day/gecko_migration.py
+++ b/testing/mozharness/scripts/merge_day/gecko_migration.py
@@ -321,15 +321,7 @@ class GeckoMigration(MercurialScript, BalrogMixin, VirtualenvMixin, SelfServeMix
             """
         curr_weave_version = str(int(curr_version) + 2)
         next_weave_version = str(int(curr_weave_version) + 1)
-        version_files = ["browser/config/version.txt", "config/milestone.txt",
-                         "mobile/android/confvars.sh", "b2g/confvars.sh"]
-        # TODO: remove the following block when version_about.txt is all way to
-        # ESR (45?)
-        version_about = "browser/config/version_about.txt"
-        if os.path.exists(os.path.join(cwd, version_about)):
-            version_files.append(version_about)
-        # TODO: end of remove block
-        for f in version_files:
+        for f in self.config["version_files"]:
             self.replace(os.path.join(cwd, f), "%s.0%s" % (curr_version, curr_suffix),
                          "%s.0%s" % (next_version, next_suffix))
 
@@ -341,9 +333,9 @@ class GeckoMigration(MercurialScript, BalrogMixin, VirtualenvMixin, SelfServeMix
                 "static const unsigned int kVersion = %s;" % next_version
             )
             self.replace(
-                os.path.join(cwd, "services/sync/Makefile.in"),
-                "weave_version := 1.%s.0" % curr_weave_version,
-                "weave_version := 1.%s.0" % next_weave_version
+                os.path.join(cwd, "services/sync/moz.build"),
+                "DEFINES['weave_version'] = '1.%s.0'" % curr_weave_version,
+                "DEFINES['weave_version'] = '1.%s.0'" % next_weave_version
             )
 
     # Branch-specific workflow helper methods {{{1

From 7eeac1fde4fcd5f008c8dea204fd2218533e426b Mon Sep 17 00:00:00 2001
From: Benjamin Bouvier 
Date: Mon, 21 Sep 2015 12:52:53 +0200
Subject: [PATCH 018/133] Bug 1204604: Check for int32 value, not int32 type,
 in SIMD.T.{replaceLane,shuffle,swizzle}; r=lth

--HG--
extra : commitid : 7MmgnJUuUwi
extra : rebase_source : d69d9d84fe3904972d5f3ddbbaf7d684bfd0b321
---
 js/src/builtin/SIMD.cpp               | 12 ++++++------
 js/src/jit-test/tests/SIMD/swizzle.js | 16 ++++++++++++++++
 js/src/jit/MIR.h                      |  1 +
 3 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/js/src/builtin/SIMD.cpp b/js/src/builtin/SIMD.cpp
index 594fb28ca4d5..77c62886d821 100644
--- a/js/src/builtin/SIMD.cpp
+++ b/js/src/builtin/SIMD.cpp
@@ -780,9 +780,9 @@ ReplaceLane(JSContext* cx, unsigned argc, Value* vp)
     Elem* vec = TypedObjectMemory(args[0]);
     Elem result[V::lanes];
 
-    if (!args[1].isInt32())
+    int32_t lanearg;
+    if (!args[1].isNumber() || !NumberIsInt32(args[1].toNumber(), &lanearg))
         return ErrorBadArgs(cx);
-    int32_t lanearg = args[1].toInt32();
     if (lanearg < 0 || uint32_t(lanearg) >= V::lanes)
         return ErrorBadArgs(cx);
     uint32_t lane = uint32_t(lanearg);
@@ -808,9 +808,9 @@ Swizzle(JSContext* cx, unsigned argc, Value* vp)
 
     uint32_t lanes[V::lanes];
     for (unsigned i = 0; i < V::lanes; i++) {
-        if (!args[i + 1].isInt32())
+        int32_t lane;
+        if (!args[i + 1].isNumber() || !NumberIsInt32(args[i + 1].toNumber(), &lane))
             return ErrorBadArgs(cx);
-        int32_t lane = args[i + 1].toInt32();
         if (lane < 0 || uint32_t(lane) >= V::lanes)
             return ErrorBadArgs(cx);
         lanes[i] = uint32_t(lane);
@@ -837,9 +837,9 @@ Shuffle(JSContext* cx, unsigned argc, Value* vp)
 
     uint32_t lanes[V::lanes];
     for (unsigned i = 0; i < V::lanes; i++) {
-        if (!args[i + 2].isInt32())
+        int32_t lane;
+        if (!args[i + 2].isNumber() || !NumberIsInt32(args[i + 2].toNumber(), &lane))
             return ErrorBadArgs(cx);
-        int32_t lane = args[i + 2].toInt32();
         if (lane < 0 || uint32_t(lane) >= (2 * V::lanes))
             return ErrorBadArgs(cx);
         lanes[i] = uint32_t(lane);
diff --git a/js/src/jit-test/tests/SIMD/swizzle.js b/js/src/jit-test/tests/SIMD/swizzle.js
index 3c0603092ba4..e54d874786d6 100644
--- a/js/src/jit-test/tests/SIMD/swizzle.js
+++ b/js/src/jit-test/tests/SIMD/swizzle.js
@@ -84,3 +84,19 @@ try {
 } catch(e) {
     assertEq(e instanceof TypeError, true);
 }
+
+(function() {
+    var zappa = 0;
+
+    function testBailouts() {
+        var i4 = SIMD.Int32x4(1, 2, 3, 4);
+        for (var i = 0; i < 300; i++) {
+            var value = i == 299 ? 2.5 : 1;
+            SIMD.Int32x4.swizzle(i4, value, 3, 2, 0);
+            zappa = i;
+        }
+    }
+
+    try { testBailouts(); } catch (e) {}
+    assertEq(zappa, 298);
+})();
diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h
index 571d6e05e447..f6b4da0e7ebd 100644
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -1853,6 +1853,7 @@ class MSimdGeneralShuffle :
 
         setResultType(type);
         specialization_ = type;
+        setGuard(); // throws if lane index is out of bounds
         setMovable();
     }
 

From 358a47b0baa9da6f63bef8cd677f1560853e246b Mon Sep 17 00:00:00 2001
From: Benjamin Bouvier 
Date: Fri, 18 Sep 2015 09:02:03 +0200
Subject: [PATCH 019/133] Bug 1205842: Don't add range asserts to recovered on
 bailouts instructions; r=nbp

--HG--
extra : commitid : CiHyGriq9B3
extra : rebase_source : e99244d4f1ed79ee00391d02626ef22f182a3fd2
---
 js/src/jit-test/tests/ion/bug1205842.js | 8 ++++++++
 js/src/jit/RangeAnalysis.cpp            | 4 ++++
 2 files changed, 12 insertions(+)
 create mode 100644 js/src/jit-test/tests/ion/bug1205842.js

diff --git a/js/src/jit-test/tests/ion/bug1205842.js b/js/src/jit-test/tests/ion/bug1205842.js
new file mode 100644
index 000000000000..a65ebf66021c
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1205842.js
@@ -0,0 +1,8 @@
+function f(x) {
+    (function() {
+        x = 0;
+    })();
+}
+for (var k = 0; k < 9; k++) {
+    f(Math.fround(1));
+}
diff --git a/js/src/jit/RangeAnalysis.cpp b/js/src/jit/RangeAnalysis.cpp
index c277f90a21f2..25dda5d0de12 100644
--- a/js/src/jit/RangeAnalysis.cpp
+++ b/js/src/jit/RangeAnalysis.cpp
@@ -2291,6 +2291,10 @@ RangeAnalysis::addRangeAssertions()
             if (r.isUnknown() || (ins->type() == MIRType_Int32 && r.isUnknownInt32()))
                 continue;
 
+            // Don't add a use to an instruction that is recovered on bailout.
+            if (ins->isRecoveredOnBailout())
+                continue;
+
             MAssertRange* guard = MAssertRange::New(alloc(), ins, new(alloc()) Range(r));
 
             // Beta nodes and interrupt checks are required to be located at the

From f1cb998d7bf481e94c42aeda69f88c414d06cc70 Mon Sep 17 00:00:00 2001
From: Benjamin Bouvier 
Date: Wed, 16 Sep 2015 17:10:13 +0200
Subject: [PATCH 020/133] Bug 1206640: Fix an implicit constructor in
 PosixNSPR.cpp; r=nbp

--HG--
extra : commitid : 9f3rNLn1aR6
extra : rebase_source : 92d5346a52c2f7125b6f434f19e2d73ccb63bbce
---
 js/src/vm/PosixNSPR.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/js/src/vm/PosixNSPR.cpp b/js/src/vm/PosixNSPR.cpp
index 9ec384935463..873987597fa4 100644
--- a/js/src/vm/PosixNSPR.cpp
+++ b/js/src/vm/PosixNSPR.cpp
@@ -270,7 +270,7 @@ class nspr::CondVar
     nspr::Lock* lock_;
 
   public:
-    CondVar(nspr::Lock* lock) : lock_(lock) {}
+    explicit CondVar(nspr::Lock* lock) : lock_(lock) {}
     pthread_cond_t& cond() { return cond_; }
     nspr::Lock* lock() { return lock_; }
 };

From 74e595efb18df2c176e000c351f120f02b24a3c5 Mon Sep 17 00:00:00 2001
From: Bas Schouten 
Date: Mon, 21 Sep 2015 00:30:59 +0200
Subject: [PATCH 021/133] Bug 1206076: Use a specialized
 PersistentBufferProvider for Canvas2D when using a SkiaGL DrawTarget.
 r=jrmuizel

---
 b2g/app/b2g.js                          | 2 +-
 dom/canvas/CanvasRenderingContext2D.cpp | 1 +
 modules/libpref/init/all.js             | 2 +-
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js
index 17832cca822f..0b267098b3d3 100644
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -954,7 +954,7 @@ pref("devtools.debugger.unix-domain-socket", "/data/local/debugger-socket");
 // falling back to Skia/software for smaller canvases
 #ifdef MOZ_WIDGET_GONK
 pref("gfx.canvas.azure.backends", "skia");
-pref("gfx.canvas.azure.accelerated", true);
+pref("gfx.canvas.azure.accelerated", false);
 #endif
 
 // Turn on dynamic cache size for Skia
diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp
index 69a771fd5ef2..be2883d0964b 100644
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -1408,6 +1408,7 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
           mTarget = Factory::CreateDrawTargetSkiaWithGrContext(glue->GetGrContext(), size, format);
           if (mTarget) {
             AddDemotableContext(this);
+            mBufferProvider = new PersistentBufferProviderBasic(mTarget);
           } else {
             printf_stderr("Failed to create a SkiaGL DrawTarget, falling back to software\n");
             mode = RenderingMode::SoftwareBackendMode;
diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js
index 9c3aab7605a6..a8c71517c688 100644
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -685,7 +685,7 @@ pref("gfx.content.azure.backends", "direct2d1.1,direct2d,cairo");
 pref("gfx.content.azure.backends", "cg");
 pref("gfx.canvas.azure.backends", "skia");
 // Accelerated cg canvas where available (10.7+)
-pref("gfx.canvas.azure.accelerated", true);
+pref("gfx.canvas.azure.accelerated", false);
 #else
 pref("gfx.canvas.azure.backends", "cairo");
 pref("gfx.content.azure.backends", "cairo");

From 71096f4bdae30d07233593292bbaef2576f6efc2 Mon Sep 17 00:00:00 2001
From: Kartikaya Gupta 
Date: Mon, 21 Sep 2015 09:29:45 -0400
Subject: [PATCH 022/133] Bug 1195435 - Fuzz the image-scrolling-zoom reftest
 failure when APZ is enabled. r=seth

--HG--
extra : commitid : GGt2Mcaooy8
---
 layout/reftests/invalidation/reftest.list | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/layout/reftests/invalidation/reftest.list b/layout/reftests/invalidation/reftest.list
index 0bb9d7ceb09e..4202ca387800 100644
--- a/layout/reftests/invalidation/reftest.list
+++ b/layout/reftests/invalidation/reftest.list
@@ -64,7 +64,7 @@ pref(layout.animated-image-layers.enabled,true) skip-if(Android||gtkWidget) == t
 != layer-splitting-5.html about:blank
 != layer-splitting-6.html about:blank
 != layer-splitting-7.html about:blank
-fuzzy-if(gtkWidget,2,4) fuzzy-if(OSX,179,1) == image-scrolling-zoom-1.html image-scrolling-zoom-1-ref.html
+fuzzy-if(gtkWidget,2,4) fuzzy-if(asyncPan,2,3955) fuzzy-if(OSX,179,1) == image-scrolling-zoom-1.html image-scrolling-zoom-1-ref.html
 != image-scrolling-zoom-1-ref.html image-scrolling-zoom-1-notref.html
 != fast-scrolling.html about:blank
 != fractional-transform-1.html about:blank

From b815d04f9b1aa8c719c4f101baa122bbbc9716d3 Mon Sep 17 00:00:00 2001
From: Jon Coppeard 
Date: Mon, 21 Sep 2015 14:31:51 +0100
Subject: [PATCH 023/133] Bug 1201057 - Move AutoEnterOOMUnsafeRegion to
 Utility.h with the other OOM simulation infrastructure r=terrence

---
 js/public/Utility.h | 39 +++++++++++++++++++++++++++++++++++++++
 js/src/jsgc.h       | 27 ---------------------------
 js/src/jsutil.h     |  3 ---
 3 files changed, 39 insertions(+), 30 deletions(-)

diff --git a/js/public/Utility.h b/js/public/Utility.h
index 4d91aa8324e7..1d6e39d77f68 100644
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -181,6 +181,45 @@ static inline bool ShouldFailWithOOM() { return false; }
 
 # endif /* DEBUG || JS_OOM_BREAKPOINT */
 
+namespace js {
+
+MOZ_NORETURN MOZ_COLD void
+CrashAtUnhandlableOOM(const char* reason);
+
+/* Disable OOM testing in sections which are not OOM safe. */
+struct MOZ_RAII AutoEnterOOMUnsafeRegion
+{
+    void crash(const char* reason) {
+        CrashAtUnhandlableOOM(reason);
+    }
+
+#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
+    AutoEnterOOMUnsafeRegion()
+      : oomEnabled_(OOM_maxAllocations != UINT32_MAX), oomAfter_(0)
+    {
+        if (oomEnabled_) {
+            oomAfter_ = int64_t(OOM_maxAllocations) - OOM_counter;
+            OOM_maxAllocations = UINT32_MAX;
+        }
+    }
+
+    ~AutoEnterOOMUnsafeRegion() {
+        MOZ_ASSERT(OOM_maxAllocations == UINT32_MAX);
+        if (oomEnabled_) {
+            int64_t maxAllocations = OOM_counter + oomAfter_;
+            MOZ_ASSERT(maxAllocations >= 0 && maxAllocations < UINT32_MAX);
+            OOM_maxAllocations = uint32_t(maxAllocations);
+        }
+    }
+
+  private:
+    bool oomEnabled_;
+    int64_t oomAfter_;
+#endif
+};
+
+} /* namespace js */
+
 static inline void* js_malloc(size_t bytes)
 {
     JS_OOM_POSSIBLY_FAIL();
diff --git a/js/src/jsgc.h b/js/src/jsgc.h
index fd204e884423..5cf8e9eca2af 100644
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -1312,33 +1312,6 @@ class MOZ_RAII AutoSuppressGC
     }
 };
 
-#ifdef DEBUG
-/* Disable OOM testing in sections which are not OOM safe. */
-class MOZ_RAII AutoEnterOOMUnsafeRegion
-{
-    bool oomEnabled_;
-    int64_t oomAfter_;
-
-  public:
-    AutoEnterOOMUnsafeRegion()
-      : oomEnabled_(OOM_maxAllocations != UINT32_MAX), oomAfter_(0)
-    {
-        if (oomEnabled_) {
-            oomAfter_ = OOM_maxAllocations - OOM_counter;
-            OOM_maxAllocations = UINT32_MAX;
-        }
-    }
-
-    ~AutoEnterOOMUnsafeRegion() {
-        MOZ_ASSERT(OOM_maxAllocations == UINT32_MAX);
-        if (oomEnabled_)
-            OOM_maxAllocations = OOM_counter + oomAfter_;
-    }
-};
-#else
-class MOZ_RAII AutoEnterOOMUnsafeRegion {};
-#endif /* DEBUG */
-
 // A singly linked list of zones.
 class ZoneList
 {
diff --git a/js/src/jsutil.h b/js/src/jsutil.h
index 3e163c86cb0c..e28cb39e0884 100644
--- a/js/src/jsutil.h
+++ b/js/src/jsutil.h
@@ -45,9 +45,6 @@ js_memcpy(void* dst_, const void* src_, size_t len)
 
 namespace js {
 
-MOZ_NORETURN MOZ_COLD void
-CrashAtUnhandlableOOM(const char* reason);
-
 template 
 struct AlignmentTestStruct
 {

From 957e1c50861dba3ebdfbf70d9d9cff8db320c834 Mon Sep 17 00:00:00 2001
From: Jon Coppeard 
Date: Mon, 21 Sep 2015 14:31:51 +0100
Subject: [PATCH 024/133] Bug 1201057 - Use AutoEnterOOMUnsafeRegion in places
 where we can't handle OOM r=terrence

---
 js/src/builtin/TestingFunctions.cpp           | 12 +++--
 js/src/builtin/TypedObject.cpp                | 10 ++--
 js/src/ds/Fifo.h                              |  3 +-
 js/src/ds/LifoAlloc.h                         |  3 +-
 js/src/gc/Marking.cpp                         | 25 +++++++---
 js/src/gc/Nursery.cpp                         |  5 +-
 js/src/gc/StoreBuffer.h                       |  8 ++--
 js/src/gc/Zone.h                              |  3 +-
 .../irregexp/NativeRegExpMacroAssembler.cpp   |  8 +++-
 js/src/irregexp/RegExpEngine.cpp              | 23 ++++++---
 js/src/irregexp/RegExpMacroAssembler.cpp      |  6 ++-
 js/src/jit/IonAnalysis.cpp                    | 10 ++--
 js/src/jit/IonBuilder.cpp                     |  3 +-
 js/src/jit/LoopUnroller.cpp                   | 39 ++++++++++-----
 js/src/jit/MIRGraph.cpp                       |  9 ++--
 js/src/jit/arm/Simulator-arm.cpp              |  6 ++-
 js/src/jscompartment.cpp                      |  5 +-
 js/src/jsgc.cpp                               | 48 +++++++++++--------
 js/src/jsobj.cpp                              | 25 +++++-----
 js/src/vm/ArgumentsObject.cpp                 |  3 +-
 js/src/vm/ArrayBufferObject.cpp               |  3 +-
 js/src/vm/Debugger.cpp                        | 16 ++++---
 js/src/vm/Debugger.h                          |  2 +-
 js/src/vm/HelperThreads.cpp                   |  3 +-
 js/src/vm/NativeObject.cpp                    |  3 +-
 js/src/vm/NativeObject.h                      |  2 +-
 js/src/vm/Runtime.h                           |  3 +-
 js/src/vm/SavedStacks.cpp                     |  5 +-
 js/src/vm/TypeInference.cpp                   | 36 ++++++++------
 js/src/vm/UnboxedObject.cpp                   |  7 ++-
 30 files changed, 214 insertions(+), 120 deletions(-)

diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp
index 8d4fc0f590e7..54297130e073 100644
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1384,13 +1384,15 @@ DisplayName(JSContext* cx, unsigned argc, Value* vp)
 static JSObject*
 ShellObjectMetadataCallback(JSContext* cx, JSObject*)
 {
+    AutoEnterOOMUnsafeRegion oomUnsafe;
+
     RootedObject obj(cx, NewBuiltinClassInstance(cx));
     if (!obj)
-        CrashAtUnhandlableOOM("ShellObjectMetadataCallback");
+        oomUnsafe.crash("ShellObjectMetadataCallback");
 
     RootedObject stack(cx, NewDenseEmptyArray(cx));
     if (!stack)
-        CrashAtUnhandlableOOM("ShellObjectMetadataCallback");
+        oomUnsafe.crash("ShellObjectMetadataCallback");
 
     static int createdIndex = 0;
     createdIndex++;
@@ -1398,13 +1400,13 @@ ShellObjectMetadataCallback(JSContext* cx, JSObject*)
     if (!JS_DefineProperty(cx, obj, "index", createdIndex, 0,
                            JS_STUBGETTER, JS_STUBSETTER))
     {
-        CrashAtUnhandlableOOM("ShellObjectMetadataCallback");
+        oomUnsafe.crash("ShellObjectMetadataCallback");
     }
 
     if (!JS_DefineProperty(cx, obj, "stack", stack, 0,
                            JS_STUBGETTER, JS_STUBSETTER))
     {
-        CrashAtUnhandlableOOM("ShellObjectMetadataCallback");
+        oomUnsafe.crash("ShellObjectMetadataCallback");
     }
 
     int stackIndex = 0;
@@ -1417,7 +1419,7 @@ ShellObjectMetadataCallback(JSContext* cx, JSObject*)
             if (!JS_DefinePropertyById(cx, stack, id, callee, 0,
                                        JS_STUBGETTER, JS_STUBSETTER))
             {
-                CrashAtUnhandlableOOM("ShellObjectMetadataCallback");
+                oomUnsafe.crash("ShellObjectMetadataCallback");
             }
             stackIndex++;
         }
diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp
index a9c06301e2fd..84adc0904d7f 100644
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -1520,8 +1520,11 @@ OutlineTypedObject::attach(JSContext* cx, ArrayBufferObject& buffer, int32_t off
 
     buffer.setHasTypedObjectViews();
 
-    if (!buffer.addView(cx, this))
-        CrashAtUnhandlableOOM("TypedObject::attach");
+    {
+        AutoEnterOOMUnsafeRegion oomUnsafe;
+        if (!buffer.addView(cx, this))
+            oomUnsafe.crash("TypedObject::attach");
+    }
 
     setOwnerAndData(&buffer, buffer.dataPointer() + offset);
 }
@@ -3026,8 +3029,9 @@ TraceListVisitor::visitReference(ReferenceTypeDescr& descr, uint8_t* mem)
       default: MOZ_CRASH("Invalid kind");
     }
 
+    AutoEnterOOMUnsafeRegion oomUnsafe;
     if (!offsets->append((uintptr_t) mem))
-        CrashAtUnhandlableOOM("TraceListVisitor::visitReference");
+        oomUnsafe.crash("TraceListVisitor::visitReference");
 }
 
 bool
diff --git a/js/src/ds/Fifo.h b/js/src/ds/Fifo.h
index de482e7a240f..fb54cb498fca 100644
--- a/js/src/ds/Fifo.h
+++ b/js/src/ds/Fifo.h
@@ -135,8 +135,9 @@ class Fifo
             // Attempt to remain in a valid state by reinserting the element
             // back at the front. If we can't remain in a valid state in the
             // face of OOMs, crash.
+            AutoEnterOOMUnsafeRegion oomUnsafe;
             if (!front_.append(mozilla::Move(t)))
-                CrashAtUnhandlableOOM("js::Fifo::popFront");
+                oomUnsafe.crash("js::Fifo::popFront");
             return false;
         }
         return true;
diff --git a/js/src/ds/LifoAlloc.h b/js/src/ds/LifoAlloc.h
index 14a97c93a409..880f6441fd46 100644
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -277,9 +277,10 @@ class LifoAlloc
 
     MOZ_ALWAYS_INLINE
     void* allocInfallible(size_t n) {
+        AutoEnterOOMUnsafeRegion oomUnsafe;
         if (void* result = allocImpl(n))
             return result;
-        CrashAtUnhandlableOOM("LifoAlloc::allocInfallible");
+        oomUnsafe.crash("LifoAlloc::allocInfallible");
         return nullptr;
     }
 
diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp
index d406e7d45f6b..1724d065490c 100644
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -2060,9 +2060,10 @@ js::TenuringTracer::moveToTenured(JSObject* src)
     if (!t) {
         zone->arenas.checkEmptyFreeList(dstKind);
         AutoMaybeStartBackgroundAllocation maybeStartBackgroundAllocation;
+        AutoEnterOOMUnsafeRegion oomUnsafe;
         t = zone->arenas.allocateFromArena(zone, dstKind, maybeStartBackgroundAllocation);
         if (!t)
-            CrashAtUnhandlableOOM("Failed to allocate object while tenuring.");
+            oomUnsafe.crash("Failed to allocate object while tenuring.");
     }
     JSObject* dst = reinterpret_cast(t);
     tenuredSize += moveObjectToTenured(dst, src, dstKind);
@@ -2212,9 +2213,14 @@ js::TenuringTracer::moveSlotsToTenured(NativeObject* dst, NativeObject* src, All
 
     Zone* zone = src->zone();
     size_t count = src->numDynamicSlots();
-    dst->slots_ = zone->pod_malloc(count);
-    if (!dst->slots_)
-        CrashAtUnhandlableOOM("Failed to allocate slots while tenuring.");
+
+    {
+        AutoEnterOOMUnsafeRegion oomUnsafe;
+        dst->slots_ = zone->pod_malloc(count);
+        if (!dst->slots_)
+            oomUnsafe.crash("Failed to allocate slots while tenuring.");
+    }
+
     PodCopy(dst->slots_, src->slots_, count);
     nursery().setSlotsForwardingPointer(src->slots_, dst->slots_, count);
     return count * sizeof(HeapSlot);
@@ -2249,9 +2255,14 @@ js::TenuringTracer::moveElementsToTenured(NativeObject* dst, NativeObject* src,
     }
 
     MOZ_ASSERT(nslots >= 2);
-    dstHeader = reinterpret_cast(zone->pod_malloc(nslots));
-    if (!dstHeader)
-        CrashAtUnhandlableOOM("Failed to allocate elements while tenuring.");
+
+    {
+        AutoEnterOOMUnsafeRegion oomUnsafe;
+        dstHeader = reinterpret_cast(zone->pod_malloc(nslots));
+        if (!dstHeader)
+            oomUnsafe.crash("Failed to allocate elements while tenuring.");
+    }
+
     js_memcpy(dstHeader, srcHeader, nslots * sizeof(HeapSlot));
     nursery().setElementsForwardingPointer(srcHeader, dstHeader, nslots);
     dst->elements_ = dstHeader->elements();
diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp
index ba670ba8e994..a663a29e937f 100644
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -315,14 +315,15 @@ Nursery::setForwardingPointer(void* oldData, void* newData, bool direct)
     if (direct) {
         *reinterpret_cast(oldData) = newData;
     } else {
+        AutoEnterOOMUnsafeRegion oomUnsafe;
         if (!forwardedBuffers.initialized() && !forwardedBuffers.init())
-            CrashAtUnhandlableOOM("Nursery::setForwardingPointer");
+            oomUnsafe.crash("Nursery::setForwardingPointer");
 #ifdef DEBUG
         if (ForwardedBufferMap::Ptr p = forwardedBuffers.lookup(oldData))
             MOZ_ASSERT(p->value() == newData);
 #endif
         if (!forwardedBuffers.put(oldData, newData))
-            CrashAtUnhandlableOOM("Nursery::setForwardingPointer");
+            oomUnsafe.crash("Nursery::setForwardingPointer");
     }
 }
 
diff --git a/js/src/gc/StoreBuffer.h b/js/src/gc/StoreBuffer.h
index d0484524d18a..71a9a3c81f6f 100644
--- a/js/src/gc/StoreBuffer.h
+++ b/js/src/gc/StoreBuffer.h
@@ -107,8 +107,9 @@ class StoreBuffer
         void sinkStore(StoreBuffer* owner) {
             MOZ_ASSERT(stores_.initialized());
             if (last_) {
+                AutoEnterOOMUnsafeRegion oomUnsafe;
                 if (!stores_.put(last_))
-                    CrashAtUnhandlableOOM("Failed to allocate for MonoTypeBuffer::put.");
+                    oomUnsafe.crash("Failed to allocate for MonoTypeBuffer::put.");
             }
             last_ = T();
 
@@ -167,15 +168,16 @@ class StoreBuffer
             /* Ensure T is derived from BufferableRef. */
             (void)static_cast(&t);
 
+            AutoEnterOOMUnsafeRegion oomUnsafe;
             unsigned size = sizeof(T);
             unsigned* sizep = storage_->pod_malloc();
             if (!sizep)
-                CrashAtUnhandlableOOM("Failed to allocate for GenericBuffer::put.");
+                oomUnsafe.crash("Failed to allocate for GenericBuffer::put.");
             *sizep = size;
 
             T* tp = storage_->new_(t);
             if (!tp)
-                CrashAtUnhandlableOOM("Failed to allocate for GenericBuffer::put.");
+                oomUnsafe.crash("Failed to allocate for GenericBuffer::put.");
 
             if (isAboutToOverflow())
                 owner->setAboutToOverflow();
diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h
index 365a63a6d21a..e5ce3777097d 100644
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -258,8 +258,9 @@ struct Zone : public JS::shadow::Zone,
     void enqueueForPromotionToTenuredLogging(JSObject& obj) {
         MOZ_ASSERT(hasDebuggers());
         MOZ_ASSERT(!IsInsideNursery(&obj));
+        js::AutoEnterOOMUnsafeRegion oomUnsafe;
         if (!awaitingTenureLogging.append(&obj))
-            js::CrashAtUnhandlableOOM("Zone::enqueueForPromotionToTenuredLogging");
+            oomUnsafe.crash("Zone::enqueueForPromotionToTenuredLogging");
     }
     void logPromotionsToTenured();
 
diff --git a/js/src/irregexp/NativeRegExpMacroAssembler.cpp b/js/src/irregexp/NativeRegExpMacroAssembler.cpp
index 81b9f18202f5..63a41d9547b2 100644
--- a/js/src/irregexp/NativeRegExpMacroAssembler.cpp
+++ b/js/src/irregexp/NativeRegExpMacroAssembler.cpp
@@ -987,8 +987,12 @@ NativeRegExpMacroAssembler::PushBacktrack(Label* label)
     CodeOffsetLabel patchOffset = masm.movWithPatch(ImmPtr(nullptr), temp0);
 
     MOZ_ASSERT(!label->bound());
-    if (!labelPatches.append(LabelPatch(label, patchOffset)))
-        CrashAtUnhandlableOOM("NativeRegExpMacroAssembler::PushBacktrack");
+
+    {
+        AutoEnterOOMUnsafeRegion oomUnsafe;
+        if (!labelPatches.append(LabelPatch(label, patchOffset)))
+            oomUnsafe.crash("NativeRegExpMacroAssembler::PushBacktrack");
+    }
 
     PushBacktrack(temp0);
     CheckBacktrackStackLimit();
diff --git a/js/src/irregexp/RegExpEngine.cpp b/js/src/irregexp/RegExpEngine.cpp
index 2e2608c71825..b510530f4a0e 100644
--- a/js/src/irregexp/RegExpEngine.cpp
+++ b/js/src/irregexp/RegExpEngine.cpp
@@ -1509,8 +1509,9 @@ class irregexp::RegExpCompiler
                         int capture_count);
 
     inline void AddWork(RegExpNode* node) {
+        AutoEnterOOMUnsafeRegion oomUnsafe;
         if (!work_list_.append(node))
-            CrashAtUnhandlableOOM("AddWork");
+            oomUnsafe.crash("AddWork");
     }
 
     static const int kImplementationOffset = 0;
@@ -2394,9 +2395,13 @@ BoyerMooreLookahead::EmitSkipInstructions(RegExpMacroAssembler* masm)
         return true;
     }
 
-    uint8_t* boolean_skip_table = static_cast(js_malloc(kSize));
-    if (!boolean_skip_table || !masm->shared->addTable(boolean_skip_table))
-        CrashAtUnhandlableOOM("Table malloc");
+    uint8_t* boolean_skip_table;
+    {
+        AutoEnterOOMUnsafeRegion oomUnsafe;
+        boolean_skip_table = static_cast(js_malloc(kSize));
+        if (!boolean_skip_table || !masm->shared->addTable(boolean_skip_table))
+            oomUnsafe.crash("Table malloc");
+    }
 
     int skip_distance = GetSkipTable(min_lookahead, max_lookahead, boolean_skip_table);
     MOZ_ASSERT(skip_distance != 0);
@@ -3101,9 +3106,13 @@ EmitUseLookupTable(RegExpMacroAssembler* masm,
     }
 
     // TODO(erikcorry): Cache these.
-    uint8_t* ba = static_cast(js_malloc(kSize));
-    if (!ba || !masm->shared->addTable(ba))
-        CrashAtUnhandlableOOM("Table malloc");
+    uint8_t* ba;
+    {
+        AutoEnterOOMUnsafeRegion oomUnsafe;
+        ba = static_cast(js_malloc(kSize));
+        if (!ba || !masm->shared->addTable(ba))
+            oomUnsafe.crash("Table malloc");
+    }
 
     for (int i = 0; i < kSize; i++)
         ba[i] = templ[i];
diff --git a/js/src/irregexp/RegExpMacroAssembler.cpp b/js/src/irregexp/RegExpMacroAssembler.cpp
index bf370a47a2f2..197c3f3b452d 100644
--- a/js/src/irregexp/RegExpMacroAssembler.cpp
+++ b/js/src/irregexp/RegExpMacroAssembler.cpp
@@ -523,12 +523,14 @@ InterpretedRegExpMacroAssembler::Emit8(uint32_t word)
 void
 InterpretedRegExpMacroAssembler::Expand()
 {
+    AutoEnterOOMUnsafeRegion oomUnsafe;
+
     int newLength = Max(100, length_ * 2);
     if (newLength < length_ + 4)
-        CrashAtUnhandlableOOM("InterpretedRegExpMacroAssembler::Expand");
+        oomUnsafe.crash("InterpretedRegExpMacroAssembler::Expand");
 
     buffer_ = (uint8_t*) js_realloc(buffer_, newLength);
     if (!buffer_)
-        CrashAtUnhandlableOOM("InterpretedRegExpMacroAssembler::Expand");
+        oomUnsafe.crash("InterpretedRegExpMacroAssembler::Expand");
     length_ = newLength;
 }
diff --git a/js/src/jit/IonAnalysis.cpp b/js/src/jit/IonAnalysis.cpp
index 2d6e3864cad0..60625437cad5 100644
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -322,8 +322,11 @@ MaybeFoldConditionBlock(MIRGraph& graph, MBasicBlock* initialBlock)
     }
 
     // Make sure the test block does not have any outgoing loop backedges.
-    if (!SplitCriticalEdgesForBlock(graph, testBlock))
-        CrashAtUnhandlableOOM("MaybeFoldConditionBlock");
+    {
+        AutoEnterOOMUnsafeRegion oomUnsafe;
+        if (!SplitCriticalEdgesForBlock(graph, testBlock))
+            oomUnsafe.crash("MaybeFoldConditionBlock");
+    }
 
     MPhi* phi;
     MTest* finalTest;
@@ -2932,8 +2935,9 @@ LinearSum::add(MDefinition* term, int32_t scale)
         }
     }
 
+    AutoEnterOOMUnsafeRegion oomUnsafe;
     if (!terms_.append(LinearTerm(term, scale)))
-        CrashAtUnhandlableOOM("LinearSum::add");
+        oomUnsafe.crash("LinearSum::add");
 
     return true;
 }
diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
index afb46ab68022..d4bd7ec7d21f 100644
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -11104,8 +11104,9 @@ IonBuilder::convertUnboxedObjects(MDefinition* obj)
             continue;
 
         if (UnboxedLayout* layout = key->group()->maybeUnboxedLayout()) {
+            AutoEnterOOMUnsafeRegion oomUnsafe;
             if (layout->nativeGroup() && !list.append(key->group()))
-                CrashAtUnhandlableOOM("IonBuilder::convertUnboxedObjects");
+                oomUnsafe.crash("IonBuilder::convertUnboxedObjects");
         }
     }
 
diff --git a/js/src/jit/LoopUnroller.cpp b/js/src/jit/LoopUnroller.cpp
index f31ff5a8c972..24ba03b4305f 100644
--- a/js/src/jit/LoopUnroller.cpp
+++ b/js/src/jit/LoopUnroller.cpp
@@ -46,7 +46,7 @@ struct LoopUnroller
 
     MDefinition* getReplacementDefinition(MDefinition* def);
     MResumePoint* makeReplacementResumePoint(MBasicBlock* block, MResumePoint* rp);
-    void makeReplacementInstruction(MInstruction* ins);
+    bool makeReplacementInstruction(MInstruction* ins);
 
     void go(LoopIterationBound* bound);
 };
@@ -76,7 +76,7 @@ LoopUnroller::getReplacementDefinition(MDefinition* def)
     return p->value();
 }
 
-void
+bool
 LoopUnroller::makeReplacementInstruction(MInstruction* ins)
 {
     MDefinitionVector inputs(alloc);
@@ -84,7 +84,7 @@ LoopUnroller::makeReplacementInstruction(MInstruction* ins)
         MDefinition* old = ins->getOperand(i);
         MDefinition* replacement = getReplacementDefinition(old);
         if (!inputs.append(replacement))
-            CrashAtUnhandlableOOM("LoopUnroller::makeReplacementDefinition");
+            return false;
     }
 
     MInstruction* clone = ins->clone(alloc, inputs);
@@ -92,12 +92,14 @@ LoopUnroller::makeReplacementInstruction(MInstruction* ins)
     unrolledBackedge->add(clone);
 
     if (!unrolledDefinitions.putNew(ins, clone))
-        CrashAtUnhandlableOOM("LoopUnroller::makeReplacementDefinition");
+        return false;
 
     if (MResumePoint* old = ins->resumePoint()) {
         MResumePoint* rp = makeReplacementResumePoint(unrolledBackedge, old);
         clone->setResumePoint(rp);
     }
+
+    return true;
 }
 
 MResumePoint*
@@ -108,12 +110,12 @@ LoopUnroller::makeReplacementResumePoint(MBasicBlock* block, MResumePoint* rp)
         MDefinition* old = rp->getOperand(i);
         MDefinition* replacement = old->isUnused() ? old : getReplacementDefinition(old);
         if (!inputs.append(replacement))
-            CrashAtUnhandlableOOM("LoopUnroller::makeReplacementResumePoint");
+            return nullptr;
     }
 
     MResumePoint* clone = MResumePoint::New(alloc, block, rp, inputs);
     if (!clone)
-        CrashAtUnhandlableOOM("LoopUnroller::makeReplacementResumePoint");
+        return nullptr;
 
     return clone;
 }
@@ -229,8 +231,12 @@ LoopUnroller::go(LoopIterationBound* bound)
     graph.insertBlockAfter(unrolledBackedge, newPreheader);
     graph.renumberBlocksAfter(oldPreheader);
 
+    // We don't tolerate allocation failure after this point.
+    // TODO: This is a bit drastic, is it possible to improve this?
+    AutoEnterOOMUnsafeRegion oomUnsafe;
+
     if (!unrolledDefinitions.init())
-        CrashAtUnhandlableOOM("LoopUnroller::go");
+        oomUnsafe.crash("LoopUnroller::go");
 
     // Add phis to the unrolled loop header which correspond to the phis in the
     // original loop header.
@@ -246,7 +252,7 @@ LoopUnroller::go(LoopIterationBound* bound)
         unrolledHeader->addPhi(phi);
 
         if (!phi->reserveLength(2))
-            CrashAtUnhandlableOOM("LoopUnroller::go");
+            oomUnsafe.crash("LoopUnroller::go");
 
         // Set the first input for the phi for now. We'll set the second after
         // finishing the unroll.
@@ -256,7 +262,7 @@ LoopUnroller::go(LoopIterationBound* bound)
         old->replaceOperand(0, phi);
 
         if (!unrolledDefinitions.putNew(old, phi))
-            CrashAtUnhandlableOOM("LoopUnroller::go");
+            oomUnsafe.crash("LoopUnroller::go");
     }
 
     // The loop condition can bail out on e.g. integer overflow, so make a
@@ -264,6 +270,8 @@ LoopUnroller::go(LoopIterationBound* bound)
     MResumePoint* headerResumePoint = header->entryResumePoint();
     if (headerResumePoint) {
         MResumePoint* rp = makeReplacementResumePoint(unrolledHeader, headerResumePoint);
+        if (!rp)
+            oomUnsafe.crash("LoopUnroller::makeReplacementResumePoint");
         unrolledHeader->setEntryResumePoint(rp);
 
         // Perform an interrupt check at the start of the unrolled loop.
@@ -285,6 +293,8 @@ LoopUnroller::go(LoopIterationBound* bound)
     // header does, so use the same resume point as for the unrolled header.
     if (headerResumePoint) {
         MResumePoint* rp = makeReplacementResumePoint(unrolledBackedge, headerResumePoint);
+        if (!rp)
+            oomUnsafe.crash("LoopUnroller::makeReplacementResumePoint");
         unrolledBackedge->setEntryResumePoint(rp);
     }
 
@@ -292,6 +302,8 @@ LoopUnroller::go(LoopIterationBound* bound)
     // instructions which use this but some other stuff wants one to be here.
     if (headerResumePoint) {
         MResumePoint* rp = makeReplacementResumePoint(newPreheader, headerResumePoint);
+        if (!rp)
+            oomUnsafe.crash("LoopUnroller::makeReplacementResumePoint");
         newPreheader->setEntryResumePoint(rp);
     }
 
@@ -305,7 +317,8 @@ LoopUnroller::go(LoopIterationBound* bound)
             for (MInstructionIterator iter(block->begin()); iter != block->end(); iter++) {
                 MInstruction* ins = *iter;
                 if (ins->canClone()) {
-                    makeReplacementInstruction(*iter);
+                    if (!makeReplacementInstruction(*iter))
+                        oomUnsafe.crash("LoopUnroller::makeReplacementDefinition");
                 } else {
                     // Control instructions are handled separately.
                     MOZ_ASSERT(ins->isTest() || ins->isGoto() || ins->isInterruptCheck());
@@ -321,7 +334,7 @@ LoopUnroller::go(LoopIterationBound* bound)
             MPhi* old = *iter;
             MDefinition* oldInput = old->getOperand(1);
             if (!phiValues.append(getReplacementDefinition(oldInput)))
-                CrashAtUnhandlableOOM("LoopUnroller::go");
+                oomUnsafe.crash("LoopUnroller::go");
         }
 
         unrolledDefinitions.clear();
@@ -343,7 +356,7 @@ LoopUnroller::go(LoopIterationBound* bound)
         for (MPhiIterator iter(header->phisBegin()); iter != header->phisEnd(); iter++) {
             MPhi* old = *iter;
             if (!unrolledDefinitions.putNew(old, phiValues[phiIndex++]))
-                CrashAtUnhandlableOOM("LoopUnroller::go");
+                oomUnsafe.crash("LoopUnroller::go");
         }
         MOZ_ASSERT(phiIndex == phiValues.length());
 
@@ -363,7 +376,7 @@ LoopUnroller::go(LoopIterationBound* bound)
 
     // Cleanup the MIR graph.
     if (!unrolledHeader->addPredecessorWithoutPhis(unrolledBackedge))
-        CrashAtUnhandlableOOM("LoopUnroller::go");
+        oomUnsafe.crash("LoopUnroller::go");
     header->replacePredecessor(oldPreheader, newPreheader);
     oldPreheader->setSuccessorWithPhis(unrolledHeader, 0);
     newPreheader->setSuccessorWithPhis(header, 0);
diff --git a/js/src/jit/MIRGraph.cpp b/js/src/jit/MIRGraph.cpp
index 64f588298cc8..4fb4b80826a3 100644
--- a/js/src/jit/MIRGraph.cpp
+++ b/js/src/jit/MIRGraph.cpp
@@ -107,8 +107,9 @@ MIRGenerator::addAbortedPreliminaryGroup(ObjectGroup* group)
         if (group == abortedPreliminaryGroups_[i])
             return;
     }
+    AutoEnterOOMUnsafeRegion oomUnsafe;
     if (!abortedPreliminaryGroups_.append(group))
-        CrashAtUnhandlableOOM("addAbortedPreliminaryGroup");
+        oomUnsafe.crash("addAbortedPreliminaryGroup");
 }
 
 bool
@@ -1137,16 +1138,18 @@ MBasicBlock::addPredecessorSameInputsAs(MBasicBlock* pred, MBasicBlock* existing
     MOZ_ASSERT(pred->hasLastIns());
     MOZ_ASSERT(!pred->successorWithPhis());
 
+    AutoEnterOOMUnsafeRegion oomUnsafe;
+
     if (!phisEmpty()) {
         size_t existingPosition = indexForPredecessor(existingPred);
         for (MPhiIterator iter = phisBegin(); iter != phisEnd(); iter++) {
             if (!iter->addInputSlow(iter->getOperand(existingPosition)))
-                CrashAtUnhandlableOOM("MBasicBlock::addPredecessorAdjustPhis");
+                oomUnsafe.crash("MBasicBlock::addPredecessorAdjustPhis");
         }
     }
 
     if (!predecessors_.append(pred))
-        CrashAtUnhandlableOOM("MBasicBlock::addPredecessorAdjustPhis");
+        oomUnsafe.crash("MBasicBlock::addPredecessorAdjustPhis");
 }
 
 bool
diff --git a/js/src/jit/arm/Simulator-arm.cpp b/js/src/jit/arm/Simulator-arm.cpp
index 5c30732f52cb..d369e759b828 100644
--- a/js/src/jit/arm/Simulator-arm.cpp
+++ b/js/src/jit/arm/Simulator-arm.cpp
@@ -967,9 +967,10 @@ GetCachePageLocked(Simulator::ICacheMap& i_cache, void* page)
     if (p)
         return p->value();
 
+    AutoEnterOOMUnsafeRegion oomUnsafe;
     CachePage* new_page = js_new();
     if (!new_page || !i_cache.add(p, page, new_page))
-        CrashAtUnhandlableOOM("Simulator CachePage");
+        oomUnsafe.crash("Simulator CachePage");
 
     return new_page;
 }
@@ -1197,9 +1198,10 @@ class Redirection
             }
         }
 
+        AutoEnterOOMUnsafeRegion oomUnsafe;
         Redirection* redir = (Redirection*)js_malloc(sizeof(Redirection));
         if (!redir)
-            CrashAtUnhandlableOOM("Simulator redirection");
+            oomUnsafe.crash("Simulator redirection");
         new(redir) Redirection(nativeFunction, type, sim);
         return redir;
     }
diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp
index fe485dc8f0d7..a017e85e16e5 100644
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -819,14 +819,15 @@ JSCompartment::setNewObjectMetadata(JSContext* cx, JSObject* obj)
     assertSameCompartment(cx, this, obj);
 
     if (JSObject* metadata = objectMetadataCallback(cx, obj)) {
+        AutoEnterOOMUnsafeRegion oomUnsafe;
         assertSameCompartment(cx, metadata);
         if (!objectMetadataTable) {
             objectMetadataTable = cx->new_(cx);
             if (!objectMetadataTable || !objectMetadataTable->init())
-                CrashAtUnhandlableOOM("setNewObjectMetadata");
+                oomUnsafe.crash("setNewObjectMetadata");
         }
         if (!objectMetadataTable->add(cx, obj, metadata))
-            CrashAtUnhandlableOOM("setNewObjectMetadata");
+            oomUnsafe.crash("setNewObjectMetadata");
     }
 }
 
diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp
index 6ff3c9616831..a8a0f528bce8 100644
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2015,19 +2015,30 @@ PtrIsInRange(const void* ptr, const void* start, size_t length)
 }
 #endif
 
-static bool
+static TenuredCell*
+AllocRelocatedCell(Zone* zone, AllocKind thingKind, size_t thingSize)
+{
+    AutoEnterOOMUnsafeRegion oomUnsafe;
+    void* dstAlloc = zone->arenas.allocateFromFreeList(thingKind, thingSize);
+    if (!dstAlloc)
+        dstAlloc = GCRuntime::refillFreeListInGC(zone, thingKind);
+    if (!dstAlloc) {
+        // This can only happen in zeal mode or debug builds as we don't
+        // otherwise relocate more cells than we have existing free space
+        // for.
+        oomUnsafe.crash("Could not allocate new arena while compacting");
+    }
+    return TenuredCell::fromPointer(dstAlloc);
+}
+
+static void
 RelocateCell(Zone* zone, TenuredCell* src, AllocKind thingKind, size_t thingSize)
 {
     JS::AutoSuppressGCAnalysis nogc(zone->runtimeFromMainThread());
 
     // Allocate a new cell.
     MOZ_ASSERT(zone == src->zone());
-    void* dstAlloc = zone->arenas.allocateFromFreeList(thingKind, thingSize);
-    if (!dstAlloc)
-        dstAlloc = GCRuntime::refillFreeListInGC(zone, thingKind);
-    if (!dstAlloc)
-        return false;
-    TenuredCell* dst = TenuredCell::fromPointer(dstAlloc);
+    TenuredCell* dst = AllocRelocatedCell(zone, thingKind, thingSize);
 
     // Copy source cell contents to destination.
     memcpy(dst, src, thingSize);
@@ -2068,8 +2079,6 @@ RelocateCell(Zone* zone, TenuredCell* src, AllocKind thingKind, size_t thingSize
     // Mark source cell as forwarded and leave a pointer to the destination.
     RelocationOverlay* overlay = RelocationOverlay::fromCell(src);
     overlay->forwardTo(dst);
-
-    return true;
 }
 
 static void
@@ -2086,12 +2095,7 @@ RelocateArena(ArenaHeader* aheader, SliceBudget& sliceBudget)
     size_t thingSize = aheader->getThingSize();
 
     for (ArenaCellIterUnderFinalize i(aheader); !i.done(); i.next()) {
-        if (!RelocateCell(zone, i.getCell(), thingKind, thingSize)) {
-            // This can only happen in zeal mode or debug builds as we don't
-            // otherwise relocate more cells than we have existing free space
-            // for.
-            CrashAtUnhandlableOOM("Could not allocate new arena while compacting");
-        }
+        RelocateCell(zone, i.getCell(), thingKind, thingSize);
         sliceBudget.step();
     }
 
@@ -3390,8 +3394,12 @@ GCHelperState::startBackgroundThread(State newState)
     MOZ_ASSERT(!thread && state() == IDLE && newState != IDLE);
     setState(newState);
 
-    if (!HelperThreadState().gcHelperWorklist().append(this))
-        CrashAtUnhandlableOOM("Could not add to pending GC helpers list");
+    {
+        AutoEnterOOMUnsafeRegion noOOM;
+        if (!HelperThreadState().gcHelperWorklist().append(this))
+            noOOM.crash("Could not add to pending GC helpers list");
+    }
+
     HelperThreadState().notifyAll(GlobalHelperThreadState::PRODUCER);
 }
 
@@ -4204,8 +4212,9 @@ js::gc::MarkingValidator::nonIncrementalMark()
         return;
 
     for (gc::WeakKeyTable::Range r = gc->marker.weakKeys.all(); !r.empty(); r.popFront()) {
+        AutoEnterOOMUnsafeRegion oomUnsafe;
         if (!savedWeakKeys.put(Move(r.front().key), Move(r.front().value)))
-            CrashAtUnhandlableOOM("saving weak keys table for validator");
+            oomUnsafe.crash("saving weak keys table for validator");
     }
 
     /*
@@ -4282,8 +4291,9 @@ js::gc::MarkingValidator::nonIncrementalMark()
 
     gc->marker.weakKeys.clear();
     for (gc::WeakKeyTable::Range r = savedWeakKeys.all(); !r.empty(); r.popFront()) {
+        AutoEnterOOMUnsafeRegion oomUnsafe;
         if (!gc->marker.weakKeys.put(Move(r.front().key), Move(r.front().value)))
-            CrashAtUnhandlableOOM("restoring weak keys table for validator");
+            oomUnsafe.crash("restoring weak keys table for validator");
     }
 
     gc->incrementalState = state;
diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp
index 52211056b872..66971d9b9365 100644
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1498,7 +1498,7 @@ js::XDRObjectLiteral(XDRState* xdr, MutableHandleObject obj);
 template bool
 js::XDRObjectLiteral(XDRState* xdr, MutableHandleObject obj);
 
-void
+bool
 NativeObject::fillInAfterSwap(JSContext* cx, const Vector& values, void* priv)
 {
     // This object has just been swapped with some other object, and its shape
@@ -1510,7 +1510,7 @@ NativeObject::fillInAfterSwap(JSContext* cx, const Vector& values, void*
     size_t nfixed = gc::GetGCKindSlots(asTenured().getAllocKind(), getClass());
     if (nfixed != shape_->numFixedSlots()) {
         if (!generateOwnShape(cx))
-            CrashAtUnhandlableOOM("fillInAfterSwap");
+            return false;
         shape_->setNumFixedSlots(nfixed);
     }
 
@@ -1527,11 +1527,12 @@ NativeObject::fillInAfterSwap(JSContext* cx, const Vector& values, void*
     if (size_t ndynamic = dynamicSlotsCount(nfixed, values.length(), getClass())) {
         slots_ = cx->zone()->pod_malloc(ndynamic);
         if (!slots_)
-            CrashAtUnhandlableOOM("fillInAfterSwap");
+            return false;
         Debug_SetSlotRangeToCrashOnTouch(slots_, ndynamic);
     }
 
     initSlotRange(0, values.begin(), values.length());
+    return true;
 }
 
 void
@@ -1552,12 +1553,14 @@ JSObject::swap(JSContext* cx, HandleObject a, HandleObject b)
                IsBackgroundFinalized(b->asTenured().getAllocKind()));
     MOZ_ASSERT(a->compartment() == b->compartment());
 
+    AutoEnterOOMUnsafeRegion oomUnsafe;
+
     AutoCompartment ac(cx, a);
 
     if (!a->getGroup(cx))
-        CrashAtUnhandlableOOM("JSObject::swap");
+        oomUnsafe.crash("JSObject::swap");
     if (!b->getGroup(cx))
-        CrashAtUnhandlableOOM("JSObject::swap");
+        oomUnsafe.crash("JSObject::swap");
 
     /*
      * Neither object may be in the nursery, but ensure we update any embedded
@@ -1616,7 +1619,7 @@ JSObject::swap(JSContext* cx, HandleObject a, HandleObject b)
             apriv = na->hasPrivate() ? na->getPrivate() : nullptr;
             for (size_t i = 0; i < na->slotSpan(); i++) {
                 if (!avals.append(na->getSlot(i)))
-                    CrashAtUnhandlableOOM("JSObject::swap");
+                    oomUnsafe.crash("JSObject::swap");
             }
         }
         Vector bvals(cx);
@@ -1625,7 +1628,7 @@ JSObject::swap(JSContext* cx, HandleObject a, HandleObject b)
             bpriv = nb->hasPrivate() ? nb->getPrivate() : nullptr;
             for (size_t i = 0; i < nb->slotSpan(); i++) {
                 if (!bvals.append(nb->getSlot(i)))
-                    CrashAtUnhandlableOOM("JSObject::swap");
+                    oomUnsafe.crash("JSObject::swap");
             }
         }
 
@@ -1638,10 +1641,10 @@ JSObject::swap(JSContext* cx, HandleObject a, HandleObject b)
         a->fixDictionaryShapeAfterSwap();
         b->fixDictionaryShapeAfterSwap();
 
-        if (na)
-            b->as().fillInAfterSwap(cx, avals, apriv);
-        if (nb)
-            a->as().fillInAfterSwap(cx, bvals, bpriv);
+        if (na && !b->as().fillInAfterSwap(cx, avals, apriv))
+            oomUnsafe.crash("fillInAfterSwap");
+        if (nb && !a->as().fillInAfterSwap(cx, bvals, bpriv))
+            oomUnsafe.crash("fillInAfterSwap");
     }
 
     // Swapping the contents of two objects invalidates type sets which contain
diff --git a/js/src/vm/ArgumentsObject.cpp b/js/src/vm/ArgumentsObject.cpp
index b8cc2371d104..191ac0b78aa3 100644
--- a/js/src/vm/ArgumentsObject.cpp
+++ b/js/src/vm/ArgumentsObject.cpp
@@ -611,10 +611,11 @@ ArgumentsObject::objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject
         return 0;
     }
 
+    AutoEnterOOMUnsafeRegion oomUnsafe;
     uint32_t nbytes = nsrc->data()->dataBytes;
     uint8_t* data = nsrc->zone()->pod_malloc(nbytes);
     if (!data)
-        CrashAtUnhandlableOOM("Failed to allocate ArgumentsObject data while tenuring.");
+        oomUnsafe.crash("Failed to allocate ArgumentsObject data while tenuring.");
     ndst->initFixedSlot(DATA_SLOT, PrivateValue(data));
 
     mozilla::PodCopy(data, reinterpret_cast(nsrc->data()), nbytes);
diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp
index 2c1a4b4669c0..9a3588f35060 100644
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -523,8 +523,9 @@ ArrayBufferObject::neuter(JSContext* cx, Handle buffer,
     if (buffer->hasTypedObjectViews()) {
         // Make sure the global object's group has been instantiated, so the
         // flag change will be observed.
+        AutoEnterOOMUnsafeRegion oomUnsafe;
         if (!cx->global()->getGroup(cx))
-            CrashAtUnhandlableOOM("ArrayBufferObject::neuter");
+            oomUnsafe.crash("ArrayBufferObject::neuter");
         MarkObjectGroupFlags(cx, cx->global(), OBJECT_FLAG_TYPED_OBJECT_NEUTERED);
         cx->compartment()->neuteredTypedObjects = 1;
     }
diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp
index f710c81f7bbc..2f3a2978df6c 100644
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -1713,12 +1713,14 @@ Debugger::TenurePromotionsLogEntry::TenurePromotionsLogEntry(JSRuntime* rt, JSOb
 void
 Debugger::logTenurePromotion(JSRuntime* rt, JSObject& obj, double when)
 {
+    AutoEnterOOMUnsafeRegion oomUnsafe;
+
     if (!tenurePromotionsLog.emplaceBack(rt, obj, when))
-        CrashAtUnhandlableOOM("Debugger::logTenurePromotion");
+        oomUnsafe.crash("Debugger::logTenurePromotion");
 
     if (tenurePromotionsLog.length() > maxTenurePromotionsLogLength) {
         if (!tenurePromotionsLog.popFront())
-            CrashAtUnhandlableOOM("Debugger::logTenurePromotion");
+            oomUnsafe.crash("Debugger::logTenurePromotion");
         MOZ_ASSERT(tenurePromotionsLog.length() == maxTenurePromotionsLogLength);
         tenurePromotionsLogOverflowed = true;
     }
@@ -3437,15 +3439,15 @@ Debugger::addDebuggeeGlobal(JSContext* cx, Handle global)
     return true;
 }
 
-bool
+void
 Debugger::recomputeDebuggeeZoneSet()
 {
+    AutoEnterOOMUnsafeRegion oomUnsafe;
     debuggeeZones.clear();
     for (auto range = debuggees.all(); !range.empty(); range.popFront()) {
         if (!debuggeeZones.put(range.front()->zone()))
-            return false;
+            oomUnsafe.crash("Debugger::removeDebuggeeGlobal");
     }
-    return true;
 }
 
 template
@@ -3514,8 +3516,8 @@ Debugger::removeDebuggeeGlobal(FreeOp* fop, GlobalObject* global,
     else
         debuggees.remove(global);
 
-    if (!recomputeDebuggeeZoneSet())
-        CrashAtUnhandlableOOM("Debugger::removeDebuggeeGlobal");
+    recomputeDebuggeeZoneSet();
+
     if (!debuggeeZones.has(global->zone()))
         zoneDebuggersVector->erase(findDebuggerInVector(this, zoneDebuggersVector));
 
diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h
index b291805bbb34..7f10b461013f 100644
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -372,7 +372,7 @@ class Debugger : private mozilla::LinkedListElement
     /*
      * Recompute the set of debuggee zones based on the set of debuggee globals.
      */
-    bool recomputeDebuggeeZoneSet();
+    void recomputeDebuggeeZoneSet();
 
     /*
      * Return true if there is an existing object metadata callback for the
diff --git a/js/src/vm/HelperThreads.cpp b/js/src/vm/HelperThreads.cpp
index 203d3a394102..dbc6fd84b3d0 100644
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -117,8 +117,9 @@ js::StartOffThreadIonCompile(JSContext* cx, jit::IonBuilder* builder)
 static void
 FinishOffThreadIonCompile(jit::IonBuilder* builder)
 {
+    AutoEnterOOMUnsafeRegion oomUnsafe;
     if (!HelperThreadState().ionFinishedList().append(builder))
-        CrashAtUnhandlableOOM("FinishOffThreadIonCompile");
+        oomUnsafe.crash("FinishOffThreadIonCompile");
 }
 
 static inline bool
diff --git a/js/src/vm/NativeObject.cpp b/js/src/vm/NativeObject.cpp
index 6633b1468166..404e400b80e2 100644
--- a/js/src/vm/NativeObject.cpp
+++ b/js/src/vm/NativeObject.cpp
@@ -364,8 +364,9 @@ NativeObject::setLastPropertyMakeNative(ExclusiveContext* cx, Shape* shape)
 
     // A failure at this point will leave the object as a mutant, and we
     // can't recover.
+    AutoEnterOOMUnsafeRegion oomUnsafe;
     if (oldSpan != newSpan && !updateSlotsForSpan(cx, oldSpan, newSpan))
-        CrashAtUnhandlableOOM("NativeObject::setLastPropertyMakeNative");
+        oomUnsafe.crash("NativeObject::setLastPropertyMakeNative");
 }
 
 bool
diff --git a/js/src/vm/NativeObject.h b/js/src/vm/NativeObject.h
index 7f7624e524bb..3eb575ecf1e8 100644
--- a/js/src/vm/NativeObject.h
+++ b/js/src/vm/NativeObject.h
@@ -713,7 +713,7 @@ class NativeObject : public JSObject
                         JSGetterOp getter, JSSetterOp setter, uint32_t slot, unsigned attrs,
                         unsigned flags, ShapeTable::Entry* entry, bool allowDictionary);
 
-    void fillInAfterSwap(JSContext* cx, const Vector& values, void* priv);
+    bool fillInAfterSwap(JSContext* cx, const Vector& values, void* priv);
 
   public:
     // Return true if this object has been converted from shared-immutable
diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h
index 68d1e366e304..1b23c29ad325 100644
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -1854,8 +1854,9 @@ FreeOp::freeLater(void* p)
     // and won't hold onto the pointers to free indefinitely.
     MOZ_ASSERT(this != runtime()->defaultFreeOp());
 
+    AutoEnterOOMUnsafeRegion oomUnsafe;
     if (!freeLaterList.append(p))
-        CrashAtUnhandlableOOM("FreeOp::freeLater");
+        oomUnsafe.crash("FreeOp::freeLater");
 }
 
 /*
diff --git a/js/src/vm/SavedStacks.cpp b/js/src/vm/SavedStacks.cpp
index 502c9d0fbd84..6063229f2d78 100644
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -1369,12 +1369,13 @@ SavedStacksMetadataCallback(JSContext* cx, JSObject* target)
                                                 std::log(notSamplingProb));
     }
 
+    AutoEnterOOMUnsafeRegion oomUnsafe;
     RootedSavedFrame frame(cx);
     if (!stacks.saveCurrentStack(cx, &frame))
-        CrashAtUnhandlableOOM("SavedStacksMetadataCallback");
+        oomUnsafe.crash("SavedStacksMetadataCallback");
 
     if (!Debugger::onLogAllocationSite(cx, obj, frame, JS_GetCurrentEmbedderTime()))
-        CrashAtUnhandlableOOM("SavedStacksMetadataCallback");
+        oomUnsafe.crash("SavedStacksMetadataCallback");
 
     MOZ_ASSERT_IF(frame, !frame->is());
     return frame;
diff --git a/js/src/vm/TypeInference.cpp b/js/src/vm/TypeInference.cpp
index 6558561721f2..a202fb991b80 100644
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -1277,9 +1277,12 @@ js::EnsureTrackPropertyTypes(JSContext* cx, JSObject* obj, jsid id)
 
     if (obj->isSingleton()) {
         AutoEnterAnalysis enter(cx);
-        if (obj->hasLazyGroup() && !obj->getGroup(cx)) {
-            CrashAtUnhandlableOOM("Could not allocate ObjectGroup in EnsureTrackPropertyTypes");
-            return;
+        if (obj->hasLazyGroup()) {
+            AutoEnterOOMUnsafeRegion oomUnsafe;
+            if (!obj->getGroup(cx)) {
+                oomUnsafe.crash("Could not allocate ObjectGroup in EnsureTrackPropertyTypes");
+                return;
+            }
         }
         if (!obj->group()->unknownProperties() && !obj->group()->getProperty(cx, obj, id)) {
             MOZ_ASSERT(obj->group()->unknownProperties());
@@ -2460,8 +2463,9 @@ TypeZone::processPendingRecompiles(FreeOp* fop, RecompileInfoVector& recompiles)
      */
     RecompileInfoVector pending;
     for (size_t i = 0; i < recompiles.length(); i++) {
+        AutoEnterOOMUnsafeRegion oomUnsafe;
         if (!pending.append(recompiles[i]))
-            CrashAtUnhandlableOOM("processPendingRecompiles");
+            oomUnsafe.crash("processPendingRecompiles");
     }
     recompiles.clear();
 
@@ -2482,8 +2486,9 @@ TypeZone::addPendingRecompile(JSContext* cx, const RecompileInfo& info)
 
     co->setPendingInvalidation();
 
+    AutoEnterOOMUnsafeRegion oomUnsafe;
     if (!cx->zone()->types.activeAnalysis->pendingRecompiles.append(info))
-        CrashAtUnhandlableOOM("Could not update pendingRecompiles");
+        oomUnsafe.crash("Could not update pendingRecompiles");
 }
 
 void
@@ -3768,10 +3773,11 @@ TypeNewScript::maybeAnalyze(JSContext* cx, ObjectGroup* group, bool* regenerate,
         // with an unboxed layout. Currently it is a mutant object with a
         // non-native group and native shape, so make it safe for GC by changing
         // its group to the default for its prototype.
+        AutoEnterOOMUnsafeRegion oomUnsafe;
         ObjectGroup* plainGroup = ObjectGroup::defaultNewGroup(cx, &PlainObject::class_,
                                                                group->proto());
         if (!plainGroup)
-            CrashAtUnhandlableOOM("TypeNewScript::maybeAnalyze");
+            oomUnsafe.crash("TypeNewScript::maybeAnalyze");
         templateObject_->setGroup(plainGroup);
         templateObject_ = nullptr;
 
@@ -3858,10 +3864,10 @@ TypeNewScript::rollbackPartiallyInitializedObjects(JSContext* cx, ObjectGroup* g
             continue;
         }
 
-        if (thisv.toObject().is() &&
-            !UnboxedPlainObject::convertToNative(cx, &thisv.toObject()))
-        {
-            CrashAtUnhandlableOOM("rollbackPartiallyInitializedObjects");
+        if (thisv.toObject().is()) {
+            AutoEnterOOMUnsafeRegion oomUnsafe;
+            if (!UnboxedPlainObject::convertToNative(cx, &thisv.toObject()))
+                oomUnsafe.crash("rollbackPartiallyInitializedObjects");
         }
 
         // Found a matching frame.
@@ -3995,13 +4001,15 @@ ConstraintTypeSet::trace(Zone* zone, JSTracer* trc)
             if (!key)
                 continue;
             TraceObjectKey(trc, &key);
+
+            AutoEnterOOMUnsafeRegion oomUnsafe;
             ObjectKey** pentry =
                 TypeHashSet::Insert
                     (zone->types.typeLifoAlloc, objectSet, objectCount, key);
-            if (pentry)
-                *pentry = key;
-            else
-                CrashAtUnhandlableOOM("ConstraintTypeSet::trace");
+            if (!pentry)
+                oomUnsafe.crash("ConstraintTypeSet::trace");
+
+            *pentry = key;
         }
         setBaseObjectCount(objectCount);
     } else if (objectCount == 1) {
diff --git a/js/src/vm/UnboxedObject.cpp b/js/src/vm/UnboxedObject.cpp
index 1536ddd028bc..1cb7c1906cda 100644
--- a/js/src/vm/UnboxedObject.cpp
+++ b/js/src/vm/UnboxedObject.cpp
@@ -1224,9 +1224,10 @@ UnboxedArrayObject::objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObj
     } else {
         MOZ_ASSERT(allocKind == gc::AllocKind::OBJECT0);
 
+        AutoEnterOOMUnsafeRegion oomUnsafe;
         uint8_t* data = nsrc->zone()->pod_malloc(nbytes);
         if (!data)
-            CrashAtUnhandlableOOM("Failed to allocate unboxed array elements while tenuring.");
+            oomUnsafe.crash("Failed to allocate unboxed array elements while tenuring.");
         ndst->elements_ = data;
     }
 
@@ -1883,8 +1884,10 @@ UnboxedArrayObject::fillAfterConvert(ExclusiveContext* cx,
     if (!initlen)
         return;
 
+    AutoEnterOOMUnsafeRegion oomUnsafe;
     if (!growElements(cx, initlen))
-        CrashAtUnhandlableOOM("UnboxedArrayObject::fillAfterConvert");
+        oomUnsafe.crash("UnboxedArrayObject::fillAfterConvert");
+
     setInitializedLength(initlen);
 
     for (size_t i = 0; i < size_t(initlen); i++)

From 416bd71ac3e5e0e444937203d4e56034077e38f3 Mon Sep 17 00:00:00 2001
From: Jon Coppeard 
Date: Mon, 21 Sep 2015 14:31:51 +0100
Subject: [PATCH 025/133] Bug 1201057 - Update shell args for OOM tests now we
 don't have to worry about unhandlable OOMs r=terrence

---
 js/src/jit-test/tests/gc/bug-1165966.js          | 2 +-
 js/src/jit-test/tests/gc/bug-1171909.js          | 2 +-
 js/src/jit-test/tests/gc/oomInDebugger.js        | 2 +-
 js/src/jit-test/tests/gc/oomInFormatStackDump.js | 2 +-
 js/src/jit-test/tests/gc/oomInNewGlobal.js       | 2 +-
 js/src/jit-test/tests/gc/oomInParseFunction.js   | 2 +-
 js/src/jit-test/tests/gc/oomInWeakMap.js         | 2 +-
 7 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/js/src/jit-test/tests/gc/bug-1165966.js b/js/src/jit-test/tests/gc/bug-1165966.js
index 0cdaabd1feb5..24464e68343a 100644
--- a/js/src/jit-test/tests/gc/bug-1165966.js
+++ b/js/src/jit-test/tests/gc/bug-1165966.js
@@ -1,4 +1,4 @@
-// |jit-test| --no-ggc; allow-unhandlable-oom; --no-ion
+// |jit-test| --no-threads; --no-ion
 load(libdir + 'oomTest.js');
 var g = newGlobal();
 oomTest(function() {
diff --git a/js/src/jit-test/tests/gc/bug-1171909.js b/js/src/jit-test/tests/gc/bug-1171909.js
index 590c41b78220..01179fa052ad 100644
--- a/js/src/jit-test/tests/gc/bug-1171909.js
+++ b/js/src/jit-test/tests/gc/bug-1171909.js
@@ -1,3 +1,3 @@
-// |jit-test| --no-ggc; allow-unhandlable-oom
+// |jit-test| --no-threads; allow-unhandlable-oom
 load(libdir + 'oomTest.js');
 oomTest((function(x) { assertEq(x + y + ex, 25); }));
diff --git a/js/src/jit-test/tests/gc/oomInDebugger.js b/js/src/jit-test/tests/gc/oomInDebugger.js
index f17ed281a538..39cae89bf28f 100644
--- a/js/src/jit-test/tests/gc/oomInDebugger.js
+++ b/js/src/jit-test/tests/gc/oomInDebugger.js
@@ -1,4 +1,4 @@
-// |jit-test| --no-ggc; allow-unhandlable-oom
+// |jit-test| --no-threads
 
 load(libdir + 'oomTest.js');
 var g = newGlobal();
diff --git a/js/src/jit-test/tests/gc/oomInFormatStackDump.js b/js/src/jit-test/tests/gc/oomInFormatStackDump.js
index 6a64a5076f3c..4c2ea4feefaf 100644
--- a/js/src/jit-test/tests/gc/oomInFormatStackDump.js
+++ b/js/src/jit-test/tests/gc/oomInFormatStackDump.js
@@ -1,4 +1,4 @@
-// |jit-test| --no-ggc; allow-unhandlable-oom; --no-threads
+// |jit-test| --no-threads
 
 load(libdir + 'oomTest.js');
 oomTest(() => getBacktrace({args: true, locals: true, thisprops: true}));
diff --git a/js/src/jit-test/tests/gc/oomInNewGlobal.js b/js/src/jit-test/tests/gc/oomInNewGlobal.js
index 64c2054d5717..b12d1d49ae62 100644
--- a/js/src/jit-test/tests/gc/oomInNewGlobal.js
+++ b/js/src/jit-test/tests/gc/oomInNewGlobal.js
@@ -1,4 +1,4 @@
-// |jit-test| --no-ggc; allow-unhandlable-oom
+// |jit-test| --no-threads
 
 load(libdir + 'oomTest.js');
 oomTest(newGlobal);
diff --git a/js/src/jit-test/tests/gc/oomInParseFunction.js b/js/src/jit-test/tests/gc/oomInParseFunction.js
index 672f9dfd4b9d..e25eccb5ba48 100644
--- a/js/src/jit-test/tests/gc/oomInParseFunction.js
+++ b/js/src/jit-test/tests/gc/oomInParseFunction.js
@@ -1,4 +1,4 @@
-// |jit-test| --no-ggc; allow-unhandlable-oom
+// |jit-test| --no-threads
 
 load(libdir + 'oomTest.js');
 oomTest(() => eval("function f() {}"));
diff --git a/js/src/jit-test/tests/gc/oomInWeakMap.js b/js/src/jit-test/tests/gc/oomInWeakMap.js
index df9867fc647e..2cc1fb8c5ab9 100644
--- a/js/src/jit-test/tests/gc/oomInWeakMap.js
+++ b/js/src/jit-test/tests/gc/oomInWeakMap.js
@@ -1,4 +1,4 @@
-// |jit-test| --no-ggc; allow-unhandlable-oom; --no-threads
+// |jit-test| --no-threads
 
 load(libdir + 'oomTest.js');
 oomTest(function () {

From d01f456063c06ce311377af445a60bd8bddb6fbe Mon Sep 17 00:00:00 2001
From: Jim Chen 
Date: Mon, 21 Sep 2015 10:13:32 -0400
Subject: [PATCH 026/133] Bug 1197976 - Use runnable events for nsAppShell
 event loop; r=snorp nsAppShell is currently based on AndroidGeckoEvent
 objects, which mirror GeckoEvent on the Java side. With GeckoEvent going
 away, we will be gradually removing AndroidGeckoEvent as well. This patch
 makes the nsAppShell event loop based on runnable objects, which derive from
 nsAppShell::Event. Using runnable objects is much more flexible and allows
 us, for example, to post a lambda to the event loop to be run later.

---
 widget/android/nsAppShell.cpp |  56 ++-------------
 widget/android/nsAppShell.h   | 131 +++++++++++++++++++++++++++++-----
 2 files changed, 119 insertions(+), 68 deletions(-)

diff --git a/widget/android/nsAppShell.cpp b/widget/android/nsAppShell.cpp
index b3ff9072e163..466cf01b5fab 100644
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -30,9 +30,7 @@
 #include "nsCDefaultURIFixup.h"
 #include "nsToolkitCompsCID.h"
 
-#include "mozilla/HangMonitor.h"
 #include "mozilla/Services.h"
-#include "mozilla/unused.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Hal.h"
 #include "prenv.h"
@@ -185,10 +183,7 @@ public:
 };
 
 nsAppShell::nsAppShell()
-    : mQueueLock("nsAppShell.mQueueLock"),
-      mCondLock("nsAppShell.mCondLock"),
-      mQueueCond(mCondLock, "nsAppShell.mQueueCond"),
-      mQueuedViewportEvent(nullptr)
+    : mQueuedViewportEvent(nullptr)
 {
     gAppShell = this;
 
@@ -216,6 +211,10 @@ nsAppShell::nsAppShell()
 
 nsAppShell::~nsAppShell()
 {
+    while (mEventQueue.Pop(/* mayWait */ false)) {
+        NS_WARNING("Discarded event on shutdown");
+    }
+
     gAppShell = nullptr;
 
     if (sPowerManagerService) {
@@ -233,8 +232,7 @@ nsAppShell::~nsAppShell()
 void
 nsAppShell::NotifyNativeEvent()
 {
-    MutexAutoLock lock(mCondLock);
-    mQueueCond.Notify();
+    mEventQueue.Signal();
 }
 
 #define PREFNAME_COALESCE_TOUCHES "dom.event.touch.coalescing.enabled"
@@ -312,15 +310,6 @@ nsAppShell::Observe(nsISupports* aSubject,
     return NS_OK;
 }
 
-void
-nsAppShell::ScheduleNativeEventCallback()
-{
-    EVLOG("nsAppShell::ScheduleNativeEventCallback pth: %p thread: %p main: %d", (void*) pthread_self(), (void*) NS_GetCurrentThread(), NS_IsMainThread());
-
-    // this is valid to be called from any thread, so do so.
-    PostEvent(AndroidGeckoEvent::MakeNativePoke());
-}
-
 bool
 nsAppShell::ProcessNextNativeEvent(bool mayWait)
 {
@@ -818,34 +807,6 @@ nsAppShell::ResendLastResizeEvent(nsWindow* aDest) {
     }
 }
 
-AndroidGeckoEvent*
-nsAppShell::PopNextEvent()
-{
-    AndroidGeckoEvent *ae = nullptr;
-    MutexAutoLock lock(mQueueLock);
-    if (mEventQueue.Length()) {
-        ae = mEventQueue[0];
-        mEventQueue.RemoveElementAt(0);
-        if (mQueuedViewportEvent == ae) {
-            mQueuedViewportEvent = nullptr;
-        }
-    }
-
-    return ae;
-}
-
-AndroidGeckoEvent*
-nsAppShell::PeekNextEvent()
-{
-    AndroidGeckoEvent *ae = nullptr;
-    MutexAutoLock lock(mQueueLock);
-    if (mEventQueue.Length()) {
-        ae = mEventQueue[0];
-    }
-
-    return ae;
-}
-
 void
 nsAppShell::PostEvent(AndroidGeckoEvent *ae)
 {
@@ -921,11 +882,6 @@ nsAppShell::PostEvent(AndroidGeckoEvent *ae)
     NotifyNativeEvent();
 }
 
-void
-nsAppShell::OnResume()
-{
-}
-
 nsresult
 nsAppShell::AddObserver(const nsAString &aObserverKey, nsIObserver *aObserver)
 {
diff --git a/widget/android/nsAppShell.h b/widget/android/nsAppShell.h
index f7c4c51266d4..1fc46c1c0eb7 100644
--- a/widget/android/nsAppShell.h
+++ b/widget/android/nsAppShell.h
@@ -6,8 +6,12 @@
 #ifndef nsAppShell_h__
 #define nsAppShell_h__
 
-#include "mozilla/CondVar.h"
-#include "mozilla/Mutex.h"
+#include "mozilla/HangMonitor.h"
+#include "mozilla/LinkedList.h"
+#include "mozilla/Monitor.h"
+#include "mozilla/Move.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/unused.h"
 #include "nsBaseAppShell.h"
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
@@ -25,10 +29,41 @@ class nsWindow;
 class nsAppShell :
     public nsBaseAppShell
 {
-    typedef mozilla::CondVar CondVar;
-    typedef mozilla::Mutex Mutex;
-
 public:
+    struct Event : mozilla::LinkedListElement
+    {
+        bool HasSameTypeAs(const Event* other) const
+        {
+            // Compare vtable addresses to determine same type.
+            return *reinterpret_cast(this)
+                    == *reinterpret_cast(other);
+        }
+
+        virtual ~Event() {}
+        virtual void Run() = 0;
+
+        virtual void PostTo(mozilla::LinkedList& queue)
+        {
+            queue.insertBack(this);
+        }
+
+        virtual mozilla::HangMonitor::ActivityType ActivityType() const
+        {
+            return mozilla::HangMonitor::kGeneralActivity;
+        }
+    };
+
+    template
+    class LambdaEvent : public Event
+    {
+    protected:
+        T lambda;
+
+    public:
+        LambdaEvent(T&& l) : lambda(mozilla::Move(l)) {}
+        void Run() override { return lambda(); }
+    };
+
     static nsAppShell *gAppShell;
     static mozilla::AndroidGeckoEvent *gEarlyEvent;
 
@@ -40,15 +75,31 @@ public:
     nsresult Init();
 
     void NotifyNativeEvent();
+    bool ProcessNextNativeEvent(bool mayWait) override;
 
-    virtual bool ProcessNextNativeEvent(bool mayWait) override;
+    // Post a subclass of Event.
+    // e.g. PostEvent(mozilla::MakeUnique());
+    template
+    void PostEvent(mozilla::UniquePtr&& event)
+    {
+        mEventQueue.Post(mozilla::Move(event));
+    }
 
-    void PostEvent(mozilla::AndroidGeckoEvent *event);
-    void OnResume();
+    // Post a event that will call a lambda
+    // e.g. PostEvent([=] { /* do something */ });
+    template
+    void PostEvent(T&& lambda)
+    {
+        mEventQueue.Post(mozilla::MakeUnique>(
+                mozilla::Move(lambda)));
+    }
+
+    void PostEvent(mozilla::AndroidGeckoEvent* event);
 
-    nsresult AddObserver(const nsAString &aObserverKey, nsIObserver *aObserver);
     void ResendLastResizeEvent(nsWindow* aDest);
 
+    void OnResume() {}
+
     void SetBrowserApp(nsIAndroidBrowserApp* aBrowserApp) {
         mBrowserApp = aBrowserApp;
     }
@@ -58,21 +109,65 @@ public:
     }
 
 protected:
-    virtual void ScheduleNativeEventCallback() override;
     virtual ~nsAppShell();
 
-    Mutex mQueueLock;
-    Mutex mCondLock;
-    CondVar mQueueCond;
+    nsresult AddObserver(const nsAString &aObserverKey, nsIObserver *aObserver);
+
+    void ScheduleNativeEventCallback() override
+    {
+        // Capturing the nsAppShell instance is safe because if the app
+        // shell is detroyed, this lambda will not be called either.
+        PostEvent([this] {
+            NativeEventCallback();
+        });
+    }
+
+    class Queue
+    {
+        mozilla::Monitor mMonitor;
+        mozilla::LinkedList mQueue;
+
+    public:
+        Queue() : mMonitor("nsAppShell.Queue")
+        {}
+
+        void Signal()
+        {
+            mozilla::MonitorAutoLock lock(mMonitor);
+            lock.NotifyAll();
+        }
+
+        void Post(mozilla::UniquePtr&& event)
+        {
+            MOZ_ASSERT(event && !event->isInList());
+
+            mozilla::MonitorAutoLock lock(mMonitor);
+            event->PostTo(mQueue);
+            if (event->isInList()) {
+                // Ownership of event object transfers to the queue.
+                mozilla::unused << event.release();
+            }
+            lock.NotifyAll();
+        }
+
+        mozilla::UniquePtr Pop(bool mayWait)
+        {
+            mozilla::MonitorAutoLock lock(mMonitor);
+
+            if (mayWait && mQueue.isEmpty()) {
+                lock.Wait();
+            }
+            // Ownership of event object transfers to the return value.
+            return mozilla::UniquePtr(mQueue.popFirst());
+        }
+
+    } mEventQueue;
+
     mozilla::AndroidGeckoEvent *mQueuedViewportEvent;
     bool mAllowCoalescingTouches;
-    nsTArray mEventQueue;
-    nsInterfaceHashtable mObserversHash;
-
-    mozilla::AndroidGeckoEvent *PopNextEvent();
-    mozilla::AndroidGeckoEvent *PeekNextEvent();
 
     nsCOMPtr mBrowserApp;
+    nsInterfaceHashtable mObserversHash;
 };
 
 #endif // nsAppShell_h__

From f57ad9e80a7bc3b3dbb3717d1b6304f099c8f064 Mon Sep 17 00:00:00 2001
From: Jim Chen 
Date: Mon, 21 Sep 2015 10:13:32 -0400
Subject: [PATCH 027/133] Bug 1197976 - Provide compatibility with
 AndroidGeckoEvent; r=snorp With the new nsAppShell event loop based on
 runnable events, we need to implement AndroidGeckoEvent handling as a
 runnable event. This patch adds nsAppShell::LegacyGeckoEvent and adopts its
 implementation from existing code that handle AndroidGeckoEvent.

---
 widget/android/nsAppShell.cpp | 175 ++++++++++++++++++++--------------
 widget/android/nsAppShell.h   |   9 +-
 2 files changed, 109 insertions(+), 75 deletions(-)

diff --git a/widget/android/nsAppShell.cpp b/widget/android/nsAppShell.cpp
index 466cf01b5fab..f93e5fb8530e 100644
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -318,11 +318,11 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
     PROFILER_LABEL("nsAppShell", "ProcessNextNativeEvent",
         js::ProfileEntry::Category::EVENTS);
 
-    nsAutoPtr curEvent;
-    {
-        MutexAutoLock lock(mCondLock);
+    mozilla::UniquePtr curEvent;
+
+    {
+        curEvent = mEventQueue.Pop(/* mayWait */ false);
 
-        curEvent = PopNextEvent();
         if (!curEvent && mayWait) {
             // This processes messages in the Android Looper. Note that we only
             // get here if the normal Gecko event loop has been awoken
@@ -338,34 +338,52 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
                 js::ProfileEntry::Category::EVENTS);
             mozilla::HangMonitor::Suspend();
 
-            // hmm, should we really hardcode this 10s?
-#if defined(DEBUG_ANDROID_EVENTS)
-            PRTime t0, t1;
-            EVLOG("nsAppShell: waiting on mQueueCond");
-            t0 = PR_Now();
-            mQueueCond.Wait(PR_MillisecondsToInterval(10000));
-            t1 = PR_Now();
-            EVLOG("nsAppShell: wait done, waited %d ms", (int)(t1-t0)/1000);
-#else
-            mQueueCond.Wait();
-#endif
-
-            curEvent = PopNextEvent();
+            curEvent = mEventQueue.Pop(/* mayWait */ true);
         }
     }
 
     if (!curEvent)
         return false;
 
-    mozilla::HangMonitor::NotifyActivity(curEvent->IsInputEvent() ?
-            mozilla::HangMonitor::kUIActivity :
-            mozilla::HangMonitor::kGeneralActivity);
+    mozilla::HangMonitor::NotifyActivity(curEvent->ActivityType());
+
+    curEvent->Run();
+    return true;
+}
+
+class nsAppShell::LegacyGeckoEvent : public Event
+{
+    mozilla::UniquePtr ae;
+
+public:
+    LegacyGeckoEvent(AndroidGeckoEvent* e) : ae(e) {}
+
+    void Run() override;
+    void PostTo(mozilla::LinkedList& queue) override;
+
+    mozilla::HangMonitor::ActivityType ActivityType() const
+    {
+        return ae->IsInputEvent() ? mozilla::HangMonitor::kUIActivity
+                                  : mozilla::HangMonitor::kGeneralActivity;
+    }
+};
+
+void
+nsAppShell::PostEvent(AndroidGeckoEvent* event)
+{
+    mEventQueue.Post(mozilla::MakeUnique(event));
+}
+
+void
+nsAppShell::LegacyGeckoEvent::Run()
+{
+    const mozilla::UniquePtr& curEvent = ae;
 
     EVLOG("nsAppShell: event %p %d", (void*)curEvent.get(), curEvent->Type());
 
     switch (curEvent->Type()) {
     case AndroidGeckoEvent::NATIVE_POKE:
-        NativeEventCallback();
+        nsAppShell::gAppShell->NativeEventCallback();
         break;
 
     case AndroidGeckoEvent::SENSOR_EVENT: {
@@ -485,19 +503,19 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
     }
 
     case AndroidGeckoEvent::THUMBNAIL: {
-        if (!mBrowserApp)
+        if (!nsAppShell::gAppShell->mBrowserApp)
             break;
 
         int32_t tabId = curEvent->MetaState();
         const nsTArray& points = curEvent->Points();
         RefCountedJavaObject* buffer = curEvent->ByteBuffer();
-        nsRefPtr sr = new ThumbnailRunnable(mBrowserApp, tabId, points, buffer);
+        nsRefPtr sr = new ThumbnailRunnable(nsAppShell::gAppShell->mBrowserApp, tabId, points, buffer);
         MessageLoop::current()->PostIdleTask(FROM_HERE, NewRunnableMethod(sr.get(), &ThumbnailRunnable::Run));
         break;
     }
 
     case AndroidGeckoEvent::ZOOMEDVIEW: {
-        if (!mBrowserApp)
+        if (!nsAppShell::gAppShell->mBrowserApp)
             break;
         int32_t tabId = curEvent->MetaState();
         const nsTArray& points = curEvent->Points();
@@ -507,7 +525,7 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
 
         nsCOMPtr domWindow;
         nsCOMPtr tab;
-        mBrowserApp->GetBrowserTab(tabId, getter_AddRefs(tab));
+        nsAppShell::gAppShell->mBrowserApp->GetBrowserTab(tabId, getter_AddRefs(tab));
         if (!tab) {
             NS_ERROR("Can't find tab!");
             break;
@@ -525,6 +543,11 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
 
     case AndroidGeckoEvent::VIEWPORT:
     case AndroidGeckoEvent::BROADCAST: {
+        {
+            MonitorAutoLock lock(nsAppShell::gAppShell->mEventQueue.mMonitor);
+            nsAppShell::gAppShell->mQueuedViewportEvent = nullptr;
+        }
+
         if (curEvent->Characters().Length() == 0)
             break;
 
@@ -543,7 +566,7 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
             break;
 
         nsCOMPtr obs;
-        mBrowserApp->GetUITelemetryObserver(getter_AddRefs(obs));
+        nsAppShell::gAppShell->mBrowserApp->GetUITelemetryObserver(getter_AddRefs(obs));
         if (!obs)
             break;
 
@@ -560,7 +583,7 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
             break;
 
         nsCOMPtr obs;
-        mBrowserApp->GetUITelemetryObserver(getter_AddRefs(obs));
+        nsAppShell::gAppShell->mBrowserApp->GetUITelemetryObserver(getter_AddRefs(obs));
         if (!obs)
             break;
 
@@ -576,7 +599,7 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
             break;
 
         nsCOMPtr obs;
-        mBrowserApp->GetUITelemetryObserver(getter_AddRefs(obs));
+        nsAppShell::gAppShell->mBrowserApp->GetUITelemetryObserver(getter_AddRefs(obs));
         if (!obs)
             break;
 
@@ -621,10 +644,10 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
 
     case AndroidGeckoEvent::SIZE_CHANGED: {
         // store the last resize event to dispatch it to new windows with a FORCED_RESIZE event
-        if (curEvent != gLastSizeChange) {
-            gLastSizeChange = AndroidGeckoEvent::CopyResizeEvent(curEvent);
+        if (curEvent.get() != gLastSizeChange) {
+            gLastSizeChange = AndroidGeckoEvent::CopyResizeEvent(curEvent.get());
         }
-        nsWindow::OnGlobalAndroidEvent(curEvent);
+        nsWindow::OnGlobalAndroidEvent(curEvent.get());
         break;
     }
 
@@ -679,7 +702,7 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
     case AndroidGeckoEvent::CALL_OBSERVER:
     {
         nsCOMPtr observer;
-        mObserversHash.Get(curEvent->Characters(), getter_AddRefs(observer));
+        nsAppShell::gAppShell->mObserversHash.Get(curEvent->Characters(), getter_AddRefs(observer));
 
         if (observer) {
             observer->Observe(nullptr, NS_ConvertUTF16toUTF8(curEvent->CharactersExtra()).get(),
@@ -692,11 +715,11 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
     }
 
     case AndroidGeckoEvent::REMOVE_OBSERVER:
-        mObserversHash.Remove(curEvent->Characters());
+        nsAppShell::gAppShell->mObserversHash.Remove(curEvent->Characters());
         break;
 
     case AndroidGeckoEvent::ADD_OBSERVER:
-        AddObserver(curEvent->Characters(), curEvent->Observer());
+        nsAppShell::gAppShell->AddObserver(curEvent->Characters(), curEvent->Observer());
         break;
 
     case AndroidGeckoEvent::PREFERENCES_GET:
@@ -709,15 +732,15 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
         }
 
         if (curEvent->Type() == AndroidGeckoEvent::PREFERENCES_GET) {
-            mBrowserApp->GetPreferences(curEvent->RequestId(), prefNamePtrs, count);
+            nsAppShell::gAppShell->mBrowserApp->GetPreferences(curEvent->RequestId(), prefNamePtrs, count);
         } else {
-            mBrowserApp->ObservePreferences(curEvent->RequestId(), prefNamePtrs, count);
+            nsAppShell::gAppShell->mBrowserApp->ObservePreferences(curEvent->RequestId(), prefNamePtrs, count);
         }
         break;
     }
 
     case AndroidGeckoEvent::PREFERENCES_REMOVE_OBSERVERS:
-        mBrowserApp->RemovePreferenceObservers(curEvent->RequestId());
+        nsAppShell::gAppShell->mBrowserApp->RemovePreferenceObservers(curEvent->RequestId());
         break;
 
     case AndroidGeckoEvent::LOW_MEMORY:
@@ -787,7 +810,7 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
         break;
 
     default:
-        nsWindow::OnGlobalAndroidEvent(curEvent);
+        nsWindow::OnGlobalAndroidEvent(curEvent.get());
         break;
     }
 
@@ -796,19 +819,10 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
     }
 
     EVLOG("nsAppShell: -- done event %p %d", (void*)curEvent.get(), curEvent->Type());
-
-    return true;
 }
 
 void
-nsAppShell::ResendLastResizeEvent(nsWindow* aDest) {
-    if (gLastSizeChange) {
-        nsWindow::OnGlobalAndroidEvent(gLastSizeChange);
-    }
-}
-
-void
-nsAppShell::PostEvent(AndroidGeckoEvent *ae)
+nsAppShell::LegacyGeckoEvent::PostTo(mozilla::LinkedList& queue)
 {
     {
         // set this to true when inserting events that we can coalesce
@@ -816,7 +830,6 @@ nsAppShell::PostEvent(AndroidGeckoEvent *ae)
         // of events that are unaffected by viewport changes.
         bool allowCoalescingNextViewport = false;
 
-        MutexAutoLock lock(mQueueLock);
         EVLOG("nsAppShell::PostEvent %p %d", ae, ae->Type());
         switch (ae->Type()) {
         case AndroidGeckoEvent::COMPOSITOR_CREATE:
@@ -824,44 +837,53 @@ nsAppShell::PostEvent(AndroidGeckoEvent *ae)
         case AndroidGeckoEvent::COMPOSITOR_RESUME:
             // Give priority to these events, but maintain their order wrt each other.
             {
-                uint32_t i = 0;
-                while (i < mEventQueue.Length() &&
-                       (mEventQueue[i]->Type() == AndroidGeckoEvent::COMPOSITOR_CREATE ||
-                        mEventQueue[i]->Type() == AndroidGeckoEvent::COMPOSITOR_PAUSE ||
-                        mEventQueue[i]->Type() == AndroidGeckoEvent::COMPOSITOR_RESUME)) {
-                    i++;
+                Event* event = queue.getFirst();
+                while (event && event->HasSameTypeAs(this)) {
+                    const auto& e = static_cast(event)->ae;
+                    if (e->Type() != AndroidGeckoEvent::COMPOSITOR_CREATE
+                            && e->Type() != AndroidGeckoEvent::COMPOSITOR_PAUSE
+                            && e->Type() != AndroidGeckoEvent::COMPOSITOR_RESUME) {
+                        break;
+                    }
+                    event = event->getNext();
                 }
-                EVLOG("nsAppShell: Inserting compositor event %d at position %d to maintain priority order", ae->Type(), i);
-                mEventQueue.InsertElementAt(i, ae);
+                if (event) {
+                    event->setPrevious(this);
+                } else {
+                    queue.insertFront(this);
+                }
+                EVLOG("nsAppShell: Inserting compositor event %d to maintain priority order", ae->Type());
             }
             break;
 
         case AndroidGeckoEvent::VIEWPORT:
-            if (mQueuedViewportEvent) {
+            if (nsAppShell::gAppShell->mQueuedViewportEvent) {
                 // drop the previous viewport event now that we have a new one
-                EVLOG("nsAppShell: Dropping old viewport event at %p in favour of new VIEWPORT event %p", mQueuedViewportEvent, ae);
-                mEventQueue.RemoveElement(mQueuedViewportEvent);
-                delete mQueuedViewportEvent;
+                EVLOG("nsAppShell: Dropping old viewport event at %p in favour of new VIEWPORT event %p",
+                      nsAppShell::gAppShell->mQueuedViewportEvent, ae);
+                // Delete the event and remove from list.
+                delete nsAppShell::gAppShell->mQueuedViewportEvent;
             }
-            mQueuedViewportEvent = ae;
+            nsAppShell::gAppShell->mQueuedViewportEvent = this;
             allowCoalescingNextViewport = true;
 
-            mEventQueue.AppendElement(ae);
+            queue.insertBack(this);
             break;
 
         case AndroidGeckoEvent::MOTION_EVENT:
         case AndroidGeckoEvent::APZ_INPUT_EVENT:
-            if (mAllowCoalescingTouches && mEventQueue.Length() > 0) {
-                int len = mEventQueue.Length();
-                AndroidGeckoEvent* event = mEventQueue[len - 1];
-                if (ae->CanCoalesceWith(event)) {
+            if (nsAppShell::gAppShell->mAllowCoalescingTouches) {
+                Event* const event = queue.getLast();
+                if (event && event->HasSameTypeAs(this) && ae->CanCoalesceWith(
+                        static_cast(event)->ae.get())) {
+
                     // consecutive motion-move events; drop the last one before adding the new one
                     EVLOG("nsAppShell: Dropping old move event at %p in favour of new move event %p", event, ae);
-                    mEventQueue.RemoveElementAt(len - 1);
+                    // Delete the event and remove from list.
                     delete event;
                 }
             }
-            mEventQueue.AppendElement(ae);
+            queue.insertBack(this);
             break;
 
         case AndroidGeckoEvent::NATIVE_POKE:
@@ -869,17 +891,24 @@ nsAppShell::PostEvent(AndroidGeckoEvent *ae)
             // fall through
 
         default:
-            mEventQueue.AppendElement(ae);
+            queue.insertBack(this);
             break;
         }
 
         // if the event wasn't on our whitelist then reset mQueuedViewportEvent
         // so that we don't coalesce future viewport events into the last viewport
         // event we added
-        if (!allowCoalescingNextViewport)
-            mQueuedViewportEvent = nullptr;
+        if (!allowCoalescingNextViewport) {
+            nsAppShell::gAppShell->mQueuedViewportEvent = nullptr;
+        }
+    }
+}
+
+void
+nsAppShell::ResendLastResizeEvent(nsWindow* aDest) {
+    if (gLastSizeChange) {
+        nsWindow::OnGlobalAndroidEvent(gLastSizeChange);
     }
-    NotifyNativeEvent();
 }
 
 nsresult
diff --git a/widget/android/nsAppShell.h b/widget/android/nsAppShell.h
index 1fc46c1c0eb7..3e86a4790593 100644
--- a/widget/android/nsAppShell.h
+++ b/widget/android/nsAppShell.h
@@ -53,6 +53,8 @@ public:
         }
     };
 
+    class LegacyGeckoEvent;
+
     template
     class LambdaEvent : public Event
     {
@@ -65,7 +67,6 @@ public:
     };
 
     static nsAppShell *gAppShell;
-    static mozilla::AndroidGeckoEvent *gEarlyEvent;
 
     nsAppShell();
 
@@ -124,7 +125,11 @@ protected:
 
     class Queue
     {
+    public:
+        // XXX need to be public for the mQueuedViewportEvent ugliness.
         mozilla::Monitor mMonitor;
+
+    private:
         mozilla::LinkedList mQueue;
 
     public:
@@ -163,7 +168,7 @@ protected:
 
     } mEventQueue;
 
-    mozilla::AndroidGeckoEvent *mQueuedViewportEvent;
+    Event* mQueuedViewportEvent;
     bool mAllowCoalescingTouches;
 
     nsCOMPtr mBrowserApp;

From 1f5985cce73f5ee6d76991e983be97b5d2167ee2 Mon Sep 17 00:00:00 2001
From: Jim Chen 
Date: Mon, 21 Sep 2015 10:13:32 -0400
Subject: [PATCH 028/133] Bug 1197957 - Introduce GeckoView.Window class;
 r=snorp GeckoView.Window is a class that acts as the interface between
 GeckoView in Java and nsWindow in C++. It will contain native methods that
 GeckoView will use to interact with nsWindow.

On initialization, Window.open is called to create a nsWindow and
establish the JNI association between Window and the native nsWindow.
Then, whenever Window instance methods are called, the JNI stubs will
automatically call members of nsWindow.
---
 mobile/android/base/GeckoView.java      | 10 +++
 widget/android/GeneratedJNINatives.h    | 19 ++++++
 widget/android/GeneratedJNIWrappers.cpp | 18 +++++
 widget/android/GeneratedJNIWrappers.h   | 87 +++++++++++++++++++++++++
 4 files changed, 134 insertions(+)

diff --git a/mobile/android/base/GeckoView.java b/mobile/android/base/GeckoView.java
index 1921bdbe726f..b38b2bd60f63 100644
--- a/mobile/android/base/GeckoView.java
+++ b/mobile/android/base/GeckoView.java
@@ -12,8 +12,10 @@ import java.util.Set;
 
 import org.json.JSONException;
 import org.json.JSONObject;
+import org.mozilla.gecko.annotation.WrapForJNI;
 import org.mozilla.gecko.gfx.LayerView;
 import org.mozilla.gecko.mozglue.GeckoLoader;
+import org.mozilla.gecko.mozglue.JNIObject;
 import org.mozilla.gecko.util.Clipboard;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.GeckoEventListener;
@@ -104,6 +106,14 @@ public class GeckoView extends LayerView
         }
     };
 
+    @WrapForJNI
+    private static final class Window extends JNIObject {
+        static native void open(Window instance, int width, int height);
+        @Override protected native void disposeNative();
+    }
+
+    private final Window window = new Window();
+
     public GeckoView(Context context) {
         super(context);
         init(context, null, true);
diff --git a/widget/android/GeneratedJNINatives.h b/widget/android/GeneratedJNINatives.h
index 3e04a51888bc..cec0a747ae0c 100644
--- a/widget/android/GeneratedJNINatives.h
+++ b/widget/android/GeneratedJNINatives.h
@@ -66,6 +66,25 @@ public:
 template
 constexpr JNINativeMethod GeckoThread::Natives::methods[];
 
+template
+class GeckoView::Window::Natives : public mozilla::jni::NativeImpl
+{
+public:
+    static constexpr JNINativeMethod methods[] = {
+
+        mozilla::jni::MakeNativeMethod(
+                mozilla::jni::NativeStub
+                ::template Wrap<&Impl::DisposeNative>),
+
+        mozilla::jni::MakeNativeMethod(
+                mozilla::jni::NativeStub
+                ::template Wrap<&Impl::Open>)
+    };
+};
+
+template
+constexpr JNINativeMethod GeckoView::Window::Natives::methods[];
+
 template
 class NativeJSContainer::Natives : public mozilla::jni::NativeImpl
 {
diff --git a/widget/android/GeneratedJNIWrappers.cpp b/widget/android/GeneratedJNIWrappers.cpp
index 363d5de0baa2..21a967de8341 100644
--- a/widget/android/GeneratedJNIWrappers.cpp
+++ b/widget/android/GeneratedJNIWrappers.cpp
@@ -938,6 +938,24 @@ auto GeckoThread::State::RUNNING() -> State::LocalRef
     return mozilla::jni::Field::Get(nullptr, nullptr);
 }
 
+constexpr char GeckoView::name[];
+
+constexpr char GeckoView::Window::name[];
+
+constexpr char GeckoView::Window::New_t::name[];
+constexpr char GeckoView::Window::New_t::signature[];
+
+auto GeckoView::Window::New() -> Window::LocalRef
+{
+    return mozilla::jni::Constructor::Call(nullptr, nullptr);
+}
+
+constexpr char GeckoView::Window::DisposeNative_t::name[];
+constexpr char GeckoView::Window::DisposeNative_t::signature[];
+
+constexpr char GeckoView::Window::Open_t::name[];
+constexpr char GeckoView::Window::Open_t::signature[];
+
 constexpr char RestrictedProfiles::name[];
 
 constexpr char RestrictedProfiles::IsAllowed_t::name[];
diff --git a/widget/android/GeneratedJNIWrappers.h b/widget/android/GeneratedJNIWrappers.h
index f222acce0580..2a0b340cd0cc 100644
--- a/widget/android/GeneratedJNIWrappers.h
+++ b/widget/android/GeneratedJNIWrappers.h
@@ -2225,6 +2225,93 @@ public:
 
 };
 
+class GeckoView : public mozilla::jni::Class
+{
+public:
+    typedef mozilla::jni::Ref Ref;
+    typedef mozilla::jni::LocalRef LocalRef;
+    typedef mozilla::jni::GlobalRef GlobalRef;
+    typedef const mozilla::jni::Param& Param;
+
+    static constexpr char name[] =
+            "org/mozilla/gecko/GeckoView";
+
+protected:
+    GeckoView(jobject instance) : Class(instance) {}
+
+public:
+    class Window;
+
+};
+
+class GeckoView::Window : public mozilla::jni::Class
+{
+public:
+    typedef mozilla::jni::Ref Ref;
+    typedef mozilla::jni::LocalRef LocalRef;
+    typedef mozilla::jni::GlobalRef GlobalRef;
+    typedef const mozilla::jni::Param& Param;
+
+    static constexpr char name[] =
+            "org/mozilla/gecko/GeckoView$Window";
+
+protected:
+    Window(jobject instance) : Class(instance) {}
+
+public:
+    struct New_t {
+        typedef Window Owner;
+        typedef Window::LocalRef ReturnType;
+        typedef Window::Param SetterType;
+        typedef mozilla::jni::Args<> Args;
+        static constexpr char name[] = "";
+        static constexpr char signature[] =
+                "()V";
+        static const bool isStatic = false;
+        static const bool isMultithreaded = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+    };
+
+    static auto New() -> Window::LocalRef;
+
+public:
+    struct DisposeNative_t {
+        typedef Window Owner;
+        typedef void ReturnType;
+        typedef void SetterType;
+        typedef mozilla::jni::Args<> Args;
+        static constexpr char name[] = "disposeNative";
+        static constexpr char signature[] =
+                "()V";
+        static const bool isStatic = false;
+        static const bool isMultithreaded = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+    };
+
+public:
+    struct Open_t {
+        typedef Window Owner;
+        typedef void ReturnType;
+        typedef void SetterType;
+        typedef mozilla::jni::Args<
+                Window::Param,
+                int32_t,
+                int32_t> Args;
+        static constexpr char name[] = "open";
+        static constexpr char signature[] =
+                "(Lorg/mozilla/gecko/GeckoView$Window;II)V";
+        static const bool isStatic = true;
+        static const bool isMultithreaded = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+    };
+
+public:
+    template class Natives;
+};
+
 class RestrictedProfiles : public mozilla::jni::Class
 {
 public:

From 99ef489a78210b866eaeffdee439b084f31db23d Mon Sep 17 00:00:00 2001
From: Jim Chen 
Date: Mon, 21 Sep 2015 10:13:32 -0400
Subject: [PATCH 029/133] Bug 1197957 - Implement GeckoView.Window.open in
 nsWindow; r=snorp nsWindow will implement native methods of GeckoView.Window.
 This patch implements the open method, which opens a new window in the same
 manner as the CLH, and associates the new nsWindow with the GeckoView.Window
 instance.

---
 widget/android/nsAppShell.cpp |   1 +
 widget/android/nsWindow.cpp   | 129 ++++++++++++++++++++++++++++++++--
 widget/android/nsWindow.h     |   7 ++
 3 files changed, 132 insertions(+), 5 deletions(-)

diff --git a/widget/android/nsAppShell.cpp b/widget/android/nsAppShell.cpp
index f93e5fb8530e..7c92e66449b3 100644
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -196,6 +196,7 @@ nsAppShell::nsAppShell()
         AndroidBridge::ConstructBridge();
         GeckoThreadNatives::Init();
         mozilla::ANRReporter::Init();
+        nsWindow::InitNatives();
 
         widget::GeckoThread::SetState(widget::GeckoThread::State::JNI_READY());
     }
diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp
index d476e7a56c9c..3d2fa397138a 100644
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -13,6 +13,7 @@
 #include "mozilla/TextComposition.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/TouchEvents.h"
+#include "mozilla/WeakPtr.h"
 
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ContentChild.h"
@@ -25,15 +26,22 @@ using mozilla::dom::ContentParent;
 using mozilla::dom::ContentChild;
 using mozilla::unused;
 
+#include "nsWindow.h"
+
+#include "nsIObserverService.h"
+#include "nsISelection.h"
+#include "nsISupportsArray.h"
+#include "nsISupportsPrimitives.h"
+#include "nsIWidgetListener.h"
+#include "nsIWindowWatcher.h"
+
 #include "nsAppShell.h"
+#include "nsFocusManager.h"
 #include "nsIdleService.h"
 #include "nsLayoutUtils.h"
-#include "nsWindow.h"
-#include "nsIObserverService.h"
-#include "nsFocusManager.h"
-#include "nsIWidgetListener.h"
 #include "nsViewManager.h"
-#include "nsISelection.h"
+
+#include "WidgetUtils.h"
 
 #include "nsIDOMSimpleGestureEvent.h"
 
@@ -59,6 +67,7 @@ using mozilla::unused;
 #include "AndroidBridge.h"
 #include "AndroidBridgeUtilities.h"
 #include "android_npapi.h"
+#include "GeneratedJNINatives.h"
 
 #include "imgIEncoder.h"
 
@@ -132,12 +141,122 @@ static bool gMenuConsumed;
 // one.
 static nsTArray gTopLevelWindows;
 
+// FIXME: because we don't support separate nsWindow for each GeckoView
+// yet, we have to attach a new GeckoView to an existing nsWindow if it
+// exists. Eventually, an nsWindow will be opened/closed as each GeckoView
+// is created/destroyed.
+static nsWindow* gGeckoViewWindow;
+
 static bool sFailedToCreateGLContext = false;
 
 // Multitouch swipe thresholds in inches
 static const double SWIPE_MAX_PINCH_DELTA_INCHES = 0.4;
 static const double SWIPE_MIN_DISTANCE_INCHES = 0.6;
 
+
+class nsWindow::Natives
+    : public GeckoView::Window::Natives
+    , public SupportsWeakPtr
+{
+    typedef GeckoView::Window::Natives Base;
+
+    nsWindow& window;
+
+public:
+    MOZ_DECLARE_WEAKREFERENCE_TYPENAME(Natives);
+
+    Natives(nsWindow* w) : window(*w) {}
+
+    // Detach and destroy the window that we created in Open().
+    void DisposeNative(const GeckoView::Window::LocalRef& instance);
+
+    // Create and attach a window.
+    static void Open(const jni::ClassObject::LocalRef& cls,
+                     GeckoView::Window::Param gvWindow,
+                     int32_t width, int32_t height);
+};
+
+void
+nsWindow::Natives::Open(const jni::ClassObject::LocalRef& cls,
+                        GeckoView::Window::Param gvWindow,
+                        int32_t width, int32_t height)
+{
+    MOZ_ASSERT(NS_IsMainThread());
+
+    PROFILER_LABEL("nsWindow", "Natives::Open",
+                   js::ProfileEntry::Category::OTHER);
+
+    if (gGeckoViewWindow) {
+        // Should have been created the first time.
+        MOZ_ASSERT(gGeckoViewWindow->mNatives);
+        AttachNative(GeckoView::Window::LocalRef(cls.Env(), gvWindow),
+                     gGeckoViewWindow->mNatives.get());
+        return;
+    }
+
+    nsCOMPtr ww = do_GetService(NS_WINDOWWATCHER_CONTRACTID);
+    MOZ_ASSERT(ww);
+
+    nsAdoptingCString url = Preferences::GetCString("toolkit.defaultChromeURI");
+    if (!url) {
+        url = NS_LITERAL_CSTRING("chrome://browser/content/browser.xul");
+    }
+
+    nsCOMPtr args
+            = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID);
+    nsCOMPtr widthArg
+            = do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID);
+    nsCOMPtr heightArg
+            = do_CreateInstance(NS_SUPPORTS_PRINT32_CONTRACTID);
+
+    // Arguments are optional so it's okay if this fails.
+    if (args && widthArg && heightArg &&
+            NS_SUCCEEDED(widthArg->SetData(width)) &&
+            NS_SUCCEEDED(heightArg->SetData(height)))
+    {
+        args->AppendElement(widthArg);
+        args->AppendElement(heightArg);
+    }
+
+    nsCOMPtr window;
+    ww->OpenWindow(nullptr, url, "_blank", "chrome,dialog=no,all",
+                   args, getter_AddRefs(window));
+    MOZ_ASSERT(window);
+
+    nsCOMPtr widget = WidgetUtils::DOMWindowToWidget(window);
+    MOZ_ASSERT(widget);
+
+    gGeckoViewWindow = static_cast(widget.get());
+    gGeckoViewWindow->mNatives = mozilla::MakeUnique(gGeckoViewWindow);
+    AttachNative(GeckoView::Window::LocalRef(cls.Env(), gvWindow),
+                 gGeckoViewWindow->mNatives.get());
+}
+
+void
+nsWindow::Natives::DisposeNative(const GeckoView::Window::LocalRef& instance)
+{
+    // FIXME: because we don't support separate nsWindow for each GeckoView
+    // yet, we have to keep this window around in case another GeckoView
+    // wants to attach.
+    /*
+    if (mWidgetListener) {
+        nsCOMPtr xulWindow(mWidgetListener->GetXULWindow());
+        // GeckoView-created top-level windows should be a XUL window.
+        MOZ_ASSERT(xulWindow);
+        nsCOMPtr baseWindow(do_QueryInterface(xulWindow));
+        MOZ_ASSERT(baseWindow);
+        baseWindow->Destroy();
+    }
+    */
+    Base::DisposeNative(instance);
+}
+
+void
+nsWindow::InitNatives()
+{
+    nsWindow::Natives::Init();
+}
+
 nsWindow*
 nsWindow::TopWindow()
 {
diff --git a/widget/android/nsWindow.h b/widget/android/nsWindow.h
index f5691273775b..d201949cd083 100644
--- a/widget/android/nsWindow.h
+++ b/widget/android/nsWindow.h
@@ -15,6 +15,7 @@
 #include "mozilla/EventForwards.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/TextRange.h"
+#include "mozilla/UniquePtr.h"
 
 struct ANPEvent;
 
@@ -43,6 +44,12 @@ public:
 
     NS_DECL_ISUPPORTS_INHERITED
 
+    static void InitNatives();
+    class Natives;
+    // Object that implements native GeckoView calls;
+    // nullptr for nsWindows that were not opened from GeckoView.
+    mozilla::UniquePtr mNatives;
+
     static void OnGlobalAndroidEvent(mozilla::AndroidGeckoEvent *ae);
     static gfxIntSize GetAndroidScreenBounds();
     static nsWindow* TopWindow();

From 28f883f2f8c93d6ea09ae11b1adaa1b76b222ecf Mon Sep 17 00:00:00 2001
From: Jim Chen 
Date: Mon, 21 Sep 2015 10:13:32 -0400
Subject: [PATCH 030/133] Bug 1197957 - Let GeckoView open the nsWindow instead
 of CLH; r=snorp Currently, BrowserCLH opens a single new window on startup.
 Now that GeckoView is able to open windows through GeckoView.Window, we
 should make GeckoView open its own window, which we can do earlier in
 startup, and will make it possible to support multiple GeckoView's down the
 road.

---
 mobile/android/base/GeckoApp.java        |  1 -
 mobile/android/base/GeckoThread.java     | 22 +++--------
 mobile/android/base/GeckoView.java       | 27 +++++++++++--
 mobile/android/chrome/content/browser.js |  7 +---
 mobile/android/components/BrowserCLH.js  | 50 ++++--------------------
 5 files changed, 38 insertions(+), 69 deletions(-)

diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java
index 1f66f6852fec..63a5364f52d0 100644
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -1227,7 +1227,6 @@ public abstract class GeckoApp
             final String uri = getURIFromIntent(intent);
 
             GeckoThread.ensureInit(args, action,
-                    TextUtils.isEmpty(uri) ? null : uri,
                     /* debugging */ ACTION_DEBUG.equals(action));
 
             if (!TextUtils.isEmpty(uri)) {
diff --git a/mobile/android/base/GeckoThread.java b/mobile/android/base/GeckoThread.java
index b44a38c67558..4b15a81d28ab 100644
--- a/mobile/android/base/GeckoThread.java
+++ b/mobile/android/base/GeckoThread.java
@@ -22,7 +22,6 @@ import android.os.Looper;
 import android.os.Message;
 import android.os.MessageQueue;
 import android.os.SystemClock;
-import android.util.DisplayMetrics;
 import android.util.Log;
 
 import java.io.IOException;
@@ -109,27 +108,25 @@ public class GeckoThread extends Thread implements GeckoEventListener {
 
     private final String mArgs;
     private final String mAction;
-    private final String mUri;
     private final boolean mDebugging;
 
-    GeckoThread(String args, String action, String uri, boolean debugging) {
+    GeckoThread(String args, String action, boolean debugging) {
         mArgs = args;
         mAction = action;
-        mUri = uri;
         mDebugging = debugging;
 
         setName("Gecko");
         EventDispatcher.getInstance().registerGeckoThreadListener(this, "Gecko:Ready");
     }
 
-    public static boolean ensureInit(String args, String action, String uri) {
-        return ensureInit(args, action, uri, /* debugging */ false);
+    public static boolean ensureInit(String args, String action) {
+        return ensureInit(args, action, /* debugging */ false);
     }
 
-    public static boolean ensureInit(String args, String action, String uri, boolean debugging) {
+    public static boolean ensureInit(String args, String action, boolean debugging) {
         ThreadUtils.assertOnUiThread();
         if (isState(State.INITIAL) && sGeckoThread == null) {
-            sGeckoThread = new GeckoThread(args, action, uri, debugging);
+            sGeckoThread = new GeckoThread(args, action, debugging);
             return true;
         }
         return false;
@@ -361,10 +358,6 @@ public class GeckoThread extends Thread implements GeckoEventListener {
             args.append(' ').append(userArgs);
         }
 
-        if (mUri != null) {
-            args.append(" -url ").append(mUri);
-        }
-
         final String type = getTypeFromAction(mAction);
         if (type != null) {
             args.append(" ").append(type);
@@ -380,11 +373,6 @@ public class GeckoThread extends Thread implements GeckoEventListener {
             args.append(" -purgecaches");
         }
 
-        final DisplayMetrics metrics
-                = GeckoAppShell.getContext().getResources().getDisplayMetrics();
-        args.append(" -width ").append(metrics.widthPixels)
-            .append(" -height ").append(metrics.heightPixels);
-
         return args.toString();
     }
 
diff --git a/mobile/android/base/GeckoView.java b/mobile/android/base/GeckoView.java
index b38b2bd60f63..704bcd28bbea 100644
--- a/mobile/android/base/GeckoView.java
+++ b/mobile/android/base/GeckoView.java
@@ -31,6 +31,7 @@ import android.content.SharedPreferences;
 import android.content.res.TypedArray;
 import android.os.Bundle;
 import android.util.AttributeSet;
+import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.View;
 
@@ -167,11 +168,9 @@ public class GeckoView extends LayerView
             final GeckoProfile profile = GeckoProfile.get(context);
          }
 
+        GeckoThread.ensureInit(null, null);
         if (url != null) {
-            GeckoThread.ensureInit(null, Intent.ACTION_VIEW, url);
             GeckoAppShell.sendEventToGecko(GeckoEvent.createURILoadEvent(url));
-        } else {
-            GeckoThread.ensureInit(null, null, null);
         }
 
         if (context instanceof Activity) {
@@ -205,6 +204,28 @@ public class GeckoView extends LayerView
         }
     }
 
+    @Override
+    public void onAttachedToWindow()
+    {
+        super.onAttachedToWindow();
+
+        final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
+
+        if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
+            Window.open(window, metrics.widthPixels, metrics.heightPixels);
+        } else {
+            GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY, Window.class,
+                    "open", window, metrics.widthPixels, metrics.heightPixels);
+        }
+    }
+
+    @Override
+    public void onDetachedFromWindow()
+    {
+        super.onAttachedToWindow();
+        window.disposeNative();
+    }
+
     /**
     * Add a Browser to the GeckoView container.
     * @param url The URL resource to load into the new Browser.
diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js
index 3b6befdd55b5..462ee2087850 100644
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -492,14 +492,11 @@ var BrowserApp = {
     Tabs.init();
     SearchEngines.init();
 
-    let url = null;
     if ("arguments" in window) {
       if (window.arguments[0])
-        url = window.arguments[0];
+        gScreenWidth = window.arguments[0];
       if (window.arguments[1])
-        gScreenWidth = window.arguments[1];
-      if (window.arguments[2])
-        gScreenHeight = window.arguments[2];
+        gScreenHeight = window.arguments[1];
     }
 
     // XXX maybe we don't do this if the launch was kicked off from external
diff --git a/mobile/android/components/BrowserCLH.js b/mobile/android/components/BrowserCLH.js
index 56bf1c25eb15..421d5d7a4f08 100644
--- a/mobile/android/components/BrowserCLH.js
+++ b/mobile/android/components/BrowserCLH.js
@@ -14,26 +14,6 @@ function dump(a) {
   Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).logStringMessage(a);
 }
 
-function openWindow(aParent, aURL, aTarget, aFeatures, aArgs) {
-  let argsArray = Cc["@mozilla.org/supports-array;1"].createInstance(Ci.nsISupportsArray);
-  let urlString = null;
-  let widthInt = Cc["@mozilla.org/supports-PRInt32;1"].createInstance(Ci.nsISupportsPRInt32);
-  let heightInt = Cc["@mozilla.org/supports-PRInt32;1"].createInstance(Ci.nsISupportsPRInt32);
-
-  if ("url" in aArgs) {
-    urlString = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
-    urlString.data = aArgs.url;
-  }
-  widthInt.data = "width" in aArgs ? aArgs.width : 1;
-  heightInt.data = "height" in aArgs ? aArgs.height : 1;
-
-  argsArray.AppendElement(urlString, false);
-  argsArray.AppendElement(widthInt, false);
-  argsArray.AppendElement(heightInt, false);
-  return Services.ww.openWindow(aParent, aURL, aTarget, aFeatures, argsArray);
-}
-
-
 function resolveURIInternal(aCmdLine, aArgument) {
   let uri = aCmdLine.resolveURI(aArgument);
   if (uri)
@@ -56,21 +36,18 @@ BrowserCLH.prototype = {
     let openURL = "about:home";
     let pinned = false;
 
-    let width = 1;
-    let height = 1;
-
     try {
       openURL = aCmdLine.handleFlagWithParam("url", false);
     } catch (e) { /* Optional */ }
-    try {
-      pinned = aCmdLine.handleFlag("bookmark", false);
-    } catch (e) { /* Optional */ }
+
+    if (!openURL) {
+      // We don't have an URL on initial launch, and because the Fennec
+      // CLH is not used for initial launch, we simply return here.
+      return;
+    }
 
     try {
-      width = aCmdLine.handleFlagWithParam("width", false);
-    } catch (e) { /* Optional */ }
-    try {
-      height = aCmdLine.handleFlagWithParam("height", false);
+      pinned = aCmdLine.handleFlag("bookmark", false);
     } catch (e) { /* Optional */ }
 
     try {
@@ -82,19 +59,6 @@ BrowserCLH.prototype = {
       if (browserWin) {
         let whereFlags = pinned ? Ci.nsIBrowserDOMWindow.OPEN_SWITCHTAB : Ci.nsIBrowserDOMWindow.OPEN_NEWTAB;
         browserWin.browserDOMWindow.openURI(uri, null, whereFlags, Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
-      } else {
-        let args = {
-          url: openURL,
-          width: width,
-          height: height,
-        };
-
-        let flags = "chrome,dialog=no,all";
-        let chromeURL = "chrome://browser/content/browser.xul";
-        try {
-          chromeURL = Services.prefs.getCharPref("toolkit.defaultChromeURI");
-        } catch(e) {}
-        browserWin = openWindow(null, chromeURL, "_blank", flags, args);
       }
 
       aCmdLine.preventDefault = true;

From 635fd10c85ce2f8f44d226239dc67b1320f4c0db Mon Sep 17 00:00:00 2001
From: Jim Chen 
Date: Mon, 21 Sep 2015 10:13:33 -0400
Subject: [PATCH 031/133] Bug 1197957 - Dispatch nsWindow native calls to Gecko
 thread; r=snorp A C++ class that implments native JNI methods can choose to
 inherit UsesGeckoThreadProxy. Once enabled, all native JNI calls on that
 class will be automatically dispatched to the Gecko thread as a runnable
 event.

---
 widget/android/nsAppShell.h | 14 ++++++++++++++
 widget/android/nsWindow.cpp | 13 +++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/widget/android/nsAppShell.h b/widget/android/nsAppShell.h
index 3e86a4790593..1f0005f6f8d4 100644
--- a/widget/android/nsAppShell.h
+++ b/widget/android/nsAppShell.h
@@ -12,6 +12,7 @@
 #include "mozilla/Move.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/unused.h"
+#include "mozilla/jni/Natives.h"
 #include "nsBaseAppShell.h"
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
@@ -175,5 +176,18 @@ protected:
     nsInterfaceHashtable mObserversHash;
 };
 
+// Class that implement native JNI methods can inherit from
+// UsesGeckoThreadProxy to have the native call forwarded
+// automatically to the Gecko thread.
+class UsesGeckoThreadProxy : public mozilla::jni::UsesNativeCallProxy
+{
+public:
+    template
+    static void OnNativeCall(Functor&& call)
+    {
+        nsAppShell::gAppShell->PostEvent(mozilla::Move(call));
+    }
+};
+
 #endif // nsAppShell_h__
 
diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp
index 3d2fa397138a..0467f543fdff 100644
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -157,6 +157,7 @@ static const double SWIPE_MIN_DISTANCE_INCHES = 0.6;
 class nsWindow::Natives
     : public GeckoView::Window::Natives
     , public SupportsWeakPtr
+    , public UsesGeckoThreadProxy
 {
     typedef GeckoView::Window::Natives Base;
 
@@ -165,6 +166,18 @@ class nsWindow::Natives
 public:
     MOZ_DECLARE_WEAKREFERENCE_TYPENAME(Natives);
 
+    template
+    static void OnNativeCall(Functor&& call)
+    {
+        if (call.IsTarget(&Open) && NS_IsMainThread()) {
+            // Gecko state probably just switched to PROFILE_READY, and the
+            // event loop is not running yet. Skip the event loop here so we
+            // can get a head start on opening our window.
+            return call();
+        }
+        return UsesGeckoThreadProxy::OnNativeCall(mozilla::Move(call));
+    }
+
     Natives(nsWindow* w) : window(*w) {}
 
     // Detach and destroy the window that we created in Open().

From e6f22f3cfa852df1d4a002b35a83ff1746f5d360 Mon Sep 17 00:00:00 2001
From: Jim Chen 
Date: Mon, 21 Sep 2015 10:13:33 -0400
Subject: [PATCH 032/133] Bug 1197957 - Switch PROFILE_READY state to
 correspond to profile-after-change; r=snorp Originally, the GeckoThread
 PROFILE_READY state was chosen to correspond to the profile-do-change event,
 to give priority to JNI code (e.g. window creation) over other events that
 may be registered under profile-after-change event. However, this leads to
 broken tests because our testing infra expects things like window creation to
 happen during profile-after-change at the earliest. This is because we have
 to wait for addons like SpecialPowers to be loaded between profile-do-change
 and profile-after-change. This patch changes the PROFILE_READY state to
 correspond to the profile-after-change event, so things are consistent again.

---
 widget/android/nsAppShell.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/widget/android/nsAppShell.cpp b/widget/android/nsAppShell.cpp
index 7c92e66449b3..429eb4a629a6 100644
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -253,7 +253,7 @@ nsAppShell::Init()
         mozilla::services::GetObserverService();
     if (obsServ) {
         obsServ->AddObserver(this, "browser-delayed-startup-finished", false);
-        obsServ->AddObserver(this, "profile-do-change", false);
+        obsServ->AddObserver(this, "profile-after-change", false);
         obsServ->AddObserver(this, "xpcom-shutdown", false);
     }
 
@@ -286,7 +286,7 @@ nsAppShell::Observe(nsISupports* aSubject,
         NS_CreateServicesFromCategory("browser-delayed-startup-finished", nullptr,
                                       "browser-delayed-startup-finished");
 
-    } else if (!strcmp(aTopic, "profile-do-change")) {
+    } else if (!strcmp(aTopic, "profile-after-change")) {
         if (jni::IsAvailable()) {
             widget::GeckoThread::SetState(
                     widget::GeckoThread::State::PROFILE_READY());
@@ -305,7 +305,7 @@ nsAppShell::Observe(nsISupports* aSubject,
         nsCOMPtr obsServ =
             mozilla::services::GetObserverService();
         if (obsServ) {
-            obsServ->RemoveObserver(this, "profile-do-change");
+            obsServ->RemoveObserver(this, "profile-after-change");
         }
     }
     return NS_OK;

From c58047810f4394fee3881bcad7720d3d33a31e2c Mon Sep 17 00:00:00 2001
From: Sotaro Ikeda 
Date: Mon, 21 Sep 2015 07:21:52 -0700
Subject: [PATCH 033/133] Bug 1172719 - Fix SharedSurface fence handling on
 gonk r=jgilbert,nical

---
 gfx/gl/SharedSurface.cpp                      |  1 +
 gfx/layers/client/CanvasClient.cpp            | 13 ++++
 gfx/layers/client/TextureClient.h             |  4 +-
 .../client/TextureClientSharedSurface.cpp     | 65 +++++++++++++++++++
 .../client/TextureClientSharedSurface.h       |  5 ++
 5 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/gfx/gl/SharedSurface.cpp b/gfx/gl/SharedSurface.cpp
index e5454d5964ea..634cc794a731 100644
--- a/gfx/gl/SharedSurface.cpp
+++ b/gfx/gl/SharedSurface.cpp
@@ -336,6 +336,7 @@ SurfaceFactory::NewTexClient(const gfx::IntSize& size)
         mRecycleFreePool.pop();
 
         if (cur->Surf()->mSize == size) {
+            cur->Surf()->WaitForBufferOwnership();
             return cur.forget();
         }
 
diff --git a/gfx/layers/client/CanvasClient.cpp b/gfx/layers/client/CanvasClient.cpp
index 76449ec733a6..cd2222c60236 100644
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -371,11 +371,24 @@ CanvasClientSharedSurface::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
     return;
   }
 
+#ifndef MOZ_WIDGET_GONK
   if (mFront) {
     if (mFront->GetFlags() & TextureFlags::RECYCLE) {
       mFront->WaitForCompositorRecycle();
     }
   }
+#else
+  // AutoRemoveTexture does the followings.
+  // - Ensure to deliver FenceHandle from TextureHost to TextureClient, before
+  //   next TextureClient usage.
+  // - Control TextureClient's recycling timing.
+  // - Call RemoveTexture() after newFront's UseTextures() call.
+  //   It could improve performance of Host side's EGL handling on gonk
+  AutoRemoveTexture autoRemove(this);
+  if (mFront && mFront != newFront) {
+    autoRemove.mTexture = mFront;
+  }
+#endif
 
   mFront = newFront;
 
diff --git a/gfx/layers/client/TextureClient.h b/gfx/layers/client/TextureClient.h
index 85ae2e356519..1337cbfed7f6 100644
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -442,7 +442,7 @@ public:
     mReleaseFenceHandle.Merge(aReleaseFenceHandle);
   }
 
-  FenceHandle GetAndResetReleaseFenceHandle()
+  virtual FenceHandle GetAndResetReleaseFenceHandle()
   {
     FenceHandle fence;
     mReleaseFenceHandle.TransferToAnotherFenceHandle(fence);
@@ -454,7 +454,7 @@ public:
     mAcquireFenceHandle = aAcquireFenceHandle;
   }
 
-  const FenceHandle& GetAcquireFenceHandle() const
+  virtual const FenceHandle& GetAcquireFenceHandle() const
   {
     return mAcquireFenceHandle;
   }
diff --git a/gfx/layers/client/TextureClientSharedSurface.cpp b/gfx/layers/client/TextureClientSharedSurface.cpp
index 0cf720609a3b..909362ae5071 100644
--- a/gfx/layers/client/TextureClientSharedSurface.cpp
+++ b/gfx/layers/client/TextureClientSharedSurface.cpp
@@ -13,6 +13,10 @@
 #include "nsThreadUtils.h"
 #include "SharedSurface.h"
 
+#ifdef MOZ_WIDGET_GONK
+#include "SharedSurfaceGralloc.h"
+#endif
+
 namespace mozilla {
 namespace layers {
 
@@ -41,5 +45,66 @@ SharedSurfaceTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescripto
   return mSurf->ToSurfaceDescriptor(&aOutDescriptor);
 }
 
+void
+SharedSurfaceTextureClient::SetReleaseFenceHandle(const FenceHandle& aReleaseFenceHandle)
+{
+#ifdef MOZ_WIDGET_GONK
+  SharedSurface_Gralloc* surf = nullptr;
+  if (mSurf->mType == SharedSurfaceType::Gralloc) {
+    surf = SharedSurface_Gralloc::Cast(mSurf.get());
+  }
+  if (surf && surf->GetTextureClient()) {
+    surf->GetTextureClient()->SetReleaseFenceHandle(aReleaseFenceHandle);
+    return;
+  }
+#endif
+  TextureClient::SetReleaseFenceHandle(aReleaseFenceHandle);
+}
+
+FenceHandle
+SharedSurfaceTextureClient::GetAndResetReleaseFenceHandle()
+{
+#ifdef MOZ_WIDGET_GONK
+  SharedSurface_Gralloc* surf = nullptr;
+  if (mSurf->mType == SharedSurfaceType::Gralloc) {
+    surf = SharedSurface_Gralloc::Cast(mSurf.get());
+  }
+  if (surf && surf->GetTextureClient()) {
+    return surf->GetTextureClient()->GetAndResetReleaseFenceHandle();
+  }
+#endif
+  return TextureClient::GetAndResetReleaseFenceHandle();
+}
+
+void
+SharedSurfaceTextureClient::SetAcquireFenceHandle(const FenceHandle& aAcquireFenceHandle)
+{
+#ifdef MOZ_WIDGET_GONK
+  SharedSurface_Gralloc* surf = nullptr;
+  if (mSurf->mType == SharedSurfaceType::Gralloc) {
+    surf = SharedSurface_Gralloc::Cast(mSurf.get());
+  }
+  if (surf && surf->GetTextureClient()) {
+    return surf->GetTextureClient()->SetAcquireFenceHandle(aAcquireFenceHandle);
+  }
+#endif
+  TextureClient::SetAcquireFenceHandle(aAcquireFenceHandle);
+}
+
+const FenceHandle&
+SharedSurfaceTextureClient::GetAcquireFenceHandle() const
+{
+#ifdef MOZ_WIDGET_GONK
+  SharedSurface_Gralloc* surf = nullptr;
+  if (mSurf->mType == SharedSurfaceType::Gralloc) {
+    surf = SharedSurface_Gralloc::Cast(mSurf.get());
+  }
+  if (surf && surf->GetTextureClient()) {
+    return surf->GetTextureClient()->GetAcquireFenceHandle();
+  }
+#endif
+  return TextureClient::GetAcquireFenceHandle();
+}
+
 } // namespace layers
 } // namespace mozilla
diff --git a/gfx/layers/client/TextureClientSharedSurface.h b/gfx/layers/client/TextureClientSharedSurface.h
index 55ea098b63dc..8f645e244047 100644
--- a/gfx/layers/client/TextureClientSharedSurface.h
+++ b/gfx/layers/client/TextureClientSharedSurface.h
@@ -64,6 +64,11 @@ public:
 
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) override;
 
+  virtual void SetReleaseFenceHandle(const FenceHandle& aReleaseFenceHandle) override;
+  virtual FenceHandle GetAndResetReleaseFenceHandle() override;
+  virtual void SetAcquireFenceHandle(const FenceHandle& aAcquireFenceHandle) override;
+  virtual const FenceHandle& GetAcquireFenceHandle() const override;
+
   gl::SharedSurface* Surf() const {
     return mSurf.get();
   }

From 3907bbb54961d70b48fd31cc8d547cb8006455f9 Mon Sep 17 00:00:00 2001
From: Eugen Sawin 
Date: Thu, 27 Aug 2015 23:43:59 +0200
Subject: [PATCH 034/133] Bug 1190379: Use AndroidDecoderModule for VP8/9.
 r=jya

---
 .../platforms/android/AndroidDecoderModule.cpp   | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/dom/media/platforms/android/AndroidDecoderModule.cpp b/dom/media/platforms/android/AndroidDecoderModule.cpp
index 28e9b17112d7..12c220f4e6cd 100644
--- a/dom/media/platforms/android/AndroidDecoderModule.cpp
+++ b/dom/media/platforms/android/AndroidDecoderModule.cpp
@@ -19,7 +19,6 @@
 #include "nsPromiseFlatString.h"
 
 #include 
-#include 
 
 using namespace mozilla;
 using namespace mozilla::gl;
@@ -34,10 +33,21 @@ namespace mozilla {
     NS_WARNING("callback not set"); \
   }
 
+static const char* TranslateMimeType(const nsACString& aMimeType)
+{
+  if (aMimeType.EqualsLiteral("video/webm; codecs=vp8")) {
+    return "video/x-vnd.on2.vp8";
+  } else if (aMimeType.EqualsLiteral("video/webm; codecs=vp9")) {
+    return "video/x-vnd.on2.vp9";
+  }
+  return PromiseFlatCString(aMimeType).get();
+}
+
 static MediaCodec::LocalRef CreateDecoder(const nsACString& aMimeType)
 {
   MediaCodec::LocalRef codec;
-  NS_ENSURE_SUCCESS(MediaCodec::CreateDecoderByType(PromiseFlatCString(aMimeType).get(), &codec), nullptr);
+  NS_ENSURE_SUCCESS(MediaCodec::CreateDecoderByType(TranslateMimeType(aMimeType),
+                    &codec), nullptr);
   return codec;
 }
 
@@ -287,7 +297,7 @@ AndroidDecoderModule::CreateVideoDecoder(
   MediaFormat::LocalRef format;
 
   NS_ENSURE_SUCCESS(MediaFormat::CreateVideoFormat(
-      aConfig.mMimeType,
+      TranslateMimeType(aConfig.mMimeType),
       aConfig.mDisplay.width,
       aConfig.mDisplay.height,
       &format), nullptr);

From 0e728cd2a39ef91b7b19af8127fe67ae91c57c10 Mon Sep 17 00:00:00 2001
From: Ryan VanderMeulen 
Date: Mon, 21 Sep 2015 10:48:01 -0400
Subject: [PATCH 035/133] Bug 1205346 - Remove automation for the
 mozilla-b2g34_v2_1s branch. r=catlee DONTBUILD

---
 testing/mozharness/configs/merge_day/b2g_tag.py | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/testing/mozharness/configs/merge_day/b2g_tag.py b/testing/mozharness/configs/merge_day/b2g_tag.py
index d6d46d89a0d9..916c91c2bc83 100644
--- a/testing/mozharness/configs/merge_day/b2g_tag.py
+++ b/testing/mozharness/configs/merge_day/b2g_tag.py
@@ -1,8 +1,4 @@
 LIVE_B2G_BRANCHES = {
-    "mozilla-b2g34_v2_1s": {
-        "gaia_branch": "v2.1s",
-        "tag_name": "B2G_2_1s_%(DATE)s_MERGEDAY",
-    },
     "mozilla-b2g37_v2_2": {
         "gaia_branch": "v2.2",
         "tag_name": "B2G_2_2_%(DATE)s_MERGEDAY",

From 554272fa7f6c4dc78b74a505a1bf68f8d4181d6c Mon Sep 17 00:00:00 2001
From: Nicolas Silva 
Date: Mon, 21 Sep 2015 16:54:40 +0200
Subject: [PATCH 036/133] Bug 1072313 - Never call
 TextureClient::KeepUntilFullDeallocation off the ipdl thread. r=mattwoodrow

---
 gfx/layers/client/TextureClient.cpp           |  1 +
 gfx/layers/client/TextureClient.h             | 11 +++++++-
 gfx/layers/d3d11/TextureD3D11.cpp             | 26 +++++++++++++------
 gfx/layers/d3d11/TextureD3D11.h               |  4 +++
 gfx/layers/d3d9/TextureD3D9.cpp               |  7 ++++-
 gfx/layers/d3d9/TextureD3D9.h                 |  2 ++
 gfx/layers/ipc/ImageBridgeChild.cpp           |  2 +-
 .../opengl/MacIOSurfaceTextureClientOGL.cpp   |  5 ++++
 .../opengl/MacIOSurfaceTextureClientOGL.h     |  2 ++
 9 files changed, 49 insertions(+), 11 deletions(-)

diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp
index ce847d311b22..23e899c353b0 100644
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -557,6 +557,7 @@ TextureClient::KeepUntilFullDeallocation(UniquePtr aKeep, bool aMainT
 
 void TextureClient::ForceRemove(bool sync)
 {
+  FinalizeOnIPDLThread();
   if (mValid && mActor) {
     if (sync || GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
       MOZ_PERFORMANCE_WARNING("gfx", "TextureClient/Host pair requires synchronous deallocation");
diff --git a/gfx/layers/client/TextureClient.h b/gfx/layers/client/TextureClient.h
index 1337cbfed7f6..373b5a307486 100644
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -408,6 +408,8 @@ public:
    * help avoid race conditions in some cases.
    * It's a temporary hack to ensure that DXGI textures don't get destroyed
    * between serialization and deserialization.
+   *
+   * This must not be called off the texture's IPDL thread.
    */
   void KeepUntilFullDeallocation(UniquePtr aKeep, bool aMainThreadOnly = false);
 
@@ -504,13 +506,20 @@ private:
   static void TextureClientRecycleCallback(TextureClient* aClient, void* aClosure);
 
   /**
-   * Called once, just before the destructor.
+   * Called once, during the destruction of the Texture, on the thread in which
+   * texture's reference count reaches 0 (could be any thread).
    *
    * Here goes the shut-down code that uses virtual methods.
    * Must only be called by Release().
    */
   B2G_ACL_EXPORT void Finalize();
 
+  /**
+   * Called once during the destruction of the texture on the IPDL thread, if
+   * the texture is shared on the compositor (otherwise it is not called at all).
+   */
+  virtual void FinalizeOnIPDLThread() {}
+
   friend class AtomicRefCountedWithFinalize;
 
 protected:
diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp
index bf0f945da777..51c8513316ec 100644
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -198,13 +198,6 @@ TextureClientD3D11::TextureClientD3D11(ISurfaceAllocator* aAllocator,
 
 TextureClientD3D11::~TextureClientD3D11()
 {
-  if (mActor) {
-    if (mTexture) {
-      KeepUntilFullDeallocation(MakeUnique>(mTexture));
-    } else if (mTexture10) {
-      KeepUntilFullDeallocation(MakeUnique>(mTexture10));
-    }
-  }
 #ifdef DEBUG
   // An Azure DrawTarget needs to be locked when it gets nullptr'ed as this is
   // when it calls EndDraw. This EndDraw should not execute anything so it
@@ -228,6 +221,18 @@ TextureClientD3D11::~TextureClientD3D11()
 #endif
 }
 
+void
+TextureClientD3D11::FinalizeOnIPDLThread()
+{
+  if (mActor) {
+    if (mTexture) {
+      KeepUntilFullDeallocation(MakeUnique>(mTexture));
+    } else if (mTexture10) {
+      KeepUntilFullDeallocation(MakeUnique>(mTexture10));
+    }
+  }
+}
+
 // static
 already_AddRefed
 TextureClientD3D11::Create(ISurfaceAllocator* aAllocator,
@@ -656,11 +661,16 @@ protected:
 };
 
 DXGIYCbCrTextureClient::~DXGIYCbCrTextureClient()
+{
+  MOZ_COUNT_DTOR(DXGIYCbCrTextureClient);
+}
+
+void
+DXGIYCbCrTextureClient::FinalizeOnIPDLThread()
 {
   if (mHoldRefs[0] && mActor) {
     KeepUntilFullDeallocation(MakeUnique(mHoldRefs), true);
   }
-  MOZ_COUNT_DTOR(DXGIYCbCrTextureClient);
 }
 
 // static
diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h
index c3d1ad8c002d..b19877ce49b2 100644
--- a/gfx/layers/d3d11/TextureD3D11.h
+++ b/gfx/layers/d3d11/TextureD3D11.h
@@ -88,6 +88,8 @@ public:
 protected:
   bool AllocateD3D11Surface(ID3D11Device* aDevice, const gfx::IntSize& aSize);
 
+  virtual void FinalizeOnIPDLThread() override;
+
   gfx::IntSize mSize;
   RefPtr mTexture10;
   RefPtr mTexture;
@@ -157,6 +159,8 @@ public:
     CreateSimilar(TextureFlags, TextureAllocationFlags) const override{ return nullptr; }
 
 private:
+  virtual void FinalizeOnIPDLThread() override;
+
   RefPtr mHoldRefs[3];
   HANDLE mHandles[3];
   gfx::IntSize mSize;
diff --git a/gfx/layers/d3d9/TextureD3D9.cpp b/gfx/layers/d3d9/TextureD3D9.cpp
index 2f46658cdb2c..17ea1e48c35b 100644
--- a/gfx/layers/d3d9/TextureD3D9.cpp
+++ b/gfx/layers/d3d9/TextureD3D9.cpp
@@ -660,6 +660,12 @@ SharedTextureClientD3D9::SharedTextureClientD3D9(ISurfaceAllocator* aAllocator,
 }
 
 SharedTextureClientD3D9::~SharedTextureClientD3D9()
+{
+  MOZ_COUNT_DTOR(SharedTextureClientD3D9);
+}
+
+void
+SharedTextureClientD3D9::FinalizeOnIPDLThread()
 {
   if (mTexture && mActor) {
     KeepUntilFullDeallocation(MakeUnique>(mTexture));
@@ -667,7 +673,6 @@ SharedTextureClientD3D9::~SharedTextureClientD3D9()
   if (mTexture) {
     gfxWindowsPlatform::sD3D9SharedTextureUsed -= mDesc.Width * mDesc.Height * 4;
   }
-  MOZ_COUNT_DTOR(SharedTextureClientD3D9);
 }
 
 // static
diff --git a/gfx/layers/d3d9/TextureD3D9.h b/gfx/layers/d3d9/TextureD3D9.h
index 27ff3093be66..5708775af9d0 100644
--- a/gfx/layers/d3d9/TextureD3D9.h
+++ b/gfx/layers/d3d9/TextureD3D9.h
@@ -285,6 +285,8 @@ public:
   }
 
 private:
+  virtual void FinalizeOnIPDLThread() override;
+
   RefPtr mDevice;
   RefPtr mTexture;
   gfx::SurfaceFormat mFormat;
diff --git a/gfx/layers/ipc/ImageBridgeChild.cpp b/gfx/layers/ipc/ImageBridgeChild.cpp
index 301c6b578479..06cb4ca773dc 100644
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -188,7 +188,7 @@ static void ImageBridgeShutdownStep1(ReentrantMonitor *aBarrier, bool *aDone)
     InfallibleTArray textures;
     sImageBridgeChildSingleton->ManagedPTextureChild(textures);
     for (int i = textures.Length() - 1; i >= 0; --i) {
-      TextureClient* client = TextureClient::AsTextureClient(textures[i]);
+      RefPtr client = TextureClient::AsTextureClient(textures[i]);
       if (client) {
         client->ForceRemove();
       }
diff --git a/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp
index 159b41291fc7..fbefd06c8f65 100644
--- a/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp
+++ b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp
@@ -16,6 +16,11 @@ MacIOSurfaceTextureClientOGL::MacIOSurfaceTextureClientOGL(ISurfaceAllocator* aA
 {}
 
 MacIOSurfaceTextureClientOGL::~MacIOSurfaceTextureClientOGL()
+{
+}
+
+void
+MacIOSurfaceTextureClientOGL::FinalizeOnIPDLThread()
 {
   if (mActor && mSurface) {
     KeepUntilFullDeallocation(MakeUnique>(mSurface));
diff --git a/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h
index 5a0c03825d36..7548beeafdc7 100644
--- a/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h
+++ b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h
@@ -50,6 +50,8 @@ public:
   CreateSimilar(TextureFlags, TextureAllocationFlags) const override { return nullptr; }
 
 protected:
+  virtual void FinalizeOnIPDLThread() override;
+
   RefPtr mSurface;
   bool mIsLocked;
 };

From 47de316d52c598b7ce3b1f27211bb8855d70cfe0 Mon Sep 17 00:00:00 2001
From: Christoph Kerschbaumer 
Date: Fri, 31 Oct 2014 13:37:59 -0700
Subject: [PATCH 037/133] Bug 1048048 - add preload content policy types -
 tests (r=dveditz)

---
 .../test/csp/file_report_for_import.css       |   1 +
 .../test/csp/file_report_for_import.html      |  10 ++
 .../csp/file_report_for_import_server.sjs     |  49 ++++++++
 dom/security/test/csp/mochitest.ini           |   4 +
 .../test/csp/test_report_for_import.html      | 112 ++++++++++++++++++
 5 files changed, 176 insertions(+)
 create mode 100644 dom/security/test/csp/file_report_for_import.css
 create mode 100644 dom/security/test/csp/file_report_for_import.html
 create mode 100644 dom/security/test/csp/file_report_for_import_server.sjs
 create mode 100644 dom/security/test/csp/test_report_for_import.html

diff --git a/dom/security/test/csp/file_report_for_import.css b/dom/security/test/csp/file_report_for_import.css
new file mode 100644
index 000000000000..b578b77b33fb
--- /dev/null
+++ b/dom/security/test/csp/file_report_for_import.css
@@ -0,0 +1 @@
+@import url("http://example.com/tests/dom/security/test/csp/file_report_for_import_server.sjs?stylesheet");
diff --git a/dom/security/test/csp/file_report_for_import.html b/dom/security/test/csp/file_report_for_import.html
new file mode 100644
index 000000000000..77a36faea1b6
--- /dev/null
+++ b/dom/security/test/csp/file_report_for_import.html
@@ -0,0 +1,10 @@
+
+
+  
+    Bug 1048048 - Test sending csp-report when using import in css
+    
+  
+  
+  empty body, just testing @import in the included css for bug 1048048
+
+
diff --git a/dom/security/test/csp/file_report_for_import_server.sjs b/dom/security/test/csp/file_report_for_import_server.sjs
new file mode 100644
index 000000000000..e69852b1b791
--- /dev/null
+++ b/dom/security/test/csp/file_report_for_import_server.sjs
@@ -0,0 +1,49 @@
+// Custom *.sjs file specifically for the needs of Bug:
+// Bug 1048048 - CSP violation report not sent for @import
+
+const CC = Components.Constructor;
+const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
+                             "nsIBinaryInputStream",
+                             "setInputStream");
+
+function handleRequest(request, response)
+{
+  // avoid confusing cache behaviors
+  response.setHeader("Cache-Control", "no-cache", false);
+  response.setHeader("Content-Type", "text/html", false);
+  var queryString = request.queryString;
+
+  // (1) lets process the queryresult request async and
+  // wait till we have received the image request.
+  if (queryString === "queryresult") {
+    response.processAsync();
+    setObjectState("queryResult", response);
+    return;
+  }
+
+  // (2) handle the csp-report and return the JSON back to
+  // the testfile using the afore stored xml request in (1).
+  if (queryString === "report") {
+    getObjectState("queryResult", function(queryResponse) {
+      if (!queryResponse) {
+        return;
+      }
+
+      // send the report back to the XML request for verification
+      var report = new BinaryInputStream(request.bodyInputStream);
+      var avail;
+      var bytes = [];
+      while ((avail = report.available()) > 0) {
+        Array.prototype.push.apply(bytes, report.readByteArray(avail));
+      }
+      var data = String.fromCharCode.apply(null, bytes);
+      queryResponse.bodyOutputStream.write(data, data.length);
+      queryResponse.finish();
+    });
+    return;
+  }
+
+  // we should not get here ever, but just in case return
+  // something unexpected.
+  response.write("doh!");
+}
diff --git a/dom/security/test/csp/mochitest.ini b/dom/security/test/csp/mochitest.ini
index 13897873308c..0ca3b70da82c 100644
--- a/dom/security/test/csp/mochitest.ini
+++ b/dom/security/test/csp/mochitest.ini
@@ -127,6 +127,9 @@ support-files =
   file_upgrade_insecure_referrer_server.sjs
   file_upgrade_insecure_cors.html
   file_upgrade_insecure_cors_server.sjs
+  file_report_for_import.css
+  file_report_for_import.html
+  file_report_for_import_server.sjs
 
 [test_base-uri.html]
 [test_blob_data_schemes.html]
@@ -191,5 +194,6 @@ skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'gonk' || toolk
 skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'gonk' || toolkit == 'android'
 [test_upgrade_insecure_cors.html]
 skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'gonk' || toolkit == 'android'
+[test_report_for_import.html]
 [test_blocked_uri_in_reports.html]
 skip-if = e10s || buildapp == 'b2g' # http-on-opening-request observer not supported in child process (bug 1009632)
diff --git a/dom/security/test/csp/test_report_for_import.html b/dom/security/test/csp/test_report_for_import.html
new file mode 100644
index 000000000000..346af65b74ef
--- /dev/null
+++ b/dom/security/test/csp/test_report_for_import.html
@@ -0,0 +1,112 @@
+
+
+
+
+  Test for Bug 548193
+  
+  
+
+
+

+ + + + +
+ + From 319984decc15b0516e112b566fd45ee4ae3562f6 Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Sun, 20 Sep 2015 14:55:44 -0700 Subject: [PATCH 038/133] Bug 1048048 - add preload content policy types (r=ehsan) --- dom/base/nsContentPolicy.cpp | 16 +++++++ dom/base/nsContentPolicyUtils.h | 75 ++++++++++++++++--------------- dom/base/nsContentUtils.cpp | 20 +++++++++ dom/base/nsContentUtils.h | 10 +++++ dom/base/nsIContentPolicy.idl | 2 +- dom/base/nsIContentPolicyBase.idl | 43 +++++++++++++++++- dom/cache/DBSchema.cpp | 7 ++- dom/fetch/InternalRequest.cpp | 7 ++- dom/fetch/InternalRequest.h | 6 +-- 9 files changed, 143 insertions(+), 43 deletions(-) diff --git a/dom/base/nsContentPolicy.cpp b/dom/base/nsContentPolicy.cpp index 9b2ec5528799..7f0c8a3a1345 100644 --- a/dom/base/nsContentPolicy.cpp +++ b/dom/base/nsContentPolicy.cpp @@ -13,6 +13,7 @@ #include "nsISupports.h" #include "nsXPCOM.h" #include "nsContentPolicyUtils.h" +#include "mozilla/dom/nsCSPService.h" #include "nsContentPolicy.h" #include "nsIURI.h" #include "nsIDocShell.h" @@ -123,9 +124,15 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod, nsContentPolicyType externalTypeOrScript = nsContentUtils::InternalContentPolicyTypeToExternalOrScript(contentType); + nsContentPolicyType externalTypeOrPreload = + nsContentUtils::InternalContentPolicyTypeToExternalOrPreload(contentType); + nsCOMPtr mixedContentBlocker = do_GetService(NS_MIXEDCONTENTBLOCKER_CONTRACTID); + nsCOMPtr cspService = + do_GetService(CSPSERVICE_CONTRACTID); + /* * Enumerate mPolicies and ask each of them, taking the logical AND of * their permissions. @@ -144,6 +151,15 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod, if (isMixedContentBlocker) { type = externalTypeOrScript; } + // Send the internal content policy type for CSP which needs to + // know about preloads, in particular: + // * TYPE_INTERNAL_SCRIPT_PRELOAD + // * TYPE_INTERNAL_IMAGE_PRELOAD + // * TYPE_INTERNAL_STYLESHEET_PRELOAD + bool isCSP = cspService == entries[i]; + if (isCSP) { + type = externalTypeOrPreload; + } rv = (entries[i]->*policyMethod)(type, contentLocation, requestingLocation, requestingContext, mimeType, extra, requestPrincipal, diff --git a/dom/base/nsContentPolicyUtils.h b/dom/base/nsContentPolicyUtils.h index e3bc0c051399..cddee3a6543c 100644 --- a/dom/base/nsContentPolicyUtils.h +++ b/dom/base/nsContentPolicyUtils.h @@ -92,41 +92,46 @@ inline const char * NS_CP_ContentTypeName(uint32_t contentType) { switch (contentType) { - CASE_RETURN( TYPE_OTHER ); - CASE_RETURN( TYPE_SCRIPT ); - CASE_RETURN( TYPE_IMAGE ); - CASE_RETURN( TYPE_STYLESHEET ); - CASE_RETURN( TYPE_OBJECT ); - CASE_RETURN( TYPE_DOCUMENT ); - CASE_RETURN( TYPE_SUBDOCUMENT ); - CASE_RETURN( TYPE_REFRESH ); - CASE_RETURN( TYPE_XBL ); - CASE_RETURN( TYPE_PING ); - CASE_RETURN( TYPE_XMLHTTPREQUEST ); - CASE_RETURN( TYPE_OBJECT_SUBREQUEST ); - CASE_RETURN( TYPE_DTD ); - CASE_RETURN( TYPE_FONT ); - CASE_RETURN( TYPE_MEDIA ); - CASE_RETURN( TYPE_WEBSOCKET ); - CASE_RETURN( TYPE_CSP_REPORT ); - CASE_RETURN( TYPE_XSLT ); - CASE_RETURN( TYPE_BEACON ); - CASE_RETURN( TYPE_FETCH ); - CASE_RETURN( TYPE_IMAGESET ); - CASE_RETURN( TYPE_WEB_MANIFEST ); - CASE_RETURN( TYPE_INTERNAL_SCRIPT ); - CASE_RETURN( TYPE_INTERNAL_WORKER ); - CASE_RETURN( TYPE_INTERNAL_SHARED_WORKER ); - CASE_RETURN( TYPE_INTERNAL_EMBED ); - CASE_RETURN( TYPE_INTERNAL_OBJECT ); - CASE_RETURN( TYPE_INTERNAL_FRAME ); - CASE_RETURN( TYPE_INTERNAL_IFRAME ); - CASE_RETURN( TYPE_INTERNAL_AUDIO ); - CASE_RETURN( TYPE_INTERNAL_VIDEO ); - CASE_RETURN( TYPE_INTERNAL_TRACK ); - CASE_RETURN( TYPE_INTERNAL_XMLHTTPREQUEST ); - CASE_RETURN( TYPE_INTERNAL_EVENTSOURCE ); - CASE_RETURN( TYPE_INTERNAL_SERVICE_WORKER ); + CASE_RETURN( TYPE_OTHER ); + CASE_RETURN( TYPE_SCRIPT ); + CASE_RETURN( TYPE_IMAGE ); + CASE_RETURN( TYPE_STYLESHEET ); + CASE_RETURN( TYPE_OBJECT ); + CASE_RETURN( TYPE_DOCUMENT ); + CASE_RETURN( TYPE_SUBDOCUMENT ); + CASE_RETURN( TYPE_REFRESH ); + CASE_RETURN( TYPE_XBL ); + CASE_RETURN( TYPE_PING ); + CASE_RETURN( TYPE_XMLHTTPREQUEST ); + CASE_RETURN( TYPE_OBJECT_SUBREQUEST ); + CASE_RETURN( TYPE_DTD ); + CASE_RETURN( TYPE_FONT ); + CASE_RETURN( TYPE_MEDIA ); + CASE_RETURN( TYPE_WEBSOCKET ); + CASE_RETURN( TYPE_CSP_REPORT ); + CASE_RETURN( TYPE_XSLT ); + CASE_RETURN( TYPE_BEACON ); + CASE_RETURN( TYPE_FETCH ); + CASE_RETURN( TYPE_IMAGESET ); + CASE_RETURN( TYPE_WEB_MANIFEST ); + CASE_RETURN( TYPE_INTERNAL_SCRIPT ); + CASE_RETURN( TYPE_INTERNAL_WORKER ); + CASE_RETURN( TYPE_INTERNAL_SHARED_WORKER ); + CASE_RETURN( TYPE_INTERNAL_EMBED ); + CASE_RETURN( TYPE_INTERNAL_OBJECT ); + CASE_RETURN( TYPE_INTERNAL_FRAME ); + CASE_RETURN( TYPE_INTERNAL_IFRAME ); + CASE_RETURN( TYPE_INTERNAL_AUDIO ); + CASE_RETURN( TYPE_INTERNAL_VIDEO ); + CASE_RETURN( TYPE_INTERNAL_TRACK ); + CASE_RETURN( TYPE_INTERNAL_XMLHTTPREQUEST ); + CASE_RETURN( TYPE_INTERNAL_EVENTSOURCE ); + CASE_RETURN( TYPE_INTERNAL_SERVICE_WORKER ); + CASE_RETURN( TYPE_INTERNAL_SCRIPT_PRELOAD ); + CASE_RETURN( TYPE_INTERNAL_IMAGE ); + CASE_RETURN( TYPE_INTERNAL_IMAGE_PRELOAD ); + CASE_RETURN( TYPE_INTERNAL_STYLESHEET ); + CASE_RETURN( TYPE_INTERNAL_STYLESHEET_PRELOAD ); default: return ""; } diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index bb06e960f920..8936622c0b9a 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -7959,6 +7959,7 @@ nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType) { switch (aType) { case nsIContentPolicy::TYPE_INTERNAL_SCRIPT: + case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD: case nsIContentPolicy::TYPE_INTERNAL_WORKER: case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER: case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER: @@ -7981,6 +7982,14 @@ nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType) case nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE: return nsIContentPolicy::TYPE_XMLHTTPREQUEST; + case nsIContentPolicy::TYPE_INTERNAL_IMAGE: + case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD: + return nsIContentPolicy::TYPE_IMAGE; + + case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET: + case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD: + return nsIContentPolicy::TYPE_STYLESHEET; + default: return aType; } @@ -8002,6 +8011,17 @@ nsContentUtils::InternalContentPolicyTypeToExternalOrScript(nsContentPolicyType } } +/* static */ +nsContentPolicyType +nsContentUtils::InternalContentPolicyTypeToExternalOrPreload(nsContentPolicyType aType) +{ + if (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD || + aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD || + aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD) { + return aType; + } + return InternalContentPolicyTypeToExternal(aType); +} nsresult nsContentUtils::SetFetchReferrerURIWithPolicy(nsIPrincipal* aPrincipal, diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index 5182181b2886..133cb80d712d 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -965,6 +965,16 @@ public: */ static nsContentPolicyType InternalContentPolicyTypeToExternalOrScript(nsContentPolicyType aType); + /** + * Map internal content policy types to external ones or preload types: + * * TYPE_INTERNAL_SCRIPT_PRELOAD + * * TYPE_INTERNAL_IMAGE_PRELOAD + * * TYPE_INTERNAL_STYLESHEET_PRELOAD + * + * Note: DO NOT call this function unless you know what you're doing! + */ + static nsContentPolicyType InternalContentPolicyTypeToExternalOrPreload(nsContentPolicyType aType); + /** * Quick helper to determine whether there are any mutation listeners * of a given type that apply to this content or any of its ancestors. diff --git a/dom/base/nsIContentPolicy.idl b/dom/base/nsIContentPolicy.idl index 63ec72e223e8..a73565a9a91e 100644 --- a/dom/base/nsIContentPolicy.idl +++ b/dom/base/nsIContentPolicy.idl @@ -20,7 +20,7 @@ interface nsIPrincipal; * by launching a dialog to prompt the user for something). */ -[scriptable,uuid(ce321216-c404-40a7-a711-d80454ec6b76)] +[scriptable,uuid(caad4f1f-d047-46ac-ae9d-dc598e4fb91b)] interface nsIContentPolicy : nsIContentPolicyBase { /** diff --git a/dom/base/nsIContentPolicyBase.idl b/dom/base/nsIContentPolicyBase.idl index e31608fe9bd5..c064ecaf74c9 100644 --- a/dom/base/nsIContentPolicyBase.idl +++ b/dom/base/nsIContentPolicyBase.idl @@ -24,7 +24,7 @@ typedef unsigned long nsContentPolicyType; * by launching a dialog to prompt the user for something). */ -[scriptable,uuid(8527ae0d-0c43-4413-bc46-85c0bcb66876)] +[scriptable,uuid(17418187-d86f-48dd-92d1-238838df0a4e)] interface nsIContentPolicyBase : nsISupports { /** @@ -280,6 +280,47 @@ interface nsIContentPolicyBase : nsISupports */ const nsContentPolicyType TYPE_INTERNAL_SERVICE_WORKER = 35; + /** + * Indicates an internal constant for *preloaded* scripts + * loaded through script elements. + * + * This will be mapped to TYPE_SCRIPT before being passed + * to content policy implementations. + */ + const nsContentPolicyType TYPE_INTERNAL_SCRIPT_PRELOAD = 36; + + /** + * Indicates an internal constant for normal images. + * + * This will be mapped to TYPE_IMAGE before being passed + * to content policy implementations. + */ + const nsContentPolicyType TYPE_INTERNAL_IMAGE = 37; + + /** + * Indicates an internal constant for *preloaded* images. + * + * This will be mapped to TYPE_IMAGE before being passed + * to content policy implementations. + */ + const nsContentPolicyType TYPE_INTERNAL_IMAGE_PRELOAD = 38; + + /** + * Indicates an internal constant for normal stylesheets. + * + * This will be mapped to TYPE_STYLESHEET before being passed + * to content policy implementations. + */ + const nsContentPolicyType TYPE_INTERNAL_STYLESHEET = 39; + + /** + * Indicates an internal constant for *preloaded* stylesheets. + * + * This will be mapped to TYPE_STYLESHEET before being passed + * to content policy implementations. + */ + const nsContentPolicyType TYPE_INTERNAL_STYLESHEET_PRELOAD = 40; + /* When adding new content types, please update nsContentBlocker, * NS_CP_ContentTypeName, nsCSPContext, all nsIContentPolicy * implementations, the static_assert in dom/cache/DBSchema.cpp, diff --git a/dom/cache/DBSchema.cpp b/dom/cache/DBSchema.cpp index 52a93333425d..e2f6904bbd9a 100644 --- a/dom/cache/DBSchema.cpp +++ b/dom/cache/DBSchema.cpp @@ -275,7 +275,12 @@ static_assert(nsIContentPolicy::TYPE_INVALID == 0 && nsIContentPolicy::TYPE_INTERNAL_TRACK == 32 && nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST == 33 && nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE == 34 && - nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER == 35, + nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER == 35 && + nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD == 36 && + nsIContentPolicy::TYPE_INTERNAL_IMAGE == 37 && + nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD == 38 && + nsIContentPolicy::TYPE_INTERNAL_STYLESHEET == 39 && + nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD == 40, "nsContentPolicyType values are as expected"); namespace { diff --git a/dom/fetch/InternalRequest.cpp b/dom/fetch/InternalRequest.cpp index d2a8f2bc1f85..2baed642b12c 100644 --- a/dom/fetch/InternalRequest.cpp +++ b/dom/fetch/InternalRequest.cpp @@ -116,6 +116,7 @@ InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aConte context = RequestContext::Internal; break; case nsIContentPolicy::TYPE_INTERNAL_SCRIPT: + case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD: case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER: context = RequestContext::Script; break; @@ -125,10 +126,12 @@ InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aConte case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER: context = RequestContext::Sharedworker; break; - case nsIContentPolicy::TYPE_IMAGE: + case nsIContentPolicy::TYPE_INTERNAL_IMAGE: + case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD: context = RequestContext::Image; break; - case nsIContentPolicy::TYPE_STYLESHEET: + case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET: + case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD: context = RequestContext::Style; break; case nsIContentPolicy::TYPE_INTERNAL_OBJECT: diff --git a/dom/fetch/InternalRequest.h b/dom/fetch/InternalRequest.h index caa005756bcd..8c9d84238667 100644 --- a/dom/fetch/InternalRequest.h +++ b/dom/fetch/InternalRequest.h @@ -43,7 +43,7 @@ namespace dom { * frame | TYPE_INTERNAL_FRAME * hyperlink | * iframe | TYPE_INTERNAL_IFRAME - * image | TYPE_IMAGE + * image | TYPE_INTERNAL_IMAGE, TYPE_INTERNAL_IMAGE_PRELOAD * imageset | TYPE_IMAGESET * import | Not supported by Gecko * internal | TYPE_DOCUMENT, TYPE_XBL, TYPE_OTHER @@ -53,10 +53,10 @@ namespace dom { * ping | TYPE_PING * plugin | TYPE_OBJECT_SUBREQUEST * prefetch | - * script | TYPE_INTERNAL_SCRIPT + * script | TYPE_INTERNAL_SCRIPT, TYPE_INTERNAL_SCRIPT_PRELOAD * sharedworker | TYPE_INTERNAL_SHARED_WORKER * subresource | Not supported by Gecko - * style | TYPE_STYLESHEET + * style | TYPE_INTERNAL_STYLESHEET, TYPE_INTERNAL_STYLESHEET_PRELOAD * track | TYPE_INTERNAL_TRACK * video | TYPE_INTERNAL_VIDEO * worker | TYPE_INTERNAL_WORKER From 19dc79ddbbdf61a8deea678166ab53b99fc5f8ad Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Sun, 20 Sep 2015 14:55:59 -0700 Subject: [PATCH 039/133] Bug 1048048 - add preload content policy types for images (r=seth) --- browser/modules/ContentLinkHandler.jsm | 2 +- browser/modules/WindowsPreviewPerTab.jsm | 2 +- dom/base/nsContentUtils.h | 8 ++++---- dom/base/nsDocument.cpp | 6 ++++-- dom/base/nsImageLoadingContent.cpp | 2 +- dom/base/nsObjectLoadingContent.cpp | 2 +- dom/html/ImageDocument.cpp | 2 +- embedding/browser/nsContextMenuInfo.cpp | 2 +- image/imgLoader.cpp | 4 ++-- layout/generic/nsImageFrame.cpp | 2 +- toolkit/components/places/AsyncFaviconHelpers.cpp | 2 +- toolkit/components/places/nsAnnoProtocolHandler.cpp | 2 +- toolkit/components/places/nsFaviconService.cpp | 2 +- .../browser/browser_favicon_setAndFetchFaviconForPage.js | 2 +- .../tests/favicons/test_moz-anno_favicon_mime_type.js | 6 +++--- toolkit/components/search/nsSearchService.js | 2 +- toolkit/devtools/gcli/commands/screenshot.js | 2 +- .../internal/LightweightThemeImageOptimizer.jsm | 2 +- toolkit/webapps/NativeApp.jsm | 2 +- widget/cocoa/OSXNotificationCenter.mm | 2 +- widget/cocoa/nsMenuItemIconX.mm | 2 +- widget/windows/WinUtils.cpp | 2 +- 22 files changed, 31 insertions(+), 29 deletions(-) diff --git a/browser/modules/ContentLinkHandler.jsm b/browser/modules/ContentLinkHandler.jsm index 46cf75a25e56..9d4da688984b 100644 --- a/browser/modules/ContentLinkHandler.jsm +++ b/browser/modules/ContentLinkHandler.jsm @@ -164,7 +164,7 @@ this.ContentLinkHandler = { } // Security says okay, now ask content policy - if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_IMAGE, + if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE, uri, targetDoc.documentURIObject, aLink, aLink.type, null) != Ci.nsIContentPolicy.ACCEPT) diff --git a/browser/modules/WindowsPreviewPerTab.jsm b/browser/modules/WindowsPreviewPerTab.jsm index 86623de5fe88..8f32ac8a4db6 100644 --- a/browser/modules/WindowsPreviewPerTab.jsm +++ b/browser/modules/WindowsPreviewPerTab.jsm @@ -79,7 +79,7 @@ function _imageFromURI(doc, uri, privateMode, callback) { null, // aLoadingPrincipal null, // aTriggeringPrincipal Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_IMAGE); + Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); try { channel.QueryInterface(Ci.nsIPrivateBrowsingChannel); channel.setPrivate(privateMode); diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index 133cb80d712d..43a3d36ddc5c 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -624,7 +624,7 @@ public: * @param aContext the context the image is loaded in (eg an element) * @param aLoadingDocument the document we belong to * @param aLoadingPrincipal the principal doing the load - * @param [aContentPolicyType=nsIContentPolicy::TYPE_IMAGE] (Optional) + * @param [aContentPolicyType=nsIContentPolicy::TYPE_INTERNAL_IMAGE] (Optional) * The CP content type to use * @param aImageBlockingStatus the nsIContentPolicy blocking status for this * image. This will be set even if a security check fails for the @@ -640,7 +640,7 @@ public: nsIDocument* aLoadingDocument, nsIPrincipal* aLoadingPrincipal, int16_t* aImageBlockingStatus = nullptr, - uint32_t aContentPolicyType = nsIContentPolicy::TYPE_IMAGE); + uint32_t aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE); /** * Returns true if objects in aDocument shouldn't initiate image loads. @@ -660,7 +660,7 @@ public: * creation * @param aObserver the observer for the image load * @param aLoadFlags the load flags to use. See nsIRequest - * @param [aContentPolicyType=nsIContentPolicy::TYPE_IMAGE] (Optional) + * @param [aContentPolicyType=nsIContentPolicy::TYPE_INTERNAL_IMAGE] (Optional) * The CP content type to use * @return the imgIRequest for the image load */ @@ -673,7 +673,7 @@ public: int32_t aLoadFlags, const nsAString& initiatorType, imgRequestProxy** aRequest, - uint32_t aContentPolicyType = nsIContentPolicy::TYPE_IMAGE); + uint32_t aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE); /** * Obtain an image loader that respects the given document/channel's privacy status. diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index ec065056449d..5e25bba21ee6 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -9739,7 +9739,8 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr, int16_t blockingStatus; if (nsContentUtils::IsImageInCache(uri, static_cast(this)) || !nsContentUtils::CanLoadImage(uri, static_cast(this), - this, NodePrincipal(), &blockingStatus)) { + this, NodePrincipal(), &blockingStatus, + nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD)) { return; } @@ -9769,7 +9770,8 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr, nullptr, // no observer loadFlags, NS_LITERAL_STRING("img"), - getter_AddRefs(request)); + getter_AddRefs(request), + nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD); // Pin image-reference to avoid evicting it from the img-cache before // the "real" load occurs. Unpinned in DispatchContentLoadedEvents and diff --git a/dom/base/nsImageLoadingContent.cpp b/dom/base/nsImageLoadingContent.cpp index 626671a56b3a..d91fc96b928e 100644 --- a/dom/base/nsImageLoadingContent.cpp +++ b/dom/base/nsImageLoadingContent.cpp @@ -589,7 +589,7 @@ nsImageLoadingContent::PolicyTypeForLoad(ImageLoadType aImageLoadType) MOZ_ASSERT(aImageLoadType == eImageLoadType_Normal, "Unknown ImageLoadType type in PolicyTypeForLoad"); - return nsIContentPolicy::TYPE_IMAGE; + return nsIContentPolicy::TYPE_INTERNAL_IMAGE; } int32_t diff --git a/dom/base/nsObjectLoadingContent.cpp b/dom/base/nsObjectLoadingContent.cpp index 1767895fa595..5f5f670d1cb7 100644 --- a/dom/base/nsObjectLoadingContent.cpp +++ b/dom/base/nsObjectLoadingContent.cpp @@ -1530,7 +1530,7 @@ nsObjectLoadingContent::CheckProcessPolicy(int16_t *aContentPolicy) int32_t objectType; switch (mType) { case eType_Image: - objectType = nsIContentPolicy::TYPE_IMAGE; + objectType = nsIContentPolicy::TYPE_INTERNAL_IMAGE; break; case eType_Document: objectType = nsIContentPolicy::TYPE_DOCUMENT; diff --git a/dom/html/ImageDocument.cpp b/dom/html/ImageDocument.cpp index 3c7ce4327fe4..46a10bad8c62 100644 --- a/dom/html/ImageDocument.cpp +++ b/dom/html/ImageDocument.cpp @@ -99,7 +99,7 @@ ImageListener::OnStartRequest(nsIRequest* request, nsISupports *ctxt) } int16_t decision = nsIContentPolicy::ACCEPT; - nsresult rv = NS_CheckContentProcessPolicy(nsIContentPolicy::TYPE_IMAGE, + nsresult rv = NS_CheckContentProcessPolicy(nsIContentPolicy::TYPE_INTERNAL_IMAGE, channelURI, channelPrincipal, domWindow->GetFrameElementInternal(), diff --git a/embedding/browser/nsContextMenuInfo.cpp b/embedding/browser/nsContextMenuInfo.cpp index 3df8c9fd80b5..aa36e3d44bfc 100644 --- a/embedding/browser/nsContextMenuInfo.cpp +++ b/embedding/browser/nsContextMenuInfo.cpp @@ -294,7 +294,7 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode* aDOMNode, return il->LoadImage(bgUri, nullptr, nullptr, doc->GetReferrerPolicy(), principal, nullptr, nullptr, nullptr, nsIRequest::LOAD_NORMAL, - nullptr, nsIContentPolicy::TYPE_IMAGE, + nullptr, nsIContentPolicy::TYPE_INTERNAL_IMAGE, EmptyString(), aRequest); } } diff --git a/image/imgLoader.cpp b/image/imgLoader.cpp index f3dbbec3b60c..806172c8373e 100644 --- a/image/imgLoader.cpp +++ b/image/imgLoader.cpp @@ -618,7 +618,7 @@ ShouldLoadCachedImage(imgRequest* aImgRequest, nsresult rv; int16_t decision = nsIContentPolicy::REJECT_REQUEST; - rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_IMAGE, + rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_IMAGE, contentLocation, aLoadingPrincipal, aLoadingContext, @@ -1981,7 +1981,7 @@ imgLoader::LoadImageXPCOM(nsIURI* aURI, { // Optional parameter, so defaults to 0 (== TYPE_INVALID) if (!aContentPolicyType) { - aContentPolicyType = nsIContentPolicy::TYPE_IMAGE; + aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE; } imgRequestProxy* proxy; ReferrerPolicy refpol = ReferrerPolicyFromString(aReferrerPolicy); diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 534d0b570aa3..9f848db2187a 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -2204,7 +2204,7 @@ nsImageFrame::LoadIcon(const nsAString& aSpec, // For icon loads, we don't need to merge with the loadgroup flags nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL; - nsContentPolicyType contentPolicyType = nsIContentPolicy::TYPE_IMAGE; + nsContentPolicyType contentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE; return il->LoadImage(realURI, /* icon URI */ nullptr, /* initial document URI; this is only diff --git a/toolkit/components/places/AsyncFaviconHelpers.cpp b/toolkit/components/places/AsyncFaviconHelpers.cpp index 7b136e447b55..b57579f85a3e 100644 --- a/toolkit/components/places/AsyncFaviconHelpers.cpp +++ b/toolkit/components/places/AsyncFaviconHelpers.cpp @@ -532,7 +532,7 @@ AsyncFetchAndSetIconFromNetwork::Run() iconURI, nsContentUtils::GetSystemPrincipal(), nsILoadInfo::SEC_NORMAL, - nsIContentPolicy::TYPE_IMAGE); + nsIContentPolicy::TYPE_INTERNAL_IMAGE); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr listenerRequestor = diff --git a/toolkit/components/places/nsAnnoProtocolHandler.cpp b/toolkit/components/places/nsAnnoProtocolHandler.cpp index c0b3823a7636..e3b7a5bf92f6 100644 --- a/toolkit/components/places/nsAnnoProtocolHandler.cpp +++ b/toolkit/components/places/nsAnnoProtocolHandler.cpp @@ -53,7 +53,7 @@ GetDefaultIcon(nsIChannel **aChannel) defaultIconURI, nsContentUtils::GetSystemPrincipal(), nsILoadInfo::SEC_NORMAL, - nsIContentPolicy::TYPE_IMAGE); + nsIContentPolicy::TYPE_INTERNAL_IMAGE); } //////////////////////////////////////////////////////////////////////////////// diff --git a/toolkit/components/places/nsFaviconService.cpp b/toolkit/components/places/nsFaviconService.cpp index 1fe0a5e353f7..6a9f28b18d83 100644 --- a/toolkit/components/places/nsFaviconService.cpp +++ b/toolkit/components/places/nsFaviconService.cpp @@ -330,7 +330,7 @@ nsFaviconService::ReplaceFaviconDataFromDataURL(nsIURI* aFaviconURI, nullptr, // aTriggeringPrincipal nullptr, // aLoadingNode nsILoadInfo::SEC_NORMAL, - nsIContentPolicy::TYPE_IMAGE); + nsIContentPolicy::TYPE_INTERNAL_IMAGE); nsCOMPtr channel; rv = protocolHandler->NewChannel2(dataURI, loadInfo, getter_AddRefs(channel)); diff --git a/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage.js b/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage.js index 98332260efb1..7e5e61833897 100644 --- a/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage.js +++ b/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage.js @@ -33,7 +33,7 @@ function test() { NetUtil.asyncFetch({ uri: favIconLocation, loadUsingSystemPrincipal: true, - contentPolicyType: Ci.nsIContentPolicy.TYPE_IMAGE + contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE }, function(inputStream, status) { if (!Components.isSuccessCode(status)) { ok(false, "Could not get the icon file"); diff --git a/toolkit/components/places/tests/favicons/test_moz-anno_favicon_mime_type.js b/toolkit/components/places/tests/favicons/test_moz-anno_favicon_mime_type.js index 26e20f1329ed..06584fc34653 100644 --- a/toolkit/components/places/tests/favicons/test_moz-anno_favicon_mime_type.js +++ b/toolkit/components/places/tests/favicons/test_moz-anno_favicon_mime_type.js @@ -63,7 +63,7 @@ function run_test() Services.scriptSecurityManager.getSystemPrincipal(), null, // aTriggeringPrincipal Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_IMAGE); + Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); channel.asyncOpen(new streamListener("image/png"), null); do_test_pending(); @@ -76,7 +76,7 @@ function run_test() Services.scriptSecurityManager.getSystemPrincipal(), null, // aTriggeringPrincipal Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_IMAGE); + Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); channel.asyncOpen(new streamListener("image/png"), null); do_test_pending(); @@ -94,7 +94,7 @@ function run_test() Services.scriptSecurityManager.getSystemPrincipal(), null, // aTriggeringPrincipal Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_IMAGE); + Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); channel.asyncOpen(new streamListener("image/png"), null); do_test_pending(); } diff --git a/toolkit/components/search/nsSearchService.js b/toolkit/components/search/nsSearchService.js index 1e095208bdc9..bcf6f43a0d72 100644 --- a/toolkit/components/search/nsSearchService.js +++ b/toolkit/components/search/nsSearchService.js @@ -2081,7 +2081,7 @@ Engine.prototype = { Services.scriptSecurityManager.getSystemPrincipal(), null, // aTriggeringPrincipal Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_IMAGE); + Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); let iconLoadCallback = function (aByteArray, aEngine) { // This callback may run after we've already set a preferred icon, diff --git a/toolkit/devtools/gcli/commands/screenshot.js b/toolkit/devtools/gcli/commands/screenshot.js index 44caace02750..1f9b91a928a8 100644 --- a/toolkit/devtools/gcli/commands/screenshot.js +++ b/toolkit/devtools/gcli/commands/screenshot.js @@ -357,7 +357,7 @@ function saveToClipboard(context, reply) { Services.scriptSecurityManager.getSystemPrincipal(), null, // aTriggeringPrincipal Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_IMAGE); + Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); const input = channel.open(); const imgTools = Cc["@mozilla.org/image/tools;1"] .getService(Ci.imgITools); diff --git a/toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm b/toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm index c97dd3f0c447..cb25c76a33e7 100644 --- a/toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm +++ b/toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm @@ -119,7 +119,7 @@ var ImageFile = { this._netUtil.asyncFetch({ uri: aURI, loadUsingSystemPrincipal: true, - contentPolicyType: Ci.nsIContentPolicy.TYPE_IMAGE + contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE }, function read_asyncFetch(aInputStream, aStatus, aRequest) { if (Components.isSuccessCode(aStatus) && aRequest instanceof Ci.nsIChannel) { let channel = aRequest.QueryInterface(Ci.nsIChannel); diff --git a/toolkit/webapps/NativeApp.jsm b/toolkit/webapps/NativeApp.jsm index 111719e4fdaf..d9be20a768e6 100644 --- a/toolkit/webapps/NativeApp.jsm +++ b/toolkit/webapps/NativeApp.jsm @@ -464,7 +464,7 @@ function downloadIcon(aIconURI) { let channel = NetUtil.newChannel({ uri: aIconURI, loadingPrincipal: principal, - contentPolicyType: Ci.nsIContentPolicy.TYPE_IMAGE}); + contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE}); let { BadCertHandler } = Cu.import("resource://gre/modules/CertUtils.jsm", {}); // Pass true to avoid optional redirect-cert-checking behavior. channel.notificationCallbacks = new BadCertHandler(true); diff --git a/widget/cocoa/OSXNotificationCenter.mm b/widget/cocoa/OSXNotificationCenter.mm index a54052d6ec22..145badb3b520 100644 --- a/widget/cocoa/OSXNotificationCenter.mm +++ b/widget/cocoa/OSXNotificationCenter.mm @@ -250,7 +250,7 @@ OSXNotificationCenter::ShowAlertNotification(const nsAString & aImageUrl, const this, nullptr, aInPrivateBrowsing ? nsIRequest::LOAD_ANONYMOUS : nsIRequest::LOAD_NORMAL, - nullptr, nsIContentPolicy::TYPE_IMAGE, + nullptr, nsIContentPolicy::TYPE_INTERNAL_IMAGE, EmptyString(), getter_AddRefs(osxni->mIconRequest)); if (NS_SUCCEEDED(rv)) { diff --git a/widget/cocoa/nsMenuItemIconX.mm b/widget/cocoa/nsMenuItemIconX.mm index d4ed69fe8cfb..26c73101cbcf 100644 --- a/widget/cocoa/nsMenuItemIconX.mm +++ b/widget/cocoa/nsMenuItemIconX.mm @@ -310,7 +310,7 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconURI) mozilla::net::RP_Default, nullptr, loadGroup, this, nullptr, nsIRequest::LOAD_NORMAL, nullptr, - nsIContentPolicy::TYPE_IMAGE, EmptyString(), + nsIContentPolicy::TYPE_INTERNAL_IMAGE, EmptyString(), getter_AddRefs(mIconRequest)); if (NS_FAILED(rv)) return rv; diff --git a/widget/windows/WinUtils.cpp b/widget/windows/WinUtils.cpp index 1aba34da641c..f8c8184966fd 100644 --- a/widget/windows/WinUtils.cpp +++ b/widget/windows/WinUtils.cpp @@ -1108,7 +1108,7 @@ nsresult AsyncFaviconDataReady::OnFaviconDataNotAvailable(void) mozIconURI, nsContentUtils::GetSystemPrincipal(), nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, - nsIContentPolicy::TYPE_IMAGE); + nsIContentPolicy::TYPE_INTERNAL_IMAGE); NS_ENSURE_SUCCESS(rv, rv); From ffddcba82d64463fca2d59b857956d6f653bf2d0 Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Sun, 20 Sep 2015 14:56:10 -0700 Subject: [PATCH 040/133] Bug 1048048 - add preload content policy types for stylesheets (r=cam) --- dom/base/nsDocument.cpp | 2 +- dom/xbl/nsXBLResourceLoader.cpp | 2 +- dom/xslt/xslt/txMozillaStylesheetCompiler.cpp | 6 +-- editor/libeditor/nsHTMLEditor.cpp | 2 +- layout/style/Loader.cpp | 46 ++++++++++++------- layout/style/Loader.h | 11 ++++- toolkit/devtools/server/actors/styleeditor.js | 2 +- toolkit/devtools/server/actors/stylesheets.js | 6 +-- 8 files changed, 48 insertions(+), 29 deletions(-) diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 5e25bba21ee6..d9003637933c 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -9885,7 +9885,7 @@ nsDocument::PreloadStyle(nsIURI* uri, const nsAString& charset, nsCOMPtr obs = new StubCSSLoaderObserver(); // Charset names are always ASCII. - CSSLoader()->LoadSheet(uri, NodePrincipal(), + CSSLoader()->LoadSheet(uri, true, NodePrincipal(), NS_LossyConvertUTF16toASCII(charset), obs, Element::StringToCORSMode(aCrossOriginAttr), diff --git a/dom/xbl/nsXBLResourceLoader.cpp b/dom/xbl/nsXBLResourceLoader.cpp index 984efdf313da..ba2d7701b2e3 100644 --- a/dom/xbl/nsXBLResourceLoader.cpp +++ b/dom/xbl/nsXBLResourceLoader.cpp @@ -151,7 +151,7 @@ nsXBLResourceLoader::LoadResources(bool* aResult) } else { - rv = cssLoader->LoadSheet(url, docPrincipal, EmptyCString(), this); + rv = cssLoader->LoadSheet(url, false, docPrincipal, EmptyCString(), this); if (NS_SUCCEEDED(rv)) ++mPendingSheets; } diff --git a/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp b/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp index eeefcff1808c..a3955414c533 100644 --- a/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp +++ b/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp @@ -424,7 +424,7 @@ txCompileObserver::loadURI(const nsAString& aUri, // Content Policy int16_t shouldLoad = nsIContentPolicy::ACCEPT; - rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET, + rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_STYLESHEET, uri, referrerPrincipal, mLoaderDocument, @@ -524,7 +524,7 @@ TX_LoadSheet(nsIURI* aUri, txMozillaXSLTProcessor* aProcessor, // Content Policy int16_t shouldLoad = nsIContentPolicy::ACCEPT; nsresult rv = - NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET, + NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_STYLESHEET, aUri, principal, aLoaderDocument, @@ -666,7 +666,7 @@ txSyncCompileObserver::loadURI(const nsAString& aUri, // Content Policy int16_t shouldLoad = nsIContentPolicy::ACCEPT; - rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET, + rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_STYLESHEET, uri, referrerPrincipal, nullptr, diff --git a/editor/libeditor/nsHTMLEditor.cpp b/editor/libeditor/nsHTMLEditor.cpp index e46ad9851354..9092ea10467c 100644 --- a/editor/libeditor/nsHTMLEditor.cpp +++ b/editor/libeditor/nsHTMLEditor.cpp @@ -2791,7 +2791,7 @@ nsHTMLEditor::ReplaceStyleSheet(const nsAString& aURL) NS_ENSURE_SUCCESS(rv, rv); return ps->GetDocument()->CSSLoader()-> - LoadSheet(uaURI, nullptr, EmptyCString(), this); + LoadSheet(uaURI, false, nullptr, EmptyCString(), this); } NS_IMETHODIMP diff --git a/layout/style/Loader.cpp b/layout/style/Loader.cpp index 54e697316c42..7439d6b4ca90 100644 --- a/layout/style/Loader.cpp +++ b/layout/style/Loader.cpp @@ -607,7 +607,7 @@ Loader::SetPreferredSheet(const nsAString& aTitle) mDatasToNotifyOn += arr.Length(); for (uint32_t i = 0; i < arr.Length(); ++i) { --mDatasToNotifyOn; - LoadSheet(arr[i], eSheetNeedsParser); + LoadSheet(arr[i], eSheetNeedsParser, false); } } @@ -1025,7 +1025,8 @@ Loader::ObsoleteSheet(nsIURI* aURI) nsresult Loader::CheckLoadAllowed(nsIPrincipal* aSourcePrincipal, nsIURI* aTargetURI, - nsISupports* aContext) + nsISupports* aContext, + bool aIsPreload) { LOG(("css::Loader::CheckLoadAllowed")); @@ -1044,9 +1045,12 @@ Loader::CheckLoadAllowed(nsIPrincipal* aSourcePrincipal, LOG((" Passed security check")); // Check with content policy + nsContentPolicyType contentPolicyType = + aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD + : nsIContentPolicy::TYPE_INTERNAL_STYLESHEET; int16_t shouldLoad = nsIContentPolicy::ACCEPT; - rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET, + rv = NS_CheckContentLoadPolicy(contentPolicyType, aTargetURI, aSourcePrincipal, aContext, @@ -1411,7 +1415,9 @@ Loader::InsertChildSheet(CSSStyleSheet* aSheet, * a new load is kicked off asynchronously. */ nsresult -Loader::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState) +Loader::LoadSheet(SheetLoadData* aLoadData, + StyleSheetState aSheetState, + bool aIsPreload) { LOG(("css::Loader::LoadSheet")); NS_PRECONDITION(aLoadData, "Need a load data"); @@ -1561,7 +1567,7 @@ Loader::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState) mSheets->mPendingDatas.Remove(&key); LOG((" Forcing load of pending data")); - return LoadSheet(existingData, eSheetNeedsParser); + return LoadSheet(existingData, eSheetNeedsParser, aIsPreload); } // All done here; once the load completes we'll be marked complete // automatically @@ -1583,6 +1589,10 @@ Loader::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState) securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL; } + nsContentPolicyType contentPolicyType = + aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD + : nsIContentPolicy::TYPE_INTERNAL_STYLESHEET; + nsCOMPtr channel; // Note we are calling NS_NewChannelWithTriggeringPrincipal here with a node // and a principal. This is because of a case where the node is the document @@ -1594,7 +1604,7 @@ Loader::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState) aLoadData->mRequestingNode, triggeringPrincipal, securityFlags, - nsIContentPolicy::TYPE_STYLESHEET, + contentPolicyType, loadGroup, nullptr, // aCallbacks nsIChannel::LOAD_NORMAL | @@ -1610,7 +1620,7 @@ Loader::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState) aLoadData->mURI, triggeringPrincipal, securityFlags, - nsIContentPolicy::TYPE_STYLESHEET, + contentPolicyType, loadGroup, nullptr, // aCallbacks nsIChannel::LOAD_NORMAL | @@ -2044,7 +2054,7 @@ Loader::LoadStyleLink(nsIContent* aElement, if (!context) { context = mDocument; } - nsresult rv = CheckLoadAllowed(principal, aURL, context); + nsresult rv = CheckLoadAllowed(principal, aURL, context, false); if (NS_FAILED(rv)) return rv; LOG((" Passed load check")); @@ -2100,7 +2110,7 @@ Loader::LoadStyleLink(nsIContent* aElement, } // Load completion will free the data - rv = LoadSheet(data, state); + rv = LoadSheet(data, state, false); NS_ENSURE_SUCCESS(rv, rv); data->mMustNotify = true; @@ -2178,7 +2188,7 @@ Loader::LoadChildSheet(CSSStyleSheet* aParentSheet, } nsIPrincipal* principal = aParentSheet->Principal(); - nsresult rv = CheckLoadAllowed(principal, aURL, context); + nsresult rv = CheckLoadAllowed(principal, aURL, context, false); if (NS_FAILED(rv)) return rv; LOG((" Passed load check")); @@ -2242,7 +2252,7 @@ Loader::LoadChildSheet(CSSStyleSheet* aParentSheet, bool syncLoad = data->mSyncLoad; // Load completion will release the data - rv = LoadSheet(data, state); + rv = LoadSheet(data, state, false); NS_ENSURE_SUCCESS(rv, rv); // If syncLoad is true, |data| will be deleted by now. @@ -2258,7 +2268,7 @@ Loader::LoadSheetSync(nsIURI* aURL, bool aAllowUnsafeRules, CSSStyleSheet** aSheet) { LOG(("css::Loader::LoadSheetSync")); - return InternalLoadNonDocumentSheet(aURL, aAllowUnsafeRules, + return InternalLoadNonDocumentSheet(aURL, false, aAllowUnsafeRules, aUseSystemPrincipal, nullptr, EmptyCString(), aSheet, nullptr); } @@ -2272,13 +2282,14 @@ Loader::LoadSheet(nsIURI* aURL, { LOG(("css::Loader::LoadSheet(aURL, aObserver, aSheet) api call")); NS_PRECONDITION(aSheet, "aSheet is null"); - return InternalLoadNonDocumentSheet(aURL, false, false, + return InternalLoadNonDocumentSheet(aURL, false, false, false, aOriginPrincipal, aCharset, aSheet, aObserver); } nsresult Loader::LoadSheet(nsIURI* aURL, + bool aIsPreload, nsIPrincipal* aOriginPrincipal, const nsCString& aCharset, nsICSSLoaderObserver* aObserver, @@ -2287,7 +2298,7 @@ Loader::LoadSheet(nsIURI* aURL, const nsAString& aIntegrity) { LOG(("css::Loader::LoadSheet(aURL, aObserver) api call")); - return InternalLoadNonDocumentSheet(aURL, false, false, + return InternalLoadNonDocumentSheet(aURL, aIsPreload, false, false, aOriginPrincipal, aCharset, nullptr, aObserver, aCORSMode, aReferrerPolicy, aIntegrity); @@ -2295,6 +2306,7 @@ Loader::LoadSheet(nsIURI* aURL, nsresult Loader::InternalLoadNonDocumentSheet(nsIURI* aURL, + bool aIsPreload, bool aAllowUnsafeRules, bool aUseSystemPrincipal, nsIPrincipal* aOriginPrincipal, @@ -2322,7 +2334,7 @@ Loader::InternalLoadNonDocumentSheet(nsIURI* aURL, return NS_ERROR_NOT_AVAILABLE; } - nsresult rv = CheckLoadAllowed(aOriginPrincipal, aURL, mDocument); + nsresult rv = CheckLoadAllowed(aOriginPrincipal, aURL, mDocument, aIsPreload); if (NS_FAILED(rv)) { return rv; } @@ -2357,7 +2369,7 @@ Loader::InternalLoadNonDocumentSheet(nsIURI* aURL, aOriginPrincipal, mDocument); NS_ADDREF(data); - rv = LoadSheet(data, state); + rv = LoadSheet(data, state, aIsPreload); NS_ENSURE_SUCCESS(rv, rv); if (aSheet) { @@ -2549,7 +2561,7 @@ Loader::StartAlternateLoads() mDatasToNotifyOn += arr.Length(); for (uint32_t i = 0; i < arr.Length(); ++i) { --mDatasToNotifyOn; - LoadSheet(arr[i], eSheetNeedsParser); + LoadSheet(arr[i], eSheetNeedsParser, false); } } diff --git a/layout/style/Loader.h b/layout/style/Loader.h index cd17ebeb66ee..f4da96e4c079 100644 --- a/layout/style/Loader.h +++ b/layout/style/Loader.h @@ -317,6 +317,7 @@ public: * not-yet-loaded sheet. */ nsresult LoadSheet(nsIURI* aURL, + bool aIsPreload, nsIPrincipal* aOriginPrincipal, const nsCString& aCharset, nsICSSLoaderObserver* aObserver, @@ -405,9 +406,12 @@ private: // Note: null aSourcePrincipal indicates that the content policy and // CheckLoadURI checks should be skipped. + // aIsPreload indicates whether the html parser preloads that + // stylesheet or if it is a regular load. nsresult CheckLoadAllowed(nsIPrincipal* aSourcePrincipal, nsIURI* aTargetURI, - nsISupports* aContext); + nsISupports* aContext, + bool aIsPreload); // For inline style, the aURI param is null, but the aLinkingContent @@ -446,6 +450,7 @@ private: ImportRule* aParentRule); nsresult InternalLoadNonDocumentSheet(nsIURI* aURL, + bool aIsPreload, bool aAllowUnsafeRules, bool aUseSystemPrincipal, nsIPrincipal* aOriginPrincipal, @@ -477,7 +482,9 @@ private: // Note: LoadSheet is responsible for releasing aLoadData and setting the // sheet to complete on failure. - nsresult LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState); + nsresult LoadSheet(SheetLoadData* aLoadData, + StyleSheetState aSheetState, + bool aIsPreLoad); // Parse the stylesheet in aLoadData. The sheet data comes from aInput. // Set aCompleted to true if the parse finished, false otherwise (e.g. if the diff --git a/toolkit/devtools/server/actors/styleeditor.js b/toolkit/devtools/server/actors/styleeditor.js index ba4c2cf2bff6..da667fedc56f 100644 --- a/toolkit/devtools/server/actors/styleeditor.js +++ b/toolkit/devtools/server/actors/styleeditor.js @@ -455,7 +455,7 @@ var OldStyleSheetActor = protocol.ActorClass({ } let options = { - policy: Ci.nsIContentPolicy.TYPE_STYLESHEET, + policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET, window: this.window, charset: this._getCSSCharset() }; diff --git a/toolkit/devtools/server/actors/stylesheets.js b/toolkit/devtools/server/actors/stylesheets.js index d310f060fac6..f88f9c713b48 100644 --- a/toolkit/devtools/server/actors/stylesheets.js +++ b/toolkit/devtools/server/actors/stylesheets.js @@ -606,7 +606,7 @@ var StyleSheetActor = protocol.ActorClass({ let options = { loadFromCache: true, - policy: Ci.nsIContentPolicy.TYPE_STYLESHEET, + policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET, window: this.window, charset: this._getCSSCharset() }; @@ -692,7 +692,7 @@ var StyleSheetActor = protocol.ActorClass({ url = normalize(url, this.href); let options = { loadFromCache: false, - policy: Ci.nsIContentPolicy.TYPE_STYLESHEET, + policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET, window: this.window }; let map = fetch(url, options) @@ -1020,7 +1020,7 @@ var OriginalSourceActor = protocol.ActorClass({ return promise.resolve(content); } let options = { - policy: Ci.nsIContentPolicy.TYPE_STYLESHEET, + policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET, window: this.window }; return fetch(this.url, options).then(({content}) => { From c938714dba276d206079fd511708696f331decc9 Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Sun, 20 Sep 2015 14:56:21 -0700 Subject: [PATCH 041/133] Bug 1048048 - add preload content policy types for scripts (r=baku) --- dom/base/nsScriptLoader.cpp | 24 +++++++++++++++++------- dom/base/nsScriptLoader.h | 6 ++++-- dom/media/IdpSandbox.jsm | 2 +- dom/workers/ServiceWorkerScriptCache.cpp | 4 ++-- dom/xul/XULDocument.cpp | 3 ++- 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/dom/base/nsScriptLoader.cpp b/dom/base/nsScriptLoader.cpp index 1b39e395d28a..b58c7b8622bb 100644 --- a/dom/base/nsScriptLoader.cpp +++ b/dom/base/nsScriptLoader.cpp @@ -223,10 +223,15 @@ nsresult nsScriptLoader::CheckContentPolicy(nsIDocument* aDocument, nsISupports *aContext, nsIURI *aURI, - const nsAString &aType) + const nsAString &aType, + bool aIsPreLoad) { + nsContentPolicyType contentPolicyType = aIsPreLoad + ? nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD + : nsIContentPolicy::TYPE_INTERNAL_SCRIPT; + int16_t shouldLoad = nsIContentPolicy::ACCEPT; - nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_SCRIPT, + nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType, aURI, aDocument->NodePrincipal(), aContext, @@ -249,7 +254,8 @@ nsresult nsScriptLoader::ShouldLoadScript(nsIDocument* aDocument, nsISupports* aContext, nsIURI* aURI, - const nsAString &aType) + const nsAString &aType, + bool aIsPreLoad) { // Check that the containing page is allowed to load this URI. nsresult rv = nsContentUtils::GetSecurityManager()-> @@ -259,7 +265,7 @@ nsScriptLoader::ShouldLoadScript(nsIDocument* aDocument, NS_ENSURE_SUCCESS(rv, rv); // After the security manager, the content-policy stuff gets a veto - rv = CheckContentPolicy(aDocument, aContext, aURI, aType); + rv = CheckContentPolicy(aDocument, aContext, aURI, aType, aIsPreLoad); if (NS_FAILED(rv)) { return rv; } @@ -274,7 +280,7 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType, nsISupports *context = aRequest->mElement.get() ? static_cast(aRequest->mElement.get()) : static_cast(mDocument); - nsresult rv = ShouldLoadScript(mDocument, context, aRequest->mURI, aType); + nsresult rv = ShouldLoadScript(mDocument, context, aRequest->mURI, aType, aRequest->IsPreload()); if (NS_FAILED(rv)) { return rv; } @@ -296,12 +302,16 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType, return NS_OK; } + nsContentPolicyType contentPolicyType = aRequest->IsPreload() + ? nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD + : nsIContentPolicy::TYPE_INTERNAL_SCRIPT; + nsCOMPtr channel; rv = NS_NewChannel(getter_AddRefs(channel), aRequest->mURI, mDocument, nsILoadInfo::SEC_NORMAL, - nsIContentPolicy::TYPE_INTERNAL_SCRIPT, + contentPolicyType, loadGroup, prompter, nsIRequest::LOAD_NORMAL | @@ -530,7 +540,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) if (elementCharset.Equals(preloadCharset) && ourCORSMode == request->mCORSMode && ourRefPolicy == request->mReferrerPolicy) { - rv = CheckContentPolicy(mDocument, aElement, request->mURI, type); + rv = CheckContentPolicy(mDocument, aElement, request->mURI, type, false); NS_ENSURE_SUCCESS(rv, false); } else { // Drop the preload diff --git a/dom/base/nsScriptLoader.h b/dom/base/nsScriptLoader.h index b62f229a4e95..468f50f5d5d1 100644 --- a/dom/base/nsScriptLoader.h +++ b/dom/base/nsScriptLoader.h @@ -354,7 +354,8 @@ public: static nsresult ShouldLoadScript(nsIDocument* aDocument, nsISupports* aContext, nsIURI* aURI, - const nsAString &aType); + const nsAString &aType, + bool aIsPreLoad); /** * Starts deferring deferred scripts and puts them in the mDeferredRequests @@ -435,7 +436,8 @@ private: static nsresult CheckContentPolicy(nsIDocument* aDocument, nsISupports *aContext, nsIURI *aURI, - const nsAString &aType); + const nsAString &aType, + bool aIsPreLoad); /** * Start a load for aRequest's URI. diff --git a/dom/media/IdpSandbox.jsm b/dom/media/IdpSandbox.jsm index 96b12eeebab2..6e600dcddf35 100644 --- a/dom/media/IdpSandbox.jsm +++ b/dom/media/IdpSandbox.jsm @@ -50,7 +50,7 @@ ResourceLoader.load = function(uri, doc) { // the '2' identifies this as a script load let ioChannel = ioService.newChannelFromURI2(uri, doc, doc.nodePrincipal, systemPrincipal, 0, - Ci.nsIContentPolicy.TYPE_SCRIPT); + Ci.nsIContentPolicy.TYPE_INTERNAL_SCRIPT); ioChannel.loadGroup = doc.documentLoadGroup.QueryInterface(Ci.nsILoadGroup); ioChannel.notificationCallbacks = new RedirectHttpsOnly(); diff --git a/dom/workers/ServiceWorkerScriptCache.cpp b/dom/workers/ServiceWorkerScriptCache.cpp index 9f2fb7494f49..1c44aa1ed83b 100644 --- a/dom/workers/ServiceWorkerScriptCache.cpp +++ b/dom/workers/ServiceWorkerScriptCache.cpp @@ -111,12 +111,12 @@ public: } // Note that because there is no "serviceworker" RequestContext type, we can - // use the external TYPE_SCRIPT content policy types when loading a service + // use the TYPE_INTERNAL_SCRIPT content policy types when loading a service // worker. rv = NS_NewChannel(getter_AddRefs(mChannel), uri, aPrincipal, nsILoadInfo::SEC_NORMAL, - nsIContentPolicy::TYPE_SCRIPT, + nsIContentPolicy::TYPE_INTERNAL_SCRIPT, loadGroup); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; diff --git a/dom/xul/XULDocument.cpp b/dom/xul/XULDocument.cpp index 75b67a290ee1..172c9283a789 100644 --- a/dom/xul/XULDocument.cpp +++ b/dom/xul/XULDocument.cpp @@ -3250,7 +3250,8 @@ XULDocument::LoadScript(nsXULPrototypeScript* aScriptProto, bool* aBlock) this, static_cast(this), aScriptProto->mSrcURI, - NS_LITERAL_STRING("application/x-javascript")); + NS_LITERAL_STRING("application/x-javascript"), + false); if (NS_FAILED(rv)) { *aBlock = false; return rv; From b2de9adb18ccd1063ac63f114ef07ad6e20a7b9a Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Sun, 20 Sep 2015 14:56:34 -0700 Subject: [PATCH 042/133] Bug 1048048 - add preload content policy types - csp changes (r=dveditz) --- dom/security/nsCSPContext.cpp | 35 +++++++++++------------------------ dom/security/nsCSPService.cpp | 10 ++++++---- 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/dom/security/nsCSPContext.cpp b/dom/security/nsCSPContext.cpp index 6fb841b9cc78..19c55a20026c 100644 --- a/dom/security/nsCSPContext.cpp +++ b/dom/security/nsCSPContext.cpp @@ -115,6 +115,14 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType, CSPCONTEXTLOG(("nsCSPContext::ShouldLoad, aContentLocation: %s", spec.get())); } + bool isStyleOrScriptPreLoad = + (aContentType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD || + aContentType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD); + + // Since we know whether we are dealing with a preload, we have to convert + // the internal policytype ot the external policy type before moving on. + aContentType = nsContentUtils::InternalContentPolicyTypeToExternal(aContentType); + nsresult rv = NS_OK; // This ShouldLoad function is called from nsCSPService::ShouldLoad, @@ -145,29 +153,8 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType, return NS_OK; } - // This may be a load or a preload. If it is a preload, the document will - // not have been fully parsed yet, and aRequestContext will be an - // nsIDOMHTMLDocument rather than the nsIDOMHTMLElement associated with the - // resource. As a result, we cannot extract the element's corresponding - // nonce attribute, and so we cannot correctly check the nonce on a preload. - // - // Therefore, the decision returned here for a preload may be *incorrect* as - // it cannot take the nonce into account. We will still check the load, but - // we will not cache the result or report a violation. When the "real load" - // happens subsequently, we will re-check with the additional context to - // make a final decision. - // - // We don't just return false because that would block all preloads and - // degrade performance. However, we do want to block preloads that are - // clearly blocked (their urls are not whitelisted) by CSP. - - nsCOMPtr doc = do_QueryInterface(aRequestContext); - bool isPreload = doc && - (aContentType == nsIContentPolicy::TYPE_SCRIPT || - aContentType == nsIContentPolicy::TYPE_STYLESHEET); - nsAutoString nonce; - if (!isPreload) { + if (!isStyleOrScriptPreLoad) { nsCOMPtr htmlElement = do_QueryInterface(aRequestContext); if (htmlElement) { rv = htmlElement->GetAttribute(NS_LITERAL_STRING("nonce"), nonce); @@ -184,7 +171,7 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType, originalURI, nonce, wasRedirected, - isPreload, + isStyleOrScriptPreLoad, false, // allow fallback to default-src true, // send violation reports true); // send blocked URI in violation reports @@ -193,7 +180,7 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType, : nsIContentPolicy::REJECT_SERVER; // Done looping, cache any relevant result - if (cacheKey.Length() > 0 && !isPreload) { + if (cacheKey.Length() > 0 && !isStyleOrScriptPreLoad) { mShouldLoadCache.Put(cacheKey, *outDecision); } diff --git a/dom/security/nsCSPService.cpp b/dom/security/nsCSPService.cpp index e52bfcd86ab3..9a04ac43768a 100644 --- a/dom/security/nsCSPService.cpp +++ b/dom/security/nsCSPService.cpp @@ -105,8 +105,9 @@ CSPService::ShouldLoad(uint32_t aContentType, nsIPrincipal *aRequestPrincipal, int16_t *aDecision) { - MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType), - "We should only see external content policy types here."); + MOZ_ASSERT(aContentType == + nsContentUtils::InternalContentPolicyTypeToExternalOrPreload(aContentType), + "We should only see external content policy types or preloads here."); if (!aContentLocation) { return NS_ERROR_FAILURE; @@ -251,8 +252,9 @@ CSPService::ShouldProcess(uint32_t aContentType, nsIPrincipal *aRequestPrincipal, int16_t *aDecision) { - MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType), - "We should only see external content policy types here."); + MOZ_ASSERT(aContentType == + nsContentUtils::InternalContentPolicyTypeToExternalOrPreload(aContentType), + "We should only see external content policy types or preloads here."); if (!aContentLocation) return NS_ERROR_FAILURE; From 6090d3e3cdb9b8285284c8f4108d0452987e88f8 Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Sun, 20 Sep 2015 14:56:46 -0700 Subject: [PATCH 043/133] Bug 1048048 - add preload content policy types - web platform test updates (r=dveditz) --- .../content-security-policy/style-src/style-src-3_4.html.ini | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 testing/web-platform/meta/content-security-policy/style-src/style-src-3_4.html.ini diff --git a/testing/web-platform/meta/content-security-policy/style-src/style-src-3_4.html.ini b/testing/web-platform/meta/content-security-policy/style-src/style-src-3_4.html.ini deleted file mode 100644 index c5f4d96d7a18..000000000000 --- a/testing/web-platform/meta/content-security-policy/style-src/style-src-3_4.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[style-src-3_4.html] - type: testharness - [Violation report status OK.] - expected: FAIL - From fd3141b39a09642d042bf663fc23fb6c942b7ce0 Mon Sep 17 00:00:00 2001 From: Mason Chang Date: Mon, 21 Sep 2015 08:14:05 -0700 Subject: [PATCH 044/133] Backout bug 1188075 for graphical artifacts. r=me --- gfx/thebes/gfx2DGlue.h | 2 +- gfx/thebes/gfxBlur.cpp | 463 +++--------------- gfx/thebes/gfxBlur.h | 38 +- layout/base/nsCSSRendering.cpp | 175 ++----- layout/base/nsCSSRendering.h | 43 +- .../boxshadow-color-rounding-middle-ref.html | 23 - .../boxshadow-color-rounding-middle.html | 11 - layout/reftests/box-shadow/reftest.list | 1 - 8 files changed, 125 insertions(+), 631 deletions(-) delete mode 100644 layout/reftests/box-shadow/boxshadow-color-rounding-middle-ref.html delete mode 100644 layout/reftests/box-shadow/boxshadow-color-rounding-middle.html diff --git a/gfx/thebes/gfx2DGlue.h b/gfx/thebes/gfx2DGlue.h index 8c3c19f7ddbf..0654aa2cb6d8 100644 --- a/gfx/thebes/gfx2DGlue.h +++ b/gfx/thebes/gfx2DGlue.h @@ -40,7 +40,7 @@ inline Color ToColor(const gfxRGBA &aRGBA) Float(aRGBA.b), Float(aRGBA.a)); } -inline gfxRGBA ThebesColor(const Color &aColor) +inline gfxRGBA ThebesColor(Color &aColor) { return gfxRGBA(aColor.r, aColor.g, aColor.b, aColor.a); } diff --git a/gfx/thebes/gfxBlur.cpp b/gfx/thebes/gfxBlur.cpp index 3db515050de9..db628b4b9915 100644 --- a/gfx/thebes/gfxBlur.cpp +++ b/gfx/thebes/gfxBlur.cpp @@ -170,21 +170,16 @@ struct BlurCacheKey : public PLDHashEntryHdr { gfxRGBA mShadowColor; BackendType mBackend; RectCornerRadii mCornerRadii; - bool mIsInset; - // Only used for inset blurs - bool mHasBorderRadius; - gfxIntSize mSpreadRadius; - IntSize mInnerMinSize; - - BlurCacheKey(IntSize aMinSize, gfxIntSize aBlurRadius, + BlurCacheKey(IntSize aMinimumSize, gfxIntSize aBlurRadius, RectCornerRadii* aCornerRadii, gfxRGBA aShadowColor, - BackendType aBackendType) - : BlurCacheKey(aMinSize, IntSize(0, 0), - aBlurRadius, IntSize(0, 0), - aCornerRadii, aShadowColor, - false, false, aBackendType) - {} + BackendType aBackend) + : mMinSize(aMinimumSize) + , mBlurRadius(aBlurRadius) + , mShadowColor(aShadowColor) + , mBackend(aBackend) + , mCornerRadii(aCornerRadii ? *aCornerRadii : RectCornerRadii()) + { } explicit BlurCacheKey(const BlurCacheKey* aOther) : mMinSize(aOther->mMinSize) @@ -192,26 +187,6 @@ struct BlurCacheKey : public PLDHashEntryHdr { , mShadowColor(aOther->mShadowColor) , mBackend(aOther->mBackend) , mCornerRadii(aOther->mCornerRadii) - , mIsInset(aOther->mIsInset) - , mHasBorderRadius(aOther->mHasBorderRadius) - , mSpreadRadius(aOther->mSpreadRadius) - , mInnerMinSize(aOther->mInnerMinSize) - { } - - explicit BlurCacheKey(IntSize aOuterMinSize, IntSize aInnerMinSize, - gfxIntSize aBlurRadius, gfxIntSize aSpreadRadius, - const RectCornerRadii* aCornerRadii, gfxRGBA aShadowColor, - bool aIsInset, - bool aHasBorderRadius, BackendType aBackendType) - : mMinSize(aOuterMinSize) - , mBlurRadius(aBlurRadius) - , mShadowColor(aShadowColor) - , mBackend(aBackendType) - , mCornerRadii(aCornerRadii ? *aCornerRadii : RectCornerRadii()) - , mIsInset(aIsInset) - , mHasBorderRadius(aHasBorderRadius) - , mSpreadRadius(aSpreadRadius) - , mInnerMinSize(aInnerMinSize) { } static PLDHashNumber @@ -227,42 +202,26 @@ struct BlurCacheKey : public PLDHashEntryHdr { hash = AddToHash(hash, HashBytes(&aKey->mShadowColor.a, sizeof(gfxFloat))); for (int i = 0; i < 4; i++) { - hash = AddToHash(hash, aKey->mCornerRadii[i].width, aKey->mCornerRadii[i].height); + hash = AddToHash(hash, aKey->mCornerRadii[i].width, aKey->mCornerRadii[i].height); } hash = AddToHash(hash, (uint32_t)aKey->mBackend); - - if (aKey->mIsInset) { - hash = AddToHash(hash, aKey->mSpreadRadius.width, aKey->mSpreadRadius.height); - hash = AddToHash(hash, aKey->mInnerMinSize.width, aKey->mInnerMinSize.height); - hash = AddToHash(hash, HashBytes(&aKey->mHasBorderRadius, sizeof(bool))); - } return hash; } - bool - KeyEquals(KeyTypePointer aKey) const + bool KeyEquals(KeyTypePointer aKey) const { if (aKey->mMinSize == mMinSize && aKey->mBlurRadius == mBlurRadius && aKey->mCornerRadii == mCornerRadii && aKey->mShadowColor == mShadowColor && aKey->mBackend == mBackend) { - - if (mIsInset) { - return (mHasBorderRadius == aKey->mHasBorderRadius) && - (mInnerMinSize == aKey->mInnerMinSize) && - (mSpreadRadius == aKey->mSpreadRadius); - } - return true; } return false; } - - static KeyTypePointer - KeyToPointer(KeyType aKey) + static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; } @@ -332,27 +291,6 @@ class BlurCache final : public nsExpirationTracker return blur; } - BlurCacheData* LookupInsetBoxShadow(const IntSize aOuterMinSize, - const IntSize aInnerMinSize, - const gfxIntSize& aBlurRadius, - const gfxIntSize& aSpreadRadius, - const RectCornerRadii* aCornerRadii, - const gfxRGBA& aShadowColor, - const bool& aHasBorderRadius, - BackendType aBackendType) - { - BlurCacheKey key(aOuterMinSize, aInnerMinSize, - aBlurRadius, aSpreadRadius, - aCornerRadii, aShadowColor, - true, aHasBorderRadius, aBackendType); - BlurCacheData* blur = mHashEntries.Get(key); - if (blur) { - MarkUsed(blur); - } - - return blur; - } - // Returns true if we successfully register the blur in the cache, false // otherwise. bool RegisterEntry(BlurCacheData* aValue) @@ -493,7 +431,7 @@ CreateBlurMask(const IntSize& aRectSize, } static already_AddRefed -CreateBoxShadow(SourceSurface* aBlurMask, const gfxRGBA& aShadowColor) +CreateBoxShadow(DrawTarget& aDT, SourceSurface* aBlurMask, const gfxRGBA& aShadowColor) { IntSize blurredSize = aBlurMask->GetSize(); gfxPlatform* platform = gfxPlatform::GetPlatform(); @@ -509,7 +447,7 @@ CreateBoxShadow(SourceSurface* aBlurMask, const gfxRGBA& aShadowColor) return boxShadowDT->Snapshot(); } -static SourceSurface* +SourceSurface* GetBlur(DrawTarget& aDT, const IntSize& aRectSize, const gfxIntSize& aBlurRadius, @@ -542,7 +480,7 @@ GetBlur(DrawTarget& aDT, return nullptr; } - RefPtr boxShadow = CreateBoxShadow(blurMask, aShadowColor); + RefPtr boxShadow = CreateBoxShadow(aDT, blurMask, aShadowColor); if (!boxShadow) { return nullptr; } @@ -603,68 +541,6 @@ DrawCorner(DrawTarget& aDT, SourceSurface* aSurface, aDT.DrawSurface(aSurface, aDest, aSrc); } -static void -DrawBoxShadows(DrawTarget& aDestDrawTarget, SourceSurface* aSourceBlur, - Rect aDstOuter, Rect aDstInner, Rect aSrcOuter, Rect aSrcInner, - Rect aSkipRect) -{ - // Corners: top left, top right, bottom left, bottom right - DrawCorner(aDestDrawTarget, aSourceBlur, - RectWithEdgesTRBL(aDstOuter.Y(), aDstInner.X(), - aDstInner.Y(), aDstOuter.X()), - RectWithEdgesTRBL(aSrcOuter.Y(), aSrcInner.X(), - aSrcInner.Y(), aSrcOuter.X()), - aSkipRect); - - DrawCorner(aDestDrawTarget, aSourceBlur, - RectWithEdgesTRBL(aDstOuter.Y(), aDstOuter.XMost(), - aDstInner.Y(), aDstInner.XMost()), - RectWithEdgesTRBL(aSrcOuter.Y(), aSrcOuter.XMost(), - aSrcInner.Y(), aSrcInner.XMost()), - aSkipRect); - - DrawCorner(aDestDrawTarget, aSourceBlur, - RectWithEdgesTRBL(aDstInner.YMost(), aDstInner.X(), - aDstOuter.YMost(), aDstOuter.X()), - RectWithEdgesTRBL(aSrcInner.YMost(), aSrcInner.X(), - aSrcOuter.YMost(), aSrcOuter.X()), - aSkipRect); - - DrawCorner(aDestDrawTarget, aSourceBlur, - RectWithEdgesTRBL(aDstInner.YMost(), aDstOuter.XMost(), - aDstOuter.YMost(), aDstInner.XMost()), - RectWithEdgesTRBL(aSrcInner.YMost(), aSrcOuter.XMost(), - aSrcOuter.YMost(), aSrcInner.XMost()), - aSkipRect); - - // Edges: top, left, right, bottom - RepeatOrStretchSurface(aDestDrawTarget, aSourceBlur, - RectWithEdgesTRBL(aDstOuter.Y(), aDstInner.XMost(), - aDstInner.Y(), aDstInner.X()), - RectWithEdgesTRBL(aSrcOuter.Y(), aSrcInner.XMost(), - aSrcInner.Y(), aSrcInner.X()), - aSkipRect); - RepeatOrStretchSurface(aDestDrawTarget, aSourceBlur, - RectWithEdgesTRBL(aDstInner.Y(), aDstInner.X(), - aDstInner.YMost(), aDstOuter.X()), - RectWithEdgesTRBL(aSrcInner.Y(), aSrcInner.X(), - aSrcInner.YMost(), aSrcOuter.X()), - aSkipRect); - RepeatOrStretchSurface(aDestDrawTarget, aSourceBlur, - RectWithEdgesTRBL(aDstInner.Y(), aDstOuter.XMost(), - aDstInner.YMost(), aDstInner.XMost()), - RectWithEdgesTRBL(aSrcInner.Y(), aSrcOuter.XMost(), - aSrcInner.YMost(), aSrcInner.XMost()), - aSkipRect); - RepeatOrStretchSurface(aDestDrawTarget, aSourceBlur, - RectWithEdgesTRBL(aDstInner.YMost(), aDstInner.XMost(), - aDstOuter.YMost(), aDstInner.X()), - RectWithEdgesTRBL(aSrcInner.YMost(), aSrcInner.XMost(), - aSrcOuter.YMost(), aSrcInner.X()), - aSkipRect); -} - - /*** * We draw a blurred a rectangle by only blurring a smaller rectangle and * splitting the rectangle into 9 parts. @@ -722,8 +598,60 @@ gfxAlphaBoxBlur::BlurRectangle(gfxContext* aDestinationCtx, // The target rect is smaller than the minimal size so just draw the surface destDrawTarget.DrawSurface(boxShadow, dstInner, srcInner); } else { - DrawBoxShadows(destDrawTarget, boxShadow, dstOuter, dstInner, - srcOuter, srcInner, skipRect); + // Corners: top left, top right, bottom left, bottom right + DrawCorner(destDrawTarget, boxShadow, + RectWithEdgesTRBL(dstOuter.Y(), dstInner.X(), + dstInner.Y(), dstOuter.X()), + RectWithEdgesTRBL(srcOuter.Y(), srcInner.X(), + srcInner.Y(), srcOuter.X()), + skipRect); + + DrawCorner(destDrawTarget, boxShadow, + RectWithEdgesTRBL(dstOuter.Y(), dstOuter.XMost(), + dstInner.Y(), dstInner.XMost()), + RectWithEdgesTRBL(srcOuter.Y(), srcOuter.XMost(), + srcInner.Y(), srcInner.XMost()), + skipRect); + + DrawCorner(destDrawTarget, boxShadow, + RectWithEdgesTRBL(dstInner.YMost(), dstInner.X(), + dstOuter.YMost(), dstOuter.X()), + RectWithEdgesTRBL(srcInner.YMost(), srcInner.X(), + srcOuter.YMost(), srcOuter.X()), + skipRect); + + DrawCorner(destDrawTarget, boxShadow, + RectWithEdgesTRBL(dstInner.YMost(), dstOuter.XMost(), + dstOuter.YMost(), dstInner.XMost()), + RectWithEdgesTRBL(srcInner.YMost(), srcOuter.XMost(), + srcOuter.YMost(), srcInner.XMost()), + skipRect); + + // Edges: top, left, right, bottom + RepeatOrStretchSurface(destDrawTarget, boxShadow, + RectWithEdgesTRBL(dstOuter.Y(), dstInner.XMost(), + dstInner.Y(), dstInner.X()), + RectWithEdgesTRBL(srcOuter.Y(), srcInner.XMost(), + srcInner.Y(), srcInner.X()), + skipRect); + RepeatOrStretchSurface(destDrawTarget, boxShadow, + RectWithEdgesTRBL(dstInner.Y(), dstInner.X(), + dstInner.YMost(), dstOuter.X()), + RectWithEdgesTRBL(srcInner.Y(), srcInner.X(), + srcInner.YMost(), srcOuter.X()), + skipRect); + RepeatOrStretchSurface(destDrawTarget, boxShadow, + RectWithEdgesTRBL(dstInner.Y(), dstOuter.XMost(), + dstInner.YMost(), dstInner.XMost()), + RectWithEdgesTRBL(srcInner.Y(), srcOuter.XMost(), + srcInner.YMost(), srcInner.XMost()), + skipRect); + RepeatOrStretchSurface(destDrawTarget, boxShadow, + RectWithEdgesTRBL(dstInner.YMost(), dstInner.XMost(), + dstOuter.YMost(), dstInner.X()), + RectWithEdgesTRBL(srcInner.YMost(), srcInner.XMost(), + srcOuter.YMost(), srcInner.X()), + skipRect); // Middle part RepeatOrStretchSurface(destDrawTarget, boxShadow, @@ -754,258 +682,3 @@ gfxAlphaBoxBlur::BlurRectangle(gfxContext* aDestinationCtx, destDrawTarget.PopClip(); } -static already_AddRefed -GetBoxShadowInsetPath(DrawTarget* aDrawTarget, - const Rect aOuterRect, const Rect aInnerRect, - const bool aHasBorderRadius, const RectCornerRadii& aInnerClipRadii) -{ - /*** - * We create an inset path by having two rects. - * - * ----------------------- - * | ________________ | - * | | | | - * | | | | - * | ------------------ | - * |_____________________| - * - * The outer rect and the inside rect. The path - * creates a frame around the content where we draw the inset shadow. - */ - RefPtr builder = - aDrawTarget->CreatePathBuilder(FillRule::FILL_EVEN_ODD); - AppendRectToPath(builder, aOuterRect, true); - - if (aHasBorderRadius) { - AppendRoundedRectToPath(builder, aInnerRect, aInnerClipRadii, false); - } else { - AppendRectToPath(builder, aInnerRect, false); - } - return builder->Finish(); -} - -static void -ComputeRectsForInsetBoxShadow(gfxIntSize aBlurRadius, - gfxIntSize aSpreadRadius, - const Rect& aDestRect, - const Rect& aShadowClipRect, - Rect& aOutOuterRect, - Rect& aOutInnerRect, - Margin& aOutPathMargins) -{ - gfxIntSize marginSize = aBlurRadius + aSpreadRadius; - // The sizes we're given for aBlurRadius/aSpreadRadius are radius'. - // We actually want to paint the whole blur, so we need the diameter. - // We render both the outer / inner blur portions of a blur, - // Then we clip out the outer portion later. - aOutPathMargins.SizeTo(marginSize.height, marginSize.width, marginSize.height, marginSize.width); - aOutPathMargins += aOutPathMargins; - - aOutOuterRect.x = 0; - aOutInnerRect.x = marginSize.width; - - aOutOuterRect.y = 0; - aOutInnerRect.y = marginSize.height; - - // + 1 for the middle edges so we can sample them - aOutInnerRect.width = aOutPathMargins.LeftRight() + 1; - aOutInnerRect.height = aOutPathMargins.TopBottom() + 1; - - // The outer path rect needs to be 1 blur radius past the inner edges - aOutOuterRect.width = aOutInnerRect.XMost() + marginSize.width; - aOutOuterRect.height = aOutInnerRect.YMost() + marginSize.height; - - if ((aOutOuterRect.width >= aDestRect.width) || - (aOutOuterRect.height >= aDestRect.height) || - (aOutInnerRect.width >= aShadowClipRect.width) || - (aOutInnerRect.height >= aShadowClipRect.height)) - { - aOutOuterRect.width = aDestRect.width; - aOutOuterRect.height = aDestRect.height; - aOutInnerRect.width = aShadowClipRect.width; - aOutInnerRect.height = aShadowClipRect.height; - aOutPathMargins.SizeTo(0, 0, 0, 0); - } -} - -static void -FillDestinationPath(gfxContext* aDestinationCtx, - const Rect aDestinationRect, - const Rect aShadowClipRect, - const Color& aShadowColor, - const bool aHasBorderRadius, - const RectCornerRadii& aInnerClipRadii) -{ - // When there is no blur radius, fill the path onto the destination - // surface. - aDestinationCtx->SetColor(ThebesColor(aShadowColor)); - DrawTarget* destDrawTarget = aDestinationCtx->GetDrawTarget(); - RefPtr shadowPath = GetBoxShadowInsetPath(destDrawTarget, aDestinationRect, - aShadowClipRect, aHasBorderRadius, - aInnerClipRadii); - - aDestinationCtx->SetPath(shadowPath); - aDestinationCtx->Fill(); -} - -void -CacheInsetBlur(const IntSize aMinOuterSize, - const IntSize aMinInnerSize, - const gfxIntSize& aBlurRadius, - const gfxIntSize& aSpreadRadius, - const RectCornerRadii* aCornerRadii, - const gfxRGBA& aShadowColor, - const bool& aHasBorderRadius, - BackendType aBackendType, - IntMargin aExtendBy, - SourceSurface* aBoxShadow) -{ - BlurCacheKey key(aMinOuterSize, aMinInnerSize, - aBlurRadius, aSpreadRadius, - aCornerRadii, aShadowColor, - true, aHasBorderRadius, aBackendType); - BlurCacheData* data = new BlurCacheData(aBoxShadow, aExtendBy, key); - if (!gBlurCache->RegisterEntry(data)) { - delete data; - } -} - -already_AddRefed -gfxAlphaBoxBlur::GetInsetBlur(Rect& aOuterRect, - Rect& aInnerRect, - const gfxIntSize& aBlurRadius, - const gfxIntSize& aSpreadRadius, - const RectCornerRadii& aInnerClipRadii, - const Color& aShadowColor, - const bool& aHasBorderRadius, - IntPoint& aOutTopLeft, - gfxContext* aDestinationCtx) - -{ - if (!gBlurCache) { - gBlurCache = new BlurCache(); - } - - gfxIntSize outerRectSize = RoundedToInt(aOuterRect).Size(); - gfxIntSize innerRectSize = RoundedToInt(aInnerRect).Size(); - DrawTarget* destDrawTarget = aDestinationCtx->GetDrawTarget(); - - BlurCacheData* cached = - gBlurCache->LookupInsetBoxShadow(outerRectSize, innerRectSize, aBlurRadius, aSpreadRadius, - &aInnerClipRadii, ThebesColor(aShadowColor), - aHasBorderRadius, destDrawTarget->GetBackendType()); - - if (cached) { - IntMargin extends = cached->mExtendDest; - aOutTopLeft.x = extends.left; - aOutTopLeft.y = extends.top; - // So we don't forget the actual cached blur - RefPtr cachedBlur = cached->mBlur; - return cachedBlur.forget(); - } - - // Dirty rect and skip rect are null for the min inset shadow. - // When rendering inset box shadows, we respect the spread radius by changing - // the shape of the unblurred shadow, and can pass a spread radius of zero here. - gfxIntSize zeroSpread(0, 0); - gfxContext* minGfxContext = Init(ThebesRect(aOuterRect), zeroSpread, aBlurRadius, nullptr, nullptr); - if (!minGfxContext) { - return nullptr; - } - - DrawTarget* minDrawTarget = minGfxContext->GetDrawTarget(); - RefPtr maskPath = GetBoxShadowInsetPath(minDrawTarget, aOuterRect, - aInnerRect, aHasBorderRadius, - aInnerClipRadii); - - minGfxContext->SetColor(ThebesColor(aShadowColor)); - minGfxContext->SetPath(maskPath); - minGfxContext->Fill(); - - RefPtr minMask = DoBlur(minDrawTarget, &aOutTopLeft); - if (!minMask) { - return nullptr; - } - - RefPtr minInsetBlur = CreateBoxShadow(minMask, ThebesColor(aShadowColor)); - if (!minInsetBlur) { - return nullptr; - } - - IntMargin extendBy(aOutTopLeft.y, 0, 0, aOutTopLeft.x); - CacheInsetBlur(outerRectSize, innerRectSize, - aBlurRadius, aSpreadRadius, - &aInnerClipRadii, ThebesColor(aShadowColor), - aHasBorderRadius, destDrawTarget->GetBackendType(), - extendBy, minInsetBlur); - return minInsetBlur.forget(); -} - -/*** - * Blur an inset box shadow by doing: - * 1) Create a minimal box shadow path that creates a frame. - * 2) Draw the box shadow portion over the destination surface. - * 3) The "inset" part is created by a clip rect that properly clips - * the alpha mask so that it has clean edges. We still create the full - * proper alpha mask, but let the clip deal with the clean edges. - * - * All parameters should already be in device pixels. - */ -void -gfxAlphaBoxBlur::BlurInsetBox(gfxContext* aDestinationCtx, - const Rect aDestinationRect, - const Rect aShadowClipRect, - const gfxIntSize aBlurRadius, - const gfxIntSize aSpreadRadius, - const Color& aShadowColor, - bool aHasBorderRadius, - const RectCornerRadii& aInnerClipRadii, - const Rect aSkipRect) -{ - if ((aBlurRadius.width <= 0 && aBlurRadius.height <= 0)) { - // The outer path must be rounded out - // If not blurring, we're done now. - Rect pathRect(aDestinationRect); - pathRect.RoundOut(); - FillDestinationPath(aDestinationCtx, pathRect, aShadowClipRect, - aShadowColor, aHasBorderRadius, aInnerClipRadii); - return; - } - - DrawTarget* destDrawTarget = aDestinationCtx->GetDrawTarget(); - Rect outerRect; - Rect innerRect; - Margin pathMargins; - ComputeRectsForInsetBoxShadow(aBlurRadius, aSpreadRadius, - aDestinationRect, aShadowClipRect, - outerRect, innerRect, - pathMargins); - IntPoint topLeft; - RefPtr minInsetBlur = GetInsetBlur(outerRect, innerRect, - aBlurRadius, aSpreadRadius, - aInnerClipRadii, aShadowColor, - aHasBorderRadius, - topLeft, aDestinationCtx); - if (!minInsetBlur) { - return; - } - - Rect destRectOuter(aDestinationRect); - destRectOuter.RoundIn(); - Rect destRectInner(destRectOuter); - destRectInner.Deflate(pathMargins); - - Rect srcRectOuter(outerRect); - srcRectOuter.MoveBy(abs(topLeft.x), abs(topLeft.y)); - Rect srcRectInner(srcRectOuter); - srcRectInner.Deflate(pathMargins); - - if (srcRectOuter.IsEqualInterior(srcRectInner)) { - destDrawTarget->DrawSurface(minInsetBlur, destRectOuter, srcRectOuter); - } else { - DrawBoxShadows(*destDrawTarget, minInsetBlur, - destRectOuter, destRectInner, - srcRectOuter, srcRectInner, - aSkipRect); - } -} diff --git a/gfx/thebes/gfxBlur.h b/gfx/thebes/gfxBlur.h index e8b808fef412..57466d7d4fdc 100644 --- a/gfx/thebes/gfxBlur.h +++ b/gfx/thebes/gfxBlur.h @@ -20,7 +20,6 @@ struct gfxRGBA; namespace mozilla { namespace gfx { class AlphaBoxBlur; - struct Color; struct RectCornerRadii; class SourceSurface; class DrawTarget; @@ -136,44 +135,9 @@ public: static void ShutdownBlurCache(); - /*** - * Blurs an inset box shadow according to a given path. - * This is equivalent to calling Init(), drawing the inset path, - * and calling paint. Do not call Init() if using this method. - * - * @param aDestinationCtx The destination to blur to. - * @param aDestinationRect The destination rect in device pixels - * @param aShadowClipRect The destiniation inner rect of the - * inset path in device pixels. - * @param aBlurRadius The standard deviation of the blur. - * @param aSpreadRadius The spread radius in device pixels. - * @param aShadowColor The color of the blur. - * @param aHasBorderRadius If this element also has a border radius - * @param aInnerClipRadii Corner radii for the inside rect if it is a rounded rect. - * @param aSkipRect An area in device pixels we don't have to paint in. - */ - void BlurInsetBox(gfxContext* aDestinationCtx, - const mozilla::gfx::Rect aDestinationRect, - const mozilla::gfx::Rect aShadowClipRect, - const gfxIntSize aBlurRadius, - const gfxIntSize aSpreadRadius, - const mozilla::gfx::Color& aShadowColor, - const bool aHasBorderRadius, - const RectCornerRadii& aInnerClipRadii, - const mozilla::gfx::Rect aSkipRect); + protected: - already_AddRefed - GetInsetBlur(mozilla::gfx::Rect& aOuterRect, - mozilla::gfx::Rect& aInnerRect, - const gfxIntSize& aBlurRadius, - const gfxIntSize& aSpreadRadius, - const RectCornerRadii& aInnerClipRadii, - const mozilla::gfx::Color& aShadowColor, - const bool& aHasBorderRadius, - mozilla::gfx::IntPoint& aOutTopLeft, - gfxContext* aDestinationCtx); - /** * The context of the temporary alpha surface. */ diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index 0382a56e078f..4bbb186cb7aa 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -1581,22 +1581,29 @@ nsCSSRendering::PaintBoxShadowInner(nsPresContext* aPresContext, gfxContext* renderContext = aRenderingContext.ThebesContext(); DrawTarget* drawTarget = renderContext->GetDrawTarget(); nsContextBoxBlur blurringArea; + gfxContext* shadowContext = + blurringArea.Init(shadowPaintRect, 0, blurRadius, twipsPerPixel, + renderContext, aDirtyRect, &skipGfxRect); + if (!shadowContext) + continue; + DrawTarget* shadowDT = shadowContext->GetDrawTarget(); + + // shadowContext is owned by either blurringArea or aRenderingContext. + MOZ_ASSERT(shadowContext == renderContext || + shadowContext == blurringArea.GetContext()); + + // Set the shadow color; if not specified, use the foreground color + Color shadowColor = Color::FromABGR(shadowItem->mHasColor ? + shadowItem->mColor : + aForFrame->StyleColor()->mColor); + renderContext->Save(); + renderContext->SetColor(ThebesColor(shadowColor)); // Clip the context to the area of the frame's padding rect, so no part of the // shadow is painted outside. Also cut out anything beyond where the inset shadow // will be. Rect shadowGfxRect = NSRectToRect(paddingRect, twipsPerPixel); shadowGfxRect.Round(); - - // Set the shadow color; if not specified, use the foreground color - Color shadowColor = Color::FromABGR(shadowItem->mHasColor ? - shadowItem->mColor : - aForFrame->StyleColor()->mColor); - - renderContext->Save(); - - // This clips the outside border radius. - // clipRectRadii is the border radius inside the inset shadow. if (hasBorderRadius) { RefPtr roundedRect = MakePathForRoundedRect(*drawTarget, shadowGfxRect, innerRadii); @@ -1605,13 +1612,22 @@ nsCSSRendering::PaintBoxShadowInner(nsPresContext* aPresContext, renderContext->Clip(shadowGfxRect); } - nsContextBoxBlur insetBoxBlur; - gfxRect destRect = nsLayoutUtils::RectToGfxRect(shadowPaintRect, twipsPerPixel); - insetBoxBlur.InsetBoxBlur(renderContext, ToRect(destRect), - shadowClipGfxRect, shadowColor, - blurRadius, spreadDistanceAppUnits, - twipsPerPixel, hasBorderRadius, - clipRectRadii, ToRect(skipGfxRect)); + // Fill the surface minus the area within the frame that we should + // not paint in, and blur and apply it. + RefPtr builder = + shadowDT->CreatePathBuilder(FillRule::FILL_EVEN_ODD); + AppendRectToPath(builder, shadowPaintGfxRect, true); + if (hasBorderRadius) { + AppendRoundedRectToPath(builder, shadowClipGfxRect, clipRectRadii, false); + } else { + AppendRectToPath(builder, shadowClipGfxRect, false); + } + RefPtr path = builder->Finish(); + shadowContext->SetPath(path); + shadowContext->Fill(); + shadowContext->NewPath(); + + blurringArea.DoPaint(); renderContext->Restore(); } } @@ -5307,12 +5323,27 @@ nsContextBoxBlur::Init(const nsRect& aRect, nscoord aSpreadRadius, return nullptr; } - gfxIntSize blurRadius; - gfxIntSize spreadRadius; - GetBlurAndSpreadRadius(aDestinationCtx, aAppUnitsPerDevPixel, - aBlurRadius, aSpreadRadius, - blurRadius, spreadRadius); + gfxFloat scaleX = 1; + gfxFloat scaleY = 1; + // Do blurs in device space when possible. + // Chrome/Skia always does the blurs in device space + // and will sometimes get incorrect results (e.g. rotated blurs) + gfxMatrix transform = aDestinationCtx->CurrentMatrix(); + // XXX: we could probably handle negative scales but for now it's easier just to fallback + if (transform.HasNonAxisAlignedTransform() || transform._11 <= 0.0 || transform._22 <= 0.0) { + transform = gfxMatrix(); + } else { + scaleX = transform._11; + scaleY = transform._22; + } + + // compute a large or smaller blur radius + gfxIntSize blurRadius = ComputeBlurRadius(aBlurRadius, aAppUnitsPerDevPixel, scaleX, scaleY); + gfxIntSize spreadRadius = gfxIntSize(std::min(int32_t(aSpreadRadius * scaleX / aAppUnitsPerDevPixel), + int32_t(MAX_SPREAD_RADIUS)), + std::min(int32_t(aSpreadRadius * scaleY / aAppUnitsPerDevPixel), + int32_t(MAX_SPREAD_RADIUS))); mDestinationCtx = aDestinationCtx; // If not blurring, draw directly onto the destination device @@ -5330,7 +5361,6 @@ nsContextBoxBlur::Init(const nsRect& aRect, nscoord aSpreadRadius, nsLayoutUtils::RectToGfxRect(aDirtyRect, aAppUnitsPerDevPixel); dirtyRect.RoundOut(); - gfxMatrix transform = aDestinationCtx->CurrentMatrix(); rect = transform.TransformBounds(rect); mPreTransformed = !transform.IsIdentity(); @@ -5357,9 +5387,8 @@ nsContextBoxBlur::Init(const nsRect& aRect, nscoord aSpreadRadius, void nsContextBoxBlur::DoPaint() { - if (mContext == mDestinationCtx) { + if (mContext == mDestinationCtx) return; - } gfxContextMatrixAutoSaveRestore saveMatrix(mDestinationCtx); @@ -5457,99 +5486,3 @@ nsContextBoxBlur::BlurRectangle(gfxContext* aDestinationCtx, dirtyRect, skipRect); } - -/* static */ void -nsContextBoxBlur::GetBlurAndSpreadRadius(gfxContext* aDestinationCtx, - int32_t aAppUnitsPerDevPixel, - nscoord aBlurRadius, - nscoord aSpreadRadius, - gfxIntSize& aOutBlurRadius, - gfxIntSize& aOutSpreadRadius, - bool aConstrainSpreadRadius) -{ - gfxFloat scaleX = 1; - gfxFloat scaleY = 1; - - // Do blurs in device space when possible. - // Chrome/Skia always does the blurs in device space - // and will sometimes get incorrect results (e.g. rotated blurs) - gfxMatrix transform = aDestinationCtx->CurrentMatrix(); - // XXX: we could probably handle negative scales but for now it's easier just to fallback - if (transform.HasNonAxisAlignedTransform() || transform._11 <= 0.0 || transform._22 <= 0.0) { - transform = gfxMatrix(); - } else { - scaleX = transform._11; - scaleY = transform._22; - } - - // compute a large or smaller blur radius - aOutBlurRadius = ComputeBlurRadius(aBlurRadius, aAppUnitsPerDevPixel, scaleX, scaleY); - aOutSpreadRadius = - gfxIntSize(int32_t(aSpreadRadius * scaleX / aAppUnitsPerDevPixel), - int32_t(aSpreadRadius * scaleY / aAppUnitsPerDevPixel)); - - - if (aConstrainSpreadRadius) { - aOutSpreadRadius.width = std::min(aOutSpreadRadius.width, int32_t(MAX_SPREAD_RADIUS)); - aOutSpreadRadius.height = std::min(aOutSpreadRadius.height, int32_t(MAX_SPREAD_RADIUS)); - } -} - -/* static */ bool -nsContextBoxBlur::InsetBoxBlur(gfxContext* aDestinationCtx, - Rect aDestinationRect, - Rect aShadowClipRect, - Color& aShadowColor, - nscoord aBlurRadiusAppUnits, - nscoord aSpreadDistanceAppUnits, - int32_t aAppUnitsPerDevPixel, - bool aHasBorderRadius, - RectCornerRadii& aInnerClipRectRadii, - Rect aSkipRect) -{ - if (aDestinationRect.IsEmpty()) { - mContext = nullptr; - return false; - } - - gfxIntSize blurRadius; - gfxIntSize spreadRadius; - // Convert the blur and spread radius to device pixels - bool constrainSpreadRadius = false; - GetBlurAndSpreadRadius(aDestinationCtx, aAppUnitsPerDevPixel, - aBlurRadiusAppUnits, aSpreadDistanceAppUnits, - blurRadius, spreadRadius, constrainSpreadRadius); - - // The blur and spread radius are scaled already, so scale all - // input data to the blur. This way, we don't have to scale the min - // inset blur to the invert of the dest context, then rescale it back - // when we draw to the destination surface. - gfxSize scale = aDestinationCtx->CurrentMatrix().ScaleFactors(true); - Matrix currentMatrix = ToMatrix(aDestinationCtx->CurrentMatrix()); - - Rect transformedDestRect = currentMatrix.TransformBounds(aDestinationRect); - Rect transformedShadowClipRect = currentMatrix.TransformBounds(aShadowClipRect); - Rect transformedSkipRect = currentMatrix.TransformBounds(aSkipRect); - - transformedDestRect.RoundIn(); - transformedShadowClipRect.Round(); - transformedSkipRect.RoundIn(); - - for (size_t i = 0; i < 4; i++) { - aInnerClipRectRadii[i].width = std::floor(scale.width * aInnerClipRectRadii[i].width); - aInnerClipRectRadii[i].height = std::floor(scale.height * aInnerClipRectRadii[i].height); - } - - { - gfxContextAutoSaveRestore autoRestore(aDestinationCtx); - aDestinationCtx->SetMatrix(gfxMatrix()); - - mAlphaBoxBlur.BlurInsetBox(aDestinationCtx, transformedDestRect, - transformedShadowClipRect, - blurRadius, spreadRadius, - aShadowColor, - aHasBorderRadius, - aInnerClipRectRadii, transformedSkipRect); - } - return true; -} diff --git a/layout/base/nsCSSRendering.h b/layout/base/nsCSSRendering.h index bdc4133a9b36..7d2fa81c20a6 100644 --- a/layout/base/nsCSSRendering.h +++ b/layout/base/nsCSSRendering.h @@ -25,7 +25,6 @@ class nsRenderingContext; namespace mozilla { namespace gfx { -struct Color; class DrawTarget; } // namespace gfx @@ -945,48 +944,7 @@ public: const nsRect& aDirtyRect, const gfxRect& aSkipRect); - /** - * Draws a blurred inset box shadow shape onto the destination surface. - * Like BlurRectangle, this is equivalent to calling Init(), - * drawing a rectangle onto the returned surface - * and then calling DoPaint, but may let us optimize better in the - * backend. - * - * @param aDestinationCtx The destination to blur to. - * @param aDestinationRect The rectangle to blur in app units. - * @param aShadowClipRect The inside clip rect that creates the path. - * @param aShadowColor The color of the blur - * @param aBlurRadiusAppUnits The blur radius in app units - * @param aSpreadRadiusAppUnits The spread radius in app units. - * @param aAppUnitsPerDevPixel The number of app units in a device pixel, - * for conversion. Most of the time you'll - * pass this from the current PresContext if - * available. - * @param aHasBorderRadius If this inset box blur has a border radius - * @param aInnerClipRectRadii The clip rect radii used for the inside rect's path. - * @param aSkipRect An area in device pixels (NOT app units!) to avoid - * blurring over, to prevent unnecessary work. - */ - bool InsetBoxBlur(gfxContext* aDestinationCtx, - mozilla::gfx::Rect aDestinationRect, - mozilla::gfx::Rect aShadowClipRect, - mozilla::gfx::Color& aShadowColor, - nscoord aBlurRadiusAppUnits, - nscoord aSpreadRadiusAppUnits, - int32_t aAppUnitsPerDevPixel, - bool aHasBorderRadius, - RectCornerRadii& aInnerClipRectRadii, - mozilla::gfx::Rect aSkipRect); - protected: - static void GetBlurAndSpreadRadius(gfxContext* aContext, - int32_t aAppUnitsPerDevPixel, - nscoord aBlurRadius, - nscoord aSpreadRadius, - gfxIntSize& aOutBlurRadius, - gfxIntSize& aOutSpreadRadius, - bool aConstrainSpreadRadius = true); - gfxAlphaBoxBlur mAlphaBoxBlur; nsRefPtr mContext; gfxContext* mDestinationCtx; @@ -994,6 +952,7 @@ protected: /* This is true if the blur already has it's content transformed * by mDestinationCtx's transform */ bool mPreTransformed; + }; #endif /* nsCSSRendering_h___ */ diff --git a/layout/reftests/box-shadow/boxshadow-color-rounding-middle-ref.html b/layout/reftests/box-shadow/boxshadow-color-rounding-middle-ref.html deleted file mode 100644 index aa2a57e81d4d..000000000000 --- a/layout/reftests/box-shadow/boxshadow-color-rounding-middle-ref.html +++ /dev/null @@ -1,23 +0,0 @@ - - - -
-
-
-
diff --git a/layout/reftests/box-shadow/boxshadow-color-rounding-middle.html b/layout/reftests/box-shadow/boxshadow-color-rounding-middle.html deleted file mode 100644 index 1693fb9a3dde..000000000000 --- a/layout/reftests/box-shadow/boxshadow-color-rounding-middle.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
diff --git a/layout/reftests/box-shadow/reftest.list b/layout/reftests/box-shadow/reftest.list index 183fdd610118..c2587fcf0024 100644 --- a/layout/reftests/box-shadow/reftest.list +++ b/layout/reftests/box-shadow/reftest.list @@ -21,7 +21,6 @@ random-if(d2d) == boxshadow-threecorners.html boxshadow-threecorners-ref.html == boxshadow-skiprect.html boxshadow-skiprect-ref.html == boxshadow-opacity.html boxshadow-opacity-ref.html == boxshadow-color-rounding.html boxshadow-color-rounding-ref.html -== boxshadow-color-rounding-middle.html boxshadow-color-rounding-middle-ref.html == overflow-not-scrollable-1.html overflow-not-scrollable-1-ref.html == overflow-not-scrollable-1.html overflow-not-scrollable-1-ref2.html From cd079d2bf916c411b6177207d6cf65d213573089 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Mon, 21 Sep 2015 09:08:34 -0700 Subject: [PATCH 045/133] Backed out 7 changesets (bug 1048048) for android crashes in various chunks CLOSED TREE Backed out changeset b5abe23a4ea5 (bug 1048048) Backed out changeset 4f91b10e8be0 (bug 1048048) Backed out changeset 450d4a13c90e (bug 1048048) Backed out changeset 6a727c40eb68 (bug 1048048) Backed out changeset 88c2333ff745 (bug 1048048) Backed out changeset 740ab1ecd079 (bug 1048048) Backed out changeset 02c6d6aef163 (bug 1048048) --- browser/modules/ContentLinkHandler.jsm | 2 +- browser/modules/WindowsPreviewPerTab.jsm | 2 +- dom/base/nsContentPolicy.cpp | 16 --- dom/base/nsContentPolicyUtils.h | 75 ++++++------ dom/base/nsContentUtils.cpp | 20 ---- dom/base/nsContentUtils.h | 18 +-- dom/base/nsDocument.cpp | 8 +- dom/base/nsIContentPolicy.idl | 2 +- dom/base/nsIContentPolicyBase.idl | 43 +------ dom/base/nsImageLoadingContent.cpp | 2 +- dom/base/nsObjectLoadingContent.cpp | 2 +- dom/base/nsScriptLoader.cpp | 24 ++-- dom/base/nsScriptLoader.h | 6 +- dom/cache/DBSchema.cpp | 7 +- dom/fetch/InternalRequest.cpp | 7 +- dom/fetch/InternalRequest.h | 6 +- dom/html/ImageDocument.cpp | 2 +- dom/media/IdpSandbox.jsm | 2 +- dom/security/nsCSPContext.cpp | 35 ++++-- dom/security/nsCSPService.cpp | 10 +- .../test/csp/file_report_for_import.css | 1 - .../test/csp/file_report_for_import.html | 10 -- .../csp/file_report_for_import_server.sjs | 49 -------- dom/security/test/csp/mochitest.ini | 4 - .../test/csp/test_report_for_import.html | 112 ------------------ dom/workers/ServiceWorkerScriptCache.cpp | 4 +- dom/xbl/nsXBLResourceLoader.cpp | 2 +- dom/xslt/xslt/txMozillaStylesheetCompiler.cpp | 6 +- dom/xul/XULDocument.cpp | 3 +- editor/libeditor/nsHTMLEditor.cpp | 2 +- embedding/browser/nsContextMenuInfo.cpp | 2 +- image/imgLoader.cpp | 4 +- layout/generic/nsImageFrame.cpp | 2 +- layout/style/Loader.cpp | 46 +++---- layout/style/Loader.h | 11 +- .../style-src/style-src-3_4.html.ini | 5 + .../components/places/AsyncFaviconHelpers.cpp | 2 +- .../places/nsAnnoProtocolHandler.cpp | 2 +- .../components/places/nsFaviconService.cpp | 2 +- ...owser_favicon_setAndFetchFaviconForPage.js | 2 +- .../test_moz-anno_favicon_mime_type.js | 6 +- toolkit/components/search/nsSearchService.js | 2 +- toolkit/devtools/gcli/commands/screenshot.js | 2 +- toolkit/devtools/server/actors/styleeditor.js | 2 +- toolkit/devtools/server/actors/stylesheets.js | 6 +- .../LightweightThemeImageOptimizer.jsm | 2 +- toolkit/webapps/NativeApp.jsm | 2 +- widget/cocoa/OSXNotificationCenter.mm | 2 +- widget/cocoa/nsMenuItemIconX.mm | 2 +- widget/windows/WinUtils.cpp | 2 +- 50 files changed, 147 insertions(+), 441 deletions(-) delete mode 100644 dom/security/test/csp/file_report_for_import.css delete mode 100644 dom/security/test/csp/file_report_for_import.html delete mode 100644 dom/security/test/csp/file_report_for_import_server.sjs delete mode 100644 dom/security/test/csp/test_report_for_import.html create mode 100644 testing/web-platform/meta/content-security-policy/style-src/style-src-3_4.html.ini diff --git a/browser/modules/ContentLinkHandler.jsm b/browser/modules/ContentLinkHandler.jsm index 9d4da688984b..46cf75a25e56 100644 --- a/browser/modules/ContentLinkHandler.jsm +++ b/browser/modules/ContentLinkHandler.jsm @@ -164,7 +164,7 @@ this.ContentLinkHandler = { } // Security says okay, now ask content policy - if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE, + if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_IMAGE, uri, targetDoc.documentURIObject, aLink, aLink.type, null) != Ci.nsIContentPolicy.ACCEPT) diff --git a/browser/modules/WindowsPreviewPerTab.jsm b/browser/modules/WindowsPreviewPerTab.jsm index 8f32ac8a4db6..86623de5fe88 100644 --- a/browser/modules/WindowsPreviewPerTab.jsm +++ b/browser/modules/WindowsPreviewPerTab.jsm @@ -79,7 +79,7 @@ function _imageFromURI(doc, uri, privateMode, callback) { null, // aLoadingPrincipal null, // aTriggeringPrincipal Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); + Ci.nsIContentPolicy.TYPE_IMAGE); try { channel.QueryInterface(Ci.nsIPrivateBrowsingChannel); channel.setPrivate(privateMode); diff --git a/dom/base/nsContentPolicy.cpp b/dom/base/nsContentPolicy.cpp index 7f0c8a3a1345..9b2ec5528799 100644 --- a/dom/base/nsContentPolicy.cpp +++ b/dom/base/nsContentPolicy.cpp @@ -13,7 +13,6 @@ #include "nsISupports.h" #include "nsXPCOM.h" #include "nsContentPolicyUtils.h" -#include "mozilla/dom/nsCSPService.h" #include "nsContentPolicy.h" #include "nsIURI.h" #include "nsIDocShell.h" @@ -124,15 +123,9 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod, nsContentPolicyType externalTypeOrScript = nsContentUtils::InternalContentPolicyTypeToExternalOrScript(contentType); - nsContentPolicyType externalTypeOrPreload = - nsContentUtils::InternalContentPolicyTypeToExternalOrPreload(contentType); - nsCOMPtr mixedContentBlocker = do_GetService(NS_MIXEDCONTENTBLOCKER_CONTRACTID); - nsCOMPtr cspService = - do_GetService(CSPSERVICE_CONTRACTID); - /* * Enumerate mPolicies and ask each of them, taking the logical AND of * their permissions. @@ -151,15 +144,6 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod, if (isMixedContentBlocker) { type = externalTypeOrScript; } - // Send the internal content policy type for CSP which needs to - // know about preloads, in particular: - // * TYPE_INTERNAL_SCRIPT_PRELOAD - // * TYPE_INTERNAL_IMAGE_PRELOAD - // * TYPE_INTERNAL_STYLESHEET_PRELOAD - bool isCSP = cspService == entries[i]; - if (isCSP) { - type = externalTypeOrPreload; - } rv = (entries[i]->*policyMethod)(type, contentLocation, requestingLocation, requestingContext, mimeType, extra, requestPrincipal, diff --git a/dom/base/nsContentPolicyUtils.h b/dom/base/nsContentPolicyUtils.h index cddee3a6543c..e3bc0c051399 100644 --- a/dom/base/nsContentPolicyUtils.h +++ b/dom/base/nsContentPolicyUtils.h @@ -92,46 +92,41 @@ inline const char * NS_CP_ContentTypeName(uint32_t contentType) { switch (contentType) { - CASE_RETURN( TYPE_OTHER ); - CASE_RETURN( TYPE_SCRIPT ); - CASE_RETURN( TYPE_IMAGE ); - CASE_RETURN( TYPE_STYLESHEET ); - CASE_RETURN( TYPE_OBJECT ); - CASE_RETURN( TYPE_DOCUMENT ); - CASE_RETURN( TYPE_SUBDOCUMENT ); - CASE_RETURN( TYPE_REFRESH ); - CASE_RETURN( TYPE_XBL ); - CASE_RETURN( TYPE_PING ); - CASE_RETURN( TYPE_XMLHTTPREQUEST ); - CASE_RETURN( TYPE_OBJECT_SUBREQUEST ); - CASE_RETURN( TYPE_DTD ); - CASE_RETURN( TYPE_FONT ); - CASE_RETURN( TYPE_MEDIA ); - CASE_RETURN( TYPE_WEBSOCKET ); - CASE_RETURN( TYPE_CSP_REPORT ); - CASE_RETURN( TYPE_XSLT ); - CASE_RETURN( TYPE_BEACON ); - CASE_RETURN( TYPE_FETCH ); - CASE_RETURN( TYPE_IMAGESET ); - CASE_RETURN( TYPE_WEB_MANIFEST ); - CASE_RETURN( TYPE_INTERNAL_SCRIPT ); - CASE_RETURN( TYPE_INTERNAL_WORKER ); - CASE_RETURN( TYPE_INTERNAL_SHARED_WORKER ); - CASE_RETURN( TYPE_INTERNAL_EMBED ); - CASE_RETURN( TYPE_INTERNAL_OBJECT ); - CASE_RETURN( TYPE_INTERNAL_FRAME ); - CASE_RETURN( TYPE_INTERNAL_IFRAME ); - CASE_RETURN( TYPE_INTERNAL_AUDIO ); - CASE_RETURN( TYPE_INTERNAL_VIDEO ); - CASE_RETURN( TYPE_INTERNAL_TRACK ); - CASE_RETURN( TYPE_INTERNAL_XMLHTTPREQUEST ); - CASE_RETURN( TYPE_INTERNAL_EVENTSOURCE ); - CASE_RETURN( TYPE_INTERNAL_SERVICE_WORKER ); - CASE_RETURN( TYPE_INTERNAL_SCRIPT_PRELOAD ); - CASE_RETURN( TYPE_INTERNAL_IMAGE ); - CASE_RETURN( TYPE_INTERNAL_IMAGE_PRELOAD ); - CASE_RETURN( TYPE_INTERNAL_STYLESHEET ); - CASE_RETURN( TYPE_INTERNAL_STYLESHEET_PRELOAD ); + CASE_RETURN( TYPE_OTHER ); + CASE_RETURN( TYPE_SCRIPT ); + CASE_RETURN( TYPE_IMAGE ); + CASE_RETURN( TYPE_STYLESHEET ); + CASE_RETURN( TYPE_OBJECT ); + CASE_RETURN( TYPE_DOCUMENT ); + CASE_RETURN( TYPE_SUBDOCUMENT ); + CASE_RETURN( TYPE_REFRESH ); + CASE_RETURN( TYPE_XBL ); + CASE_RETURN( TYPE_PING ); + CASE_RETURN( TYPE_XMLHTTPREQUEST ); + CASE_RETURN( TYPE_OBJECT_SUBREQUEST ); + CASE_RETURN( TYPE_DTD ); + CASE_RETURN( TYPE_FONT ); + CASE_RETURN( TYPE_MEDIA ); + CASE_RETURN( TYPE_WEBSOCKET ); + CASE_RETURN( TYPE_CSP_REPORT ); + CASE_RETURN( TYPE_XSLT ); + CASE_RETURN( TYPE_BEACON ); + CASE_RETURN( TYPE_FETCH ); + CASE_RETURN( TYPE_IMAGESET ); + CASE_RETURN( TYPE_WEB_MANIFEST ); + CASE_RETURN( TYPE_INTERNAL_SCRIPT ); + CASE_RETURN( TYPE_INTERNAL_WORKER ); + CASE_RETURN( TYPE_INTERNAL_SHARED_WORKER ); + CASE_RETURN( TYPE_INTERNAL_EMBED ); + CASE_RETURN( TYPE_INTERNAL_OBJECT ); + CASE_RETURN( TYPE_INTERNAL_FRAME ); + CASE_RETURN( TYPE_INTERNAL_IFRAME ); + CASE_RETURN( TYPE_INTERNAL_AUDIO ); + CASE_RETURN( TYPE_INTERNAL_VIDEO ); + CASE_RETURN( TYPE_INTERNAL_TRACK ); + CASE_RETURN( TYPE_INTERNAL_XMLHTTPREQUEST ); + CASE_RETURN( TYPE_INTERNAL_EVENTSOURCE ); + CASE_RETURN( TYPE_INTERNAL_SERVICE_WORKER ); default: return ""; } diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 8936622c0b9a..bb06e960f920 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -7959,7 +7959,6 @@ nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType) { switch (aType) { case nsIContentPolicy::TYPE_INTERNAL_SCRIPT: - case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD: case nsIContentPolicy::TYPE_INTERNAL_WORKER: case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER: case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER: @@ -7982,14 +7981,6 @@ nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType) case nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE: return nsIContentPolicy::TYPE_XMLHTTPREQUEST; - case nsIContentPolicy::TYPE_INTERNAL_IMAGE: - case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD: - return nsIContentPolicy::TYPE_IMAGE; - - case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET: - case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD: - return nsIContentPolicy::TYPE_STYLESHEET; - default: return aType; } @@ -8011,17 +8002,6 @@ nsContentUtils::InternalContentPolicyTypeToExternalOrScript(nsContentPolicyType } } -/* static */ -nsContentPolicyType -nsContentUtils::InternalContentPolicyTypeToExternalOrPreload(nsContentPolicyType aType) -{ - if (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD || - aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD || - aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD) { - return aType; - } - return InternalContentPolicyTypeToExternal(aType); -} nsresult nsContentUtils::SetFetchReferrerURIWithPolicy(nsIPrincipal* aPrincipal, diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index 43a3d36ddc5c..5182181b2886 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -624,7 +624,7 @@ public: * @param aContext the context the image is loaded in (eg an element) * @param aLoadingDocument the document we belong to * @param aLoadingPrincipal the principal doing the load - * @param [aContentPolicyType=nsIContentPolicy::TYPE_INTERNAL_IMAGE] (Optional) + * @param [aContentPolicyType=nsIContentPolicy::TYPE_IMAGE] (Optional) * The CP content type to use * @param aImageBlockingStatus the nsIContentPolicy blocking status for this * image. This will be set even if a security check fails for the @@ -640,7 +640,7 @@ public: nsIDocument* aLoadingDocument, nsIPrincipal* aLoadingPrincipal, int16_t* aImageBlockingStatus = nullptr, - uint32_t aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE); + uint32_t aContentPolicyType = nsIContentPolicy::TYPE_IMAGE); /** * Returns true if objects in aDocument shouldn't initiate image loads. @@ -660,7 +660,7 @@ public: * creation * @param aObserver the observer for the image load * @param aLoadFlags the load flags to use. See nsIRequest - * @param [aContentPolicyType=nsIContentPolicy::TYPE_INTERNAL_IMAGE] (Optional) + * @param [aContentPolicyType=nsIContentPolicy::TYPE_IMAGE] (Optional) * The CP content type to use * @return the imgIRequest for the image load */ @@ -673,7 +673,7 @@ public: int32_t aLoadFlags, const nsAString& initiatorType, imgRequestProxy** aRequest, - uint32_t aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE); + uint32_t aContentPolicyType = nsIContentPolicy::TYPE_IMAGE); /** * Obtain an image loader that respects the given document/channel's privacy status. @@ -965,16 +965,6 @@ public: */ static nsContentPolicyType InternalContentPolicyTypeToExternalOrScript(nsContentPolicyType aType); - /** - * Map internal content policy types to external ones or preload types: - * * TYPE_INTERNAL_SCRIPT_PRELOAD - * * TYPE_INTERNAL_IMAGE_PRELOAD - * * TYPE_INTERNAL_STYLESHEET_PRELOAD - * - * Note: DO NOT call this function unless you know what you're doing! - */ - static nsContentPolicyType InternalContentPolicyTypeToExternalOrPreload(nsContentPolicyType aType); - /** * Quick helper to determine whether there are any mutation listeners * of a given type that apply to this content or any of its ancestors. diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index d9003637933c..ec065056449d 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -9739,8 +9739,7 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr, int16_t blockingStatus; if (nsContentUtils::IsImageInCache(uri, static_cast(this)) || !nsContentUtils::CanLoadImage(uri, static_cast(this), - this, NodePrincipal(), &blockingStatus, - nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD)) { + this, NodePrincipal(), &blockingStatus)) { return; } @@ -9770,8 +9769,7 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr, nullptr, // no observer loadFlags, NS_LITERAL_STRING("img"), - getter_AddRefs(request), - nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD); + getter_AddRefs(request)); // Pin image-reference to avoid evicting it from the img-cache before // the "real" load occurs. Unpinned in DispatchContentLoadedEvents and @@ -9885,7 +9883,7 @@ nsDocument::PreloadStyle(nsIURI* uri, const nsAString& charset, nsCOMPtr obs = new StubCSSLoaderObserver(); // Charset names are always ASCII. - CSSLoader()->LoadSheet(uri, true, NodePrincipal(), + CSSLoader()->LoadSheet(uri, NodePrincipal(), NS_LossyConvertUTF16toASCII(charset), obs, Element::StringToCORSMode(aCrossOriginAttr), diff --git a/dom/base/nsIContentPolicy.idl b/dom/base/nsIContentPolicy.idl index a73565a9a91e..63ec72e223e8 100644 --- a/dom/base/nsIContentPolicy.idl +++ b/dom/base/nsIContentPolicy.idl @@ -20,7 +20,7 @@ interface nsIPrincipal; * by launching a dialog to prompt the user for something). */ -[scriptable,uuid(caad4f1f-d047-46ac-ae9d-dc598e4fb91b)] +[scriptable,uuid(ce321216-c404-40a7-a711-d80454ec6b76)] interface nsIContentPolicy : nsIContentPolicyBase { /** diff --git a/dom/base/nsIContentPolicyBase.idl b/dom/base/nsIContentPolicyBase.idl index c064ecaf74c9..e31608fe9bd5 100644 --- a/dom/base/nsIContentPolicyBase.idl +++ b/dom/base/nsIContentPolicyBase.idl @@ -24,7 +24,7 @@ typedef unsigned long nsContentPolicyType; * by launching a dialog to prompt the user for something). */ -[scriptable,uuid(17418187-d86f-48dd-92d1-238838df0a4e)] +[scriptable,uuid(8527ae0d-0c43-4413-bc46-85c0bcb66876)] interface nsIContentPolicyBase : nsISupports { /** @@ -280,47 +280,6 @@ interface nsIContentPolicyBase : nsISupports */ const nsContentPolicyType TYPE_INTERNAL_SERVICE_WORKER = 35; - /** - * Indicates an internal constant for *preloaded* scripts - * loaded through script elements. - * - * This will be mapped to TYPE_SCRIPT before being passed - * to content policy implementations. - */ - const nsContentPolicyType TYPE_INTERNAL_SCRIPT_PRELOAD = 36; - - /** - * Indicates an internal constant for normal images. - * - * This will be mapped to TYPE_IMAGE before being passed - * to content policy implementations. - */ - const nsContentPolicyType TYPE_INTERNAL_IMAGE = 37; - - /** - * Indicates an internal constant for *preloaded* images. - * - * This will be mapped to TYPE_IMAGE before being passed - * to content policy implementations. - */ - const nsContentPolicyType TYPE_INTERNAL_IMAGE_PRELOAD = 38; - - /** - * Indicates an internal constant for normal stylesheets. - * - * This will be mapped to TYPE_STYLESHEET before being passed - * to content policy implementations. - */ - const nsContentPolicyType TYPE_INTERNAL_STYLESHEET = 39; - - /** - * Indicates an internal constant for *preloaded* stylesheets. - * - * This will be mapped to TYPE_STYLESHEET before being passed - * to content policy implementations. - */ - const nsContentPolicyType TYPE_INTERNAL_STYLESHEET_PRELOAD = 40; - /* When adding new content types, please update nsContentBlocker, * NS_CP_ContentTypeName, nsCSPContext, all nsIContentPolicy * implementations, the static_assert in dom/cache/DBSchema.cpp, diff --git a/dom/base/nsImageLoadingContent.cpp b/dom/base/nsImageLoadingContent.cpp index d91fc96b928e..626671a56b3a 100644 --- a/dom/base/nsImageLoadingContent.cpp +++ b/dom/base/nsImageLoadingContent.cpp @@ -589,7 +589,7 @@ nsImageLoadingContent::PolicyTypeForLoad(ImageLoadType aImageLoadType) MOZ_ASSERT(aImageLoadType == eImageLoadType_Normal, "Unknown ImageLoadType type in PolicyTypeForLoad"); - return nsIContentPolicy::TYPE_INTERNAL_IMAGE; + return nsIContentPolicy::TYPE_IMAGE; } int32_t diff --git a/dom/base/nsObjectLoadingContent.cpp b/dom/base/nsObjectLoadingContent.cpp index 5f5f670d1cb7..1767895fa595 100644 --- a/dom/base/nsObjectLoadingContent.cpp +++ b/dom/base/nsObjectLoadingContent.cpp @@ -1530,7 +1530,7 @@ nsObjectLoadingContent::CheckProcessPolicy(int16_t *aContentPolicy) int32_t objectType; switch (mType) { case eType_Image: - objectType = nsIContentPolicy::TYPE_INTERNAL_IMAGE; + objectType = nsIContentPolicy::TYPE_IMAGE; break; case eType_Document: objectType = nsIContentPolicy::TYPE_DOCUMENT; diff --git a/dom/base/nsScriptLoader.cpp b/dom/base/nsScriptLoader.cpp index b58c7b8622bb..1b39e395d28a 100644 --- a/dom/base/nsScriptLoader.cpp +++ b/dom/base/nsScriptLoader.cpp @@ -223,15 +223,10 @@ nsresult nsScriptLoader::CheckContentPolicy(nsIDocument* aDocument, nsISupports *aContext, nsIURI *aURI, - const nsAString &aType, - bool aIsPreLoad) + const nsAString &aType) { - nsContentPolicyType contentPolicyType = aIsPreLoad - ? nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD - : nsIContentPolicy::TYPE_INTERNAL_SCRIPT; - int16_t shouldLoad = nsIContentPolicy::ACCEPT; - nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType, + nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_SCRIPT, aURI, aDocument->NodePrincipal(), aContext, @@ -254,8 +249,7 @@ nsresult nsScriptLoader::ShouldLoadScript(nsIDocument* aDocument, nsISupports* aContext, nsIURI* aURI, - const nsAString &aType, - bool aIsPreLoad) + const nsAString &aType) { // Check that the containing page is allowed to load this URI. nsresult rv = nsContentUtils::GetSecurityManager()-> @@ -265,7 +259,7 @@ nsScriptLoader::ShouldLoadScript(nsIDocument* aDocument, NS_ENSURE_SUCCESS(rv, rv); // After the security manager, the content-policy stuff gets a veto - rv = CheckContentPolicy(aDocument, aContext, aURI, aType, aIsPreLoad); + rv = CheckContentPolicy(aDocument, aContext, aURI, aType); if (NS_FAILED(rv)) { return rv; } @@ -280,7 +274,7 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType, nsISupports *context = aRequest->mElement.get() ? static_cast(aRequest->mElement.get()) : static_cast(mDocument); - nsresult rv = ShouldLoadScript(mDocument, context, aRequest->mURI, aType, aRequest->IsPreload()); + nsresult rv = ShouldLoadScript(mDocument, context, aRequest->mURI, aType); if (NS_FAILED(rv)) { return rv; } @@ -302,16 +296,12 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType, return NS_OK; } - nsContentPolicyType contentPolicyType = aRequest->IsPreload() - ? nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD - : nsIContentPolicy::TYPE_INTERNAL_SCRIPT; - nsCOMPtr channel; rv = NS_NewChannel(getter_AddRefs(channel), aRequest->mURI, mDocument, nsILoadInfo::SEC_NORMAL, - contentPolicyType, + nsIContentPolicy::TYPE_INTERNAL_SCRIPT, loadGroup, prompter, nsIRequest::LOAD_NORMAL | @@ -540,7 +530,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) if (elementCharset.Equals(preloadCharset) && ourCORSMode == request->mCORSMode && ourRefPolicy == request->mReferrerPolicy) { - rv = CheckContentPolicy(mDocument, aElement, request->mURI, type, false); + rv = CheckContentPolicy(mDocument, aElement, request->mURI, type); NS_ENSURE_SUCCESS(rv, false); } else { // Drop the preload diff --git a/dom/base/nsScriptLoader.h b/dom/base/nsScriptLoader.h index 468f50f5d5d1..b62f229a4e95 100644 --- a/dom/base/nsScriptLoader.h +++ b/dom/base/nsScriptLoader.h @@ -354,8 +354,7 @@ public: static nsresult ShouldLoadScript(nsIDocument* aDocument, nsISupports* aContext, nsIURI* aURI, - const nsAString &aType, - bool aIsPreLoad); + const nsAString &aType); /** * Starts deferring deferred scripts and puts them in the mDeferredRequests @@ -436,8 +435,7 @@ private: static nsresult CheckContentPolicy(nsIDocument* aDocument, nsISupports *aContext, nsIURI *aURI, - const nsAString &aType, - bool aIsPreLoad); + const nsAString &aType); /** * Start a load for aRequest's URI. diff --git a/dom/cache/DBSchema.cpp b/dom/cache/DBSchema.cpp index e2f6904bbd9a..52a93333425d 100644 --- a/dom/cache/DBSchema.cpp +++ b/dom/cache/DBSchema.cpp @@ -275,12 +275,7 @@ static_assert(nsIContentPolicy::TYPE_INVALID == 0 && nsIContentPolicy::TYPE_INTERNAL_TRACK == 32 && nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST == 33 && nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE == 34 && - nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER == 35 && - nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD == 36 && - nsIContentPolicy::TYPE_INTERNAL_IMAGE == 37 && - nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD == 38 && - nsIContentPolicy::TYPE_INTERNAL_STYLESHEET == 39 && - nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD == 40, + nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER == 35, "nsContentPolicyType values are as expected"); namespace { diff --git a/dom/fetch/InternalRequest.cpp b/dom/fetch/InternalRequest.cpp index 2baed642b12c..d2a8f2bc1f85 100644 --- a/dom/fetch/InternalRequest.cpp +++ b/dom/fetch/InternalRequest.cpp @@ -116,7 +116,6 @@ InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aConte context = RequestContext::Internal; break; case nsIContentPolicy::TYPE_INTERNAL_SCRIPT: - case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD: case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER: context = RequestContext::Script; break; @@ -126,12 +125,10 @@ InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aConte case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER: context = RequestContext::Sharedworker; break; - case nsIContentPolicy::TYPE_INTERNAL_IMAGE: - case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD: + case nsIContentPolicy::TYPE_IMAGE: context = RequestContext::Image; break; - case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET: - case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD: + case nsIContentPolicy::TYPE_STYLESHEET: context = RequestContext::Style; break; case nsIContentPolicy::TYPE_INTERNAL_OBJECT: diff --git a/dom/fetch/InternalRequest.h b/dom/fetch/InternalRequest.h index 8c9d84238667..caa005756bcd 100644 --- a/dom/fetch/InternalRequest.h +++ b/dom/fetch/InternalRequest.h @@ -43,7 +43,7 @@ namespace dom { * frame | TYPE_INTERNAL_FRAME * hyperlink | * iframe | TYPE_INTERNAL_IFRAME - * image | TYPE_INTERNAL_IMAGE, TYPE_INTERNAL_IMAGE_PRELOAD + * image | TYPE_IMAGE * imageset | TYPE_IMAGESET * import | Not supported by Gecko * internal | TYPE_DOCUMENT, TYPE_XBL, TYPE_OTHER @@ -53,10 +53,10 @@ namespace dom { * ping | TYPE_PING * plugin | TYPE_OBJECT_SUBREQUEST * prefetch | - * script | TYPE_INTERNAL_SCRIPT, TYPE_INTERNAL_SCRIPT_PRELOAD + * script | TYPE_INTERNAL_SCRIPT * sharedworker | TYPE_INTERNAL_SHARED_WORKER * subresource | Not supported by Gecko - * style | TYPE_INTERNAL_STYLESHEET, TYPE_INTERNAL_STYLESHEET_PRELOAD + * style | TYPE_STYLESHEET * track | TYPE_INTERNAL_TRACK * video | TYPE_INTERNAL_VIDEO * worker | TYPE_INTERNAL_WORKER diff --git a/dom/html/ImageDocument.cpp b/dom/html/ImageDocument.cpp index 46a10bad8c62..3c7ce4327fe4 100644 --- a/dom/html/ImageDocument.cpp +++ b/dom/html/ImageDocument.cpp @@ -99,7 +99,7 @@ ImageListener::OnStartRequest(nsIRequest* request, nsISupports *ctxt) } int16_t decision = nsIContentPolicy::ACCEPT; - nsresult rv = NS_CheckContentProcessPolicy(nsIContentPolicy::TYPE_INTERNAL_IMAGE, + nsresult rv = NS_CheckContentProcessPolicy(nsIContentPolicy::TYPE_IMAGE, channelURI, channelPrincipal, domWindow->GetFrameElementInternal(), diff --git a/dom/media/IdpSandbox.jsm b/dom/media/IdpSandbox.jsm index 6e600dcddf35..96b12eeebab2 100644 --- a/dom/media/IdpSandbox.jsm +++ b/dom/media/IdpSandbox.jsm @@ -50,7 +50,7 @@ ResourceLoader.load = function(uri, doc) { // the '2' identifies this as a script load let ioChannel = ioService.newChannelFromURI2(uri, doc, doc.nodePrincipal, systemPrincipal, 0, - Ci.nsIContentPolicy.TYPE_INTERNAL_SCRIPT); + Ci.nsIContentPolicy.TYPE_SCRIPT); ioChannel.loadGroup = doc.documentLoadGroup.QueryInterface(Ci.nsILoadGroup); ioChannel.notificationCallbacks = new RedirectHttpsOnly(); diff --git a/dom/security/nsCSPContext.cpp b/dom/security/nsCSPContext.cpp index 19c55a20026c..6fb841b9cc78 100644 --- a/dom/security/nsCSPContext.cpp +++ b/dom/security/nsCSPContext.cpp @@ -115,14 +115,6 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType, CSPCONTEXTLOG(("nsCSPContext::ShouldLoad, aContentLocation: %s", spec.get())); } - bool isStyleOrScriptPreLoad = - (aContentType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD || - aContentType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD); - - // Since we know whether we are dealing with a preload, we have to convert - // the internal policytype ot the external policy type before moving on. - aContentType = nsContentUtils::InternalContentPolicyTypeToExternal(aContentType); - nsresult rv = NS_OK; // This ShouldLoad function is called from nsCSPService::ShouldLoad, @@ -153,8 +145,29 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType, return NS_OK; } + // This may be a load or a preload. If it is a preload, the document will + // not have been fully parsed yet, and aRequestContext will be an + // nsIDOMHTMLDocument rather than the nsIDOMHTMLElement associated with the + // resource. As a result, we cannot extract the element's corresponding + // nonce attribute, and so we cannot correctly check the nonce on a preload. + // + // Therefore, the decision returned here for a preload may be *incorrect* as + // it cannot take the nonce into account. We will still check the load, but + // we will not cache the result or report a violation. When the "real load" + // happens subsequently, we will re-check with the additional context to + // make a final decision. + // + // We don't just return false because that would block all preloads and + // degrade performance. However, we do want to block preloads that are + // clearly blocked (their urls are not whitelisted) by CSP. + + nsCOMPtr doc = do_QueryInterface(aRequestContext); + bool isPreload = doc && + (aContentType == nsIContentPolicy::TYPE_SCRIPT || + aContentType == nsIContentPolicy::TYPE_STYLESHEET); + nsAutoString nonce; - if (!isStyleOrScriptPreLoad) { + if (!isPreload) { nsCOMPtr htmlElement = do_QueryInterface(aRequestContext); if (htmlElement) { rv = htmlElement->GetAttribute(NS_LITERAL_STRING("nonce"), nonce); @@ -171,7 +184,7 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType, originalURI, nonce, wasRedirected, - isStyleOrScriptPreLoad, + isPreload, false, // allow fallback to default-src true, // send violation reports true); // send blocked URI in violation reports @@ -180,7 +193,7 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType, : nsIContentPolicy::REJECT_SERVER; // Done looping, cache any relevant result - if (cacheKey.Length() > 0 && !isStyleOrScriptPreLoad) { + if (cacheKey.Length() > 0 && !isPreload) { mShouldLoadCache.Put(cacheKey, *outDecision); } diff --git a/dom/security/nsCSPService.cpp b/dom/security/nsCSPService.cpp index 9a04ac43768a..e52bfcd86ab3 100644 --- a/dom/security/nsCSPService.cpp +++ b/dom/security/nsCSPService.cpp @@ -105,9 +105,8 @@ CSPService::ShouldLoad(uint32_t aContentType, nsIPrincipal *aRequestPrincipal, int16_t *aDecision) { - MOZ_ASSERT(aContentType == - nsContentUtils::InternalContentPolicyTypeToExternalOrPreload(aContentType), - "We should only see external content policy types or preloads here."); + MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType), + "We should only see external content policy types here."); if (!aContentLocation) { return NS_ERROR_FAILURE; @@ -252,9 +251,8 @@ CSPService::ShouldProcess(uint32_t aContentType, nsIPrincipal *aRequestPrincipal, int16_t *aDecision) { - MOZ_ASSERT(aContentType == - nsContentUtils::InternalContentPolicyTypeToExternalOrPreload(aContentType), - "We should only see external content policy types or preloads here."); + MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType), + "We should only see external content policy types here."); if (!aContentLocation) return NS_ERROR_FAILURE; diff --git a/dom/security/test/csp/file_report_for_import.css b/dom/security/test/csp/file_report_for_import.css deleted file mode 100644 index b578b77b33fb..000000000000 --- a/dom/security/test/csp/file_report_for_import.css +++ /dev/null @@ -1 +0,0 @@ -@import url("http://example.com/tests/dom/security/test/csp/file_report_for_import_server.sjs?stylesheet"); diff --git a/dom/security/test/csp/file_report_for_import.html b/dom/security/test/csp/file_report_for_import.html deleted file mode 100644 index 77a36faea1b6..000000000000 --- a/dom/security/test/csp/file_report_for_import.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - Bug 1048048 - Test sending csp-report when using import in css - - - - empty body, just testing @import in the included css for bug 1048048 - - diff --git a/dom/security/test/csp/file_report_for_import_server.sjs b/dom/security/test/csp/file_report_for_import_server.sjs deleted file mode 100644 index e69852b1b791..000000000000 --- a/dom/security/test/csp/file_report_for_import_server.sjs +++ /dev/null @@ -1,49 +0,0 @@ -// Custom *.sjs file specifically for the needs of Bug: -// Bug 1048048 - CSP violation report not sent for @import - -const CC = Components.Constructor; -const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1", - "nsIBinaryInputStream", - "setInputStream"); - -function handleRequest(request, response) -{ - // avoid confusing cache behaviors - response.setHeader("Cache-Control", "no-cache", false); - response.setHeader("Content-Type", "text/html", false); - var queryString = request.queryString; - - // (1) lets process the queryresult request async and - // wait till we have received the image request. - if (queryString === "queryresult") { - response.processAsync(); - setObjectState("queryResult", response); - return; - } - - // (2) handle the csp-report and return the JSON back to - // the testfile using the afore stored xml request in (1). - if (queryString === "report") { - getObjectState("queryResult", function(queryResponse) { - if (!queryResponse) { - return; - } - - // send the report back to the XML request for verification - var report = new BinaryInputStream(request.bodyInputStream); - var avail; - var bytes = []; - while ((avail = report.available()) > 0) { - Array.prototype.push.apply(bytes, report.readByteArray(avail)); - } - var data = String.fromCharCode.apply(null, bytes); - queryResponse.bodyOutputStream.write(data, data.length); - queryResponse.finish(); - }); - return; - } - - // we should not get here ever, but just in case return - // something unexpected. - response.write("doh!"); -} diff --git a/dom/security/test/csp/mochitest.ini b/dom/security/test/csp/mochitest.ini index 0ca3b70da82c..13897873308c 100644 --- a/dom/security/test/csp/mochitest.ini +++ b/dom/security/test/csp/mochitest.ini @@ -127,9 +127,6 @@ support-files = file_upgrade_insecure_referrer_server.sjs file_upgrade_insecure_cors.html file_upgrade_insecure_cors_server.sjs - file_report_for_import.css - file_report_for_import.html - file_report_for_import_server.sjs [test_base-uri.html] [test_blob_data_schemes.html] @@ -194,6 +191,5 @@ skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'gonk' || toolk skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'gonk' || toolkit == 'android' [test_upgrade_insecure_cors.html] skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'gonk' || toolkit == 'android' -[test_report_for_import.html] [test_blocked_uri_in_reports.html] skip-if = e10s || buildapp == 'b2g' # http-on-opening-request observer not supported in child process (bug 1009632) diff --git a/dom/security/test/csp/test_report_for_import.html b/dom/security/test/csp/test_report_for_import.html deleted file mode 100644 index 346af65b74ef..000000000000 --- a/dom/security/test/csp/test_report_for_import.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - Test for Bug 548193 - - - - -

- - - - - - - diff --git a/dom/workers/ServiceWorkerScriptCache.cpp b/dom/workers/ServiceWorkerScriptCache.cpp index 1c44aa1ed83b..9f2fb7494f49 100644 --- a/dom/workers/ServiceWorkerScriptCache.cpp +++ b/dom/workers/ServiceWorkerScriptCache.cpp @@ -111,12 +111,12 @@ public: } // Note that because there is no "serviceworker" RequestContext type, we can - // use the TYPE_INTERNAL_SCRIPT content policy types when loading a service + // use the external TYPE_SCRIPT content policy types when loading a service // worker. rv = NS_NewChannel(getter_AddRefs(mChannel), uri, aPrincipal, nsILoadInfo::SEC_NORMAL, - nsIContentPolicy::TYPE_INTERNAL_SCRIPT, + nsIContentPolicy::TYPE_SCRIPT, loadGroup); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; diff --git a/dom/xbl/nsXBLResourceLoader.cpp b/dom/xbl/nsXBLResourceLoader.cpp index ba2d7701b2e3..984efdf313da 100644 --- a/dom/xbl/nsXBLResourceLoader.cpp +++ b/dom/xbl/nsXBLResourceLoader.cpp @@ -151,7 +151,7 @@ nsXBLResourceLoader::LoadResources(bool* aResult) } else { - rv = cssLoader->LoadSheet(url, false, docPrincipal, EmptyCString(), this); + rv = cssLoader->LoadSheet(url, docPrincipal, EmptyCString(), this); if (NS_SUCCEEDED(rv)) ++mPendingSheets; } diff --git a/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp b/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp index a3955414c533..eeefcff1808c 100644 --- a/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp +++ b/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp @@ -424,7 +424,7 @@ txCompileObserver::loadURI(const nsAString& aUri, // Content Policy int16_t shouldLoad = nsIContentPolicy::ACCEPT; - rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_STYLESHEET, + rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET, uri, referrerPrincipal, mLoaderDocument, @@ -524,7 +524,7 @@ TX_LoadSheet(nsIURI* aUri, txMozillaXSLTProcessor* aProcessor, // Content Policy int16_t shouldLoad = nsIContentPolicy::ACCEPT; nsresult rv = - NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_STYLESHEET, + NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET, aUri, principal, aLoaderDocument, @@ -666,7 +666,7 @@ txSyncCompileObserver::loadURI(const nsAString& aUri, // Content Policy int16_t shouldLoad = nsIContentPolicy::ACCEPT; - rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_STYLESHEET, + rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET, uri, referrerPrincipal, nullptr, diff --git a/dom/xul/XULDocument.cpp b/dom/xul/XULDocument.cpp index 172c9283a789..75b67a290ee1 100644 --- a/dom/xul/XULDocument.cpp +++ b/dom/xul/XULDocument.cpp @@ -3250,8 +3250,7 @@ XULDocument::LoadScript(nsXULPrototypeScript* aScriptProto, bool* aBlock) this, static_cast(this), aScriptProto->mSrcURI, - NS_LITERAL_STRING("application/x-javascript"), - false); + NS_LITERAL_STRING("application/x-javascript")); if (NS_FAILED(rv)) { *aBlock = false; return rv; diff --git a/editor/libeditor/nsHTMLEditor.cpp b/editor/libeditor/nsHTMLEditor.cpp index 9092ea10467c..e46ad9851354 100644 --- a/editor/libeditor/nsHTMLEditor.cpp +++ b/editor/libeditor/nsHTMLEditor.cpp @@ -2791,7 +2791,7 @@ nsHTMLEditor::ReplaceStyleSheet(const nsAString& aURL) NS_ENSURE_SUCCESS(rv, rv); return ps->GetDocument()->CSSLoader()-> - LoadSheet(uaURI, false, nullptr, EmptyCString(), this); + LoadSheet(uaURI, nullptr, EmptyCString(), this); } NS_IMETHODIMP diff --git a/embedding/browser/nsContextMenuInfo.cpp b/embedding/browser/nsContextMenuInfo.cpp index aa36e3d44bfc..3df8c9fd80b5 100644 --- a/embedding/browser/nsContextMenuInfo.cpp +++ b/embedding/browser/nsContextMenuInfo.cpp @@ -294,7 +294,7 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode* aDOMNode, return il->LoadImage(bgUri, nullptr, nullptr, doc->GetReferrerPolicy(), principal, nullptr, nullptr, nullptr, nsIRequest::LOAD_NORMAL, - nullptr, nsIContentPolicy::TYPE_INTERNAL_IMAGE, + nullptr, nsIContentPolicy::TYPE_IMAGE, EmptyString(), aRequest); } } diff --git a/image/imgLoader.cpp b/image/imgLoader.cpp index 806172c8373e..f3dbbec3b60c 100644 --- a/image/imgLoader.cpp +++ b/image/imgLoader.cpp @@ -618,7 +618,7 @@ ShouldLoadCachedImage(imgRequest* aImgRequest, nsresult rv; int16_t decision = nsIContentPolicy::REJECT_REQUEST; - rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_IMAGE, + rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_IMAGE, contentLocation, aLoadingPrincipal, aLoadingContext, @@ -1981,7 +1981,7 @@ imgLoader::LoadImageXPCOM(nsIURI* aURI, { // Optional parameter, so defaults to 0 (== TYPE_INVALID) if (!aContentPolicyType) { - aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE; + aContentPolicyType = nsIContentPolicy::TYPE_IMAGE; } imgRequestProxy* proxy; ReferrerPolicy refpol = ReferrerPolicyFromString(aReferrerPolicy); diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 9f848db2187a..534d0b570aa3 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -2204,7 +2204,7 @@ nsImageFrame::LoadIcon(const nsAString& aSpec, // For icon loads, we don't need to merge with the loadgroup flags nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL; - nsContentPolicyType contentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE; + nsContentPolicyType contentPolicyType = nsIContentPolicy::TYPE_IMAGE; return il->LoadImage(realURI, /* icon URI */ nullptr, /* initial document URI; this is only diff --git a/layout/style/Loader.cpp b/layout/style/Loader.cpp index 7439d6b4ca90..54e697316c42 100644 --- a/layout/style/Loader.cpp +++ b/layout/style/Loader.cpp @@ -607,7 +607,7 @@ Loader::SetPreferredSheet(const nsAString& aTitle) mDatasToNotifyOn += arr.Length(); for (uint32_t i = 0; i < arr.Length(); ++i) { --mDatasToNotifyOn; - LoadSheet(arr[i], eSheetNeedsParser, false); + LoadSheet(arr[i], eSheetNeedsParser); } } @@ -1025,8 +1025,7 @@ Loader::ObsoleteSheet(nsIURI* aURI) nsresult Loader::CheckLoadAllowed(nsIPrincipal* aSourcePrincipal, nsIURI* aTargetURI, - nsISupports* aContext, - bool aIsPreload) + nsISupports* aContext) { LOG(("css::Loader::CheckLoadAllowed")); @@ -1045,12 +1044,9 @@ Loader::CheckLoadAllowed(nsIPrincipal* aSourcePrincipal, LOG((" Passed security check")); // Check with content policy - nsContentPolicyType contentPolicyType = - aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD - : nsIContentPolicy::TYPE_INTERNAL_STYLESHEET; int16_t shouldLoad = nsIContentPolicy::ACCEPT; - rv = NS_CheckContentLoadPolicy(contentPolicyType, + rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET, aTargetURI, aSourcePrincipal, aContext, @@ -1415,9 +1411,7 @@ Loader::InsertChildSheet(CSSStyleSheet* aSheet, * a new load is kicked off asynchronously. */ nsresult -Loader::LoadSheet(SheetLoadData* aLoadData, - StyleSheetState aSheetState, - bool aIsPreload) +Loader::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState) { LOG(("css::Loader::LoadSheet")); NS_PRECONDITION(aLoadData, "Need a load data"); @@ -1567,7 +1561,7 @@ Loader::LoadSheet(SheetLoadData* aLoadData, mSheets->mPendingDatas.Remove(&key); LOG((" Forcing load of pending data")); - return LoadSheet(existingData, eSheetNeedsParser, aIsPreload); + return LoadSheet(existingData, eSheetNeedsParser); } // All done here; once the load completes we'll be marked complete // automatically @@ -1589,10 +1583,6 @@ Loader::LoadSheet(SheetLoadData* aLoadData, securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL; } - nsContentPolicyType contentPolicyType = - aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD - : nsIContentPolicy::TYPE_INTERNAL_STYLESHEET; - nsCOMPtr channel; // Note we are calling NS_NewChannelWithTriggeringPrincipal here with a node // and a principal. This is because of a case where the node is the document @@ -1604,7 +1594,7 @@ Loader::LoadSheet(SheetLoadData* aLoadData, aLoadData->mRequestingNode, triggeringPrincipal, securityFlags, - contentPolicyType, + nsIContentPolicy::TYPE_STYLESHEET, loadGroup, nullptr, // aCallbacks nsIChannel::LOAD_NORMAL | @@ -1620,7 +1610,7 @@ Loader::LoadSheet(SheetLoadData* aLoadData, aLoadData->mURI, triggeringPrincipal, securityFlags, - contentPolicyType, + nsIContentPolicy::TYPE_STYLESHEET, loadGroup, nullptr, // aCallbacks nsIChannel::LOAD_NORMAL | @@ -2054,7 +2044,7 @@ Loader::LoadStyleLink(nsIContent* aElement, if (!context) { context = mDocument; } - nsresult rv = CheckLoadAllowed(principal, aURL, context, false); + nsresult rv = CheckLoadAllowed(principal, aURL, context); if (NS_FAILED(rv)) return rv; LOG((" Passed load check")); @@ -2110,7 +2100,7 @@ Loader::LoadStyleLink(nsIContent* aElement, } // Load completion will free the data - rv = LoadSheet(data, state, false); + rv = LoadSheet(data, state); NS_ENSURE_SUCCESS(rv, rv); data->mMustNotify = true; @@ -2188,7 +2178,7 @@ Loader::LoadChildSheet(CSSStyleSheet* aParentSheet, } nsIPrincipal* principal = aParentSheet->Principal(); - nsresult rv = CheckLoadAllowed(principal, aURL, context, false); + nsresult rv = CheckLoadAllowed(principal, aURL, context); if (NS_FAILED(rv)) return rv; LOG((" Passed load check")); @@ -2252,7 +2242,7 @@ Loader::LoadChildSheet(CSSStyleSheet* aParentSheet, bool syncLoad = data->mSyncLoad; // Load completion will release the data - rv = LoadSheet(data, state, false); + rv = LoadSheet(data, state); NS_ENSURE_SUCCESS(rv, rv); // If syncLoad is true, |data| will be deleted by now. @@ -2268,7 +2258,7 @@ Loader::LoadSheetSync(nsIURI* aURL, bool aAllowUnsafeRules, CSSStyleSheet** aSheet) { LOG(("css::Loader::LoadSheetSync")); - return InternalLoadNonDocumentSheet(aURL, false, aAllowUnsafeRules, + return InternalLoadNonDocumentSheet(aURL, aAllowUnsafeRules, aUseSystemPrincipal, nullptr, EmptyCString(), aSheet, nullptr); } @@ -2282,14 +2272,13 @@ Loader::LoadSheet(nsIURI* aURL, { LOG(("css::Loader::LoadSheet(aURL, aObserver, aSheet) api call")); NS_PRECONDITION(aSheet, "aSheet is null"); - return InternalLoadNonDocumentSheet(aURL, false, false, false, + return InternalLoadNonDocumentSheet(aURL, false, false, aOriginPrincipal, aCharset, aSheet, aObserver); } nsresult Loader::LoadSheet(nsIURI* aURL, - bool aIsPreload, nsIPrincipal* aOriginPrincipal, const nsCString& aCharset, nsICSSLoaderObserver* aObserver, @@ -2298,7 +2287,7 @@ Loader::LoadSheet(nsIURI* aURL, const nsAString& aIntegrity) { LOG(("css::Loader::LoadSheet(aURL, aObserver) api call")); - return InternalLoadNonDocumentSheet(aURL, aIsPreload, false, false, + return InternalLoadNonDocumentSheet(aURL, false, false, aOriginPrincipal, aCharset, nullptr, aObserver, aCORSMode, aReferrerPolicy, aIntegrity); @@ -2306,7 +2295,6 @@ Loader::LoadSheet(nsIURI* aURL, nsresult Loader::InternalLoadNonDocumentSheet(nsIURI* aURL, - bool aIsPreload, bool aAllowUnsafeRules, bool aUseSystemPrincipal, nsIPrincipal* aOriginPrincipal, @@ -2334,7 +2322,7 @@ Loader::InternalLoadNonDocumentSheet(nsIURI* aURL, return NS_ERROR_NOT_AVAILABLE; } - nsresult rv = CheckLoadAllowed(aOriginPrincipal, aURL, mDocument, aIsPreload); + nsresult rv = CheckLoadAllowed(aOriginPrincipal, aURL, mDocument); if (NS_FAILED(rv)) { return rv; } @@ -2369,7 +2357,7 @@ Loader::InternalLoadNonDocumentSheet(nsIURI* aURL, aOriginPrincipal, mDocument); NS_ADDREF(data); - rv = LoadSheet(data, state, aIsPreload); + rv = LoadSheet(data, state); NS_ENSURE_SUCCESS(rv, rv); if (aSheet) { @@ -2561,7 +2549,7 @@ Loader::StartAlternateLoads() mDatasToNotifyOn += arr.Length(); for (uint32_t i = 0; i < arr.Length(); ++i) { --mDatasToNotifyOn; - LoadSheet(arr[i], eSheetNeedsParser, false); + LoadSheet(arr[i], eSheetNeedsParser); } } diff --git a/layout/style/Loader.h b/layout/style/Loader.h index f4da96e4c079..cd17ebeb66ee 100644 --- a/layout/style/Loader.h +++ b/layout/style/Loader.h @@ -317,7 +317,6 @@ public: * not-yet-loaded sheet. */ nsresult LoadSheet(nsIURI* aURL, - bool aIsPreload, nsIPrincipal* aOriginPrincipal, const nsCString& aCharset, nsICSSLoaderObserver* aObserver, @@ -406,12 +405,9 @@ private: // Note: null aSourcePrincipal indicates that the content policy and // CheckLoadURI checks should be skipped. - // aIsPreload indicates whether the html parser preloads that - // stylesheet or if it is a regular load. nsresult CheckLoadAllowed(nsIPrincipal* aSourcePrincipal, nsIURI* aTargetURI, - nsISupports* aContext, - bool aIsPreload); + nsISupports* aContext); // For inline style, the aURI param is null, but the aLinkingContent @@ -450,7 +446,6 @@ private: ImportRule* aParentRule); nsresult InternalLoadNonDocumentSheet(nsIURI* aURL, - bool aIsPreload, bool aAllowUnsafeRules, bool aUseSystemPrincipal, nsIPrincipal* aOriginPrincipal, @@ -482,9 +477,7 @@ private: // Note: LoadSheet is responsible for releasing aLoadData and setting the // sheet to complete on failure. - nsresult LoadSheet(SheetLoadData* aLoadData, - StyleSheetState aSheetState, - bool aIsPreLoad); + nsresult LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState); // Parse the stylesheet in aLoadData. The sheet data comes from aInput. // Set aCompleted to true if the parse finished, false otherwise (e.g. if the diff --git a/testing/web-platform/meta/content-security-policy/style-src/style-src-3_4.html.ini b/testing/web-platform/meta/content-security-policy/style-src/style-src-3_4.html.ini new file mode 100644 index 000000000000..c5f4d96d7a18 --- /dev/null +++ b/testing/web-platform/meta/content-security-policy/style-src/style-src-3_4.html.ini @@ -0,0 +1,5 @@ +[style-src-3_4.html] + type: testharness + [Violation report status OK.] + expected: FAIL + diff --git a/toolkit/components/places/AsyncFaviconHelpers.cpp b/toolkit/components/places/AsyncFaviconHelpers.cpp index b57579f85a3e..7b136e447b55 100644 --- a/toolkit/components/places/AsyncFaviconHelpers.cpp +++ b/toolkit/components/places/AsyncFaviconHelpers.cpp @@ -532,7 +532,7 @@ AsyncFetchAndSetIconFromNetwork::Run() iconURI, nsContentUtils::GetSystemPrincipal(), nsILoadInfo::SEC_NORMAL, - nsIContentPolicy::TYPE_INTERNAL_IMAGE); + nsIContentPolicy::TYPE_IMAGE); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr listenerRequestor = diff --git a/toolkit/components/places/nsAnnoProtocolHandler.cpp b/toolkit/components/places/nsAnnoProtocolHandler.cpp index e3b7a5bf92f6..c0b3823a7636 100644 --- a/toolkit/components/places/nsAnnoProtocolHandler.cpp +++ b/toolkit/components/places/nsAnnoProtocolHandler.cpp @@ -53,7 +53,7 @@ GetDefaultIcon(nsIChannel **aChannel) defaultIconURI, nsContentUtils::GetSystemPrincipal(), nsILoadInfo::SEC_NORMAL, - nsIContentPolicy::TYPE_INTERNAL_IMAGE); + nsIContentPolicy::TYPE_IMAGE); } //////////////////////////////////////////////////////////////////////////////// diff --git a/toolkit/components/places/nsFaviconService.cpp b/toolkit/components/places/nsFaviconService.cpp index 6a9f28b18d83..1fe0a5e353f7 100644 --- a/toolkit/components/places/nsFaviconService.cpp +++ b/toolkit/components/places/nsFaviconService.cpp @@ -330,7 +330,7 @@ nsFaviconService::ReplaceFaviconDataFromDataURL(nsIURI* aFaviconURI, nullptr, // aTriggeringPrincipal nullptr, // aLoadingNode nsILoadInfo::SEC_NORMAL, - nsIContentPolicy::TYPE_INTERNAL_IMAGE); + nsIContentPolicy::TYPE_IMAGE); nsCOMPtr channel; rv = protocolHandler->NewChannel2(dataURI, loadInfo, getter_AddRefs(channel)); diff --git a/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage.js b/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage.js index 7e5e61833897..98332260efb1 100644 --- a/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage.js +++ b/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage.js @@ -33,7 +33,7 @@ function test() { NetUtil.asyncFetch({ uri: favIconLocation, loadUsingSystemPrincipal: true, - contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE + contentPolicyType: Ci.nsIContentPolicy.TYPE_IMAGE }, function(inputStream, status) { if (!Components.isSuccessCode(status)) { ok(false, "Could not get the icon file"); diff --git a/toolkit/components/places/tests/favicons/test_moz-anno_favicon_mime_type.js b/toolkit/components/places/tests/favicons/test_moz-anno_favicon_mime_type.js index 06584fc34653..26e20f1329ed 100644 --- a/toolkit/components/places/tests/favicons/test_moz-anno_favicon_mime_type.js +++ b/toolkit/components/places/tests/favicons/test_moz-anno_favicon_mime_type.js @@ -63,7 +63,7 @@ function run_test() Services.scriptSecurityManager.getSystemPrincipal(), null, // aTriggeringPrincipal Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); + Ci.nsIContentPolicy.TYPE_IMAGE); channel.asyncOpen(new streamListener("image/png"), null); do_test_pending(); @@ -76,7 +76,7 @@ function run_test() Services.scriptSecurityManager.getSystemPrincipal(), null, // aTriggeringPrincipal Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); + Ci.nsIContentPolicy.TYPE_IMAGE); channel.asyncOpen(new streamListener("image/png"), null); do_test_pending(); @@ -94,7 +94,7 @@ function run_test() Services.scriptSecurityManager.getSystemPrincipal(), null, // aTriggeringPrincipal Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); + Ci.nsIContentPolicy.TYPE_IMAGE); channel.asyncOpen(new streamListener("image/png"), null); do_test_pending(); } diff --git a/toolkit/components/search/nsSearchService.js b/toolkit/components/search/nsSearchService.js index bcf6f43a0d72..1e095208bdc9 100644 --- a/toolkit/components/search/nsSearchService.js +++ b/toolkit/components/search/nsSearchService.js @@ -2081,7 +2081,7 @@ Engine.prototype = { Services.scriptSecurityManager.getSystemPrincipal(), null, // aTriggeringPrincipal Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); + Ci.nsIContentPolicy.TYPE_IMAGE); let iconLoadCallback = function (aByteArray, aEngine) { // This callback may run after we've already set a preferred icon, diff --git a/toolkit/devtools/gcli/commands/screenshot.js b/toolkit/devtools/gcli/commands/screenshot.js index 1f9b91a928a8..44caace02750 100644 --- a/toolkit/devtools/gcli/commands/screenshot.js +++ b/toolkit/devtools/gcli/commands/screenshot.js @@ -357,7 +357,7 @@ function saveToClipboard(context, reply) { Services.scriptSecurityManager.getSystemPrincipal(), null, // aTriggeringPrincipal Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); + Ci.nsIContentPolicy.TYPE_IMAGE); const input = channel.open(); const imgTools = Cc["@mozilla.org/image/tools;1"] .getService(Ci.imgITools); diff --git a/toolkit/devtools/server/actors/styleeditor.js b/toolkit/devtools/server/actors/styleeditor.js index da667fedc56f..ba4c2cf2bff6 100644 --- a/toolkit/devtools/server/actors/styleeditor.js +++ b/toolkit/devtools/server/actors/styleeditor.js @@ -455,7 +455,7 @@ var OldStyleSheetActor = protocol.ActorClass({ } let options = { - policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET, + policy: Ci.nsIContentPolicy.TYPE_STYLESHEET, window: this.window, charset: this._getCSSCharset() }; diff --git a/toolkit/devtools/server/actors/stylesheets.js b/toolkit/devtools/server/actors/stylesheets.js index f88f9c713b48..d310f060fac6 100644 --- a/toolkit/devtools/server/actors/stylesheets.js +++ b/toolkit/devtools/server/actors/stylesheets.js @@ -606,7 +606,7 @@ var StyleSheetActor = protocol.ActorClass({ let options = { loadFromCache: true, - policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET, + policy: Ci.nsIContentPolicy.TYPE_STYLESHEET, window: this.window, charset: this._getCSSCharset() }; @@ -692,7 +692,7 @@ var StyleSheetActor = protocol.ActorClass({ url = normalize(url, this.href); let options = { loadFromCache: false, - policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET, + policy: Ci.nsIContentPolicy.TYPE_STYLESHEET, window: this.window }; let map = fetch(url, options) @@ -1020,7 +1020,7 @@ var OriginalSourceActor = protocol.ActorClass({ return promise.resolve(content); } let options = { - policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET, + policy: Ci.nsIContentPolicy.TYPE_STYLESHEET, window: this.window }; return fetch(this.url, options).then(({content}) => { diff --git a/toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm b/toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm index cb25c76a33e7..c97dd3f0c447 100644 --- a/toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm +++ b/toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm @@ -119,7 +119,7 @@ var ImageFile = { this._netUtil.asyncFetch({ uri: aURI, loadUsingSystemPrincipal: true, - contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE + contentPolicyType: Ci.nsIContentPolicy.TYPE_IMAGE }, function read_asyncFetch(aInputStream, aStatus, aRequest) { if (Components.isSuccessCode(aStatus) && aRequest instanceof Ci.nsIChannel) { let channel = aRequest.QueryInterface(Ci.nsIChannel); diff --git a/toolkit/webapps/NativeApp.jsm b/toolkit/webapps/NativeApp.jsm index d9be20a768e6..111719e4fdaf 100644 --- a/toolkit/webapps/NativeApp.jsm +++ b/toolkit/webapps/NativeApp.jsm @@ -464,7 +464,7 @@ function downloadIcon(aIconURI) { let channel = NetUtil.newChannel({ uri: aIconURI, loadingPrincipal: principal, - contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE}); + contentPolicyType: Ci.nsIContentPolicy.TYPE_IMAGE}); let { BadCertHandler } = Cu.import("resource://gre/modules/CertUtils.jsm", {}); // Pass true to avoid optional redirect-cert-checking behavior. channel.notificationCallbacks = new BadCertHandler(true); diff --git a/widget/cocoa/OSXNotificationCenter.mm b/widget/cocoa/OSXNotificationCenter.mm index 145badb3b520..a54052d6ec22 100644 --- a/widget/cocoa/OSXNotificationCenter.mm +++ b/widget/cocoa/OSXNotificationCenter.mm @@ -250,7 +250,7 @@ OSXNotificationCenter::ShowAlertNotification(const nsAString & aImageUrl, const this, nullptr, aInPrivateBrowsing ? nsIRequest::LOAD_ANONYMOUS : nsIRequest::LOAD_NORMAL, - nullptr, nsIContentPolicy::TYPE_INTERNAL_IMAGE, + nullptr, nsIContentPolicy::TYPE_IMAGE, EmptyString(), getter_AddRefs(osxni->mIconRequest)); if (NS_SUCCEEDED(rv)) { diff --git a/widget/cocoa/nsMenuItemIconX.mm b/widget/cocoa/nsMenuItemIconX.mm index 26c73101cbcf..d4ed69fe8cfb 100644 --- a/widget/cocoa/nsMenuItemIconX.mm +++ b/widget/cocoa/nsMenuItemIconX.mm @@ -310,7 +310,7 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconURI) mozilla::net::RP_Default, nullptr, loadGroup, this, nullptr, nsIRequest::LOAD_NORMAL, nullptr, - nsIContentPolicy::TYPE_INTERNAL_IMAGE, EmptyString(), + nsIContentPolicy::TYPE_IMAGE, EmptyString(), getter_AddRefs(mIconRequest)); if (NS_FAILED(rv)) return rv; diff --git a/widget/windows/WinUtils.cpp b/widget/windows/WinUtils.cpp index f8c8184966fd..1aba34da641c 100644 --- a/widget/windows/WinUtils.cpp +++ b/widget/windows/WinUtils.cpp @@ -1108,7 +1108,7 @@ nsresult AsyncFaviconDataReady::OnFaviconDataNotAvailable(void) mozIconURI, nsContentUtils::GetSystemPrincipal(), nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, - nsIContentPolicy::TYPE_INTERNAL_IMAGE); + nsIContentPolicy::TYPE_IMAGE); NS_ENSURE_SUCCESS(rv, rv); From 38fc20426edbea9a4e66d6f9769c8c2daa957181 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Mon, 21 Sep 2015 09:09:29 -0700 Subject: [PATCH 046/133] Backed out changeset 49a711e67d8b (bug 1190379) for various android crashes CLOSED TREE --- .../platforms/android/AndroidDecoderModule.cpp | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/dom/media/platforms/android/AndroidDecoderModule.cpp b/dom/media/platforms/android/AndroidDecoderModule.cpp index 12c220f4e6cd..28e9b17112d7 100644 --- a/dom/media/platforms/android/AndroidDecoderModule.cpp +++ b/dom/media/platforms/android/AndroidDecoderModule.cpp @@ -19,6 +19,7 @@ #include "nsPromiseFlatString.h" #include +#include using namespace mozilla; using namespace mozilla::gl; @@ -33,21 +34,10 @@ namespace mozilla { NS_WARNING("callback not set"); \ } -static const char* TranslateMimeType(const nsACString& aMimeType) -{ - if (aMimeType.EqualsLiteral("video/webm; codecs=vp8")) { - return "video/x-vnd.on2.vp8"; - } else if (aMimeType.EqualsLiteral("video/webm; codecs=vp9")) { - return "video/x-vnd.on2.vp9"; - } - return PromiseFlatCString(aMimeType).get(); -} - static MediaCodec::LocalRef CreateDecoder(const nsACString& aMimeType) { MediaCodec::LocalRef codec; - NS_ENSURE_SUCCESS(MediaCodec::CreateDecoderByType(TranslateMimeType(aMimeType), - &codec), nullptr); + NS_ENSURE_SUCCESS(MediaCodec::CreateDecoderByType(PromiseFlatCString(aMimeType).get(), &codec), nullptr); return codec; } @@ -297,7 +287,7 @@ AndroidDecoderModule::CreateVideoDecoder( MediaFormat::LocalRef format; NS_ENSURE_SUCCESS(MediaFormat::CreateVideoFormat( - TranslateMimeType(aConfig.mMimeType), + aConfig.mMimeType, aConfig.mDisplay.width, aConfig.mDisplay.height, &format), nullptr); From 3dadd92f0f83909ce858d7e4ab44e46be7614211 Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Sun, 20 Sep 2015 14:56:46 -0700 Subject: [PATCH 047/133] Bug 1048048 - add preload content policy types - web platform test updates (r=dveditz) --HG-- extra : source : b5abe23a4ea5934d7cb1e75e86c5b79eeb5e9f22 --- .../content-security-policy/style-src/style-src-3_4.html.ini | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 testing/web-platform/meta/content-security-policy/style-src/style-src-3_4.html.ini diff --git a/testing/web-platform/meta/content-security-policy/style-src/style-src-3_4.html.ini b/testing/web-platform/meta/content-security-policy/style-src/style-src-3_4.html.ini deleted file mode 100644 index c5f4d96d7a18..000000000000 --- a/testing/web-platform/meta/content-security-policy/style-src/style-src-3_4.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[style-src-3_4.html] - type: testharness - [Violation report status OK.] - expected: FAIL - From f3e1d73e5801f6df54ce5ff8474175e698c3593f Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Sun, 20 Sep 2015 14:56:34 -0700 Subject: [PATCH 048/133] Bug 1048048 - add preload content policy types - csp changes (r=dveditz) --HG-- extra : source : 4f91b10e8be000ee5408461c74099ca96156c0cf --- dom/security/nsCSPContext.cpp | 35 +++++++++++------------------------ dom/security/nsCSPService.cpp | 10 ++++++---- 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/dom/security/nsCSPContext.cpp b/dom/security/nsCSPContext.cpp index 6fb841b9cc78..19c55a20026c 100644 --- a/dom/security/nsCSPContext.cpp +++ b/dom/security/nsCSPContext.cpp @@ -115,6 +115,14 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType, CSPCONTEXTLOG(("nsCSPContext::ShouldLoad, aContentLocation: %s", spec.get())); } + bool isStyleOrScriptPreLoad = + (aContentType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD || + aContentType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD); + + // Since we know whether we are dealing with a preload, we have to convert + // the internal policytype ot the external policy type before moving on. + aContentType = nsContentUtils::InternalContentPolicyTypeToExternal(aContentType); + nsresult rv = NS_OK; // This ShouldLoad function is called from nsCSPService::ShouldLoad, @@ -145,29 +153,8 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType, return NS_OK; } - // This may be a load or a preload. If it is a preload, the document will - // not have been fully parsed yet, and aRequestContext will be an - // nsIDOMHTMLDocument rather than the nsIDOMHTMLElement associated with the - // resource. As a result, we cannot extract the element's corresponding - // nonce attribute, and so we cannot correctly check the nonce on a preload. - // - // Therefore, the decision returned here for a preload may be *incorrect* as - // it cannot take the nonce into account. We will still check the load, but - // we will not cache the result or report a violation. When the "real load" - // happens subsequently, we will re-check with the additional context to - // make a final decision. - // - // We don't just return false because that would block all preloads and - // degrade performance. However, we do want to block preloads that are - // clearly blocked (their urls are not whitelisted) by CSP. - - nsCOMPtr doc = do_QueryInterface(aRequestContext); - bool isPreload = doc && - (aContentType == nsIContentPolicy::TYPE_SCRIPT || - aContentType == nsIContentPolicy::TYPE_STYLESHEET); - nsAutoString nonce; - if (!isPreload) { + if (!isStyleOrScriptPreLoad) { nsCOMPtr htmlElement = do_QueryInterface(aRequestContext); if (htmlElement) { rv = htmlElement->GetAttribute(NS_LITERAL_STRING("nonce"), nonce); @@ -184,7 +171,7 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType, originalURI, nonce, wasRedirected, - isPreload, + isStyleOrScriptPreLoad, false, // allow fallback to default-src true, // send violation reports true); // send blocked URI in violation reports @@ -193,7 +180,7 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType, : nsIContentPolicy::REJECT_SERVER; // Done looping, cache any relevant result - if (cacheKey.Length() > 0 && !isPreload) { + if (cacheKey.Length() > 0 && !isStyleOrScriptPreLoad) { mShouldLoadCache.Put(cacheKey, *outDecision); } diff --git a/dom/security/nsCSPService.cpp b/dom/security/nsCSPService.cpp index e52bfcd86ab3..9a04ac43768a 100644 --- a/dom/security/nsCSPService.cpp +++ b/dom/security/nsCSPService.cpp @@ -105,8 +105,9 @@ CSPService::ShouldLoad(uint32_t aContentType, nsIPrincipal *aRequestPrincipal, int16_t *aDecision) { - MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType), - "We should only see external content policy types here."); + MOZ_ASSERT(aContentType == + nsContentUtils::InternalContentPolicyTypeToExternalOrPreload(aContentType), + "We should only see external content policy types or preloads here."); if (!aContentLocation) { return NS_ERROR_FAILURE; @@ -251,8 +252,9 @@ CSPService::ShouldProcess(uint32_t aContentType, nsIPrincipal *aRequestPrincipal, int16_t *aDecision) { - MOZ_ASSERT(aContentType == nsContentUtils::InternalContentPolicyTypeToExternal(aContentType), - "We should only see external content policy types here."); + MOZ_ASSERT(aContentType == + nsContentUtils::InternalContentPolicyTypeToExternalOrPreload(aContentType), + "We should only see external content policy types or preloads here."); if (!aContentLocation) return NS_ERROR_FAILURE; From 2fac10d1231282c1d60861f90326553217b47c19 Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Sun, 20 Sep 2015 14:56:21 -0700 Subject: [PATCH 049/133] Bug 1048048 - add preload content policy types for scripts (r=baku) --HG-- extra : source : 450d4a13c90e95a58caa398e4fcc0a71f4800071 --- dom/base/nsScriptLoader.cpp | 24 +++++++++++++++++------- dom/base/nsScriptLoader.h | 6 ++++-- dom/media/IdpSandbox.jsm | 2 +- dom/workers/ServiceWorkerScriptCache.cpp | 4 ++-- dom/xul/XULDocument.cpp | 3 ++- 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/dom/base/nsScriptLoader.cpp b/dom/base/nsScriptLoader.cpp index 1b39e395d28a..b58c7b8622bb 100644 --- a/dom/base/nsScriptLoader.cpp +++ b/dom/base/nsScriptLoader.cpp @@ -223,10 +223,15 @@ nsresult nsScriptLoader::CheckContentPolicy(nsIDocument* aDocument, nsISupports *aContext, nsIURI *aURI, - const nsAString &aType) + const nsAString &aType, + bool aIsPreLoad) { + nsContentPolicyType contentPolicyType = aIsPreLoad + ? nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD + : nsIContentPolicy::TYPE_INTERNAL_SCRIPT; + int16_t shouldLoad = nsIContentPolicy::ACCEPT; - nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_SCRIPT, + nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType, aURI, aDocument->NodePrincipal(), aContext, @@ -249,7 +254,8 @@ nsresult nsScriptLoader::ShouldLoadScript(nsIDocument* aDocument, nsISupports* aContext, nsIURI* aURI, - const nsAString &aType) + const nsAString &aType, + bool aIsPreLoad) { // Check that the containing page is allowed to load this URI. nsresult rv = nsContentUtils::GetSecurityManager()-> @@ -259,7 +265,7 @@ nsScriptLoader::ShouldLoadScript(nsIDocument* aDocument, NS_ENSURE_SUCCESS(rv, rv); // After the security manager, the content-policy stuff gets a veto - rv = CheckContentPolicy(aDocument, aContext, aURI, aType); + rv = CheckContentPolicy(aDocument, aContext, aURI, aType, aIsPreLoad); if (NS_FAILED(rv)) { return rv; } @@ -274,7 +280,7 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType, nsISupports *context = aRequest->mElement.get() ? static_cast(aRequest->mElement.get()) : static_cast(mDocument); - nsresult rv = ShouldLoadScript(mDocument, context, aRequest->mURI, aType); + nsresult rv = ShouldLoadScript(mDocument, context, aRequest->mURI, aType, aRequest->IsPreload()); if (NS_FAILED(rv)) { return rv; } @@ -296,12 +302,16 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType, return NS_OK; } + nsContentPolicyType contentPolicyType = aRequest->IsPreload() + ? nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD + : nsIContentPolicy::TYPE_INTERNAL_SCRIPT; + nsCOMPtr channel; rv = NS_NewChannel(getter_AddRefs(channel), aRequest->mURI, mDocument, nsILoadInfo::SEC_NORMAL, - nsIContentPolicy::TYPE_INTERNAL_SCRIPT, + contentPolicyType, loadGroup, prompter, nsIRequest::LOAD_NORMAL | @@ -530,7 +540,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) if (elementCharset.Equals(preloadCharset) && ourCORSMode == request->mCORSMode && ourRefPolicy == request->mReferrerPolicy) { - rv = CheckContentPolicy(mDocument, aElement, request->mURI, type); + rv = CheckContentPolicy(mDocument, aElement, request->mURI, type, false); NS_ENSURE_SUCCESS(rv, false); } else { // Drop the preload diff --git a/dom/base/nsScriptLoader.h b/dom/base/nsScriptLoader.h index b62f229a4e95..468f50f5d5d1 100644 --- a/dom/base/nsScriptLoader.h +++ b/dom/base/nsScriptLoader.h @@ -354,7 +354,8 @@ public: static nsresult ShouldLoadScript(nsIDocument* aDocument, nsISupports* aContext, nsIURI* aURI, - const nsAString &aType); + const nsAString &aType, + bool aIsPreLoad); /** * Starts deferring deferred scripts and puts them in the mDeferredRequests @@ -435,7 +436,8 @@ private: static nsresult CheckContentPolicy(nsIDocument* aDocument, nsISupports *aContext, nsIURI *aURI, - const nsAString &aType); + const nsAString &aType, + bool aIsPreLoad); /** * Start a load for aRequest's URI. diff --git a/dom/media/IdpSandbox.jsm b/dom/media/IdpSandbox.jsm index 96b12eeebab2..6e600dcddf35 100644 --- a/dom/media/IdpSandbox.jsm +++ b/dom/media/IdpSandbox.jsm @@ -50,7 +50,7 @@ ResourceLoader.load = function(uri, doc) { // the '2' identifies this as a script load let ioChannel = ioService.newChannelFromURI2(uri, doc, doc.nodePrincipal, systemPrincipal, 0, - Ci.nsIContentPolicy.TYPE_SCRIPT); + Ci.nsIContentPolicy.TYPE_INTERNAL_SCRIPT); ioChannel.loadGroup = doc.documentLoadGroup.QueryInterface(Ci.nsILoadGroup); ioChannel.notificationCallbacks = new RedirectHttpsOnly(); diff --git a/dom/workers/ServiceWorkerScriptCache.cpp b/dom/workers/ServiceWorkerScriptCache.cpp index 9f2fb7494f49..1c44aa1ed83b 100644 --- a/dom/workers/ServiceWorkerScriptCache.cpp +++ b/dom/workers/ServiceWorkerScriptCache.cpp @@ -111,12 +111,12 @@ public: } // Note that because there is no "serviceworker" RequestContext type, we can - // use the external TYPE_SCRIPT content policy types when loading a service + // use the TYPE_INTERNAL_SCRIPT content policy types when loading a service // worker. rv = NS_NewChannel(getter_AddRefs(mChannel), uri, aPrincipal, nsILoadInfo::SEC_NORMAL, - nsIContentPolicy::TYPE_SCRIPT, + nsIContentPolicy::TYPE_INTERNAL_SCRIPT, loadGroup); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; diff --git a/dom/xul/XULDocument.cpp b/dom/xul/XULDocument.cpp index 75b67a290ee1..172c9283a789 100644 --- a/dom/xul/XULDocument.cpp +++ b/dom/xul/XULDocument.cpp @@ -3250,7 +3250,8 @@ XULDocument::LoadScript(nsXULPrototypeScript* aScriptProto, bool* aBlock) this, static_cast(this), aScriptProto->mSrcURI, - NS_LITERAL_STRING("application/x-javascript")); + NS_LITERAL_STRING("application/x-javascript"), + false); if (NS_FAILED(rv)) { *aBlock = false; return rv; From c1259a401c17bde053dd9d58e44c147b5a5c3bcc Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Sun, 20 Sep 2015 14:56:10 -0700 Subject: [PATCH 050/133] Bug 1048048 - add preload content policy types for stylesheets (r=cam) --HG-- extra : source : 6a727c40eb68d4b84d64d1e173b7401a982fda23 --- dom/base/nsDocument.cpp | 2 +- dom/xbl/nsXBLResourceLoader.cpp | 2 +- dom/xslt/xslt/txMozillaStylesheetCompiler.cpp | 6 +-- editor/libeditor/nsHTMLEditor.cpp | 2 +- layout/style/Loader.cpp | 46 ++++++++++++------- layout/style/Loader.h | 11 ++++- toolkit/devtools/server/actors/styleeditor.js | 2 +- toolkit/devtools/server/actors/stylesheets.js | 6 +-- 8 files changed, 48 insertions(+), 29 deletions(-) diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index ec065056449d..eddff9031aec 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -9883,7 +9883,7 @@ nsDocument::PreloadStyle(nsIURI* uri, const nsAString& charset, nsCOMPtr obs = new StubCSSLoaderObserver(); // Charset names are always ASCII. - CSSLoader()->LoadSheet(uri, NodePrincipal(), + CSSLoader()->LoadSheet(uri, true, NodePrincipal(), NS_LossyConvertUTF16toASCII(charset), obs, Element::StringToCORSMode(aCrossOriginAttr), diff --git a/dom/xbl/nsXBLResourceLoader.cpp b/dom/xbl/nsXBLResourceLoader.cpp index 984efdf313da..ba2d7701b2e3 100644 --- a/dom/xbl/nsXBLResourceLoader.cpp +++ b/dom/xbl/nsXBLResourceLoader.cpp @@ -151,7 +151,7 @@ nsXBLResourceLoader::LoadResources(bool* aResult) } else { - rv = cssLoader->LoadSheet(url, docPrincipal, EmptyCString(), this); + rv = cssLoader->LoadSheet(url, false, docPrincipal, EmptyCString(), this); if (NS_SUCCEEDED(rv)) ++mPendingSheets; } diff --git a/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp b/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp index eeefcff1808c..a3955414c533 100644 --- a/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp +++ b/dom/xslt/xslt/txMozillaStylesheetCompiler.cpp @@ -424,7 +424,7 @@ txCompileObserver::loadURI(const nsAString& aUri, // Content Policy int16_t shouldLoad = nsIContentPolicy::ACCEPT; - rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET, + rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_STYLESHEET, uri, referrerPrincipal, mLoaderDocument, @@ -524,7 +524,7 @@ TX_LoadSheet(nsIURI* aUri, txMozillaXSLTProcessor* aProcessor, // Content Policy int16_t shouldLoad = nsIContentPolicy::ACCEPT; nsresult rv = - NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET, + NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_STYLESHEET, aUri, principal, aLoaderDocument, @@ -666,7 +666,7 @@ txSyncCompileObserver::loadURI(const nsAString& aUri, // Content Policy int16_t shouldLoad = nsIContentPolicy::ACCEPT; - rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET, + rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_STYLESHEET, uri, referrerPrincipal, nullptr, diff --git a/editor/libeditor/nsHTMLEditor.cpp b/editor/libeditor/nsHTMLEditor.cpp index e46ad9851354..9092ea10467c 100644 --- a/editor/libeditor/nsHTMLEditor.cpp +++ b/editor/libeditor/nsHTMLEditor.cpp @@ -2791,7 +2791,7 @@ nsHTMLEditor::ReplaceStyleSheet(const nsAString& aURL) NS_ENSURE_SUCCESS(rv, rv); return ps->GetDocument()->CSSLoader()-> - LoadSheet(uaURI, nullptr, EmptyCString(), this); + LoadSheet(uaURI, false, nullptr, EmptyCString(), this); } NS_IMETHODIMP diff --git a/layout/style/Loader.cpp b/layout/style/Loader.cpp index 54e697316c42..7439d6b4ca90 100644 --- a/layout/style/Loader.cpp +++ b/layout/style/Loader.cpp @@ -607,7 +607,7 @@ Loader::SetPreferredSheet(const nsAString& aTitle) mDatasToNotifyOn += arr.Length(); for (uint32_t i = 0; i < arr.Length(); ++i) { --mDatasToNotifyOn; - LoadSheet(arr[i], eSheetNeedsParser); + LoadSheet(arr[i], eSheetNeedsParser, false); } } @@ -1025,7 +1025,8 @@ Loader::ObsoleteSheet(nsIURI* aURI) nsresult Loader::CheckLoadAllowed(nsIPrincipal* aSourcePrincipal, nsIURI* aTargetURI, - nsISupports* aContext) + nsISupports* aContext, + bool aIsPreload) { LOG(("css::Loader::CheckLoadAllowed")); @@ -1044,9 +1045,12 @@ Loader::CheckLoadAllowed(nsIPrincipal* aSourcePrincipal, LOG((" Passed security check")); // Check with content policy + nsContentPolicyType contentPolicyType = + aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD + : nsIContentPolicy::TYPE_INTERNAL_STYLESHEET; int16_t shouldLoad = nsIContentPolicy::ACCEPT; - rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET, + rv = NS_CheckContentLoadPolicy(contentPolicyType, aTargetURI, aSourcePrincipal, aContext, @@ -1411,7 +1415,9 @@ Loader::InsertChildSheet(CSSStyleSheet* aSheet, * a new load is kicked off asynchronously. */ nsresult -Loader::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState) +Loader::LoadSheet(SheetLoadData* aLoadData, + StyleSheetState aSheetState, + bool aIsPreload) { LOG(("css::Loader::LoadSheet")); NS_PRECONDITION(aLoadData, "Need a load data"); @@ -1561,7 +1567,7 @@ Loader::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState) mSheets->mPendingDatas.Remove(&key); LOG((" Forcing load of pending data")); - return LoadSheet(existingData, eSheetNeedsParser); + return LoadSheet(existingData, eSheetNeedsParser, aIsPreload); } // All done here; once the load completes we'll be marked complete // automatically @@ -1583,6 +1589,10 @@ Loader::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState) securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL; } + nsContentPolicyType contentPolicyType = + aIsPreload ? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD + : nsIContentPolicy::TYPE_INTERNAL_STYLESHEET; + nsCOMPtr channel; // Note we are calling NS_NewChannelWithTriggeringPrincipal here with a node // and a principal. This is because of a case where the node is the document @@ -1594,7 +1604,7 @@ Loader::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState) aLoadData->mRequestingNode, triggeringPrincipal, securityFlags, - nsIContentPolicy::TYPE_STYLESHEET, + contentPolicyType, loadGroup, nullptr, // aCallbacks nsIChannel::LOAD_NORMAL | @@ -1610,7 +1620,7 @@ Loader::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState) aLoadData->mURI, triggeringPrincipal, securityFlags, - nsIContentPolicy::TYPE_STYLESHEET, + contentPolicyType, loadGroup, nullptr, // aCallbacks nsIChannel::LOAD_NORMAL | @@ -2044,7 +2054,7 @@ Loader::LoadStyleLink(nsIContent* aElement, if (!context) { context = mDocument; } - nsresult rv = CheckLoadAllowed(principal, aURL, context); + nsresult rv = CheckLoadAllowed(principal, aURL, context, false); if (NS_FAILED(rv)) return rv; LOG((" Passed load check")); @@ -2100,7 +2110,7 @@ Loader::LoadStyleLink(nsIContent* aElement, } // Load completion will free the data - rv = LoadSheet(data, state); + rv = LoadSheet(data, state, false); NS_ENSURE_SUCCESS(rv, rv); data->mMustNotify = true; @@ -2178,7 +2188,7 @@ Loader::LoadChildSheet(CSSStyleSheet* aParentSheet, } nsIPrincipal* principal = aParentSheet->Principal(); - nsresult rv = CheckLoadAllowed(principal, aURL, context); + nsresult rv = CheckLoadAllowed(principal, aURL, context, false); if (NS_FAILED(rv)) return rv; LOG((" Passed load check")); @@ -2242,7 +2252,7 @@ Loader::LoadChildSheet(CSSStyleSheet* aParentSheet, bool syncLoad = data->mSyncLoad; // Load completion will release the data - rv = LoadSheet(data, state); + rv = LoadSheet(data, state, false); NS_ENSURE_SUCCESS(rv, rv); // If syncLoad is true, |data| will be deleted by now. @@ -2258,7 +2268,7 @@ Loader::LoadSheetSync(nsIURI* aURL, bool aAllowUnsafeRules, CSSStyleSheet** aSheet) { LOG(("css::Loader::LoadSheetSync")); - return InternalLoadNonDocumentSheet(aURL, aAllowUnsafeRules, + return InternalLoadNonDocumentSheet(aURL, false, aAllowUnsafeRules, aUseSystemPrincipal, nullptr, EmptyCString(), aSheet, nullptr); } @@ -2272,13 +2282,14 @@ Loader::LoadSheet(nsIURI* aURL, { LOG(("css::Loader::LoadSheet(aURL, aObserver, aSheet) api call")); NS_PRECONDITION(aSheet, "aSheet is null"); - return InternalLoadNonDocumentSheet(aURL, false, false, + return InternalLoadNonDocumentSheet(aURL, false, false, false, aOriginPrincipal, aCharset, aSheet, aObserver); } nsresult Loader::LoadSheet(nsIURI* aURL, + bool aIsPreload, nsIPrincipal* aOriginPrincipal, const nsCString& aCharset, nsICSSLoaderObserver* aObserver, @@ -2287,7 +2298,7 @@ Loader::LoadSheet(nsIURI* aURL, const nsAString& aIntegrity) { LOG(("css::Loader::LoadSheet(aURL, aObserver) api call")); - return InternalLoadNonDocumentSheet(aURL, false, false, + return InternalLoadNonDocumentSheet(aURL, aIsPreload, false, false, aOriginPrincipal, aCharset, nullptr, aObserver, aCORSMode, aReferrerPolicy, aIntegrity); @@ -2295,6 +2306,7 @@ Loader::LoadSheet(nsIURI* aURL, nsresult Loader::InternalLoadNonDocumentSheet(nsIURI* aURL, + bool aIsPreload, bool aAllowUnsafeRules, bool aUseSystemPrincipal, nsIPrincipal* aOriginPrincipal, @@ -2322,7 +2334,7 @@ Loader::InternalLoadNonDocumentSheet(nsIURI* aURL, return NS_ERROR_NOT_AVAILABLE; } - nsresult rv = CheckLoadAllowed(aOriginPrincipal, aURL, mDocument); + nsresult rv = CheckLoadAllowed(aOriginPrincipal, aURL, mDocument, aIsPreload); if (NS_FAILED(rv)) { return rv; } @@ -2357,7 +2369,7 @@ Loader::InternalLoadNonDocumentSheet(nsIURI* aURL, aOriginPrincipal, mDocument); NS_ADDREF(data); - rv = LoadSheet(data, state); + rv = LoadSheet(data, state, aIsPreload); NS_ENSURE_SUCCESS(rv, rv); if (aSheet) { @@ -2549,7 +2561,7 @@ Loader::StartAlternateLoads() mDatasToNotifyOn += arr.Length(); for (uint32_t i = 0; i < arr.Length(); ++i) { --mDatasToNotifyOn; - LoadSheet(arr[i], eSheetNeedsParser); + LoadSheet(arr[i], eSheetNeedsParser, false); } } diff --git a/layout/style/Loader.h b/layout/style/Loader.h index cd17ebeb66ee..f4da96e4c079 100644 --- a/layout/style/Loader.h +++ b/layout/style/Loader.h @@ -317,6 +317,7 @@ public: * not-yet-loaded sheet. */ nsresult LoadSheet(nsIURI* aURL, + bool aIsPreload, nsIPrincipal* aOriginPrincipal, const nsCString& aCharset, nsICSSLoaderObserver* aObserver, @@ -405,9 +406,12 @@ private: // Note: null aSourcePrincipal indicates that the content policy and // CheckLoadURI checks should be skipped. + // aIsPreload indicates whether the html parser preloads that + // stylesheet or if it is a regular load. nsresult CheckLoadAllowed(nsIPrincipal* aSourcePrincipal, nsIURI* aTargetURI, - nsISupports* aContext); + nsISupports* aContext, + bool aIsPreload); // For inline style, the aURI param is null, but the aLinkingContent @@ -446,6 +450,7 @@ private: ImportRule* aParentRule); nsresult InternalLoadNonDocumentSheet(nsIURI* aURL, + bool aIsPreload, bool aAllowUnsafeRules, bool aUseSystemPrincipal, nsIPrincipal* aOriginPrincipal, @@ -477,7 +482,9 @@ private: // Note: LoadSheet is responsible for releasing aLoadData and setting the // sheet to complete on failure. - nsresult LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState); + nsresult LoadSheet(SheetLoadData* aLoadData, + StyleSheetState aSheetState, + bool aIsPreLoad); // Parse the stylesheet in aLoadData. The sheet data comes from aInput. // Set aCompleted to true if the parse finished, false otherwise (e.g. if the diff --git a/toolkit/devtools/server/actors/styleeditor.js b/toolkit/devtools/server/actors/styleeditor.js index ba4c2cf2bff6..da667fedc56f 100644 --- a/toolkit/devtools/server/actors/styleeditor.js +++ b/toolkit/devtools/server/actors/styleeditor.js @@ -455,7 +455,7 @@ var OldStyleSheetActor = protocol.ActorClass({ } let options = { - policy: Ci.nsIContentPolicy.TYPE_STYLESHEET, + policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET, window: this.window, charset: this._getCSSCharset() }; diff --git a/toolkit/devtools/server/actors/stylesheets.js b/toolkit/devtools/server/actors/stylesheets.js index d310f060fac6..f88f9c713b48 100644 --- a/toolkit/devtools/server/actors/stylesheets.js +++ b/toolkit/devtools/server/actors/stylesheets.js @@ -606,7 +606,7 @@ var StyleSheetActor = protocol.ActorClass({ let options = { loadFromCache: true, - policy: Ci.nsIContentPolicy.TYPE_STYLESHEET, + policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET, window: this.window, charset: this._getCSSCharset() }; @@ -692,7 +692,7 @@ var StyleSheetActor = protocol.ActorClass({ url = normalize(url, this.href); let options = { loadFromCache: false, - policy: Ci.nsIContentPolicy.TYPE_STYLESHEET, + policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET, window: this.window }; let map = fetch(url, options) @@ -1020,7 +1020,7 @@ var OriginalSourceActor = protocol.ActorClass({ return promise.resolve(content); } let options = { - policy: Ci.nsIContentPolicy.TYPE_STYLESHEET, + policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET, window: this.window }; return fetch(this.url, options).then(({content}) => { From 9f1e9e2eaa1ac066c748a6f1c51e19bb5ef952b8 Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Sun, 20 Sep 2015 14:55:59 -0700 Subject: [PATCH 051/133] Bug 1048048 - add preload content policy types for images (r=seth) --HG-- extra : source : 88c2333ff7455b6988eb8d6ccc5e92b414a7ccf8 --- browser/modules/ContentLinkHandler.jsm | 2 +- browser/modules/WindowsPreviewPerTab.jsm | 2 +- dom/base/nsContentUtils.h | 8 ++++---- dom/base/nsDocument.cpp | 6 ++++-- dom/base/nsImageLoadingContent.cpp | 2 +- dom/base/nsObjectLoadingContent.cpp | 2 +- dom/html/ImageDocument.cpp | 2 +- embedding/browser/nsContextMenuInfo.cpp | 2 +- image/imgLoader.cpp | 4 ++-- layout/generic/nsImageFrame.cpp | 2 +- toolkit/components/places/AsyncFaviconHelpers.cpp | 2 +- toolkit/components/places/nsAnnoProtocolHandler.cpp | 2 +- toolkit/components/places/nsFaviconService.cpp | 2 +- .../browser/browser_favicon_setAndFetchFaviconForPage.js | 2 +- .../tests/favicons/test_moz-anno_favicon_mime_type.js | 6 +++--- toolkit/components/search/nsSearchService.js | 2 +- toolkit/devtools/gcli/commands/screenshot.js | 2 +- .../internal/LightweightThemeImageOptimizer.jsm | 2 +- toolkit/webapps/NativeApp.jsm | 2 +- widget/cocoa/OSXNotificationCenter.mm | 2 +- widget/cocoa/nsMenuItemIconX.mm | 2 +- widget/windows/WinUtils.cpp | 2 +- 22 files changed, 31 insertions(+), 29 deletions(-) diff --git a/browser/modules/ContentLinkHandler.jsm b/browser/modules/ContentLinkHandler.jsm index 46cf75a25e56..9d4da688984b 100644 --- a/browser/modules/ContentLinkHandler.jsm +++ b/browser/modules/ContentLinkHandler.jsm @@ -164,7 +164,7 @@ this.ContentLinkHandler = { } // Security says okay, now ask content policy - if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_IMAGE, + if (contentPolicy.shouldLoad(Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE, uri, targetDoc.documentURIObject, aLink, aLink.type, null) != Ci.nsIContentPolicy.ACCEPT) diff --git a/browser/modules/WindowsPreviewPerTab.jsm b/browser/modules/WindowsPreviewPerTab.jsm index 86623de5fe88..8f32ac8a4db6 100644 --- a/browser/modules/WindowsPreviewPerTab.jsm +++ b/browser/modules/WindowsPreviewPerTab.jsm @@ -79,7 +79,7 @@ function _imageFromURI(doc, uri, privateMode, callback) { null, // aLoadingPrincipal null, // aTriggeringPrincipal Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_IMAGE); + Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); try { channel.QueryInterface(Ci.nsIPrivateBrowsingChannel); channel.setPrivate(privateMode); diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index 5182181b2886..fcbaae66cfad 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -624,7 +624,7 @@ public: * @param aContext the context the image is loaded in (eg an element) * @param aLoadingDocument the document we belong to * @param aLoadingPrincipal the principal doing the load - * @param [aContentPolicyType=nsIContentPolicy::TYPE_IMAGE] (Optional) + * @param [aContentPolicyType=nsIContentPolicy::TYPE_INTERNAL_IMAGE] (Optional) * The CP content type to use * @param aImageBlockingStatus the nsIContentPolicy blocking status for this * image. This will be set even if a security check fails for the @@ -640,7 +640,7 @@ public: nsIDocument* aLoadingDocument, nsIPrincipal* aLoadingPrincipal, int16_t* aImageBlockingStatus = nullptr, - uint32_t aContentPolicyType = nsIContentPolicy::TYPE_IMAGE); + uint32_t aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE); /** * Returns true if objects in aDocument shouldn't initiate image loads. @@ -660,7 +660,7 @@ public: * creation * @param aObserver the observer for the image load * @param aLoadFlags the load flags to use. See nsIRequest - * @param [aContentPolicyType=nsIContentPolicy::TYPE_IMAGE] (Optional) + * @param [aContentPolicyType=nsIContentPolicy::TYPE_INTERNAL_IMAGE] (Optional) * The CP content type to use * @return the imgIRequest for the image load */ @@ -673,7 +673,7 @@ public: int32_t aLoadFlags, const nsAString& initiatorType, imgRequestProxy** aRequest, - uint32_t aContentPolicyType = nsIContentPolicy::TYPE_IMAGE); + uint32_t aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE); /** * Obtain an image loader that respects the given document/channel's privacy status. diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index eddff9031aec..d9003637933c 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -9739,7 +9739,8 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr, int16_t blockingStatus; if (nsContentUtils::IsImageInCache(uri, static_cast(this)) || !nsContentUtils::CanLoadImage(uri, static_cast(this), - this, NodePrincipal(), &blockingStatus)) { + this, NodePrincipal(), &blockingStatus, + nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD)) { return; } @@ -9769,7 +9770,8 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr, nullptr, // no observer loadFlags, NS_LITERAL_STRING("img"), - getter_AddRefs(request)); + getter_AddRefs(request), + nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD); // Pin image-reference to avoid evicting it from the img-cache before // the "real" load occurs. Unpinned in DispatchContentLoadedEvents and diff --git a/dom/base/nsImageLoadingContent.cpp b/dom/base/nsImageLoadingContent.cpp index 626671a56b3a..d91fc96b928e 100644 --- a/dom/base/nsImageLoadingContent.cpp +++ b/dom/base/nsImageLoadingContent.cpp @@ -589,7 +589,7 @@ nsImageLoadingContent::PolicyTypeForLoad(ImageLoadType aImageLoadType) MOZ_ASSERT(aImageLoadType == eImageLoadType_Normal, "Unknown ImageLoadType type in PolicyTypeForLoad"); - return nsIContentPolicy::TYPE_IMAGE; + return nsIContentPolicy::TYPE_INTERNAL_IMAGE; } int32_t diff --git a/dom/base/nsObjectLoadingContent.cpp b/dom/base/nsObjectLoadingContent.cpp index 1767895fa595..5f5f670d1cb7 100644 --- a/dom/base/nsObjectLoadingContent.cpp +++ b/dom/base/nsObjectLoadingContent.cpp @@ -1530,7 +1530,7 @@ nsObjectLoadingContent::CheckProcessPolicy(int16_t *aContentPolicy) int32_t objectType; switch (mType) { case eType_Image: - objectType = nsIContentPolicy::TYPE_IMAGE; + objectType = nsIContentPolicy::TYPE_INTERNAL_IMAGE; break; case eType_Document: objectType = nsIContentPolicy::TYPE_DOCUMENT; diff --git a/dom/html/ImageDocument.cpp b/dom/html/ImageDocument.cpp index 3c7ce4327fe4..46a10bad8c62 100644 --- a/dom/html/ImageDocument.cpp +++ b/dom/html/ImageDocument.cpp @@ -99,7 +99,7 @@ ImageListener::OnStartRequest(nsIRequest* request, nsISupports *ctxt) } int16_t decision = nsIContentPolicy::ACCEPT; - nsresult rv = NS_CheckContentProcessPolicy(nsIContentPolicy::TYPE_IMAGE, + nsresult rv = NS_CheckContentProcessPolicy(nsIContentPolicy::TYPE_INTERNAL_IMAGE, channelURI, channelPrincipal, domWindow->GetFrameElementInternal(), diff --git a/embedding/browser/nsContextMenuInfo.cpp b/embedding/browser/nsContextMenuInfo.cpp index 3df8c9fd80b5..aa36e3d44bfc 100644 --- a/embedding/browser/nsContextMenuInfo.cpp +++ b/embedding/browser/nsContextMenuInfo.cpp @@ -294,7 +294,7 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode* aDOMNode, return il->LoadImage(bgUri, nullptr, nullptr, doc->GetReferrerPolicy(), principal, nullptr, nullptr, nullptr, nsIRequest::LOAD_NORMAL, - nullptr, nsIContentPolicy::TYPE_IMAGE, + nullptr, nsIContentPolicy::TYPE_INTERNAL_IMAGE, EmptyString(), aRequest); } } diff --git a/image/imgLoader.cpp b/image/imgLoader.cpp index f3dbbec3b60c..806172c8373e 100644 --- a/image/imgLoader.cpp +++ b/image/imgLoader.cpp @@ -618,7 +618,7 @@ ShouldLoadCachedImage(imgRequest* aImgRequest, nsresult rv; int16_t decision = nsIContentPolicy::REJECT_REQUEST; - rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_IMAGE, + rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_IMAGE, contentLocation, aLoadingPrincipal, aLoadingContext, @@ -1981,7 +1981,7 @@ imgLoader::LoadImageXPCOM(nsIURI* aURI, { // Optional parameter, so defaults to 0 (== TYPE_INVALID) if (!aContentPolicyType) { - aContentPolicyType = nsIContentPolicy::TYPE_IMAGE; + aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE; } imgRequestProxy* proxy; ReferrerPolicy refpol = ReferrerPolicyFromString(aReferrerPolicy); diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 534d0b570aa3..9f848db2187a 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -2204,7 +2204,7 @@ nsImageFrame::LoadIcon(const nsAString& aSpec, // For icon loads, we don't need to merge with the loadgroup flags nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL; - nsContentPolicyType contentPolicyType = nsIContentPolicy::TYPE_IMAGE; + nsContentPolicyType contentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE; return il->LoadImage(realURI, /* icon URI */ nullptr, /* initial document URI; this is only diff --git a/toolkit/components/places/AsyncFaviconHelpers.cpp b/toolkit/components/places/AsyncFaviconHelpers.cpp index 7b136e447b55..b57579f85a3e 100644 --- a/toolkit/components/places/AsyncFaviconHelpers.cpp +++ b/toolkit/components/places/AsyncFaviconHelpers.cpp @@ -532,7 +532,7 @@ AsyncFetchAndSetIconFromNetwork::Run() iconURI, nsContentUtils::GetSystemPrincipal(), nsILoadInfo::SEC_NORMAL, - nsIContentPolicy::TYPE_IMAGE); + nsIContentPolicy::TYPE_INTERNAL_IMAGE); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr listenerRequestor = diff --git a/toolkit/components/places/nsAnnoProtocolHandler.cpp b/toolkit/components/places/nsAnnoProtocolHandler.cpp index c0b3823a7636..e3b7a5bf92f6 100644 --- a/toolkit/components/places/nsAnnoProtocolHandler.cpp +++ b/toolkit/components/places/nsAnnoProtocolHandler.cpp @@ -53,7 +53,7 @@ GetDefaultIcon(nsIChannel **aChannel) defaultIconURI, nsContentUtils::GetSystemPrincipal(), nsILoadInfo::SEC_NORMAL, - nsIContentPolicy::TYPE_IMAGE); + nsIContentPolicy::TYPE_INTERNAL_IMAGE); } //////////////////////////////////////////////////////////////////////////////// diff --git a/toolkit/components/places/nsFaviconService.cpp b/toolkit/components/places/nsFaviconService.cpp index 1fe0a5e353f7..6a9f28b18d83 100644 --- a/toolkit/components/places/nsFaviconService.cpp +++ b/toolkit/components/places/nsFaviconService.cpp @@ -330,7 +330,7 @@ nsFaviconService::ReplaceFaviconDataFromDataURL(nsIURI* aFaviconURI, nullptr, // aTriggeringPrincipal nullptr, // aLoadingNode nsILoadInfo::SEC_NORMAL, - nsIContentPolicy::TYPE_IMAGE); + nsIContentPolicy::TYPE_INTERNAL_IMAGE); nsCOMPtr channel; rv = protocolHandler->NewChannel2(dataURI, loadInfo, getter_AddRefs(channel)); diff --git a/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage.js b/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage.js index 98332260efb1..7e5e61833897 100644 --- a/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage.js +++ b/toolkit/components/places/tests/browser/browser_favicon_setAndFetchFaviconForPage.js @@ -33,7 +33,7 @@ function test() { NetUtil.asyncFetch({ uri: favIconLocation, loadUsingSystemPrincipal: true, - contentPolicyType: Ci.nsIContentPolicy.TYPE_IMAGE + contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE }, function(inputStream, status) { if (!Components.isSuccessCode(status)) { ok(false, "Could not get the icon file"); diff --git a/toolkit/components/places/tests/favicons/test_moz-anno_favicon_mime_type.js b/toolkit/components/places/tests/favicons/test_moz-anno_favicon_mime_type.js index 26e20f1329ed..06584fc34653 100644 --- a/toolkit/components/places/tests/favicons/test_moz-anno_favicon_mime_type.js +++ b/toolkit/components/places/tests/favicons/test_moz-anno_favicon_mime_type.js @@ -63,7 +63,7 @@ function run_test() Services.scriptSecurityManager.getSystemPrincipal(), null, // aTriggeringPrincipal Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_IMAGE); + Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); channel.asyncOpen(new streamListener("image/png"), null); do_test_pending(); @@ -76,7 +76,7 @@ function run_test() Services.scriptSecurityManager.getSystemPrincipal(), null, // aTriggeringPrincipal Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_IMAGE); + Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); channel.asyncOpen(new streamListener("image/png"), null); do_test_pending(); @@ -94,7 +94,7 @@ function run_test() Services.scriptSecurityManager.getSystemPrincipal(), null, // aTriggeringPrincipal Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_IMAGE); + Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); channel.asyncOpen(new streamListener("image/png"), null); do_test_pending(); } diff --git a/toolkit/components/search/nsSearchService.js b/toolkit/components/search/nsSearchService.js index 1e095208bdc9..bcf6f43a0d72 100644 --- a/toolkit/components/search/nsSearchService.js +++ b/toolkit/components/search/nsSearchService.js @@ -2081,7 +2081,7 @@ Engine.prototype = { Services.scriptSecurityManager.getSystemPrincipal(), null, // aTriggeringPrincipal Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_IMAGE); + Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); let iconLoadCallback = function (aByteArray, aEngine) { // This callback may run after we've already set a preferred icon, diff --git a/toolkit/devtools/gcli/commands/screenshot.js b/toolkit/devtools/gcli/commands/screenshot.js index 44caace02750..1f9b91a928a8 100644 --- a/toolkit/devtools/gcli/commands/screenshot.js +++ b/toolkit/devtools/gcli/commands/screenshot.js @@ -357,7 +357,7 @@ function saveToClipboard(context, reply) { Services.scriptSecurityManager.getSystemPrincipal(), null, // aTriggeringPrincipal Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_IMAGE); + Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE); const input = channel.open(); const imgTools = Cc["@mozilla.org/image/tools;1"] .getService(Ci.imgITools); diff --git a/toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm b/toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm index c97dd3f0c447..cb25c76a33e7 100644 --- a/toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm +++ b/toolkit/mozapps/extensions/internal/LightweightThemeImageOptimizer.jsm @@ -119,7 +119,7 @@ var ImageFile = { this._netUtil.asyncFetch({ uri: aURI, loadUsingSystemPrincipal: true, - contentPolicyType: Ci.nsIContentPolicy.TYPE_IMAGE + contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE }, function read_asyncFetch(aInputStream, aStatus, aRequest) { if (Components.isSuccessCode(aStatus) && aRequest instanceof Ci.nsIChannel) { let channel = aRequest.QueryInterface(Ci.nsIChannel); diff --git a/toolkit/webapps/NativeApp.jsm b/toolkit/webapps/NativeApp.jsm index 111719e4fdaf..d9be20a768e6 100644 --- a/toolkit/webapps/NativeApp.jsm +++ b/toolkit/webapps/NativeApp.jsm @@ -464,7 +464,7 @@ function downloadIcon(aIconURI) { let channel = NetUtil.newChannel({ uri: aIconURI, loadingPrincipal: principal, - contentPolicyType: Ci.nsIContentPolicy.TYPE_IMAGE}); + contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE}); let { BadCertHandler } = Cu.import("resource://gre/modules/CertUtils.jsm", {}); // Pass true to avoid optional redirect-cert-checking behavior. channel.notificationCallbacks = new BadCertHandler(true); diff --git a/widget/cocoa/OSXNotificationCenter.mm b/widget/cocoa/OSXNotificationCenter.mm index a54052d6ec22..145badb3b520 100644 --- a/widget/cocoa/OSXNotificationCenter.mm +++ b/widget/cocoa/OSXNotificationCenter.mm @@ -250,7 +250,7 @@ OSXNotificationCenter::ShowAlertNotification(const nsAString & aImageUrl, const this, nullptr, aInPrivateBrowsing ? nsIRequest::LOAD_ANONYMOUS : nsIRequest::LOAD_NORMAL, - nullptr, nsIContentPolicy::TYPE_IMAGE, + nullptr, nsIContentPolicy::TYPE_INTERNAL_IMAGE, EmptyString(), getter_AddRefs(osxni->mIconRequest)); if (NS_SUCCEEDED(rv)) { diff --git a/widget/cocoa/nsMenuItemIconX.mm b/widget/cocoa/nsMenuItemIconX.mm index d4ed69fe8cfb..26c73101cbcf 100644 --- a/widget/cocoa/nsMenuItemIconX.mm +++ b/widget/cocoa/nsMenuItemIconX.mm @@ -310,7 +310,7 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconURI) mozilla::net::RP_Default, nullptr, loadGroup, this, nullptr, nsIRequest::LOAD_NORMAL, nullptr, - nsIContentPolicy::TYPE_IMAGE, EmptyString(), + nsIContentPolicy::TYPE_INTERNAL_IMAGE, EmptyString(), getter_AddRefs(mIconRequest)); if (NS_FAILED(rv)) return rv; diff --git a/widget/windows/WinUtils.cpp b/widget/windows/WinUtils.cpp index 1aba34da641c..f8c8184966fd 100644 --- a/widget/windows/WinUtils.cpp +++ b/widget/windows/WinUtils.cpp @@ -1108,7 +1108,7 @@ nsresult AsyncFaviconDataReady::OnFaviconDataNotAvailable(void) mozIconURI, nsContentUtils::GetSystemPrincipal(), nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, - nsIContentPolicy::TYPE_IMAGE); + nsIContentPolicy::TYPE_INTERNAL_IMAGE); NS_ENSURE_SUCCESS(rv, rv); From f69e2b393b21d51fa0110c74528e51c3184edfdf Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Sun, 20 Sep 2015 14:55:44 -0700 Subject: [PATCH 052/133] Bug 1048048 - add preload content policy types (r=ehsan) --HG-- extra : source : 740ab1ecd0794b5a304b93ef528c8aa4c68ca417 --- dom/base/nsContentPolicy.cpp | 16 +++++++ dom/base/nsContentPolicyUtils.h | 75 ++++++++++++++++--------------- dom/base/nsContentUtils.cpp | 20 +++++++++ dom/base/nsContentUtils.h | 10 +++++ dom/base/nsIContentPolicy.idl | 2 +- dom/base/nsIContentPolicyBase.idl | 43 +++++++++++++++++- dom/cache/DBSchema.cpp | 7 ++- dom/fetch/InternalRequest.cpp | 7 ++- dom/fetch/InternalRequest.h | 6 +-- 9 files changed, 143 insertions(+), 43 deletions(-) diff --git a/dom/base/nsContentPolicy.cpp b/dom/base/nsContentPolicy.cpp index 9b2ec5528799..7f0c8a3a1345 100644 --- a/dom/base/nsContentPolicy.cpp +++ b/dom/base/nsContentPolicy.cpp @@ -13,6 +13,7 @@ #include "nsISupports.h" #include "nsXPCOM.h" #include "nsContentPolicyUtils.h" +#include "mozilla/dom/nsCSPService.h" #include "nsContentPolicy.h" #include "nsIURI.h" #include "nsIDocShell.h" @@ -123,9 +124,15 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod, nsContentPolicyType externalTypeOrScript = nsContentUtils::InternalContentPolicyTypeToExternalOrScript(contentType); + nsContentPolicyType externalTypeOrPreload = + nsContentUtils::InternalContentPolicyTypeToExternalOrPreload(contentType); + nsCOMPtr mixedContentBlocker = do_GetService(NS_MIXEDCONTENTBLOCKER_CONTRACTID); + nsCOMPtr cspService = + do_GetService(CSPSERVICE_CONTRACTID); + /* * Enumerate mPolicies and ask each of them, taking the logical AND of * their permissions. @@ -144,6 +151,15 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod, if (isMixedContentBlocker) { type = externalTypeOrScript; } + // Send the internal content policy type for CSP which needs to + // know about preloads, in particular: + // * TYPE_INTERNAL_SCRIPT_PRELOAD + // * TYPE_INTERNAL_IMAGE_PRELOAD + // * TYPE_INTERNAL_STYLESHEET_PRELOAD + bool isCSP = cspService == entries[i]; + if (isCSP) { + type = externalTypeOrPreload; + } rv = (entries[i]->*policyMethod)(type, contentLocation, requestingLocation, requestingContext, mimeType, extra, requestPrincipal, diff --git a/dom/base/nsContentPolicyUtils.h b/dom/base/nsContentPolicyUtils.h index e3bc0c051399..cddee3a6543c 100644 --- a/dom/base/nsContentPolicyUtils.h +++ b/dom/base/nsContentPolicyUtils.h @@ -92,41 +92,46 @@ inline const char * NS_CP_ContentTypeName(uint32_t contentType) { switch (contentType) { - CASE_RETURN( TYPE_OTHER ); - CASE_RETURN( TYPE_SCRIPT ); - CASE_RETURN( TYPE_IMAGE ); - CASE_RETURN( TYPE_STYLESHEET ); - CASE_RETURN( TYPE_OBJECT ); - CASE_RETURN( TYPE_DOCUMENT ); - CASE_RETURN( TYPE_SUBDOCUMENT ); - CASE_RETURN( TYPE_REFRESH ); - CASE_RETURN( TYPE_XBL ); - CASE_RETURN( TYPE_PING ); - CASE_RETURN( TYPE_XMLHTTPREQUEST ); - CASE_RETURN( TYPE_OBJECT_SUBREQUEST ); - CASE_RETURN( TYPE_DTD ); - CASE_RETURN( TYPE_FONT ); - CASE_RETURN( TYPE_MEDIA ); - CASE_RETURN( TYPE_WEBSOCKET ); - CASE_RETURN( TYPE_CSP_REPORT ); - CASE_RETURN( TYPE_XSLT ); - CASE_RETURN( TYPE_BEACON ); - CASE_RETURN( TYPE_FETCH ); - CASE_RETURN( TYPE_IMAGESET ); - CASE_RETURN( TYPE_WEB_MANIFEST ); - CASE_RETURN( TYPE_INTERNAL_SCRIPT ); - CASE_RETURN( TYPE_INTERNAL_WORKER ); - CASE_RETURN( TYPE_INTERNAL_SHARED_WORKER ); - CASE_RETURN( TYPE_INTERNAL_EMBED ); - CASE_RETURN( TYPE_INTERNAL_OBJECT ); - CASE_RETURN( TYPE_INTERNAL_FRAME ); - CASE_RETURN( TYPE_INTERNAL_IFRAME ); - CASE_RETURN( TYPE_INTERNAL_AUDIO ); - CASE_RETURN( TYPE_INTERNAL_VIDEO ); - CASE_RETURN( TYPE_INTERNAL_TRACK ); - CASE_RETURN( TYPE_INTERNAL_XMLHTTPREQUEST ); - CASE_RETURN( TYPE_INTERNAL_EVENTSOURCE ); - CASE_RETURN( TYPE_INTERNAL_SERVICE_WORKER ); + CASE_RETURN( TYPE_OTHER ); + CASE_RETURN( TYPE_SCRIPT ); + CASE_RETURN( TYPE_IMAGE ); + CASE_RETURN( TYPE_STYLESHEET ); + CASE_RETURN( TYPE_OBJECT ); + CASE_RETURN( TYPE_DOCUMENT ); + CASE_RETURN( TYPE_SUBDOCUMENT ); + CASE_RETURN( TYPE_REFRESH ); + CASE_RETURN( TYPE_XBL ); + CASE_RETURN( TYPE_PING ); + CASE_RETURN( TYPE_XMLHTTPREQUEST ); + CASE_RETURN( TYPE_OBJECT_SUBREQUEST ); + CASE_RETURN( TYPE_DTD ); + CASE_RETURN( TYPE_FONT ); + CASE_RETURN( TYPE_MEDIA ); + CASE_RETURN( TYPE_WEBSOCKET ); + CASE_RETURN( TYPE_CSP_REPORT ); + CASE_RETURN( TYPE_XSLT ); + CASE_RETURN( TYPE_BEACON ); + CASE_RETURN( TYPE_FETCH ); + CASE_RETURN( TYPE_IMAGESET ); + CASE_RETURN( TYPE_WEB_MANIFEST ); + CASE_RETURN( TYPE_INTERNAL_SCRIPT ); + CASE_RETURN( TYPE_INTERNAL_WORKER ); + CASE_RETURN( TYPE_INTERNAL_SHARED_WORKER ); + CASE_RETURN( TYPE_INTERNAL_EMBED ); + CASE_RETURN( TYPE_INTERNAL_OBJECT ); + CASE_RETURN( TYPE_INTERNAL_FRAME ); + CASE_RETURN( TYPE_INTERNAL_IFRAME ); + CASE_RETURN( TYPE_INTERNAL_AUDIO ); + CASE_RETURN( TYPE_INTERNAL_VIDEO ); + CASE_RETURN( TYPE_INTERNAL_TRACK ); + CASE_RETURN( TYPE_INTERNAL_XMLHTTPREQUEST ); + CASE_RETURN( TYPE_INTERNAL_EVENTSOURCE ); + CASE_RETURN( TYPE_INTERNAL_SERVICE_WORKER ); + CASE_RETURN( TYPE_INTERNAL_SCRIPT_PRELOAD ); + CASE_RETURN( TYPE_INTERNAL_IMAGE ); + CASE_RETURN( TYPE_INTERNAL_IMAGE_PRELOAD ); + CASE_RETURN( TYPE_INTERNAL_STYLESHEET ); + CASE_RETURN( TYPE_INTERNAL_STYLESHEET_PRELOAD ); default: return ""; } diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index bb06e960f920..8936622c0b9a 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -7959,6 +7959,7 @@ nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType) { switch (aType) { case nsIContentPolicy::TYPE_INTERNAL_SCRIPT: + case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD: case nsIContentPolicy::TYPE_INTERNAL_WORKER: case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER: case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER: @@ -7981,6 +7982,14 @@ nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType) case nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE: return nsIContentPolicy::TYPE_XMLHTTPREQUEST; + case nsIContentPolicy::TYPE_INTERNAL_IMAGE: + case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD: + return nsIContentPolicy::TYPE_IMAGE; + + case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET: + case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD: + return nsIContentPolicy::TYPE_STYLESHEET; + default: return aType; } @@ -8002,6 +8011,17 @@ nsContentUtils::InternalContentPolicyTypeToExternalOrScript(nsContentPolicyType } } +/* static */ +nsContentPolicyType +nsContentUtils::InternalContentPolicyTypeToExternalOrPreload(nsContentPolicyType aType) +{ + if (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD || + aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD || + aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD) { + return aType; + } + return InternalContentPolicyTypeToExternal(aType); +} nsresult nsContentUtils::SetFetchReferrerURIWithPolicy(nsIPrincipal* aPrincipal, diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index fcbaae66cfad..43a3d36ddc5c 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -965,6 +965,16 @@ public: */ static nsContentPolicyType InternalContentPolicyTypeToExternalOrScript(nsContentPolicyType aType); + /** + * Map internal content policy types to external ones or preload types: + * * TYPE_INTERNAL_SCRIPT_PRELOAD + * * TYPE_INTERNAL_IMAGE_PRELOAD + * * TYPE_INTERNAL_STYLESHEET_PRELOAD + * + * Note: DO NOT call this function unless you know what you're doing! + */ + static nsContentPolicyType InternalContentPolicyTypeToExternalOrPreload(nsContentPolicyType aType); + /** * Quick helper to determine whether there are any mutation listeners * of a given type that apply to this content or any of its ancestors. diff --git a/dom/base/nsIContentPolicy.idl b/dom/base/nsIContentPolicy.idl index 63ec72e223e8..a73565a9a91e 100644 --- a/dom/base/nsIContentPolicy.idl +++ b/dom/base/nsIContentPolicy.idl @@ -20,7 +20,7 @@ interface nsIPrincipal; * by launching a dialog to prompt the user for something). */ -[scriptable,uuid(ce321216-c404-40a7-a711-d80454ec6b76)] +[scriptable,uuid(caad4f1f-d047-46ac-ae9d-dc598e4fb91b)] interface nsIContentPolicy : nsIContentPolicyBase { /** diff --git a/dom/base/nsIContentPolicyBase.idl b/dom/base/nsIContentPolicyBase.idl index e31608fe9bd5..c064ecaf74c9 100644 --- a/dom/base/nsIContentPolicyBase.idl +++ b/dom/base/nsIContentPolicyBase.idl @@ -24,7 +24,7 @@ typedef unsigned long nsContentPolicyType; * by launching a dialog to prompt the user for something). */ -[scriptable,uuid(8527ae0d-0c43-4413-bc46-85c0bcb66876)] +[scriptable,uuid(17418187-d86f-48dd-92d1-238838df0a4e)] interface nsIContentPolicyBase : nsISupports { /** @@ -280,6 +280,47 @@ interface nsIContentPolicyBase : nsISupports */ const nsContentPolicyType TYPE_INTERNAL_SERVICE_WORKER = 35; + /** + * Indicates an internal constant for *preloaded* scripts + * loaded through script elements. + * + * This will be mapped to TYPE_SCRIPT before being passed + * to content policy implementations. + */ + const nsContentPolicyType TYPE_INTERNAL_SCRIPT_PRELOAD = 36; + + /** + * Indicates an internal constant for normal images. + * + * This will be mapped to TYPE_IMAGE before being passed + * to content policy implementations. + */ + const nsContentPolicyType TYPE_INTERNAL_IMAGE = 37; + + /** + * Indicates an internal constant for *preloaded* images. + * + * This will be mapped to TYPE_IMAGE before being passed + * to content policy implementations. + */ + const nsContentPolicyType TYPE_INTERNAL_IMAGE_PRELOAD = 38; + + /** + * Indicates an internal constant for normal stylesheets. + * + * This will be mapped to TYPE_STYLESHEET before being passed + * to content policy implementations. + */ + const nsContentPolicyType TYPE_INTERNAL_STYLESHEET = 39; + + /** + * Indicates an internal constant for *preloaded* stylesheets. + * + * This will be mapped to TYPE_STYLESHEET before being passed + * to content policy implementations. + */ + const nsContentPolicyType TYPE_INTERNAL_STYLESHEET_PRELOAD = 40; + /* When adding new content types, please update nsContentBlocker, * NS_CP_ContentTypeName, nsCSPContext, all nsIContentPolicy * implementations, the static_assert in dom/cache/DBSchema.cpp, diff --git a/dom/cache/DBSchema.cpp b/dom/cache/DBSchema.cpp index 52a93333425d..e2f6904bbd9a 100644 --- a/dom/cache/DBSchema.cpp +++ b/dom/cache/DBSchema.cpp @@ -275,7 +275,12 @@ static_assert(nsIContentPolicy::TYPE_INVALID == 0 && nsIContentPolicy::TYPE_INTERNAL_TRACK == 32 && nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST == 33 && nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE == 34 && - nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER == 35, + nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER == 35 && + nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD == 36 && + nsIContentPolicy::TYPE_INTERNAL_IMAGE == 37 && + nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD == 38 && + nsIContentPolicy::TYPE_INTERNAL_STYLESHEET == 39 && + nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD == 40, "nsContentPolicyType values are as expected"); namespace { diff --git a/dom/fetch/InternalRequest.cpp b/dom/fetch/InternalRequest.cpp index d2a8f2bc1f85..2baed642b12c 100644 --- a/dom/fetch/InternalRequest.cpp +++ b/dom/fetch/InternalRequest.cpp @@ -116,6 +116,7 @@ InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aConte context = RequestContext::Internal; break; case nsIContentPolicy::TYPE_INTERNAL_SCRIPT: + case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD: case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER: context = RequestContext::Script; break; @@ -125,10 +126,12 @@ InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aConte case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER: context = RequestContext::Sharedworker; break; - case nsIContentPolicy::TYPE_IMAGE: + case nsIContentPolicy::TYPE_INTERNAL_IMAGE: + case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD: context = RequestContext::Image; break; - case nsIContentPolicy::TYPE_STYLESHEET: + case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET: + case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD: context = RequestContext::Style; break; case nsIContentPolicy::TYPE_INTERNAL_OBJECT: diff --git a/dom/fetch/InternalRequest.h b/dom/fetch/InternalRequest.h index caa005756bcd..8c9d84238667 100644 --- a/dom/fetch/InternalRequest.h +++ b/dom/fetch/InternalRequest.h @@ -43,7 +43,7 @@ namespace dom { * frame | TYPE_INTERNAL_FRAME * hyperlink | * iframe | TYPE_INTERNAL_IFRAME - * image | TYPE_IMAGE + * image | TYPE_INTERNAL_IMAGE, TYPE_INTERNAL_IMAGE_PRELOAD * imageset | TYPE_IMAGESET * import | Not supported by Gecko * internal | TYPE_DOCUMENT, TYPE_XBL, TYPE_OTHER @@ -53,10 +53,10 @@ namespace dom { * ping | TYPE_PING * plugin | TYPE_OBJECT_SUBREQUEST * prefetch | - * script | TYPE_INTERNAL_SCRIPT + * script | TYPE_INTERNAL_SCRIPT, TYPE_INTERNAL_SCRIPT_PRELOAD * sharedworker | TYPE_INTERNAL_SHARED_WORKER * subresource | Not supported by Gecko - * style | TYPE_STYLESHEET + * style | TYPE_INTERNAL_STYLESHEET, TYPE_INTERNAL_STYLESHEET_PRELOAD * track | TYPE_INTERNAL_TRACK * video | TYPE_INTERNAL_VIDEO * worker | TYPE_INTERNAL_WORKER From a28aacf667a8f20e6a3a7f58d7ba18b1fc1a2eb7 Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Fri, 31 Oct 2014 13:37:59 -0700 Subject: [PATCH 053/133] Bug 1048048 - add preload content policy types - tests (r=dveditz) CLOSED TREE --HG-- extra : source : 02c6d6aef163530bafee0d39761f18ca3aa1f40c extra : amend_source : bff4f1c8ed0fe42addb24774b8c6dd89fe2c7905 --- .../test/csp/file_report_for_import.css | 1 + .../test/csp/file_report_for_import.html | 10 ++ .../csp/file_report_for_import_server.sjs | 49 ++++++++ dom/security/test/csp/mochitest.ini | 4 + .../test/csp/test_report_for_import.html | 112 ++++++++++++++++++ 5 files changed, 176 insertions(+) create mode 100644 dom/security/test/csp/file_report_for_import.css create mode 100644 dom/security/test/csp/file_report_for_import.html create mode 100644 dom/security/test/csp/file_report_for_import_server.sjs create mode 100644 dom/security/test/csp/test_report_for_import.html diff --git a/dom/security/test/csp/file_report_for_import.css b/dom/security/test/csp/file_report_for_import.css new file mode 100644 index 000000000000..b578b77b33fb --- /dev/null +++ b/dom/security/test/csp/file_report_for_import.css @@ -0,0 +1 @@ +@import url("http://example.com/tests/dom/security/test/csp/file_report_for_import_server.sjs?stylesheet"); diff --git a/dom/security/test/csp/file_report_for_import.html b/dom/security/test/csp/file_report_for_import.html new file mode 100644 index 000000000000..77a36faea1b6 --- /dev/null +++ b/dom/security/test/csp/file_report_for_import.html @@ -0,0 +1,10 @@ + + + + Bug 1048048 - Test sending csp-report when using import in css + + + + empty body, just testing @import in the included css for bug 1048048 + + diff --git a/dom/security/test/csp/file_report_for_import_server.sjs b/dom/security/test/csp/file_report_for_import_server.sjs new file mode 100644 index 000000000000..e69852b1b791 --- /dev/null +++ b/dom/security/test/csp/file_report_for_import_server.sjs @@ -0,0 +1,49 @@ +// Custom *.sjs file specifically for the needs of Bug: +// Bug 1048048 - CSP violation report not sent for @import + +const CC = Components.Constructor; +const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream"); + +function handleRequest(request, response) +{ + // avoid confusing cache behaviors + response.setHeader("Cache-Control", "no-cache", false); + response.setHeader("Content-Type", "text/html", false); + var queryString = request.queryString; + + // (1) lets process the queryresult request async and + // wait till we have received the image request. + if (queryString === "queryresult") { + response.processAsync(); + setObjectState("queryResult", response); + return; + } + + // (2) handle the csp-report and return the JSON back to + // the testfile using the afore stored xml request in (1). + if (queryString === "report") { + getObjectState("queryResult", function(queryResponse) { + if (!queryResponse) { + return; + } + + // send the report back to the XML request for verification + var report = new BinaryInputStream(request.bodyInputStream); + var avail; + var bytes = []; + while ((avail = report.available()) > 0) { + Array.prototype.push.apply(bytes, report.readByteArray(avail)); + } + var data = String.fromCharCode.apply(null, bytes); + queryResponse.bodyOutputStream.write(data, data.length); + queryResponse.finish(); + }); + return; + } + + // we should not get here ever, but just in case return + // something unexpected. + response.write("doh!"); +} diff --git a/dom/security/test/csp/mochitest.ini b/dom/security/test/csp/mochitest.ini index 13897873308c..0ca3b70da82c 100644 --- a/dom/security/test/csp/mochitest.ini +++ b/dom/security/test/csp/mochitest.ini @@ -127,6 +127,9 @@ support-files = file_upgrade_insecure_referrer_server.sjs file_upgrade_insecure_cors.html file_upgrade_insecure_cors_server.sjs + file_report_for_import.css + file_report_for_import.html + file_report_for_import_server.sjs [test_base-uri.html] [test_blob_data_schemes.html] @@ -191,5 +194,6 @@ skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'gonk' || toolk skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'gonk' || toolkit == 'android' [test_upgrade_insecure_cors.html] skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'gonk' || toolkit == 'android' +[test_report_for_import.html] [test_blocked_uri_in_reports.html] skip-if = e10s || buildapp == 'b2g' # http-on-opening-request observer not supported in child process (bug 1009632) diff --git a/dom/security/test/csp/test_report_for_import.html b/dom/security/test/csp/test_report_for_import.html new file mode 100644 index 000000000000..346af65b74ef --- /dev/null +++ b/dom/security/test/csp/test_report_for_import.html @@ -0,0 +1,112 @@ + + + + + Test for Bug 548193 + + + + +

+ + + + + + + From c6aa53d1572774be4b2bcb358b17563ec363ff35 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Mon, 21 Sep 2015 10:37:07 -0700 Subject: [PATCH 054/133] Backed out changeset 09c2a214244b (bug 1072313) for Windows textureclient crashes CLOSED TREE --- gfx/layers/client/TextureClient.cpp | 1 - gfx/layers/client/TextureClient.h | 11 +------- gfx/layers/d3d11/TextureD3D11.cpp | 26 ++++++------------- gfx/layers/d3d11/TextureD3D11.h | 4 --- gfx/layers/d3d9/TextureD3D9.cpp | 7 +---- gfx/layers/d3d9/TextureD3D9.h | 2 -- gfx/layers/ipc/ImageBridgeChild.cpp | 2 +- .../opengl/MacIOSurfaceTextureClientOGL.cpp | 5 ---- .../opengl/MacIOSurfaceTextureClientOGL.h | 2 -- 9 files changed, 11 insertions(+), 49 deletions(-) diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index 23e899c353b0..ce847d311b22 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -557,7 +557,6 @@ TextureClient::KeepUntilFullDeallocation(UniquePtr aKeep, bool aMainT void TextureClient::ForceRemove(bool sync) { - FinalizeOnIPDLThread(); if (mValid && mActor) { if (sync || GetFlags() & TextureFlags::DEALLOCATE_CLIENT) { MOZ_PERFORMANCE_WARNING("gfx", "TextureClient/Host pair requires synchronous deallocation"); diff --git a/gfx/layers/client/TextureClient.h b/gfx/layers/client/TextureClient.h index 373b5a307486..1337cbfed7f6 100644 --- a/gfx/layers/client/TextureClient.h +++ b/gfx/layers/client/TextureClient.h @@ -408,8 +408,6 @@ public: * help avoid race conditions in some cases. * It's a temporary hack to ensure that DXGI textures don't get destroyed * between serialization and deserialization. - * - * This must not be called off the texture's IPDL thread. */ void KeepUntilFullDeallocation(UniquePtr aKeep, bool aMainThreadOnly = false); @@ -506,20 +504,13 @@ private: static void TextureClientRecycleCallback(TextureClient* aClient, void* aClosure); /** - * Called once, during the destruction of the Texture, on the thread in which - * texture's reference count reaches 0 (could be any thread). + * Called once, just before the destructor. * * Here goes the shut-down code that uses virtual methods. * Must only be called by Release(). */ B2G_ACL_EXPORT void Finalize(); - /** - * Called once during the destruction of the texture on the IPDL thread, if - * the texture is shared on the compositor (otherwise it is not called at all). - */ - virtual void FinalizeOnIPDLThread() {} - friend class AtomicRefCountedWithFinalize; protected: diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index 51c8513316ec..bf0f945da777 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -198,6 +198,13 @@ TextureClientD3D11::TextureClientD3D11(ISurfaceAllocator* aAllocator, TextureClientD3D11::~TextureClientD3D11() { + if (mActor) { + if (mTexture) { + KeepUntilFullDeallocation(MakeUnique>(mTexture)); + } else if (mTexture10) { + KeepUntilFullDeallocation(MakeUnique>(mTexture10)); + } + } #ifdef DEBUG // An Azure DrawTarget needs to be locked when it gets nullptr'ed as this is // when it calls EndDraw. This EndDraw should not execute anything so it @@ -221,18 +228,6 @@ TextureClientD3D11::~TextureClientD3D11() #endif } -void -TextureClientD3D11::FinalizeOnIPDLThread() -{ - if (mActor) { - if (mTexture) { - KeepUntilFullDeallocation(MakeUnique>(mTexture)); - } else if (mTexture10) { - KeepUntilFullDeallocation(MakeUnique>(mTexture10)); - } - } -} - // static already_AddRefed TextureClientD3D11::Create(ISurfaceAllocator* aAllocator, @@ -661,16 +656,11 @@ protected: }; DXGIYCbCrTextureClient::~DXGIYCbCrTextureClient() -{ - MOZ_COUNT_DTOR(DXGIYCbCrTextureClient); -} - -void -DXGIYCbCrTextureClient::FinalizeOnIPDLThread() { if (mHoldRefs[0] && mActor) { KeepUntilFullDeallocation(MakeUnique(mHoldRefs), true); } + MOZ_COUNT_DTOR(DXGIYCbCrTextureClient); } // static diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h index b19877ce49b2..c3d1ad8c002d 100644 --- a/gfx/layers/d3d11/TextureD3D11.h +++ b/gfx/layers/d3d11/TextureD3D11.h @@ -88,8 +88,6 @@ public: protected: bool AllocateD3D11Surface(ID3D11Device* aDevice, const gfx::IntSize& aSize); - virtual void FinalizeOnIPDLThread() override; - gfx::IntSize mSize; RefPtr mTexture10; RefPtr mTexture; @@ -159,8 +157,6 @@ public: CreateSimilar(TextureFlags, TextureAllocationFlags) const override{ return nullptr; } private: - virtual void FinalizeOnIPDLThread() override; - RefPtr mHoldRefs[3]; HANDLE mHandles[3]; gfx::IntSize mSize; diff --git a/gfx/layers/d3d9/TextureD3D9.cpp b/gfx/layers/d3d9/TextureD3D9.cpp index 17ea1e48c35b..2f46658cdb2c 100644 --- a/gfx/layers/d3d9/TextureD3D9.cpp +++ b/gfx/layers/d3d9/TextureD3D9.cpp @@ -660,12 +660,6 @@ SharedTextureClientD3D9::SharedTextureClientD3D9(ISurfaceAllocator* aAllocator, } SharedTextureClientD3D9::~SharedTextureClientD3D9() -{ - MOZ_COUNT_DTOR(SharedTextureClientD3D9); -} - -void -SharedTextureClientD3D9::FinalizeOnIPDLThread() { if (mTexture && mActor) { KeepUntilFullDeallocation(MakeUnique>(mTexture)); @@ -673,6 +667,7 @@ SharedTextureClientD3D9::FinalizeOnIPDLThread() if (mTexture) { gfxWindowsPlatform::sD3D9SharedTextureUsed -= mDesc.Width * mDesc.Height * 4; } + MOZ_COUNT_DTOR(SharedTextureClientD3D9); } // static diff --git a/gfx/layers/d3d9/TextureD3D9.h b/gfx/layers/d3d9/TextureD3D9.h index 5708775af9d0..27ff3093be66 100644 --- a/gfx/layers/d3d9/TextureD3D9.h +++ b/gfx/layers/d3d9/TextureD3D9.h @@ -285,8 +285,6 @@ public: } private: - virtual void FinalizeOnIPDLThread() override; - RefPtr mDevice; RefPtr mTexture; gfx::SurfaceFormat mFormat; diff --git a/gfx/layers/ipc/ImageBridgeChild.cpp b/gfx/layers/ipc/ImageBridgeChild.cpp index 06cb4ca773dc..301c6b578479 100644 --- a/gfx/layers/ipc/ImageBridgeChild.cpp +++ b/gfx/layers/ipc/ImageBridgeChild.cpp @@ -188,7 +188,7 @@ static void ImageBridgeShutdownStep1(ReentrantMonitor *aBarrier, bool *aDone) InfallibleTArray textures; sImageBridgeChildSingleton->ManagedPTextureChild(textures); for (int i = textures.Length() - 1; i >= 0; --i) { - RefPtr client = TextureClient::AsTextureClient(textures[i]); + TextureClient* client = TextureClient::AsTextureClient(textures[i]); if (client) { client->ForceRemove(); } diff --git a/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp index fbefd06c8f65..159b41291fc7 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp +++ b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp @@ -16,11 +16,6 @@ MacIOSurfaceTextureClientOGL::MacIOSurfaceTextureClientOGL(ISurfaceAllocator* aA {} MacIOSurfaceTextureClientOGL::~MacIOSurfaceTextureClientOGL() -{ -} - -void -MacIOSurfaceTextureClientOGL::FinalizeOnIPDLThread() { if (mActor && mSurface) { KeepUntilFullDeallocation(MakeUnique>(mSurface)); diff --git a/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h index 7548beeafdc7..5a0c03825d36 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h +++ b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h @@ -50,8 +50,6 @@ public: CreateSimilar(TextureFlags, TextureAllocationFlags) const override { return nullptr; } protected: - virtual void FinalizeOnIPDLThread() override; - RefPtr mSurface; bool mIsLocked; }; From 8d749762828c1045fb6466c897d0af0fa3a99deb Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Fri, 18 Sep 2015 23:07:34 -0700 Subject: [PATCH 055/133] Bug 1206590: Move gcWeakMapList from JSCompartment to JS::Zone. r=terrence --HG-- extra : rebase_source : 287d3e570e5bdd149ad4cea31c7c8cf49be773dd extra : amend_source : 1bf0a04c6adfb1ed20437fccb02b6d446c7d88eb --- js/src/gc/Marking.cpp | 4 ++-- js/src/gc/Zone.cpp | 8 +++++++ js/src/gc/Zone.h | 4 ++++ js/src/jscompartment.cpp | 9 -------- js/src/jscompartment.h | 4 ---- js/src/jsgc.cpp | 44 ++++++++++++++++++++----------------- js/src/jsweakmap.cpp | 47 ++++++++++++++++++++-------------------- js/src/jsweakmap.h | 46 +++++++++++++++++++-------------------- js/src/vm/Debugger.h | 8 +++++-- 9 files changed, 90 insertions(+), 84 deletions(-) diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 1724d065490c..c4c4d1812b13 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -1788,8 +1788,8 @@ GCMarker::enterWeakMarkingMode() if (weakMapAction() == ExpandWeakMaps) { tag_ = TracerKindTag::WeakMarking; - for (GCCompartmentGroupIter c(runtime()); !c.done(); c.next()) { - for (WeakMapBase* m = c->gcWeakMapList; m; m = m->next) { + for (GCZoneGroupIter zone(runtime()); !zone.done(); zone.next()) { + for (WeakMapBase* m = zone->gcWeakMapList; m; m = m->next) { if (m->marked) m->markEphemeronEntries(this); } diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp index cd9621a676ba..b9ee0efd5fab 100644 --- a/js/src/gc/Zone.cpp +++ b/js/src/gc/Zone.cpp @@ -27,6 +27,7 @@ JS::Zone::Zone(JSRuntime* rt) debuggers(nullptr), arenas(rt), types(this), + gcWeakMapList(nullptr), compartments(), gcGrayRoots(), gcMallocBytes(0), @@ -203,6 +204,13 @@ Zone::sweepBreakpoints(FreeOp* fop) } } +void +Zone::sweepWeakMaps() +{ + /* Finalize unreachable (key,value) pairs in all weak maps. */ + WeakMapBase::sweepZone(this); +} + void Zone::discardJitCode(FreeOp* fop) { diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h index e5ce3777097d..74c3a977fec0 100644 --- a/js/src/gc/Zone.h +++ b/js/src/gc/Zone.h @@ -242,6 +242,7 @@ struct Zone : public JS::shadow::Zone, LogTenurePromotionQueue awaitingTenureLogging; void sweepBreakpoints(js::FreeOp* fop); + void sweepWeakMaps(); void sweepCompartments(js::FreeOp* fop, bool keepAtleastOne, bool lastGC); js::jit::JitZone* createJitZone(JSContext* cx); @@ -268,6 +269,9 @@ struct Zone : public JS::shadow::Zone, js::TypeZone types; + /* Linked list of live weakmaps in this zone. */ + js::WeakMapBase* gcWeakMapList; + // The set of compartments in this zone. typedef js::Vector CompartmentVector; CompartmentVector compartments; diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index a017e85e16e5..32770804eceb 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -67,7 +67,6 @@ JSCompartment::JSCompartment(Zone* zone, const JS::CompartmentOptions& options = objectMetadataTable(nullptr), lazyArrayBuffers(nullptr), gcIncomingGrayPointers(nullptr), - gcWeakMapList(nullptr), gcPreserveJitCode(options.preserveJitCode()), debugModeBits(0), rngState(0), @@ -658,13 +657,6 @@ JSCompartment::sweepDebugScopes() debugScopes->sweep(rt); } -void -JSCompartment::sweepWeakMaps() -{ - /* Finalize unreachable (key,value) pairs in all weak maps. */ - WeakMapBase::sweepCompartment(this); -} - void JSCompartment::sweepNativeIterators() { @@ -783,7 +775,6 @@ JSCompartment::clearTables() MOZ_ASSERT(crossCompartmentWrappers.empty()); MOZ_ASSERT(!jitCompartment_); MOZ_ASSERT(!debugScopes); - MOZ_ASSERT(!gcWeakMapList); MOZ_ASSERT(enumerators->next() == enumerators); MOZ_ASSERT(regExps.empty()); diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 2803be3ded14..e61607520adf 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -454,9 +454,6 @@ struct JSCompartment */ JSObject* gcIncomingGrayPointers; - /* Linked list of live weakmaps in this compartment. */ - js::WeakMapBase* gcWeakMapList; - private: /* Whether to preserve JIT code on non-shrinking GCs. */ bool gcPreserveJitCode; @@ -546,7 +543,6 @@ struct JSCompartment void sweepJitCompartment(js::FreeOp* fop); void sweepRegExps(); void sweepDebugScopes(); - void sweepWeakMaps(); void sweepNativeIterators(); void sweepTemplateObjects(); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index a8a0f528bce8..e12a7d8b913c 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -2303,6 +2303,7 @@ GCRuntime::sweepZoneAfterCompacting(Zone* zone) FreeOp* fop = rt->defaultFreeOp(); sweepTypesAfterCompacting(zone); zone->sweepBreakpoints(fop); + zone->sweepWeakMaps(); for (CompartmentsInZoneIter c(zone); !c.done(); c.next()) { c->sweepInnerViews(); @@ -2316,7 +2317,6 @@ GCRuntime::sweepZoneAfterCompacting(Zone* zone) c->sweepSelfHostingScriptSource(); c->sweepDebugScopes(); c->sweepJitCompartment(fop); - c->sweepWeakMaps(); c->sweepNativeIterators(); c->sweepTemplateObjects(); } @@ -2636,9 +2636,9 @@ GCRuntime::updatePointersToRelocatedCells(Zone* zone) Debugger::markAll(&trc); Debugger::markIncomingCrossCompartmentEdges(&trc); + WeakMapBase::markAll(zone, &trc); for (CompartmentsInZoneIter c(zone); !c.done(); c.next()) { c->trace(&trc); - WeakMapBase::markAll(c, &trc); if (c->watchpointMap) c->watchpointMap->markAll(&trc); } @@ -3947,9 +3947,9 @@ GCRuntime::beginMarkPhase(JS::gcreason::Reason reason) zone->arenas.unmarkAll(); } - for (GCCompartmentsIter c(rt); !c.done(); c.next()) { - /* Unmark all weak maps in the compartments being collected. */ - WeakMapBase::unmarkCompartment(c); + for (GCZonesIter zone(rt); !zone.done(); zone.next()) { + /* Unmark all weak maps in the zones being collected. */ + WeakMapBase::unmarkZone(zone); } if (isFull) @@ -4031,7 +4031,7 @@ GCRuntime::beginMarkPhase(JS::gcreason::Reason reason) return true; } -template +template void GCRuntime::markWeakReferences(gcstats::Phase phase) { @@ -4047,11 +4047,13 @@ GCRuntime::markWeakReferences(gcstats::Phase phase) for (;;) { bool markedAny = false; - for (CompartmentIterT c(rt); !c.done(); c.next()) { + if (!marker.isWeakMarkingTracer()) { + for (ZoneIterT zone(rt); !zone.done(); zone.next()) + markedAny |= WeakMapBase::markZoneIteratively(zone, &marker); + } + for (CompartmentsIterT c(rt); !c.done(); c.next()) { if (c->watchpointMap) markedAny |= c->watchpointMap->markIteratively(&marker); - if (!marker.isWeakMarkingTracer()) - markedAny |= WeakMapBase::markCompartmentIteratively(c, &marker); } markedAny |= Debugger::markAllIteratively(&marker); markedAny |= jit::JitRuntime::MarkJitcodeGlobalTableIteratively(&marker); @@ -4070,7 +4072,7 @@ GCRuntime::markWeakReferences(gcstats::Phase phase) void GCRuntime::markWeakReferencesInCurrentGroup(gcstats::Phase phase) { - markWeakReferences(phase); + markWeakReferences(phase); } template @@ -4099,7 +4101,7 @@ GCRuntime::markGrayReferencesInCurrentGroup(gcstats::Phase phase) void GCRuntime::markAllWeakReferences(gcstats::Phase phase) { - markWeakReferences(phase); + markWeakReferences(phase); } void @@ -4202,8 +4204,8 @@ js::gc::MarkingValidator::nonIncrementalMark() if (!markedWeakMaps.init()) return; - for (GCCompartmentsIter c(runtime); !c.done(); c.next()) { - if (!WeakMapBase::saveCompartmentMarkedWeakMaps(c, markedWeakMaps)) + for (GCZonesIter zone(runtime); !zone.done(); zone.next()) { + if (!WeakMapBase::saveZoneMarkedWeakMaps(zone, markedWeakMaps)) return; } @@ -4235,8 +4237,8 @@ js::gc::MarkingValidator::nonIncrementalMark() { gcstats::AutoPhase ap(gc->stats, gcstats::PHASE_UNMARK); - for (GCCompartmentsIter c(runtime); !c.done(); c.next()) - WeakMapBase::unmarkCompartment(c); + for (GCZonesIter zone(runtime); !zone.done(); zone.next()) + WeakMapBase::unmarkZone(zone); MOZ_ASSERT(gcmarker->isDrained()); gcmarker->reset(); @@ -4285,8 +4287,8 @@ js::gc::MarkingValidator::nonIncrementalMark() Swap(*entry, *bitmap); } - for (GCCompartmentsIter c(runtime); !c.done(); c.next()) - WeakMapBase::unmarkCompartment(c); + for (GCZonesIter zone(runtime); !zone.done(); zone.next()) + WeakMapBase::unmarkZone(zone); WeakMapBase::restoreMarkedWeakMaps(markedWeakMaps); gc->marker.weakKeys.clear(); @@ -4490,8 +4492,8 @@ GCRuntime::findZoneEdgesForWeakMaps() * group. */ - for (GCCompartmentsIter comp(rt); !comp.done(); comp.next()) { - if (!WeakMapBase::findZoneEdgesForCompartment(comp)) + for (GCZonesIter zone(rt); !zone.done(); zone.next()) { + if (!WeakMapBase::findInterZoneEdges(zone)) return false; } @@ -5016,10 +5018,12 @@ GCRuntime::beginSweepingZoneGroup() c->sweepObjectPendingMetadata(); c->sweepDebugScopes(); c->sweepJitCompartment(&fop); - c->sweepWeakMaps(); c->sweepTemplateObjects(); } + for (GCZoneGroupIter zone(rt); !zone.done(); zone.next()) + zone->sweepWeakMaps(); + // Bug 1071218: the following two methods have not yet been // refactored to work on a single zone-group at once. diff --git a/js/src/jsweakmap.cpp b/js/src/jsweakmap.cpp index 558db06654a3..bcfaf450c9f4 100644 --- a/js/src/jsweakmap.cpp +++ b/js/src/jsweakmap.cpp @@ -28,13 +28,13 @@ using namespace js::gc; using mozilla::UniquePtr; -WeakMapBase::WeakMapBase(JSObject* memOf, JSCompartment* c) +WeakMapBase::WeakMapBase(JSObject* memOf, Zone* zone) : memberOf(memOf), - compartment(c), + zone(zone), next(WeakMapNotInList), marked(false) { - MOZ_ASSERT_IF(memberOf, memberOf->compartment() == c); + MOZ_ASSERT_IF(memberOf, memberOf->compartment()->zone() == zone); } WeakMapBase::~WeakMapBase() @@ -75,17 +75,17 @@ WeakMapBase::trace(JSTracer* tracer) } void -WeakMapBase::unmarkCompartment(JSCompartment* c) +WeakMapBase::unmarkZone(JS::Zone* zone) { - for (WeakMapBase* m = c->gcWeakMapList; m; m = m->next) + for (WeakMapBase* m = zone->gcWeakMapList; m; m = m->next) m->marked = false; } void -WeakMapBase::markAll(JSCompartment* c, JSTracer* tracer) +WeakMapBase::markAll(JS::Zone* zone, JSTracer* tracer) { MOZ_ASSERT(tracer->weakMapAction() != DoNotTraceWeakMaps); - for (WeakMapBase* m = c->gcWeakMapList; m; m = m->next) { + for (WeakMapBase* m = zone->gcWeakMapList; m; m = m->next) { m->trace(tracer); if (m->memberOf) TraceEdge(tracer, &m->memberOf, "memberOf"); @@ -93,10 +93,10 @@ WeakMapBase::markAll(JSCompartment* c, JSTracer* tracer) } bool -WeakMapBase::markCompartmentIteratively(JSCompartment* c, JSTracer* tracer) +WeakMapBase::markZoneIteratively(JS::Zone* zone, JSTracer* tracer) { bool markedAny = false; - for (WeakMapBase* m = c->gcWeakMapList; m; m = m->next) { + for (WeakMapBase* m = zone->gcWeakMapList; m; m = m->next) { if (m->marked && m->markIteratively(tracer)) markedAny = true; } @@ -104,9 +104,9 @@ WeakMapBase::markCompartmentIteratively(JSCompartment* c, JSTracer* tracer) } bool -WeakMapBase::findZoneEdgesForCompartment(JSCompartment* c) +WeakMapBase::findInterZoneEdges(JS::Zone* zone) { - for (WeakMapBase* m = c->gcWeakMapList; m; m = m->next) { + for (WeakMapBase* m = zone->gcWeakMapList; m; m = m->next) { if (!m->findZoneEdges()) return false; } @@ -114,10 +114,10 @@ WeakMapBase::findZoneEdgesForCompartment(JSCompartment* c) } void -WeakMapBase::sweepCompartment(JSCompartment* c) +WeakMapBase::sweepZone(JS::Zone* zone) { - WeakMapBase** tailPtr = &c->gcWeakMapList; - for (WeakMapBase* m = c->gcWeakMapList; m; ) { + WeakMapBase** tailPtr = &zone->gcWeakMapList; + for (WeakMapBase* m = zone->gcWeakMapList; m; ) { WeakMapBase* next = m->next; if (m->marked) { m->sweep(); @@ -133,7 +133,7 @@ WeakMapBase::sweepCompartment(JSCompartment* c) *tailPtr = nullptr; #ifdef DEBUG - for (WeakMapBase* m = c->gcWeakMapList; m; m = m->next) + for (WeakMapBase* m = zone->gcWeakMapList; m; m = m->next) MOZ_ASSERT(m->isInList() && m->marked); #endif } @@ -142,8 +142,8 @@ void WeakMapBase::traceAllMappings(WeakMapTracer* tracer) { JSRuntime* rt = tracer->runtime; - for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) { - for (WeakMapBase* m = c->gcWeakMapList; m; m = m->next) { + for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) { + for (WeakMapBase* m = zone->gcWeakMapList; m; m = m->next) { // The WeakMapTracer callback is not allowed to GC. JS::AutoSuppressGCAnalysis nogc; m->traceMappings(tracer); @@ -152,9 +152,9 @@ WeakMapBase::traceAllMappings(WeakMapTracer* tracer) } bool -WeakMapBase::saveCompartmentMarkedWeakMaps(JSCompartment* c, WeakMapSet& markedWeakMaps) +WeakMapBase::saveZoneMarkedWeakMaps(JS::Zone* zone, WeakMapSet& markedWeakMaps) { - for (WeakMapBase* m = c->gcWeakMapList; m; m = m->next) { + for (WeakMapBase* m = zone->gcWeakMapList; m; m = m->next) { if (m->marked && !markedWeakMaps.put(m)) return false; } @@ -166,7 +166,7 @@ WeakMapBase::restoreMarkedWeakMaps(WeakMapSet& markedWeakMaps) { for (WeakMapSet::Range r = markedWeakMaps.all(); !r.empty(); r.popFront()) { WeakMapBase* map = r.front(); - MOZ_ASSERT(map->compartment->zone()->isGCMarking()); + MOZ_ASSERT(map->zone->isGCMarking()); MOZ_ASSERT(!map->marked); map->marked = true; } @@ -175,8 +175,8 @@ WeakMapBase::restoreMarkedWeakMaps(WeakMapSet& markedWeakMaps) void WeakMapBase::removeWeakMapFromList(WeakMapBase* weakmap) { - JSCompartment* c = weakmap->compartment; - for (WeakMapBase** p = &c->gcWeakMapList; *p; p = &(*p)->next) { + JS::Zone* zone = weakmap->zone; + for (WeakMapBase** p = &zone->gcWeakMapList; *p; p = &(*p)->next) { if (*p == weakmap) { *p = (*p)->next; weakmap->next = WeakMapNotInList; @@ -194,7 +194,6 @@ ObjectValueMap::findZoneEdges() * zone. */ JS::AutoSuppressGCAnalysis nogc; - Zone* mapZone = compartment->zone(); for (Range r = all(); !r.empty(); r.popFront()) { JSObject* key = r.front().key(); if (key->asTenured().isMarked(BLACK) && !key->asTenured().isMarked(GRAY)) @@ -206,7 +205,7 @@ ObjectValueMap::findZoneEdges() if (!delegate) continue; Zone* delegateZone = delegate->zone(); - if (delegateZone == mapZone) + if (delegateZone == zone) continue; if (!delegateZone->gcZoneGroupEdges.put(key->zone())) return false; diff --git a/js/src/jsweakmap.h b/js/src/jsweakmap.h index 8e4ee7d5b725..aff5b262c7ed 100644 --- a/js/src/jsweakmap.h +++ b/js/src/jsweakmap.h @@ -46,44 +46,44 @@ class WeakMapBase { friend void js::GCMarker::enterWeakMarkingMode(); public: - WeakMapBase(JSObject* memOf, JSCompartment* c); + WeakMapBase(JSObject* memOf, JS::Zone* zone); virtual ~WeakMapBase(); void trace(JSTracer* tracer); // Garbage collector entry points. - // Unmark all weak maps in a compartment. - static void unmarkCompartment(JSCompartment* c); + // Unmark all weak maps in a zone. + static void unmarkZone(JS::Zone* zone); - // Mark all the weakmaps in a compartment. - static void markAll(JSCompartment* c, JSTracer* tracer); + // Mark all the weakmaps in a zone. + static void markAll(JS::Zone* zone, JSTracer* tracer); - // Check all weak maps in a compartment that have been marked as live in this garbage + // Check all weak maps in a zone that have been marked as live in this garbage // collection, and mark the values of all entries that have become strong references // to them. Return true if we marked any new values, indicating that we need to make // another pass. In other words, mark my marked maps' marked members' mid-collection. - static bool markCompartmentIteratively(JSCompartment* c, JSTracer* tracer); + static bool markZoneIteratively(JS::Zone* zone, JSTracer* tracer); // Add zone edges for weakmaps with key delegates in a different zone. - static bool findZoneEdgesForCompartment(JSCompartment* c); + static bool findInterZoneEdges(JS::Zone* zone); - // Sweep the weak maps in a compartment, removing dead weak maps and removing + // Sweep the weak maps in a zone, removing dead weak maps and removing // entries of live weak maps whose keys are dead. - static void sweepCompartment(JSCompartment* c); + static void sweepZone(JS::Zone* zone); // Trace all delayed weak map bindings. Used by the cycle collector. static void traceAllMappings(WeakMapTracer* tracer); bool isInList() { return next != WeakMapNotInList; } - // Save information about which weak maps are marked for a compartment. - static bool saveCompartmentMarkedWeakMaps(JSCompartment* c, WeakMapSet& markedWeakMaps); + // Save information about which weak maps are marked for a zone. + static bool saveZoneMarkedWeakMaps(JS::Zone* zone, WeakMapSet& markedWeakMaps); - // Restore information about which weak maps are marked for many compartments. + // Restore information about which weak maps are marked for many zones. static void restoreMarkedWeakMaps(WeakMapSet& markedWeakMaps); - // Remove a weakmap from its compartment's weakmaps list. + // Remove a weakmap from its zone's weakmaps list. static void removeWeakMapFromList(WeakMapBase* weakmap); // Any weakmap key types that want to participate in the non-iterative @@ -106,12 +106,12 @@ class WeakMapBase { // Object that this weak map is part of, if any. HeapPtrObject memberOf; - // Compartment that this weak map is part of. - JSCompartment* compartment; + // Zone containing this weak map. + JS::Zone* zone; - // Link in a list of all WeakMaps in a compartment, headed by - // JSCompartment::gcWeakMapList. The last element of the list has nullptr as - // its next. Maps not in the list have WeakMapNotInList as their next. + // Link in a list of all WeakMaps in a Zone, headed by + // JS::Zone::gcWeakMapList. The last element of the list has nullptr as its + // next. Maps not in the list have WeakMapNotInList as their next. WeakMapBase* next; // Whether this object has been traced during garbage collection. @@ -142,14 +142,14 @@ class WeakMap : public HashMap, publ typedef typename Base::AddPtr AddPtr; explicit WeakMap(JSContext* cx, JSObject* memOf = nullptr) - : Base(cx->runtime()), WeakMapBase(memOf, cx->compartment()) { } + : Base(cx->runtime()), WeakMapBase(memOf, cx->compartment()->zone()) { } bool init(uint32_t len = 16) { if (!Base::init(len)) return false; - next = compartment->gcWeakMapList; - compartment->gcWeakMapList = this; - marked = JS::IsIncrementalGCInProgress(compartment->runtimeFromMainThread()); + next = zone->gcWeakMapList; + zone->gcWeakMapList = this; + marked = JS::IsIncrementalGCInProgress(zone->runtimeFromMainThread()); return true; } diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h index 7f10b461013f..72c8e41f72fe 100644 --- a/js/src/vm/Debugger.h +++ b/js/src/vm/Debugger.h @@ -82,12 +82,16 @@ class DebuggerWeakMap : private WeakMap, Relocatabl RuntimeAllocPolicy> CountMap; CountMap zoneCounts; + JSCompartment* compartment; public: typedef WeakMap > Base; explicit DebuggerWeakMap(JSContext* cx) - : Base(cx), zoneCounts(cx->runtime()) { } + : Base(cx), + zoneCounts(cx->runtime()), + compartment(cx->compartment()) + { } ~DebuggerWeakMap() { // If our owning Debugger fails construction after already initializing @@ -121,7 +125,7 @@ class DebuggerWeakMap : private WeakMap, Relocatabl template bool relookupOrAdd(AddPtr& p, const KeyInput& k, const ValueInput& v) { - MOZ_ASSERT(v->compartment() == Base::compartment); + MOZ_ASSERT(v->compartment() == this->compartment); MOZ_ASSERT(!k->compartment()->options_.mergeable()); MOZ_ASSERT_IF(!InvisibleKeysOk, !k->compartment()->options_.invisibleToDebugger()); MOZ_ASSERT(!Base::has(k)); From fa74c411371028b624c9eb78d2e4b09389ed07e5 Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Mon, 21 Sep 2015 19:53:36 +0200 Subject: [PATCH 056/133] Bug 683218 - Disable __noSuchMethod__ support. r=jorendorff --- js/src/builtin/TestingFunctions.cpp | 13 +++++++++++++ js/src/jit-test/tests/baseline/bug945223.js | 2 ++ js/src/jit-test/tests/basic/bug717208.js | 2 ++ js/src/jit-test/tests/basic/bug732087.js | 1 + js/src/jit-test/tests/ion/callelem.js | 2 ++ js/src/jit-test/tests/jaeger/bug555922.js | 2 ++ js/src/jit-test/tests/jaeger/bug732423.js | 2 ++ js/src/jsapi.h | 10 +++++++++- js/src/tests/js1_5/extensions/no-such-method.js | 3 +++ js/src/tests/js1_5/extensions/regress-564577.js | 3 ++- js/src/tests/js1_8/regress/regress-384412.js | 2 ++ .../js1_8_5/extensions/noSuchMethod-symbols.js | 3 +++ js/src/vm/Interpreter.cpp | 3 +++ 13 files changed, 46 insertions(+), 2 deletions(-) diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 54297130e073..639c67391dcf 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -2794,6 +2794,15 @@ GetLcovInfo(JSContext* cx, unsigned argc, Value* vp) return true; } +static bool +EnableNoSuchMethod(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + cx->runtime()->options().setNoSuchMethod(true); + args.rval().setUndefined(); + return true; +} + #ifdef DEBUG static bool SetRNGState(JSContext* cx, unsigned argc, Value* vp) @@ -3260,6 +3269,10 @@ gc::ZealModeHelpText), " Generate LCOV tracefile for the given compartment. If no global are provided then\n" " the current global is used as the default one.\n"), + JS_FN_HELP("enableNoSuchMethod", EnableNoSuchMethod, 0, 0, +"enableNoSuchMethod()", +" Enables the deprecated, non-standard __noSuchMethod__ feature.\n"), + #ifdef DEBUG JS_FN_HELP("setRNGState", SetRNGState, 1, 0, "setRNGState(seed)", diff --git a/js/src/jit-test/tests/baseline/bug945223.js b/js/src/jit-test/tests/baseline/bug945223.js index ff1cf07a0792..bb947cdc4d7e 100644 --- a/js/src/jit-test/tests/baseline/bug945223.js +++ b/js/src/jit-test/tests/baseline/bug945223.js @@ -17,6 +17,8 @@ if (getJitCompilerOptions()["ion.forceinlineCaches"]) setJitCompilerOption("ion.forceinlineCaches", 0); +enableNoSuchMethod(); + Array.prototype.__proto__ = Proxy.create({ getPropertyDescriptor: function(name) { return (560566); diff --git a/js/src/jit-test/tests/basic/bug717208.js b/js/src/jit-test/tests/basic/bug717208.js index 304200108500..9fc31953b499 100644 --- a/js/src/jit-test/tests/basic/bug717208.js +++ b/js/src/jit-test/tests/basic/bug717208.js @@ -1,3 +1,5 @@ +enableNoSuchMethod(); + var count = 0; var a = {__noSuchMethod__: function() { count++; } } diff --git a/js/src/jit-test/tests/basic/bug732087.js b/js/src/jit-test/tests/basic/bug732087.js index 852b4142b6a9..678e5685a23f 100644 --- a/js/src/jit-test/tests/basic/bug732087.js +++ b/js/src/jit-test/tests/basic/bug732087.js @@ -1,3 +1,4 @@ +enableNoSuchMethod(); gczeal(2,1); var count = 0; var a = {__noSuchMethod__: function() { count++; } } diff --git a/js/src/jit-test/tests/ion/callelem.js b/js/src/jit-test/tests/ion/callelem.js index e13f35554fc4..0ff91fd1a36c 100644 --- a/js/src/jit-test/tests/ion/callelem.js +++ b/js/src/jit-test/tests/ion/callelem.js @@ -1,3 +1,5 @@ +enableNoSuchMethod(); + var res = 0; var o = {}; o.__noSuchMethod__ = function(x) { res += x; }; diff --git a/js/src/jit-test/tests/jaeger/bug555922.js b/js/src/jit-test/tests/jaeger/bug555922.js index 5cd685ae98c2..b104035cf22c 100644 --- a/js/src/jit-test/tests/jaeger/bug555922.js +++ b/js/src/jit-test/tests/jaeger/bug555922.js @@ -1,3 +1,5 @@ +enableNoSuchMethod(); + (function() { let(z) { for each(b in [{}]) { ({ diff --git a/js/src/jit-test/tests/jaeger/bug732423.js b/js/src/jit-test/tests/jaeger/bug732423.js index 7b9727623c7a..954e037c8942 100644 --- a/js/src/jit-test/tests/jaeger/bug732423.js +++ b/js/src/jit-test/tests/jaeger/bug732423.js @@ -1,3 +1,5 @@ +enableNoSuchMethod(); + function testStuff(x, y) { for (var i = 0; i < 60; i++) { x[y](); diff --git a/js/src/jsapi.h b/js/src/jsapi.h index ddc6afbb5fca..1a41d4a635af 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1156,7 +1156,8 @@ class JS_PUBLIC_API(RuntimeOptions) { asyncStack_(true), werror_(false), strictMode_(false), - extraWarnings_(false) + extraWarnings_(false), + noSuchMethod_(false) { } @@ -1238,6 +1239,12 @@ class JS_PUBLIC_API(RuntimeOptions) { return *this; } + bool noSuchMethod() const { return noSuchMethod_; } + RuntimeOptions& setNoSuchMethod(bool flag) { + noSuchMethod_ = flag; + return *this; + } + private: bool baseline_ : 1; bool ion_ : 1; @@ -1248,6 +1255,7 @@ class JS_PUBLIC_API(RuntimeOptions) { bool werror_ : 1; bool strictMode_ : 1; bool extraWarnings_ : 1; + bool noSuchMethod_ : 1; }; JS_PUBLIC_API(RuntimeOptions&) diff --git a/js/src/tests/js1_5/extensions/no-such-method.js b/js/src/tests/js1_5/extensions/no-such-method.js index 60cbfdf2025b..4e8375e7bdf3 100644 --- a/js/src/tests/js1_5/extensions/no-such-method.js +++ b/js/src/tests/js1_5/extensions/no-such-method.js @@ -1,3 +1,4 @@ +// |reftest| skip-if(!xulRuntime.shell) /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ /* 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 @@ -9,6 +10,8 @@ var summary = '__noSuchMethod__ handler'; var actual = ''; var expect = ''; +enableNoSuchMethod(); + printBugNumber(BUGNUMBER); printStatus (summary); diff --git a/js/src/tests/js1_5/extensions/regress-564577.js b/js/src/tests/js1_5/extensions/regress-564577.js index 3156999d0769..dfc6860471b8 100644 --- a/js/src/tests/js1_5/extensions/regress-564577.js +++ b/js/src/tests/js1_5/extensions/regress-564577.js @@ -1,3 +1,4 @@ +// |reftest| skip-if(!xulRuntime.shell) /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ /* * Any copyright is dedicated to the Public Domain. @@ -12,8 +13,8 @@ var summary = '__noSuchMethod__ when property exists'; var actual = ''; var expect = ''; - //----------------------------------------------------------------------------- +enableNoSuchMethod(); test(); //----------------------------------------------------------------------------- diff --git a/js/src/tests/js1_8/regress/regress-384412.js b/js/src/tests/js1_8/regress/regress-384412.js index be4c9ffef87c..2199f10241a2 100644 --- a/js/src/tests/js1_8/regress/regress-384412.js +++ b/js/src/tests/js1_8/regress/regress-384412.js @@ -1,3 +1,4 @@ +// |reftest| skip-if(!xulRuntime.shell) /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ /* 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 @@ -11,6 +12,7 @@ var expect = ''; //----------------------------------------------------------------------------- +enableNoSuchMethod(); test(); //----------------------------------------------------------------------------- diff --git a/js/src/tests/js1_8_5/extensions/noSuchMethod-symbols.js b/js/src/tests/js1_8_5/extensions/noSuchMethod-symbols.js index 01ebc77e7308..7d49b1d72050 100644 --- a/js/src/tests/js1_8_5/extensions/noSuchMethod-symbols.js +++ b/js/src/tests/js1_8_5/extensions/noSuchMethod-symbols.js @@ -1,6 +1,9 @@ +// |reftest| skip-if(!xulRuntime.shell) // Any copyright is dedicated to the Public Domain. // http://creativecommons.org/licenses/publicdomain/ +enableNoSuchMethod(); + var sym = Symbol("method"); var hits = 0; var obj = { diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index c7594c0d1913..8235d3d859b8 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -169,6 +169,9 @@ static const Class js_NoSuchMethodClass = { bool js::OnUnknownMethod(JSContext* cx, HandleObject obj, Value idval_, MutableHandleValue vp) { + if (!cx->runtime()->options().noSuchMethod()) + return true; + RootedValue idval(cx, idval_); RootedValue value(cx); From 3301b277a135d588261f4d6c24686267aa01db68 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Mon, 21 Sep 2015 09:41:29 -0700 Subject: [PATCH 057/133] Bug 1188290 - Remove an incomplete assertion about store buffer state; r=jandem --- js/src/gc/StoreBuffer.h | 8 -------- js/src/jit-test/tests/gc/bug-1188290.js | 12 ++++++++++++ js/src/jsobj.h | 8 ++++---- 3 files changed, 16 insertions(+), 12 deletions(-) create mode 100644 js/src/jit-test/tests/gc/bug-1188290.js diff --git a/js/src/gc/StoreBuffer.h b/js/src/gc/StoreBuffer.h index 71a9a3c81f6f..00353c068e77 100644 --- a/js/src/gc/StoreBuffer.h +++ b/js/src/gc/StoreBuffer.h @@ -447,14 +447,6 @@ class StoreBuffer putFromAnyThread(bufferGeneric, CallbackRef(callback, key, data)); } - void assertHasCellEdge(Cell** cellp) { - CellPtrEdge cpe(cellp); - - MOZ_ASSERT(bufferCell.has(this, CellPtrEdge(cellp)) || - !CellPtrEdge(cellp).maybeInRememberedSet(nursery_)); - - } - void assertHasValueEdge(JS::Value* vp) { MOZ_ASSERT(bufferVal.has(this, ValueEdge(vp)) || !ValueEdge(vp).maybeInRememberedSet(nursery_)); diff --git a/js/src/jit-test/tests/gc/bug-1188290.js b/js/src/jit-test/tests/gc/bug-1188290.js new file mode 100644 index 000000000000..f6f8b91bfd19 --- /dev/null +++ b/js/src/jit-test/tests/gc/bug-1188290.js @@ -0,0 +1,12 @@ +this.__proto__ = []; +var T = TypedObject; +var ObjectStruct = new T.StructType({f: T.Object}); +var o = new ObjectStruct(); +minorgc(); +function writeObject(o, v) { + o.f = v; + assertEq(typeof o.f, "object"); +} +for (var i = 0; i < 5; i++) + writeObject(o, { toString: function() { return "helo"} } +); diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 3e8da316611e..1a40bd90c5ee 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -642,11 +642,11 @@ JSObject::writeBarrierPost(void* cellp, JSObject* prev, JSObject* next) js::gc::StoreBuffer* buffer; if (next && (buffer = next->storeBuffer())) { // If we know that the prev has already inserted an entry, we can skip - // doing the lookup to add the new entry. - if (prev && prev->storeBuffer()) { - buffer->assertHasCellEdge(static_cast(cellp)); + // doing the lookup to add the new entry. Note that we cannot safely + // assert the presence of the entry because it may have been added + // via a different store buffer. + if (prev && prev->storeBuffer()) return; - } buffer->putCellFromAnyThread(static_cast(cellp)); return; } From f78dc5562550d24a9c85405734fa5f3f828e8793 Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Mon, 21 Sep 2015 12:47:02 -0400 Subject: [PATCH 058/133] Bug 1205476 - crash in mozilla::a11y::DocAccessible::ProcessInvalidationList, part2, r=davidb --- accessible/generic/DocAccessible.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accessible/generic/DocAccessible.cpp b/accessible/generic/DocAccessible.cpp index 73696495cf4f..3c6c1ff25eb3 100644 --- a/accessible/generic/DocAccessible.cpp +++ b/accessible/generic/DocAccessible.cpp @@ -1348,12 +1348,12 @@ DocAccessible::ProcessInvalidationList() // Alter the tree according to aria-owns (seize the trees). for (uint32_t idx = 0; idx < mARIAOwnsInvalidationList.Length(); idx++) { Accessible* owner = mARIAOwnsInvalidationList[idx].mOwner; - if (owner->IsDefunct()) { // eventually died until we've got here + if (!owner->IsInDocument()) { // eventually died before we've got here continue; } Accessible* child = GetAccessible(mARIAOwnsInvalidationList[idx].mChild); - if (!child) { + if (!child || !child->IsInDocument()) { continue; } From 7479d7b332ba272c5eddc74f5304c895432b3e78 Mon Sep 17 00:00:00 2001 From: Patrick McManus Date: Mon, 21 Sep 2015 13:22:23 -0400 Subject: [PATCH 059/133] bug 1206771 - fix reentrantFlag compiler warning on >= beta r=jduell --- netwerk/protocol/http/nsHttpTransaction.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/netwerk/protocol/http/nsHttpTransaction.cpp b/netwerk/protocol/http/nsHttpTransaction.cpp index ff51345b18fa..5dd887c580d3 100644 --- a/netwerk/protocol/http/nsHttpTransaction.cpp +++ b/netwerk/protocol/http/nsHttpTransaction.cpp @@ -792,6 +792,8 @@ nsHttpTransaction::WriteSegments(nsAHttpSegmentWriter *writer, uint32_t count, uint32_t *countWritten) { static bool reentrantFlag = false; + LOG(("nsHttpTransaction::WriteSegments %p reentrantFlag=%d", + this, reentrantFlag)); MOZ_DIAGNOSTIC_ASSERT(!reentrantFlag); reentrantFlag = true; MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); From ff0f1ae8672cab6698f96b86bac05384e3c2e423 Mon Sep 17 00:00:00 2001 From: "Dustin J. Mitchell" Date: Wed, 16 Sep 2015 06:48:37 -0400 Subject: [PATCH 060/133] Bug 1205241: enable linux64 opt/dbg and MacOSX64 builds on m-i and m-c; r=ted.mielczarek Properly splitting clobber (try) and non-clobber builds --HG-- rename : testing/taskcluster/tasks/builds/dbg_macosx64.yml => testing/taskcluster/tasks/builds/dbg_macosx64_clobber.yml rename : testing/taskcluster/tasks/builds/opt_macosx64.yml => testing/taskcluster/tasks/builds/opt_macosx64_clobber.yml extra : commitid : 8rc1ZSq1hkA extra : rebase_source : 01c0decaeef5737430f2f8b30d4780800accd447 --- .../taskcluster/tasks/branches/base_jobs.yml | 14 +++++ .../branches/mozilla-central/job_flags.yml | 8 --- .../tasks/branches/try/job_flags.yml | 28 +++++----- .../tasks/builds/dbg_macosx64_clobber.yml | 22 ++++++++ .../taskcluster/tasks/builds/opt_macosx64.yml | 53 +----------------- .../tasks/builds/opt_macosx64_clobber.yml | 55 +++++++++++++++++++ 6 files changed, 108 insertions(+), 72 deletions(-) create mode 100644 testing/taskcluster/tasks/builds/dbg_macosx64_clobber.yml create mode 100644 testing/taskcluster/tasks/builds/opt_macosx64_clobber.yml diff --git a/testing/taskcluster/tasks/branches/base_jobs.yml b/testing/taskcluster/tasks/branches/base_jobs.yml index ed6920efa470..da57b06eff31 100644 --- a/testing/taskcluster/tasks/branches/base_jobs.yml +++ b/testing/taskcluster/tasks/branches/base_jobs.yml @@ -110,6 +110,20 @@ builds: types: opt: task: tasks/builds/b2g_nexus_5l_eng.yml + linux64: + platforms: + - Linux64 + types: + opt: + task: tasks/builds/opt_linux64.yml + debug: + task: tasks/builds/dbg_linux64.yml + macosx64: + platforms: + - MacOSX64 + types: + debug: + task: tasks/builds/dbg_macosx64.yml tests: cppunit: diff --git a/testing/taskcluster/tasks/branches/mozilla-central/job_flags.yml b/testing/taskcluster/tasks/branches/mozilla-central/job_flags.yml index 2feb7a070a7f..a95de44d2476 100644 --- a/testing/taskcluster/tasks/branches/mozilla-central/job_flags.yml +++ b/testing/taskcluster/tasks/branches/mozilla-central/job_flags.yml @@ -34,11 +34,3 @@ builds: task: tasks/builds/b2g_flame_kk_ota_opt.yml debug: task: tasks/builds/b2g_flame_kk_ota_debug.yml - linux64: - platforms: - - Linux64 - types: - opt: - task: tasks/builds/opt_linux64.yml - debug: - task: tasks/builds/dbg_linux64.yml diff --git a/testing/taskcluster/tasks/branches/try/job_flags.yml b/testing/taskcluster/tasks/branches/try/job_flags.yml index 2c3e2172be72..139af6b8934d 100644 --- a/testing/taskcluster/tasks/branches/try/job_flags.yml +++ b/testing/taskcluster/tasks/branches/try/job_flags.yml @@ -129,20 +129,6 @@ builds: types: opt: task: tasks/builds/android_api_11.yml - linux64: - platforms: - - Linux64 - types: - opt: - task: tasks/builds/opt_linux64_clobber.yml - debug: - task: tasks/builds/dbg_linux64_clobber.yml - macosx64: - platforms: - - MacOSX64 - types: - debug: - task: tasks/builds/dbg_macosx64.yml sm-plain: platforms: - Linux64 @@ -189,6 +175,20 @@ builds: task: tasks/builds/sm_warnaserr.yml debug: task: tasks/builds/sm_warnaserrdebug.yml + linux64: + platforms: + - Linux64 + types: + opt: + task: tasks/builds/opt_linux64_clobber.yml + debug: + task: tasks/builds/dbg_linux64_clobber.yml + macosx64: + platforms: + - MacOSX64 + types: + debug: + task: tasks/builds/dbg_macosx64_clobber.yml post-build: upload-symbols: diff --git a/testing/taskcluster/tasks/builds/dbg_macosx64_clobber.yml b/testing/taskcluster/tasks/builds/dbg_macosx64_clobber.yml new file mode 100644 index 000000000000..a53ad42ac834 --- /dev/null +++ b/testing/taskcluster/tasks/builds/dbg_macosx64_clobber.yml @@ -0,0 +1,22 @@ +$inherits: + from: 'tasks/builds/opt_macosx64_clobber.yml' + variables: + build_name: 'macosx64' + build_type: 'dbg' +task: + metadata: + name: '[TC] MacOSX64 Dbg' + description: 'MacOSX64 Dbg' + + workerType: dbg-macosx64 + + payload: + env: + MH_CUSTOM_BUILD_VARIANT_CFG: 'cross-debug' + extra: + treeherder: + groupSymbol: tc + groupName: Submitted by taskcluster + symbol: B + collection: + debug: true diff --git a/testing/taskcluster/tasks/builds/opt_macosx64.yml b/testing/taskcluster/tasks/builds/opt_macosx64.yml index 26a4bf0c0aab..7c20abd44a6c 100644 --- a/testing/taskcluster/tasks/builds/opt_macosx64.yml +++ b/testing/taskcluster/tasks/builds/opt_macosx64.yml @@ -1,57 +1,10 @@ $inherits: - from: 'tasks/builds/firefox_base.yml' - variables: - build_name: 'macosx64' - build_type: 'opt' + from: 'tasks/builds/opt_macosx64_clobber.yml' task: - metadata: - name: '[TC] MacOSX64 Opt' - description: 'MacOSX64 Opt' - - workerType: opt-macosx64 - - routes: - - 'index.buildbot.branches.{{project}}.macosx64' - - 'index.buildbot.revisions.{{head_rev}}.{{project}}.macosx64' - + # same as clobber, but with a cached workspace scopes: - 'docker-worker:cache:build-macosx64-workspace' - - 'docker-worker:cache:tooltool-cache' - - 'docker-worker:relengapi-proxy:tooltool.download.internal' - - 'docker-worker:relengapi-proxy:tooltool.download.public' payload: - image: '{{#docker_image}}desktop-build{{/docker_image}}' cache: - build-macosx64-c6-workspace: '/home/worker/workspace' - tooltool-cache: '/home/worker/tooltool-cache' - - features: - relengAPIProxy: true - - env: - MOZHARNESS_SCRIPT: 'mozharness/scripts/fx_desktop_build.py' - MOZHARNESS_CONFIG: 'builds/releng_base_mac_64_cross_builds.py balrog/production.py' - MH_BRANCH: {{project}} - MH_BUILD_POOL: taskcluster - # image paths - TOOLTOOL_CACHE: '/home/worker/tooltool-cache' - - maxRunTime: 36000 - - command: ["/bin/bash", "bin/build.sh"] - - extra: - treeherderEnv: - - production - - staging - treeherder: - machine: - # see https://github.com/mozilla/treeherder/blob/master/ui/js/values.js - platform: osx-10-7 - # Rather then enforcing particular conventions we require that all build - # tasks provide the "build" extra field to specify where the build and tests - # files are located. - locations: - build: 'public/build/target.dmg' - tests: 'public/build/target.tests.zip' + build-macosx64-workspace: '/home/worker/workspace' diff --git a/testing/taskcluster/tasks/builds/opt_macosx64_clobber.yml b/testing/taskcluster/tasks/builds/opt_macosx64_clobber.yml new file mode 100644 index 000000000000..a34eb51de3a2 --- /dev/null +++ b/testing/taskcluster/tasks/builds/opt_macosx64_clobber.yml @@ -0,0 +1,55 @@ +$inherits: + from: 'tasks/builds/firefox_base.yml' + variables: + build_name: 'macosx64' + build_type: 'opt' +task: + metadata: + name: '[TC] MacOSX64 Opt' + description: 'MacOSX64 Opt' + + workerType: opt-macosx64 + + routes: + - 'index.buildbot.branches.{{project}}.macosx64' + - 'index.buildbot.revisions.{{head_rev}}.{{project}}.macosx64' + + scopes: + - 'docker-worker:cache:tooltool-cache' + - 'docker-worker:relengapi-proxy:tooltool.download.internal' + - 'docker-worker:relengapi-proxy:tooltool.download.public' + + payload: + image: '{{#docker_image}}desktop-build{{/docker_image}}' + cache: + tooltool-cache: '/home/worker/tooltool-cache' + + features: + relengAPIProxy: true + + env: + MOZHARNESS_SCRIPT: 'mozharness/scripts/fx_desktop_build.py' + MOZHARNESS_CONFIG: 'builds/releng_base_mac_64_cross_builds.py balrog/production.py' + MH_BRANCH: {{project}} + MH_BUILD_POOL: taskcluster + # image paths + TOOLTOOL_CACHE: '/home/worker/tooltool-cache' + + maxRunTime: 36000 + + command: ["/bin/bash", "bin/build.sh"] + + extra: + treeherderEnv: + - production + - staging + treeherder: + machine: + # see https://github.com/mozilla/treeherder/blob/master/ui/js/values.js + platform: osx-10-7 + # Rather then enforcing particular conventions we require that all build + # tasks provide the "build" extra field to specify where the build and tests + # files are located. + locations: + build: 'public/build/target.dmg' + tests: 'public/build/target.tests.zip' From 1273371c400a1ac49527cc9e7bdfc89f0f40d44d Mon Sep 17 00:00:00 2001 From: Steven Michaud Date: Mon, 21 Sep 2015 14:20:35 -0500 Subject: [PATCH 061/133] Bug 1206766 - Show meaningful module offsets in stack traces even when no symbol found. r=spohl --- widget/cocoa/nsCocoaDebugUtils.mm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/widget/cocoa/nsCocoaDebugUtils.mm b/widget/cocoa/nsCocoaDebugUtils.mm index 6932601b9a5d..35896dc401a8 100644 --- a/widget/cocoa/nsCocoaDebugUtils.mm +++ b/widget/cocoa/nsCocoaDebugUtils.mm @@ -240,6 +240,9 @@ nsCocoaDebugUtils::GetAddressStringInt(void* aAddress, CSTypeRef aOwner) addressName = CSSymbolGetName(symbol); CSRange range = CSSymbolGetRange(symbol); addressOffset = (unsigned long long) aAddress - range.location; + } else { + addressOffset = (unsigned long long) + aAddress - CSSymbolOwnerGetBaseAddress(owner); } } From bea16e0d3348301a51a8087af5d0cd076146ccc5 Mon Sep 17 00:00:00 2001 From: David Burns Date: Wed, 16 Sep 2015 18:43:23 +0100 Subject: [PATCH 062/133] Bug 1141519: Don't switch to content scope for logging the test end; r=jgriffin --HG-- extra : commitid : IC9y6Vij4Fj extra : rebase_source : b54d233528ffd1713bef0e2c6bae2c5b484b04fc --- testing/marionette/client/marionette/marionette_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/testing/marionette/client/marionette/marionette_test.py b/testing/marionette/client/marionette/marionette_test.py index 6f0ecb96242e..d8b9db791885 100644 --- a/testing/marionette/client/marionette/marionette_test.py +++ b/testing/marionette/client/marionette/marionette_test.py @@ -691,7 +691,6 @@ class MarionetteTestCase(CommonTestCase): def tearDown(self): if not self.marionette.check_for_crash(): - self.marionette.set_context("content") self.marionette.clear_imported_scripts() self.marionette.execute_script("log('TEST-END: %s:%s')" % (self.filepath.replace('\\', '\\\\'), self.methodName)) From 6a79407a30ab61e84e30cb6e56089c44f211a36c Mon Sep 17 00:00:00 2001 From: David Burns Date: Fri, 18 Sep 2015 21:39:01 +0100 Subject: [PATCH 063/133] Bug 1141519: added test that puts marionette into a position that can cause hangs when in content scope; r=jgriffin --HG-- extra : commitid : GrvcthCmHw1 extra : rebase_source : 1bc3fe4b2e6b1c839503f431955c5681e4edcc61 --- .../marionette/tests/unit/test_chrome.py | 35 +++++++++++++++++++ .../marionette/tests/unit/unit-tests.ini | 3 ++ 2 files changed, 38 insertions(+) create mode 100644 testing/marionette/client/marionette/tests/unit/test_chrome.py diff --git a/testing/marionette/client/marionette/tests/unit/test_chrome.py b/testing/marionette/client/marionette/tests/unit/test_chrome.py new file mode 100644 index 000000000000..72e59218e447 --- /dev/null +++ b/testing/marionette/client/marionette/tests/unit/test_chrome.py @@ -0,0 +1,35 @@ +#Copyright 2007-2009 WebDriver committers +#Copyright 2007-2009 Google Inc. +# +#Licensed under the Apache License, Version 2.0 (the "License"); +#you may not use this file except in compliance with the License. +#You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +#Unless required by applicable law or agreed to in writing, software +#distributed under the License is distributed on an "AS IS" BASIS, +#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#See the License for the specific language governing permissions and +#limitations under the License. + +from marionette_driver import By +from marionette_driver.errors import NoSuchElementException +from marionette import MarionetteTestCase + + +class ChromeTests(MarionetteTestCase): + + def test_hang_until_timeout(self): + with self.marionette.using_context('chrome'): + start_handle = self.marionette.current_chrome_window_handle + menu = self.marionette.find_element(By.ID, 'aboutName') + menu.click() + handles = self.marionette.chrome_window_handles + handles.remove(start_handle) + self.marionette.switch_to_window(handles[0]) + self.assertRaises(NoSuchElementException, self.marionette.find_element, By.ID, 'dek') + + # Clean up the window + self.marionette.close() + self.marionette.switch_to_window(start_handle) diff --git a/testing/marionette/client/marionette/tests/unit/unit-tests.ini b/testing/marionette/client/marionette/tests/unit/unit-tests.ini index d4396661a34a..dccdf01d43c1 100644 --- a/testing/marionette/client/marionette/tests/unit/unit-tests.ini +++ b/testing/marionette/client/marionette/tests/unit/unit-tests.ini @@ -159,3 +159,6 @@ skip-if = os == "win" # http://bugs.python.org/issue14574 [test_using_permissions.py] [test_shadow_dom.py] + +[test_chrome.py] +b2g = false From 4dda200aaf8278b10e2e96d663261dafd403513d Mon Sep 17 00:00:00 2001 From: David Burns Date: Wed, 16 Sep 2015 20:54:46 +0100 Subject: [PATCH 064/133] Bug 1141519: error if we are going to try send a message to a frame that we know doesnt exist; r=jgriffin --HG-- extra : commitid : HT9JmxPxSRk extra : rebase_source : 3354f9f476612c773c22262ff9ec1b455356780b --- testing/marionette/driver.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/testing/marionette/driver.js b/testing/marionette/driver.js index 8cee66e78756..2ec38b408846 100644 --- a/testing/marionette/driver.js +++ b/testing/marionette/driver.js @@ -221,7 +221,12 @@ GeckoDriver.prototype.sendAsync = function(name, msg, cmdId) { if (curRemoteFrame === null) { this.curBrowser.executeWhenReady(() => { - this.mm.broadcastAsyncMessage(name + this.curBrowser.curFrameId, msg); + if (this.curBrowser.curFrameId) { + this.mm.broadcastAsyncMessage(name + this.curBrowser.curFrameId, msg); + } + else { + throw new WebDriverError("Can not send call to listener as it doesnt exist"); + } }); } else { let remoteFrameId = curRemoteFrame.targetFrameId; From 87f6a90707435cd53c9555616f959b3e37d43073 Mon Sep 17 00:00:00 2001 From: David Burns Date: Wed, 16 Sep 2015 20:58:28 +0100 Subject: [PATCH 065/133] Bug 1141519: if we try call marionette calls in the teardown and they don't work we should just carry on; r=jgriffin --HG-- extra : commitid : 92srjBSkvhe extra : rebase_source : 33569e134ffb89036ee18651c9f8d37bec43a489 --- .../client/marionette/marionette_test.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/testing/marionette/client/marionette/marionette_test.py b/testing/marionette/client/marionette/marionette_test.py index d8b9db791885..29e058770e15 100644 --- a/testing/marionette/client/marionette/marionette_test.py +++ b/testing/marionette/client/marionette/marionette_test.py @@ -691,10 +691,17 @@ class MarionetteTestCase(CommonTestCase): def tearDown(self): if not self.marionette.check_for_crash(): - self.marionette.clear_imported_scripts() - self.marionette.execute_script("log('TEST-END: %s:%s')" % - (self.filepath.replace('\\', '\\\\'), self.methodName)) - self.marionette.test_name = None + try: + self.marionette.clear_imported_scripts() + self.marionette.execute_script("log('TEST-END: %s:%s')" % + (self.filepath.replace('\\', '\\\\'), + self.methodName)) + self.marionette.test_name = None + except: + # We have tried to log the test end when there is no listener + # object that we can access + pass + CommonTestCase.tearDown(self) def get_new_emulator(self): From 156399b67fd55c5eb51794c0b67c22d5525bdf6e Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Mon, 21 Sep 2015 22:32:15 -0400 Subject: [PATCH 066/133] Bug 1206801 - fix broken CONFIG['DEBUG'] checks in moz.build files; r=mshal These were supposed to be CONFIG['MOZ_DEBUG']. webapprt doesn't use the define it set up, however, so it was deleted rather than fixed. --- webapprt/win/moz.build | 2 -- widget/cocoa/moz.build | 2 +- xulrunner/app/moz.build | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/webapprt/win/moz.build b/webapprt/win/moz.build index 9b37940d17ad..9c159253e53c 100644 --- a/webapprt/win/moz.build +++ b/webapprt/win/moz.build @@ -14,8 +14,6 @@ SOURCES += [ ] DEFINES['XPCOM_GLUE'] = True -if CONFIG['DEBUG']: - DEFINES['DEBUG'] = True DEFINES['APP_VERSION'] = CONFIG['FIREFOX_VERSION'] diff --git a/widget/cocoa/moz.build b/widget/cocoa/moz.build index 0979cb909ff9..5e918d252607 100644 --- a/widget/cocoa/moz.build +++ b/widget/cocoa/moz.build @@ -70,7 +70,7 @@ SOURCES += [ 'nsNativeThemeCocoa.mm', ] -if not CONFIG['RELEASE_BUILD'] or CONFIG['DEBUG']: +if not CONFIG['RELEASE_BUILD'] or CONFIG['MOZ_DEBUG']: SOURCES += [ 'nsSandboxViolationSink.mm', ] diff --git a/xulrunner/app/moz.build b/xulrunner/app/moz.build index f8b75599c3f7..0195a439906f 100644 --- a/xulrunner/app/moz.build +++ b/xulrunner/app/moz.build @@ -13,7 +13,7 @@ SOURCES += [ ] DEFINES['XULRUNNER_PROGNAME'] = '"xulrunner"' -if CONFIG['DEBUG']: +if CONFIG['MOZ_DEBUG']: DEFINES['DEBUG'] = True LOCAL_INCLUDES += [ From bdefda6d0b9ab92264cf68c24b17e90dbabe14f5 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Fri, 18 Sep 2015 17:16:08 -0700 Subject: [PATCH 067/133] Bug 1205586 - new Date().toLocale{,Date,Time}String() should return appropriately differing strings as the local time zone/default locale change. r=till --- js/src/builtin/Date.js | 82 +++++++++++++++---- js/src/jsapi-tests/moz.build | 1 + js/src/jsapi-tests/testDateToLocaleString.cpp | 54 ++++++++++++ js/src/vm/SelfHosting.cpp | 11 +++ 4 files changed, 133 insertions(+), 15 deletions(-) create mode 100644 js/src/jsapi-tests/testDateToLocaleString.cpp diff --git a/js/src/builtin/Date.js b/js/src/builtin/Date.js index 5bd8575c21dc..8e938b30da9f 100644 --- a/js/src/builtin/Date.js +++ b/js/src/builtin/Date.js @@ -5,9 +5,73 @@ /*global intl_DateTimeFormat: false, */ +// This cache, once primed, has these properties: +// +// runtimeDefaultLocale: +// Locale information provided by the embedding, guiding SpiderMonkey's +// selection of a default locale. See RuntimeDefaultLocale(), whose +// value controls the value returned by DefaultLocale() that's what's +// *actually* used. +// localTZA: +// The local time zone's adjustment from UTC. See LocalTZA(). +// formatters: +// A Record storing formatters consistent with the above +// runtimeDefaultLocale/localTZA values, for use with the appropriate +// ES6 toLocale*String Date method when called with its first two +// arguments having the value |undefined|. +// +// The "formatters" Record has (some subset of) these properties, as determined +// by all values of the first argument passed to |GetCachedFormat|: +// +// dateTimeFormat: for Date's toLocaleString operation +// dateFormat: for Date's toLocaleDateString operation +// timeFormat: for Date's toLocaleTimeString operation +// +// Using this cache, then, requires 1) verifying the current +// runtimeDefaultLocale/localTZA are consistent with cached values, then +// 2) seeing if the desired formatter is cached and returning it if so, or else +// 3) create the desired formatter and store and return it. var dateTimeFormatCache = new Record(); +/** + * Get a cached DateTimeFormat formatter object, created like so: + * + * var opts = ToDateTimeOptions(undefined, required, defaults); + * return new Intl.DateTimeFormat(undefined, opts); + * + * |format| must be a key from the "formatters" Record described above. + */ +function GetCachedFormat(format, required, defaults) { + assert(format === "dateTimeFormat" || + format === "dateFormat" || + format === "timeFormat", + "unexpected format key: please update the comment by " + + "dateTimeFormatCache"); + + var runtimeDefaultLocale = RuntimeDefaultLocale(); + var localTZA = LocalTZA(); + + var formatters; + if (dateTimeFormatCache.runtimeDefaultLocale !== runtimeDefaultLocale || + dateTimeFormatCache.localTZA !== localTZA) + { + formatters = dateTimeFormatCache.formatters = new Record(); + dateTimeFormatCache.runtimeDefaultLocale = runtimeDefaultLocale; + dateTimeFormatCache.localTZA = localTZA; + } else { + formatters = dateTimeFormatCache.formatters; + } + + var fmt = formatters[format]; + if (fmt === undefined) { + var options = ToDateTimeOptions(undefined, required, defaults); + fmt = formatters[format] = intl_DateTimeFormat(undefined, options); + } + + return fmt; +} + /** * Format this Date object into a date and time string, using the locale and * formatting options provided. @@ -30,11 +94,7 @@ function Date_toLocaleString() { if (locales === undefined && options === undefined) { // This cache only optimizes for the old ES5 toLocaleString without // locales and options. - if (dateTimeFormatCache.dateTimeFormat === undefined) { - options = ToDateTimeOptions(options, "any", "all"); - dateTimeFormatCache.dateTimeFormat = intl_DateTimeFormat(locales, options); - } - dateTimeFormat = dateTimeFormatCache.dateTimeFormat; + dateTimeFormat = GetCachedFormat("dateTimeFormat", "any", "all"); } else { options = ToDateTimeOptions(options, "any", "all"); dateTimeFormat = intl_DateTimeFormat(locales, options); @@ -67,11 +127,7 @@ function Date_toLocaleDateString() { if (locales === undefined && options === undefined) { // This cache only optimizes for the old ES5 toLocaleDateString without // locales and options. - if (dateTimeFormatCache.dateFormat === undefined) { - options = ToDateTimeOptions(options, "date", "date"); - dateTimeFormatCache.dateFormat = intl_DateTimeFormat(locales, options); - } - dateTimeFormat = dateTimeFormatCache.dateFormat; + dateTimeFormat = GetCachedFormat("dateFormat", "date", "date"); } else { options = ToDateTimeOptions(options, "date", "date"); dateTimeFormat = intl_DateTimeFormat(locales, options); @@ -104,11 +160,7 @@ function Date_toLocaleTimeString() { if (locales === undefined && options === undefined) { // This cache only optimizes for the old ES5 toLocaleTimeString without // locales and options. - if (dateTimeFormatCache.timeFormat === undefined) { - options = ToDateTimeOptions(options, "time", "time"); - dateTimeFormatCache.timeFormat = intl_DateTimeFormat(locales, options); - } - dateTimeFormat = dateTimeFormatCache.timeFormat; + dateTimeFormat = GetCachedFormat("timeFormat", "time", "time"); } else { options = ToDateTimeOptions(options, "time", "time"); dateTimeFormat = intl_DateTimeFormat(locales, options); diff --git a/js/src/jsapi-tests/moz.build b/js/src/jsapi-tests/moz.build index 97eb662f1141..b7f913a39fc4 100644 --- a/js/src/jsapi-tests/moz.build +++ b/js/src/jsapi-tests/moz.build @@ -18,6 +18,7 @@ UNIFIED_SOURCES += [ 'testClassGetter.cpp', 'testCloneScript.cpp', 'testContexts.cpp', + 'testDateToLocaleString.cpp', 'testDebugger.cpp', 'testDeepFreeze.cpp', 'testDefineGetterSetterNonEnumerable.cpp', diff --git a/js/src/jsapi-tests/testDateToLocaleString.cpp b/js/src/jsapi-tests/testDateToLocaleString.cpp new file mode 100644 index 000000000000..495f7cffd2a6 --- /dev/null +++ b/js/src/jsapi-tests/testDateToLocaleString.cpp @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + */ +/* 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/. */ + +#include "jsapi-tests/tests.h" + +BEGIN_TEST(testDateToLocaleString) +{ + // This test should only attempt to run if we have Intl support: necessary + // to properly assume that changes to the default locale will predictably + // affect the behavior of the locale-sensitive Date methods tested here. + JS::Rooted haveIntl(cx); + EVAL("typeof Intl !== 'undefined'", &haveIntl); + if (!haveIntl.toBoolean()) + return true; + + // Pervasive assumption: our Intl support includes "de" (German) and + // "en" (English) and treats them differently for purposes of + // Date.prototype.toLocale{,Date,Time}String behavior. + + // Start with German. + CHECK(JS_SetDefaultLocale(rt, "de")); + + // The (constrained) Date object we'll use to test behavior. + EXEC("var d = new Date(Date.UTC(2015, 9 - 1, 17));"); + + // Test that toLocaleString behavior changes with default locale changes. + EXEC("var deAll = d.toLocaleString();"); + + CHECK(JS_SetDefaultLocale(rt, "en")); + EXEC("if (d.toLocaleString() === deAll) \n" + " throw 'toLocaleString results should have changed with system locale change';"); + + // Test that toLocaleDateString behavior changes with default locale changes. + EXEC("var enDate = d.toLocaleDateString();"); + + CHECK(JS_SetDefaultLocale(rt, "de")); + EXEC("if (d.toLocaleDateString() === enDate) \n" + " throw 'toLocaleDateString results should have changed with system locale change';"); + + // Test that toLocaleTimeString behavior changes with default locale changes. + EXEC("var deTime = d.toLocaleTimeString();"); + + CHECK(JS_SetDefaultLocale(rt, "en")); + EXEC("if (d.toLocaleTimeString() === deTime) \n" + " throw 'toLocaleTimeString results should have changed with system locale change';"); + + JS_ResetDefaultLocale(rt); + return true; +} +END_TEST(testDateToLocaleString) diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index 7c4ac5c9b0db..5b78de7b7036 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -1204,6 +1204,16 @@ intrinsic_RuntimeDefaultLocale(JSContext* cx, unsigned argc, Value* vp) return true; } +static bool +intrinsic_LocalTZA(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + MOZ_ASSERT(args.length() == 0, "the LocalTZA intrinsic takes no arguments"); + + args.rval().setDouble(cx->runtime()->dateTimeInfo.localTZA()); + return true; +} + static bool intrinsic_IsConstructing(JSContext* cx, unsigned argc, Value* vp) { @@ -1324,6 +1334,7 @@ static const JSFunctionSpec intrinsic_functions[] = { JS_FN("_ConstructorForTypedArray", intrinsic_ConstructorForTypedArray, 1,0), JS_FN("DecompileArg", intrinsic_DecompileArg, 2,0), JS_FN("RuntimeDefaultLocale", intrinsic_RuntimeDefaultLocale, 0,0), + JS_FN("LocalTZA", intrinsic_LocalTZA, 0,0), JS_INLINABLE_FN("_IsConstructing", intrinsic_IsConstructing, 0,0, IntrinsicIsConstructing), From 9f027cf4059fcbe5de376268cc17ad48e71f21db Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Fri, 18 Sep 2015 17:16:08 -0700 Subject: [PATCH 068/133] Bug 1206300 - Allow immutable prototypes to be disabled at compile time with a single-line change, but don't actually disable them. r=jorendorff --- js/src/builtin/TestingFunctions.cpp | 14 ++++++++++++++ js/src/jsfriendapi.h | 3 +++ js/src/jsobj.cpp | 16 ++++++++++++++-- .../ecma_6/extensions/setImmutablePrototype.js | 4 +++- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 639c67391dcf..413bc1a75ec5 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -2463,6 +2463,15 @@ ByteSize(JSContext* cx, unsigned argc, Value* vp) return true; } +static bool +ImmutablePrototypesEnabled(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + + args.rval().setBoolean(JS_ImmutablePrototypesEnabled()); + return true; +} + static bool SetImmutablePrototype(JSContext* cx, unsigned argc, Value* vp) { @@ -3215,6 +3224,11 @@ gc::ZealModeHelpText), " Return the size in bytes occupied by |value|, or |undefined| if value\n" " is not allocated in memory.\n"), + JS_FN_HELP("immutablePrototypesEnabled", ImmutablePrototypesEnabled, 0, 0, +"immutablePrototypesEnabled()", +" Returns true if immutable-prototype behavior (triggered by setImmutablePrototype)\n" +" is enabled, such that modifying an immutable prototype will fail."), + JS_FN_HELP("setImmutablePrototype", SetImmutablePrototype, 1, 0, "setImmutablePrototype(obj)", " Try to make obj's [[Prototype]] immutable, such that subsequent attempts to\n" diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index 0db40f85af1e..82d00050f77a 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -70,6 +70,9 @@ JS_ObjectCountDynamicSlots(JS::HandleObject obj); extern JS_FRIEND_API(size_t) JS_SetProtoCalled(JSContext* cx); +extern JS_FRIEND_API(bool) +JS_ImmutablePrototypesEnabled(); + extern JS_FRIEND_API(size_t) JS_GetCustomIteratorCount(JSContext* cx); diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 66971d9b9365..04bda668151d 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -2387,6 +2387,19 @@ JSObject::reportNotExtensible(JSContext* cx, unsigned report) nullptr, nullptr); } +// Our immutable-prototype behavior is non-standard, and it's unclear whether +// it's shippable. (Or at least it's unclear whether it's shippable with any +// provided-by-default uses exposed to script.) If this bool is true, +// immutable-prototype behavior is enforced; if it's false, behavior is not +// enforced, and immutable-prototype bits stored on objects are completely +// ignored. +static const bool ImmutablePrototypesEnabled = true; + +JS_FRIEND_API(bool) +JS_ImmutablePrototypesEnabled() +{ + return ImmutablePrototypesEnabled; +} /*** ES6 standard internal methods ***************************************************************/ @@ -2405,9 +2418,8 @@ js::SetPrototype(JSContext* cx, HandleObject obj, HandleObject proto, JS::Object } /* Disallow mutation of immutable [[Prototype]]s. */ - if (obj->nonLazyPrototypeIsImmutable()) { + if (obj->nonLazyPrototypeIsImmutable() && ImmutablePrototypesEnabled) return result.fail(JSMSG_CANT_SET_PROTO); - } /* * Disallow mutating the [[Prototype]] on ArrayBuffer objects, which diff --git a/js/src/tests/ecma_6/extensions/setImmutablePrototype.js b/js/src/tests/ecma_6/extensions/setImmutablePrototype.js index d22c7175c57a..1663f9c081f6 100644 --- a/js/src/tests/ecma_6/extensions/setImmutablePrototype.js +++ b/js/src/tests/ecma_6/extensions/setImmutablePrototype.js @@ -86,7 +86,9 @@ function checkPrototypeMutationFailure(obj, desc) function runNormalTests(global) { - if (typeof setImmutablePrototype !== "function") + if (typeof setImmutablePrototype !== "function" || + (typeof immutablePrototypesEnabled === "function" && + !immutablePrototypesEnabled())) { print("no usable setImmutablePrototype function available, skipping tests"); return; From 65b65a49996a6ae7bac91f12efd650f25ffd59de Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Sun, 23 Aug 2015 01:10:24 -0700 Subject: [PATCH 069/133] Bug 1187234 - Throw a TypeError when Array.isArray is passed a revoked proxy. r=efaust --- js/ipc/JavaScriptBase.h | 7 ++ js/ipc/PJavaScript.ipdl | 1 + js/ipc/WrapperAnswer.cpp | 27 +++++++ js/ipc/WrapperAnswer.h | 1 + js/ipc/WrapperOwner.cpp | 29 +++++++ js/ipc/WrapperOwner.h | 3 + js/public/Class.h | 37 +++++++-- js/public/Proxy.h | 3 + js/src/jsarray.cpp | 57 +++++++++++-- js/src/jsobjinlines.h | 12 --- js/src/json.cpp | 25 +++--- js/src/jswrapper.h | 3 + js/src/proxy/BaseProxyHandler.cpp | 9 +++ js/src/proxy/DeadObjectProxy.cpp | 7 ++ js/src/proxy/DeadObjectProxy.h | 1 + js/src/proxy/DirectProxyHandler.cpp | 7 ++ .../proxy/OpaqueCrossCompartmentWrapper.cpp | 8 ++ js/src/proxy/Proxy.cpp | 6 ++ js/src/proxy/Proxy.h | 1 + js/src/proxy/ScriptedDirectProxyHandler.cpp | 23 +++--- js/src/proxy/ScriptedDirectProxyHandler.h | 2 + js/src/proxy/SecurityWrapper.cpp | 9 +++ js/src/tests/ecma_6/Array/isArray.js | 79 ++++++++++++++----- 23 files changed, 294 insertions(+), 63 deletions(-) diff --git a/js/ipc/JavaScriptBase.h b/js/ipc/JavaScriptBase.h index 28c8337706fe..910b511f8c1a 100644 --- a/js/ipc/JavaScriptBase.h +++ b/js/ipc/JavaScriptBase.h @@ -91,6 +91,9 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base bool* result) { return Answer::RecvObjectClassIs(ObjectId::deserialize(objId), classValue, result); } + bool RecvIsArray(const uint64_t& objId, ReturnStatus* rs, uint32_t* answer) { + return Answer::RecvIsArray(ObjectId::deserialize(objId), rs, answer); + } bool RecvClassName(const uint64_t& objId, nsCString* result) { return Answer::RecvClassName(ObjectId::deserialize(objId), result); } @@ -179,6 +182,10 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base bool* result) { return Base::SendObjectClassIs(objId.serialize(), classValue, result); } + bool SendIsArray(const ObjectId& objId, ReturnStatus* rs, uint32_t* answer) + { + return Base::SendIsArray(objId.serialize(), rs, answer); + } bool SendClassName(const ObjectId& objId, nsCString* result) { return Base::SendClassName(objId.serialize(), result); } diff --git a/js/ipc/PJavaScript.ipdl b/js/ipc/PJavaScript.ipdl index bea7941c0edc..b1617a27a778 100644 --- a/js/ipc/PJavaScript.ipdl +++ b/js/ipc/PJavaScript.ipdl @@ -39,6 +39,7 @@ both: prio(high) sync CallOrConstruct(uint64_t objId, JSParam[] argv, bool construct) returns (ReturnStatus rs, JSVariant result, JSParam[] outparams); prio(high) sync HasInstance(uint64_t objId, JSVariant v) returns (ReturnStatus rs, bool has); prio(high) sync ObjectClassIs(uint64_t objId, uint32_t classValue) returns (bool result); + prio(high) sync IsArray(uint64_t objId) returns (ReturnStatus rs, uint32_t ans); prio(high) sync ClassName(uint64_t objId) returns (nsCString name); prio(high) sync GetPrototype(uint64_t objId) returns (ReturnStatus rs, ObjectOrNullVariant result); prio(high) sync RegExpToShared(uint64_t objId) returns (ReturnStatus rs, nsString source, uint32_t flags); diff --git a/js/ipc/WrapperAnswer.cpp b/js/ipc/WrapperAnswer.cpp index ef7f7f2718f9..a1fb01d2c83b 100644 --- a/js/ipc/WrapperAnswer.cpp +++ b/js/ipc/WrapperAnswer.cpp @@ -11,6 +11,7 @@ #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/ScriptSettings.h" #include "xpcprivate.h" +#include "js/Class.h" #include "jsfriendapi.h" using namespace JS; @@ -521,6 +522,32 @@ WrapperAnswer::RecvObjectClassIs(const ObjectId& objId, const uint32_t& classVal return true; } +bool +WrapperAnswer::RecvIsArray(const ObjectId& objId, ReturnStatus* rs, + uint32_t* ans) +{ + *ans = uint32_t(IsArrayAnswer::NotArray); + + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) + return false; + jsapi.TakeOwnershipOfErrorReporting(); + JSContext* cx = jsapi.cx(); + + RootedObject obj(cx, findObjectById(cx, objId)); + if (!obj) + return fail(jsapi, rs); + + LOG("%s.isArray()", ReceiverObj(objId)); + + IsArrayAnswer answer; + if (!JS::IsArray(cx, obj, &answer)) + return fail(jsapi, rs); + + *ans = uint32_t(answer); + return ok(rs); +} + bool WrapperAnswer::RecvClassName(const ObjectId& objId, nsCString* name) { diff --git a/js/ipc/WrapperAnswer.h b/js/ipc/WrapperAnswer.h index ebb154a76851..d28f1733d25d 100644 --- a/js/ipc/WrapperAnswer.h +++ b/js/ipc/WrapperAnswer.h @@ -53,6 +53,7 @@ class WrapperAnswer : public virtual JavaScriptShared bool RecvHasInstance(const ObjectId& objId, const JSVariant& v, ReturnStatus* rs, bool* bp); bool RecvObjectClassIs(const ObjectId& objId, const uint32_t& classValue, bool* result); + bool RecvIsArray(const ObjectId& objId, ReturnStatus* rs, uint32_t* ans); bool RecvClassName(const ObjectId& objId, nsCString* result); bool RecvGetPrototype(const ObjectId& objId, ReturnStatus* rs, ObjectOrNullVariant* result); bool RecvRegExpToShared(const ObjectId& objId, ReturnStatus* rs, nsString* source, uint32_t* flags); diff --git a/js/ipc/WrapperOwner.cpp b/js/ipc/WrapperOwner.cpp index 97e7160fc4b8..3c8dd1acb5a8 100644 --- a/js/ipc/WrapperOwner.cpp +++ b/js/ipc/WrapperOwner.cpp @@ -127,6 +127,8 @@ class CPOWProxyHandler : public BaseProxyHandler MutableHandleValue v, bool* bp) const override; virtual bool objectClassIs(HandleObject obj, js::ESClassValue classValue, JSContext* cx) const override; + virtual bool isArray(JSContext* cx, HandleObject obj, + IsArrayAnswer* answer) const override; virtual const char* className(JSContext* cx, HandleObject proxy) const override; virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const override; virtual void finalize(JSFreeOp* fop, JSObject* proxy) const override; @@ -741,6 +743,33 @@ WrapperOwner::objectClassIs(JSContext* cx, HandleObject proxy, js::ESClassValue return result; } +bool +CPOWProxyHandler::isArray(JSContext* cx, HandleObject proxy, + IsArrayAnswer* answer) const +{ + FORWARD(isArray, (cx, proxy, answer)); +} + +bool +WrapperOwner::isArray(JSContext* cx, HandleObject proxy, IsArrayAnswer* answer) +{ + ObjectId objId = idOf(proxy); + + uint32_t ans; + ReturnStatus status; + if (!SendIsArray(objId, &status, &ans)) + return ipcfail(cx); + + LOG_STACK(); + + *answer = IsArrayAnswer(ans); + MOZ_ASSERT(*answer == IsArrayAnswer::Array || + *answer == IsArrayAnswer::NotArray || + *answer == IsArrayAnswer::RevokedProxy); + + return ok(cx, status); +} + const char* CPOWProxyHandler::className(JSContext* cx, HandleObject proxy) const { diff --git a/js/ipc/WrapperOwner.h b/js/ipc/WrapperOwner.h index ac1cccc8cc34..f93dc8d3f0b4 100644 --- a/js/ipc/WrapperOwner.h +++ b/js/ipc/WrapperOwner.h @@ -55,6 +55,7 @@ class WrapperOwner : public virtual JavaScriptShared JS::AutoIdVector& props); bool hasInstance(JSContext* cx, JS::HandleObject proxy, JS::MutableHandleValue v, bool* bp); bool objectClassIs(JSContext* cx, JS::HandleObject obj, js::ESClassValue classValue); + bool isArray(JSContext* cx, JS::HandleObject proxy, JS::IsArrayAnswer* answer); const char* className(JSContext* cx, JS::HandleObject proxy); bool getPrototype(JSContext* cx, JS::HandleObject proxy, JS::MutableHandleObject protop); @@ -140,6 +141,8 @@ class WrapperOwner : public virtual JavaScriptShared ReturnStatus* rs, bool* bp) = 0; virtual bool SendObjectClassIs(const ObjectId& objId, const uint32_t& classValue, bool* result) = 0; + virtual bool SendIsArray(const ObjectId& objId, ReturnStatus* rs, + uint32_t* answer) = 0; virtual bool SendClassName(const ObjectId& objId, nsCString* result) = 0; virtual bool SendGetPrototype(const ObjectId& objId, ReturnStatus* rs, ObjectOrNullVariant* result) = 0; virtual bool SendRegExpToShared(const ObjectId& objId, ReturnStatus* rs, nsString* source, diff --git a/js/public/Class.h b/js/public/Class.h index e7a502f65c3d..6aca25ec2832 100644 --- a/js/public/Class.h +++ b/js/public/Class.h @@ -46,6 +46,37 @@ template class AutoVectorRooter; typedef AutoVectorRooter AutoIdVector; +// The answer to a successful query as to whether an object is an Array per +// ES6's internal |IsArray| operation (as exposed by |Array.isArray|). +enum class IsArrayAnswer +{ + Array, + NotArray, + RevokedProxy +}; + +// ES6 7.2.2. +// +// Returns false on failure, otherwise returns true and sets |*isArray| +// indicating whether the object passes ECMAScript's IsArray test. This is the +// same test performed by |Array.isArray|. +// +// This is NOT the same as asking whether |obj| is an Array or a wrapper around +// one. If |obj| is a proxy created by |Proxy.revocable()| and has been +// revoked, or if |obj| is a proxy whose target (at any number of hops) is a +// revoked proxy, this method throws a TypeError and returns false. +extern JS_PUBLIC_API(bool) +IsArray(JSContext* cx, HandleObject obj, bool* isArray); + +// Identical to IsArray above, but the nature of the object (if successfully +// determined) is communicated via |*answer|. In particular this method +// returns true and sets |*answer = IsArrayAnswer::RevokedProxy| when called on +// a revoked proxy. +// +// Most users will want the overload above, not this one. +extern JS_PUBLIC_API(bool) +IsArray(JSContext* cx, HandleObject obj, IsArrayAnswer* answer); + /* * Per ES6, the [[DefineOwnProperty]] internal method has three different * possible outcomes: @@ -800,11 +831,7 @@ Valueify(const JSClass* c) enum ESClassValue { ESClass_Object, ESClass_Array, ESClass_Number, ESClass_String, ESClass_Boolean, ESClass_RegExp, ESClass_ArrayBuffer, ESClass_SharedArrayBuffer, - ESClass_Date, ESClass_Set, ESClass_Map, - - // Special snowflake for the ES6 IsArray method. - // Please don't use it without calling that function. - ESClass_IsArray + ESClass_Date, ESClass_Set, ESClass_Map }; /* diff --git a/js/public/Proxy.h b/js/public/Proxy.h index 5bee3c8761a4..427ddc3480e0 100644 --- a/js/public/Proxy.h +++ b/js/public/Proxy.h @@ -323,6 +323,7 @@ class JS_FRIEND_API(BaseProxyHandler) const CallArgs& args) const; virtual bool hasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue v, bool* bp) const; virtual bool objectClassIs(HandleObject obj, ESClassValue classValue, JSContext* cx) const; + virtual bool isArray(JSContext* cx, HandleObject proxy, JS::IsArrayAnswer* answer) const; virtual const char* className(JSContext* cx, HandleObject proxy) const; virtual JSString* fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const; virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const; @@ -414,6 +415,8 @@ class JS_FRIEND_API(DirectProxyHandler) : public BaseProxyHandler bool* bp) const override; virtual bool objectClassIs(HandleObject obj, ESClassValue classValue, JSContext* cx) const override; + virtual bool isArray(JSContext* cx, HandleObject proxy, + JS::IsArrayAnswer* answer) const override; virtual const char* className(JSContext* cx, HandleObject proxy) const override; virtual JSString* fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const override; diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index b01cc76f630d..e8566ecf0189 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -57,8 +57,40 @@ using mozilla::IsNaN; using mozilla::UniquePtr; using JS::AutoCheckCannotGC; +using JS::IsArrayAnswer; using JS::ToUint32; +bool +JS::IsArray(JSContext* cx, HandleObject obj, IsArrayAnswer* answer) +{ + if (obj->is() || obj->is()) { + *answer = IsArrayAnswer::Array; + return true; + } + + if (obj->is()) + return Proxy::isArray(cx, obj, answer); + + *answer = IsArrayAnswer::NotArray; + return true; +} + +bool +JS::IsArray(JSContext* cx, HandleObject obj, bool* isArray) +{ + IsArrayAnswer answer; + if (!IsArray(cx, obj, &answer)) + return false; + + if (answer == IsArrayAnswer::RevokedProxy) { + JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED); + return false; + } + + *isArray = answer == IsArrayAnswer::Array; + return true; +} + bool js::GetLengthProperty(JSContext* cx, HandleObject obj, uint32_t* lengthp) { @@ -1996,8 +2028,13 @@ js::array_push(JSContext* cx, unsigned argc, Value* vp) // SetOrExtendAnyBoxedOrUnboxedDenseElements takes care of updating the // length for boxed and unboxed arrays. Handle updates to the length of // non-arrays here. - if (!IsArray(obj, cx)) + bool isArray; + if (!IsArray(cx, obj, &isArray)) + return false; + + if (!isArray) return SetLengthProperty(cx, obj, newlength); + return true; } } @@ -2590,7 +2627,10 @@ js::array_concat(JSContext* cx, unsigned argc, Value* vp) RootedObject narr(cx); uint32_t length; - if (IsArray(aobj, cx) && !ObjectMayHaveExtraIndexedProperties(aobj)) { + bool isArray; + if (!IsArray(cx, aobj, &isArray)) + return false; + if (isArray && !ObjectMayHaveExtraIndexedProperties(aobj)) { if (!GetLengthProperty(cx, aobj, &length)) return false; @@ -2615,7 +2655,10 @@ js::array_concat(JSContext* cx, unsigned argc, Value* vp) RootedObject obj(cx, &v.toObject()); // This should be IsConcatSpreadable - if (!IsArray(obj, cx) || ObjectMayHaveExtraIndexedProperties(obj)) + bool isArray; + if (!IsArray(cx, obj, &isArray)) + return false; + if (!isArray || ObjectMayHaveExtraIndexedProperties(obj)) break; uint32_t argLength; @@ -2671,7 +2714,10 @@ js::array_concat(JSContext* cx, unsigned argc, Value* vp) if (v.isObject()) { RootedObject obj(cx, &v.toObject()); // This should be IsConcatSpreadable - if (IsArray(obj, cx)) { + bool isArray; + if (!IsArray(cx, obj, &isArray)) + return false; + if (isArray) { uint32_t alength; if (!GetLengthProperty(cx, obj, &alength)) return false; @@ -2994,7 +3040,8 @@ array_isArray(JSContext* cx, unsigned argc, Value* vp) bool isArray = false; if (args.get(0).isObject()) { RootedObject obj(cx, &args[0].toObject()); - isArray = IsArray(obj, cx); + if (!IsArray(cx, obj, &isArray)) + return false; } args.rval().setBoolean(isArray); return true; diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 02a0c9a8c3b2..218f64fef02e 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -819,8 +819,6 @@ ObjectClassIs(HandleObject obj, ESClassValue classValue, JSContext* cx) switch (classValue) { case ESClass_Object: return obj->is() || obj->is(); case ESClass_Array: - case ESClass_IsArray: - // The difference between Array and IsArray is only relevant for proxies. return obj->is() || obj->is(); case ESClass_Number: return obj->is(); case ESClass_String: return obj->is(); @@ -844,16 +842,6 @@ IsObjectWithClass(const Value& v, ESClassValue classValue, JSContext* cx) return ObjectClassIs(obj, classValue, cx); } -// ES6 7.2.2 -inline bool -IsArray(HandleObject obj, JSContext* cx) -{ - if (obj->is() || obj->is()) - return true; - - return ObjectClassIs(obj, ESClass_IsArray, cx); -} - inline bool Unbox(JSContext* cx, HandleObject obj, MutableHandleValue vp) { diff --git a/js/src/json.cpp b/js/src/json.cpp index f97914a418e0..328c826ff971 100644 --- a/js/src/json.cpp +++ b/js/src/json.cpp @@ -8,6 +8,7 @@ #include "mozilla/FloatingPoint.h" #include "mozilla/Range.h" +#include "mozilla/ScopeExit.h" #include "jsarray.h" #include "jsatom.h" @@ -531,14 +532,13 @@ Str(JSContext* cx, const Value& v, StringifyContext* scx) RootedObject obj(cx, &v.toObject()); scx->depth++; - bool ok; - if (IsArray(obj, cx)) - ok = JA(cx, obj, scx); - else - ok = JO(cx, obj, scx); - scx->depth--; + auto dec = mozilla::MakeScopeExit([&] { scx->depth--; }); - return ok; + bool isArray; + if (!IsArray(cx, obj, &isArray)) + return false; + + return isArray ? JA(cx, obj, scx) : JO(cx, obj, scx); } /* ES5 15.12.3. */ @@ -552,9 +552,12 @@ js::Stringify(JSContext* cx, MutableHandleValue vp, JSObject* replacer_, Value s /* Step 4. */ AutoIdVector propertyList(cx); if (replacer) { + bool isArray; if (replacer->isCallable()) { /* Step 4a(i): use replacer to transform values. */ - } else if (IsArray(replacer, cx)) { + } else if (!IsArray(cx, replacer, &isArray)) { + return false; + } else if (isArray) { /* * Step 4b: The spec algorithm is unhelpfully vague about the exact * steps taken when the replacer is an array, regarding the exact @@ -721,7 +724,11 @@ Walk(JSContext* cx, HandleObject holder, HandleId name, HandleValue reviver, Mut if (val.isObject()) { RootedObject obj(cx, &val.toObject()); - if (IsArray(obj, cx)) { + bool isArray; + if (!IsArray(cx, obj, &isArray)) + return false; + + if (isArray) { /* Step 2a(ii). */ uint32_t length; if (!GetLengthProperty(cx, obj, &length)) diff --git a/js/src/jswrapper.h b/js/src/jswrapper.h index a319dcd4450f..7a996501b087 100644 --- a/js/src/jswrapper.h +++ b/js/src/jswrapper.h @@ -206,6 +206,8 @@ class JS_FRIEND_API(OpaqueCrossCompartmentWrapper) : public CrossCompartmentWrap virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject wrapper, AutoIdVector& props) const override; virtual bool objectClassIs(HandleObject obj, ESClassValue classValue, JSContext* cx) const override; + virtual bool isArray(JSContext* cx, HandleObject obj, + JS::IsArrayAnswer* answer) const override; virtual const char* className(JSContext* cx, HandleObject wrapper) const override; virtual JSString* fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const override; virtual bool defaultValue(JSContext* cx, HandleObject obj, JSType hint, MutableHandleValue vp) const override; @@ -247,6 +249,7 @@ class JS_FRIEND_API(SecurityWrapper) : public Base const CallArgs& args) const override; virtual bool objectClassIs(HandleObject obj, ESClassValue classValue, JSContext* cx) const override; + virtual bool isArray(JSContext* cx, HandleObject wrapper, JS::IsArrayAnswer* answer) const override; virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const override; virtual bool boxedValue_unbox(JSContext* cx, HandleObject proxy, MutableHandleValue vp) const override; virtual bool defaultValue(JSContext* cx, HandleObject wrapper, JSType hint, diff --git a/js/src/proxy/BaseProxyHandler.cpp b/js/src/proxy/BaseProxyHandler.cpp index 4ffd8934a553..9261975da436 100644 --- a/js/src/proxy/BaseProxyHandler.cpp +++ b/js/src/proxy/BaseProxyHandler.cpp @@ -12,6 +12,8 @@ using namespace js; +using JS::IsArrayAnswer; + bool BaseProxyHandler::enter(JSContext* cx, HandleObject wrapper, HandleId id, Action act, bool* bp) const @@ -322,6 +324,13 @@ BaseProxyHandler::objectClassIs(HandleObject proxy, ESClassValue classValue, JSC return false; } +bool +BaseProxyHandler::isArray(JSContext* cx, HandleObject proxy, IsArrayAnswer* answer) const +{ + *answer = IsArrayAnswer::NotArray; + return true; +} + void BaseProxyHandler::trace(JSTracer* trc, JSObject* proxy) const { diff --git a/js/src/proxy/DeadObjectProxy.cpp b/js/src/proxy/DeadObjectProxy.cpp index b3deaf98ece1..6e77b510fa16 100644 --- a/js/src/proxy/DeadObjectProxy.cpp +++ b/js/src/proxy/DeadObjectProxy.cpp @@ -120,6 +120,13 @@ DeadObjectProxy::objectClassIs(HandleObject obj, ESClassValue classValue, JSCont return false; } +bool +DeadObjectProxy::isArray(JSContext* cx, HandleObject obj, JS::IsArrayAnswer* answer) const +{ + ReportDead(cx); + return false; +} + const char* DeadObjectProxy::className(JSContext* cx, HandleObject wrapper) const { diff --git a/js/src/proxy/DeadObjectProxy.h b/js/src/proxy/DeadObjectProxy.h index c7639dae2a2b..7eba31d3d839 100644 --- a/js/src/proxy/DeadObjectProxy.h +++ b/js/src/proxy/DeadObjectProxy.h @@ -45,6 +45,7 @@ class DeadObjectProxy : public BaseProxyHandler bool* bp) const override; virtual bool objectClassIs(HandleObject obj, ESClassValue classValue, JSContext* cx) const override; + virtual bool isArray(JSContext* cx, HandleObject proxy, JS::IsArrayAnswer* answer) const override; virtual const char* className(JSContext* cx, HandleObject proxy) const override; virtual JSString* fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const override; virtual bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g) const override; diff --git a/js/src/proxy/DirectProxyHandler.cpp b/js/src/proxy/DirectProxyHandler.cpp index 0fdf7dc09716..47c0b65dff68 100644 --- a/js/src/proxy/DirectProxyHandler.cpp +++ b/js/src/proxy/DirectProxyHandler.cpp @@ -161,6 +161,13 @@ DirectProxyHandler::objectClassIs(HandleObject proxy, ESClassValue classValue, return ObjectClassIs(target, classValue, cx); } +bool +DirectProxyHandler::isArray(JSContext* cx, HandleObject proxy, JS::IsArrayAnswer* answer) const +{ + RootedObject target(cx, proxy->as().target()); + return IsArray(cx, target, answer); +} + const char* DirectProxyHandler::className(JSContext* cx, HandleObject proxy) const { diff --git a/js/src/proxy/OpaqueCrossCompartmentWrapper.cpp b/js/src/proxy/OpaqueCrossCompartmentWrapper.cpp index a607a58102c6..68f2bc69b150 100644 --- a/js/src/proxy/OpaqueCrossCompartmentWrapper.cpp +++ b/js/src/proxy/OpaqueCrossCompartmentWrapper.cpp @@ -157,6 +157,14 @@ OpaqueCrossCompartmentWrapper::objectClassIs(HandleObject obj, ESClassValue clas return false; } +bool +OpaqueCrossCompartmentWrapper::isArray(JSContext* cx, HandleObject obj, + JS::IsArrayAnswer* answer) const +{ + *answer = JS::IsArrayAnswer::NotArray; + return true; +} + const char* OpaqueCrossCompartmentWrapper::className(JSContext* cx, HandleObject proxy) const diff --git a/js/src/proxy/Proxy.cpp b/js/src/proxy/Proxy.cpp index 154e85168327..46b45c0e951a 100644 --- a/js/src/proxy/Proxy.cpp +++ b/js/src/proxy/Proxy.cpp @@ -461,6 +461,12 @@ Proxy::objectClassIs(HandleObject proxy, ESClassValue classValue, JSContext* cx) return proxy->as().handler()->objectClassIs(proxy, classValue, cx); } +bool +Proxy::isArray(JSContext* cx, HandleObject proxy, JS::IsArrayAnswer* answer) +{ + return proxy->as().handler()->isArray(cx, proxy, answer); +} + const char* Proxy::className(JSContext* cx, HandleObject proxy) { diff --git a/js/src/proxy/Proxy.h b/js/src/proxy/Proxy.h index 1ae6e119decb..af1366afdc68 100644 --- a/js/src/proxy/Proxy.h +++ b/js/src/proxy/Proxy.h @@ -57,6 +57,7 @@ class Proxy const CallArgs& args); static bool hasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue v, bool* bp); static bool objectClassIs(HandleObject obj, ESClassValue classValue, JSContext* cx); + static bool isArray(JSContext* cx, HandleObject proxy, JS::IsArrayAnswer* answer); static const char* className(JSContext* cx, HandleObject proxy); static JSString* fun_toString(JSContext* cx, HandleObject proxy, unsigned indent); static bool regexp_toShared(JSContext* cx, HandleObject proxy, RegExpGuard* g); diff --git a/js/src/proxy/ScriptedDirectProxyHandler.cpp b/js/src/proxy/ScriptedDirectProxyHandler.cpp index 3902d722ee14..314e7666db16 100644 --- a/js/src/proxy/ScriptedDirectProxyHandler.cpp +++ b/js/src/proxy/ScriptedDirectProxyHandler.cpp @@ -11,6 +11,8 @@ #include "jsobjinlines.h" using namespace js; + +using JS::IsArrayAnswer; using mozilla::ArrayLength; static inline bool @@ -1103,20 +1105,19 @@ bool ScriptedDirectProxyHandler::objectClassIs(HandleObject proxy, ESClassValue classValue, JSContext* cx) const { - // Special case IsArray. In every other instance ES wants to have exactly - // one object type and not a proxy around it, so return false. - if (classValue != ESClass_IsArray) - return false; + return false; +} - // In ES6 IsArray is supposed to poke at the Proxy target, instead we do this here. - // The reason for this is that we have proxies for which looking at the target might - // be impossible. So instead we use our little objectClassIs function that just works - // already across different wrappers. +bool +ScriptedDirectProxyHandler::isArray(JSContext* cx, HandleObject proxy, + IsArrayAnswer* answer) const +{ RootedObject target(cx, proxy->as().target()); - if (!target) - return false; + if (target) + return JS::IsArray(cx, target, answer); - return IsArray(target, cx); + *answer = IsArrayAnswer::RevokedProxy; + return true; } const char* diff --git a/js/src/proxy/ScriptedDirectProxyHandler.h b/js/src/proxy/ScriptedDirectProxyHandler.h index e01a4ce21524..c8e00cadac28 100644 --- a/js/src/proxy/ScriptedDirectProxyHandler.h +++ b/js/src/proxy/ScriptedDirectProxyHandler.h @@ -72,6 +72,8 @@ class ScriptedDirectProxyHandler : public BaseProxyHandler { bool* bp) const override; virtual bool objectClassIs(HandleObject obj, ESClassValue classValue, JSContext* cx) const override; + virtual bool isArray(JSContext* cx, HandleObject proxy, + JS::IsArrayAnswer* answer) const override; virtual const char* className(JSContext* cx, HandleObject proxy) const override; virtual JSString* fun_toString(JSContext* cx, HandleObject proxy, unsigned indent) const override; diff --git a/js/src/proxy/SecurityWrapper.cpp b/js/src/proxy/SecurityWrapper.cpp index 5dbfa0a5b00b..d4d07ba2f7f6 100644 --- a/js/src/proxy/SecurityWrapper.cpp +++ b/js/src/proxy/SecurityWrapper.cpp @@ -92,6 +92,15 @@ SecurityWrapper::objectClassIs(HandleObject obj, ESClassValue classValue, return false; } +template +bool +SecurityWrapper::isArray(JSContext* cx, HandleObject obj, JS::IsArrayAnswer* answer) const +{ + // This should ReportUnwrapDenied(cx), but bug 849730 disagrees. :-( + *answer = JS::IsArrayAnswer::NotArray; + return true; +} + template bool SecurityWrapper::regexp_toShared(JSContext* cx, HandleObject obj, RegExpGuard* g) const diff --git a/js/src/tests/ecma_6/Array/isArray.js b/js/src/tests/ecma_6/Array/isArray.js index ed8577406846..b752ad54e434 100644 --- a/js/src/tests/ecma_6/Array/isArray.js +++ b/js/src/tests/ecma_6/Array/isArray.js @@ -1,30 +1,67 @@ -assertEq(Array.isArray([]), true); +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ -var proxy = new Proxy([], {}); -assertEq(Array.isArray(proxy), true); +var global = this; +var otherGlobal = newGlobal(); -for (var i = 0; i < 10; i++) { - proxy = new Proxy(proxy, {}); +var thisGlobal = () => global; +var alternateGlobals = (function(i) { + return () => (i++ % 2) === 0 ? global : otherGlobal; +})(0); + +function performTests(pickGlobal) +{ + // Base case. + assertEq(Array.isArray([]), true); + + // Simple case: proxy to an array. + var proxy = new (pickGlobal()).Proxy([], {}); assertEq(Array.isArray(proxy), true); + + // Recursive proxy ultimately terminating in an array. + for (var i = 0; i < 10; i++) { + proxy = new (pickGlobal()).Proxy(proxy, {}); + assertEq(Array.isArray(proxy), true); + } + + // Revocable proxy to an array. + var revocable = (pickGlobal()).Proxy.revocable([], {}); + proxy = revocable.proxy; + assertEq(Array.isArray(proxy), true); + + // Recursive proxy ultimately terminating in a revocable proxy to an array. + for (var i = 0; i < 10; i++) { + proxy = new (pickGlobal()).Proxy(proxy, {}); + assertEq(Array.isArray(proxy), true); + } + + // Revoked proxy to (formerly) an array. + revocable.revoke(); + assertThrowsInstanceOf(() => Array.isArray(revocable.proxy), TypeError); + + // Recursive proxy ultimately terminating in a revoked proxy to an array. + assertThrowsInstanceOf(() => Array.isArray(proxy), TypeError); + } -var revocable = Proxy.revocable([], {}); -proxy = revocable.proxy; -assertEq(Array.isArray(proxy), true); +performTests(thisGlobal); +performTests(alternateGlobals); -for (var i = 0; i < 10; i++) { - proxy = new Proxy(proxy, {}); - assertEq(Array.isArray(proxy), true); +function crossGlobalTest() +{ + var array = new otherGlobal.Array(); + + // Array from another global. + assertEq(Array.isArray(array), true); + + // Proxy to an array from another global. + assertEq(Array.isArray(new Proxy(array, {})), true); + + // Other-global proxy to an array from that selfsame global. + assertEq(Array.isArray(new otherGlobal.Proxy(array, {})), true); } -revocable.revoke(); -assertEq(Array.isArray(revocable.proxy), false); -assertEq(Array.isArray(proxy), false); +crossGlobalTest(); -var global = newGlobal(); -var array = global.Array(); -assertEq(Array.isArray(array), true); -assertEq(Array.isArray(new Proxy(array, {})), true); -assertEq(Array.isArray(new global.Proxy(array, {})), true); - -reportCompare(true, true); +if (typeof reportCompare === "function") + reportCompare(true, true); From bfb725b5f3fc72f948c12f5ad3cb21d5be247c21 Mon Sep 17 00:00:00 2001 From: Edwin Flores Date: Tue, 22 Sep 2015 10:18:51 +1200 Subject: [PATCH 070/133] Bug 1187393 - Use GTK theme colours for search autocomplete popup - r=florian --- browser/themes/linux/searchbar.css | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/browser/themes/linux/searchbar.css b/browser/themes/linux/searchbar.css index b026cdb560dd..a4703ca18a44 100644 --- a/browser/themes/linux/searchbar.css +++ b/browser/themes/linux/searchbar.css @@ -54,9 +54,6 @@ menuitem[cmd="cmd_clearhistory"][disabled] { list-style-image: url("moz-icon://stock/gtk-clear?size=menu&state=disabled"); } - - - .searchbar-search-button-container { -moz-box-align: center; } @@ -88,15 +85,14 @@ menuitem[cmd="cmd_clearhistory"][disabled] { } .search-panel-current-engine { - border-bottom: 1px solid #ccc; + border-bottom: 1px solid rgba(0, 0, 0, 0.2); } .search-panel-header { font-weight: normal; - background-color: rgb(245, 245, 245); - border-top: 1px solid #ccc; + border-top: 1px solid rgba(0, 0, 0, 0.2); padding: 3px 5px; - color: #666; + color: MenuText; } .search-panel-tree[collapsed=true] + .search-panel-header { @@ -113,12 +109,12 @@ menuitem[cmd="cmd_clearhistory"][disabled] { } .search-panel-input-value { - color: black; + color: Highlight; } .search-panel-one-offs { margin: 0 -1px !important; - border-top: 1px solid #ccc; + border-top: 1px solid rgba(0, 0, 0, 0.2); } .searchbar-engine-one-off-item { @@ -130,14 +126,14 @@ menuitem[cmd="cmd_clearhistory"][disabled] { margin: 0 0; padding: 0 0; background: none; - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWCAYAAAABxvaqAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gofECQNNVW2/AAAABBJREFUGFdjOHPmzH8GehEA/KpKg9YTf4AAAAAASUVORK5CYII='); + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAWCAYAAAABxvaqAAAABmJLR0QA/wD/AP+gvaeTAAAAFElEQVQI12NgYGAwZmJgYGCgBwEAHpIAXs+dj/cAAAAASUVORK5CYII='); background-repeat: no-repeat; background-position: right center; } .searchbar-engine-one-off-item:not(.last-row) { box-sizing: content-box; - border-bottom: 1px solid #ccc; + border-bottom: 1px solid rgba(0, 0, 0, 0.2); } .searchbar-engine-one-off-item.last-of-row { @@ -178,7 +174,7 @@ menuitem[cmd="cmd_clearhistory"][disabled] { } .addengine-item:first-of-type { - border-top: 1px solid #ccc; + border-top: 1px solid rgba(0, 0, 0, 0.2); } .addengine-item[selected] { @@ -231,13 +227,15 @@ menuitem[cmd="cmd_clearhistory"][disabled] { .search-setting-button { -moz-appearance: none; + background-color: Menu; border: none; - border-top: 1px solid #ccc; + border-top: 1px solid rgba(0, 0, 0, 0.2); margin: 0; min-height: 32px; } .search-setting-button[selected] { - background-color: #d3d3d3; + background-color: Highlight; + color: HighlightText; border-top-color: #bdbebe; } From ce6cdc5ce3dd4db02c6481508f79d4da5b7e841f Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Mon, 21 Sep 2015 12:28:56 +1000 Subject: [PATCH 071/133] Bug 1205470: [MSE] Remove assertion. r=cpearce Can also remove mInitDone member as that information is redundant with the init promise being present --- dom/media/mediasource/MediaSourceDemuxer.cpp | 6 +----- dom/media/mediasource/MediaSourceDemuxer.h | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/dom/media/mediasource/MediaSourceDemuxer.cpp b/dom/media/mediasource/MediaSourceDemuxer.cpp index 4701ebf76d16..1fc0aa8ad408 100644 --- a/dom/media/mediasource/MediaSourceDemuxer.cpp +++ b/dom/media/mediasource/MediaSourceDemuxer.cpp @@ -27,7 +27,6 @@ using media::TimeIntervals; MediaSourceDemuxer::MediaSourceDemuxer() : mTaskQueue(new TaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK), /* aSupportsTailDispatch = */ true)) - , mInitDone(false) , mMonitor("MediaSourceDemuxer") { MOZ_ASSERT(NS_IsMainThread()); @@ -46,7 +45,6 @@ MediaSourceDemuxer::AttemptInit() MOZ_ASSERT(OnTaskQueue()); if (ScanSourceBuffersForContent()) { - mInitDone = true; return InitPromise::CreateAndResolve(NS_OK, __func__); } @@ -60,12 +58,10 @@ void MediaSourceDemuxer::NotifyDataArrived(uint32_t aLength, int64_t aOffset) nsRefPtr self = this; nsCOMPtr task = NS_NewRunnableFunction([self] () { - if (self->mInitDone) { + if (self->mInitPromise.IsEmpty()) { return; } - MOZ_ASSERT(!self->mInitPromise.IsEmpty()); if (self->ScanSourceBuffersForContent()) { - self->mInitDone = true; self->mInitPromise.ResolveIfExists(NS_OK, __func__); } }); diff --git a/dom/media/mediasource/MediaSourceDemuxer.h b/dom/media/mediasource/MediaSourceDemuxer.h index adfefc4317f5..ad3f068a45f7 100644 --- a/dom/media/mediasource/MediaSourceDemuxer.h +++ b/dom/media/mediasource/MediaSourceDemuxer.h @@ -74,7 +74,6 @@ private: nsTArray> mSourceBuffers; MozPromiseHolder mInitPromise; - bool mInitDone; // Monitor to protect members below across multiple threads. mutable Monitor mMonitor; From 51aed272e1dc619945573f705a1c43eb53f2c3ed Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 21 Sep 2015 15:35:26 -0700 Subject: [PATCH 072/133] Bug 1205942 (part 1) - Fix overflows in time_posix.cc. r=jld. We get the following warnings with clang. > ipc/chromium/src/base/time_posix.cc:103:57: error: overflow in expression; result is 0 with type 'long' [-Werror,-Winteger-overflow] > ipc/chromium/src/base/time_posix.cc:106:58: error: overflow in expression; result is -1000 with type 'long' [-Werror,-Winteger-overflow] This is a genuine bug. The upstream code in Chromium has changed (commit 2a278516943eee02e0206506a4b907fc0b55f27b) and this patch changes our code to be similar. I did tests and confirmed that instead of getting 0 or -1 for |milliseconds|, we now get -2147483648000 or 2147483647999, which is much better. --HG-- extra : rebase_source : f01a4f03bc1576980010426328116d03eb71079b --- ipc/chromium/src/base/time_posix.cc | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/ipc/chromium/src/base/time_posix.cc b/ipc/chromium/src/base/time_posix.cc index 8b833dcbe40c..3ea00b805734 100644 --- a/ipc/chromium/src/base/time_posix.cc +++ b/ipc/chromium/src/base/time_posix.cc @@ -99,13 +99,19 @@ Time Time::FromExploded(bool is_local, const Exploded& exploded) { // When representing the most distant time in the future, add in an extra // 999ms to avoid the time being less than any other possible value that // this function can return. + + // Take care to avoid overflows when time_t is int64_t. if (exploded.year < 1969) { - milliseconds = std::numeric_limits::min() * - kMillisecondsPerSecond; + int64_t min_seconds = (sizeof(time_t) < sizeof(int64_t)) + ? std::numeric_limits::min() + : std::numeric_limits::min(); + milliseconds = min_seconds * kMillisecondsPerSecond; } else { - milliseconds = (std::numeric_limits::max() * - kMillisecondsPerSecond) + - kMillisecondsPerSecond - 1; + int64_t max_seconds = (sizeof(time_t) < sizeof(int64_t)) + ? std::numeric_limits::max() + : std::numeric_limits::max(); + milliseconds = max_seconds * kMillisecondsPerSecond; + milliseconds += kMillisecondsPerSecond - 1; } } else { milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond; From 9f997cc6878b085accad60562db0d556d3497542 Mon Sep 17 00:00:00 2001 From: Eric Faust Date: Mon, 21 Sep 2015 15:40:25 -0700 Subject: [PATCH 073/133] Bug 1192412 - Followup: Unbreak js1_8_5/reflect-parse/classes.js, erroneously neutered. (rs=jorendorff) --- js/src/tests/js1_8_5/reflect-parse/classes.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/js/src/tests/js1_8_5/reflect-parse/classes.js b/js/src/tests/js1_8_5/reflect-parse/classes.js index 371819b2d55c..615a36673f1e 100644 --- a/js/src/tests/js1_8_5/reflect-parse/classes.js +++ b/js/src/tests/js1_8_5/reflect-parse/classes.js @@ -13,7 +13,8 @@ function classesEnabled() { function testClasses() { function methodFun(id, kind, generator, args, body = []) { assertEq(generator && kind === "method", generator); - let idN = ident(id); + assertEq(typeof id === 'string' || id === null, true); + let idN = typeof id === 'string' ? ident(id): null; let methodMaker = generator ? genFunExpr : funExpr; let methodName = kind !== "method" ? null : idN; return methodMaker(methodName, args.map(ident), blockStmt(body)); @@ -45,14 +46,14 @@ function testClasses() { function assertClass(str, methods, heritage=null) { let namelessStr = str.replace("NAME", ""); let namedStr = str.replace("NAME", "Foo"); - let namedCtor = ctorWithName("NAME"); + let namedCtor = ctorWithName("Foo"); let namelessCtor = ctorWithName(null); - let namelessMethods = methods.map(x => x == ctorPlaceholder ? namedCtor : x); + let namelessMethods = methods.map(x => x == ctorPlaceholder ? namelessCtor : x); let namedMethods = methods.map(x => x == ctorPlaceholder ? namedCtor : x); - assertClassExpr(namelessStr, methods, heritage); - assertClassExpr(namedStr, methods, heritage, ident("Foo")); + assertClassExpr(namelessStr, namelessMethods, heritage); + assertClassExpr(namedStr, namedMethods, heritage, ident("Foo")); - let template = classStmt(ident("Foo"), heritage, methods); + let template = classStmt(ident("Foo"), heritage, namedMethods); assertStmt(namedStr, template); } function assertNamedClassError(str, error) { From f5f105b74f7a707ef20fd9f5aec21b370b261e16 Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Tue, 25 Aug 2015 00:00:07 +0100 Subject: [PATCH 074/133] Bug 1099103 - Prevent numbers input using a grouping separator from being mis-processed as if the separator was a decimal separator. r=dholbert --- dom/html/test/forms/test_input_number_data.js | 5 ++ .../test/forms/test_input_number_l10n.html | 13 ++++ .../forms/test_input_number_validation.html | 15 +++++ layout/forms/nsNumberControlFrame.cpp | 64 +++++++++---------- 4 files changed, 62 insertions(+), 35 deletions(-) diff --git a/dom/html/test/forms/test_input_number_data.js b/dom/html/test/forms/test_input_number_data.js index e17f452fee19..a1b34b4a0e28 100644 --- a/dom/html/test/forms/test_input_number_data.js +++ b/dom/html/test/forms/test_input_number_data.js @@ -30,3 +30,8 @@ var tests = [ inputWithoutGrouping: "123456.78", value: 123456.78 }, ]; + +var invalidTests = [ + { desc: "Invalid German", langTag: "de", input: "12.34" } +]; + diff --git a/dom/html/test/forms/test_input_number_l10n.html b/dom/html/test/forms/test_input_number_l10n.html index db1ad0995ef4..4d46f7a80371 100644 --- a/dom/html/test/forms/test_input_number_l10n.html +++ b/dom/html/test/forms/test_input_number_l10n.html @@ -49,11 +49,24 @@ function runTest(test) { "') localization without grouping separator"); } +function runInvalidInputTest(test) { + elem.lang = test.langTag; + elem.value = 0; + elem.focus(); + elem.select(); + sendString(test.input); + is(elem.value, "", "Test " + test.desc + " ('" + test.langTag + + "') with invalid input: " + test.input); +} + function startTests() { elem = document.getElementById("input"); for (var test of tests) { runTest(test, elem); } + for (var test of invalidTests) { + runInvalidInputTest(test, elem); + } } diff --git a/dom/html/test/forms/test_input_number_validation.html b/dom/html/test/forms/test_input_number_validation.html index 8b8af2b7f278..336e47788abd 100644 --- a/dom/html/test/forms/test_input_number_validation.html +++ b/dom/html/test/forms/test_input_number_validation.html @@ -57,11 +57,26 @@ function runTest(test) { checkIsInvalid(elem, `${desc} without grouping separator`); } +function runInvalidInputTest(test) { + elem.lang = test.langTag; + + gInvalid = false; // reset + var desc = `${test.desc} (lang='${test.langTag}', id='${elem.id}')`; + elem.value = 0; + elem.focus(); + elem.select(); + sendString(test.input); + checkIsInvalid(elem, `${desc} with invalid input`); +} + function startTests() { elem = document.getElementById("input"); for (var test of tests) { runTest(test); } + for (var test of invalidTests) { + runInvalidInputTest(test); + } elem = document.getElementById("requiredinput"); for (var test of tests) { runTest(test); diff --git a/layout/forms/nsNumberControlFrame.cpp b/layout/forms/nsNumberControlFrame.cpp index d95bdda86103..78d8b5737db7 100644 --- a/layout/forms/nsNumberControlFrame.cpp +++ b/layout/forms/nsNumberControlFrame.cpp @@ -776,46 +776,40 @@ nsNumberControlFrame::GetValueOfAnonTextControl(nsAString& aValue) // // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#floating-point-numbers // - // so that it can be parsed by functions like HTMLInputElement:: - // StringToDecimal (the HTML-5-conforming parsing function) which don't know - // how to handle numbers that are formatted differently (for example, with - // non-ASCII digits, with grouping separator characters or with a decimal - // separator character other than '.'). - // - // We need to be careful to avoid normalizing numbers that are already - // formatted for a locale that matches the format of HTML 5's "valid - // floating-point number" and have no grouping separator characters. (In - // other words we want to return the number as specified by the user, not the - // de-localized serialization, since the latter will normalize the value.) - // For example, if the user's locale is English and the user types in "2e2" - // then inputElement.value should be "2e2" and not "100". This is because - // content (and tests) expect us to avoid "normalizing" the number that the - // user types in if it's not necessary in order to make sure it conforms to - // HTML 5's "valid floating-point number" format. - // - // Note that we also need to be careful when trying to avoid normalization. - // For example, just because "1.234" _looks_ like a valid floating-point - // number according to the spec does not mean that it should be returned - // as-is. If the user's locale is German, then this represents the value - // 1234, not 1.234, so it still needs to be de-localized. Alternatively, if - // the user's locale is English and they type in "1,234" we _do_ need to - // normalize the number to "1234" because HTML 5's valid floating-point - // number format does not allow the ',' grouping separator. We can detect all - // the cases where we need to convert by seeing if the locale-specific - // parsing function understands the user input to mean the same thing as the - // HTML-5-conforming parsing function. If so, then we should return the value - // as-is to avoid normalization. Otherwise, we return the de-localized - // serialization. + // This is necessary to allow the number that we return to be parsed by + // functions like HTMLInputElement::StringToDecimal (the HTML-5-conforming + // parsing function) which don't know how to handle numbers that are + // formatted differently (for example, with non-ASCII digits, with grouping + // separator characters or with a decimal separator character other than + // '.'). + ICUUtils::LanguageTagIterForContent langTagIter(mContent); double value = ICUUtils::ParseNumber(aValue, langTagIter); - if (IsFinite(value) && - value != HTMLInputElement::StringToDecimal(aValue).toDouble()) { + if (!IsFinite(value)) { aValue.Truncate(); - aValue.AppendFloat(value); + return; } + if (value == HTMLInputElement::StringToDecimal(aValue).toDouble()) { + // We want to preserve the formatting of the number as typed in by the user + // whenever possible. Since the localized serialization parses to the same + // number as the de-localized serialization, we can do that. This helps + // prevent normalization of input such as "2e2" (which would otherwise be + // converted to "200"). Content relies on this. + // + // Typically we will only get here for locales in which numbers are + // formatted in the same way as they are for HTML5's "valid floating-point + // number" format. + return; + } + // We can't preserve the formatting, otherwise functions such as + // HTMLInputElement::StringToDecimal would incorrectly process the number + // input by the user. For example, "12.345" with lang=de de-localizes as + // 12345, but HTMLInputElement::StringToDecimal would mistakenly parse it as + // 12.345. Another example would be "12,345" with lang=de which de-localizes + // as 12.345, but HTMLInputElement::StringToDecimal would parse it to NaN. + aValue.Truncate(); + aValue.AppendFloat(value); #endif - // else, we return whatever FromContent put into aValue (the number as typed - // in by the user) } bool From cc5cb89e2b59ce9b303238acc0f544af0cb12c74 Mon Sep 17 00:00:00 2001 From: Kannan Vijayan Date: Mon, 21 Sep 2015 19:07:01 -0400 Subject: [PATCH 075/133] Bug 1084009 - Part 1/3 - Parse sync scripts off the main thread. r=smaug --- dom/base/nsScriptLoader.cpp | 55 +++++++++++++++++++++++++++++++++---- dom/base/nsScriptLoader.h | 5 ++-- js/src/jsapi.cpp | 2 +- 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/dom/base/nsScriptLoader.cpp b/dom/base/nsScriptLoader.cpp index b58c7b8622bb..b431fd0cb489 100644 --- a/dom/base/nsScriptLoader.cpp +++ b/dom/base/nsScriptLoader.cpp @@ -597,7 +597,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) // loop gets a chance to spin. // KVKV TODO: Instead of processing immediately, try off-thread-parsing - // it and only schedule a ProcessRequest if that fails. + // it and only schedule a pending ProcessRequest if that fails. ProcessPendingRequestsAsync(); } else { mLoadingAsyncRequests.AppendElement(request); @@ -646,6 +646,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) } return true; } + if (request->IsDoneLoading() && ReadyToExecuteScripts()) { // The request has already been loaded and there are no pending style // sheets. If the script comes from the network stream, cheat for @@ -664,6 +665,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) ProcessPendingRequestsAsync(); return true; } + // The script hasn't loaded yet or there's a style sheet blocking it. // The script will be run when it loads or the style sheet loads. NS_ASSERTION(!mParserBlockingRequest, @@ -762,6 +764,23 @@ nsScriptLoader::ProcessOffThreadRequest(nsScriptLoadRequest* aRequest) { MOZ_ASSERT(aRequest->mProgress == nsScriptLoadRequest::Progress_Compiling); aRequest->mProgress = nsScriptLoadRequest::Progress_DoneCompiling; + if (aRequest == mParserBlockingRequest) { + if (!ReadyToExecuteScripts()) { + // If not ready to execute scripts, schedule an async call to + // ProcessPendingRequests to handle it. + ProcessPendingRequestsAsync(); + return NS_OK; + } + + // Same logic as in top of ProcessPendingRequests. + mParserBlockingRequest = nullptr; + UnblockParser(aRequest); + ProcessRequest(aRequest); + mDocument->UnblockOnload(false); + ContinueParserAsync(aRequest); + return NS_OK; + } + nsresult rv = ProcessRequest(aRequest); mDocument->UnblockOnload(false); return rv; @@ -810,9 +829,10 @@ OffThreadScriptLoaderCallback(void *aToken, void *aCallbackData) } nsresult -nsScriptLoader::AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest) +nsScriptLoader::AttemptAsyncScriptCompile(nsScriptLoadRequest* aRequest) { - if (!aRequest->mElement->GetScriptAsync() || aRequest->mIsInline) { + // Don't off-thread compile inline scripts. + if (aRequest->mIsInline) { return NS_ERROR_FAILURE; } @@ -853,7 +873,8 @@ nsScriptLoader::AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest) } nsresult -nsScriptLoader::CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest) +nsScriptLoader::CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest, + bool* oCompiledOffThread) { NS_ASSERTION(nsContentUtils::IsSafeToRunScript(), "Processing requests when running scripts is unsafe."); @@ -862,8 +883,11 @@ nsScriptLoader::CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest) NS_ASSERTION(!aRequest->InCompilingStage(), "Candidate for off-thread compile is already in compiling stage."); - nsresult rv = AttemptAsyncScriptParse(aRequest); + nsresult rv = AttemptAsyncScriptCompile(aRequest); if (rv != NS_ERROR_FAILURE) { + if (oCompiledOffThread && rv == NS_OK) { + *oCompiledOffThread = true; + } return rv; } @@ -1154,8 +1178,12 @@ nsScriptLoader::ProcessPendingRequests() mParserBlockingRequest->IsReadyToRun() && ReadyToExecuteScripts()) { request.swap(mParserBlockingRequest); + bool offThreadCompiled = request->mProgress == nsScriptLoadRequest::Progress_DoneCompiling; UnblockParser(request); ProcessRequest(request); + if (offThreadCompiled) { + mDocument->UnblockOnload(false); + } ContinueParserAsync(request); } @@ -1559,6 +1587,23 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest, // Mark this as loaded aRequest->mProgress = nsScriptLoadRequest::Progress_DoneLoading; + // If this is currently blocking the parser, attempt to compile it off-main-thread. + if (aRequest == mParserBlockingRequest) { + nsresult rv = AttemptAsyncScriptCompile(aRequest); + if (rv == NS_OK) { + NS_ASSERTION(aRequest->mProgress == nsScriptLoadRequest::Progress_Compiling, + "Request should be off-thread compiling now."); + return NS_OK; + } + + // If off-thread compile errored, return the error. + if (rv != NS_ERROR_FAILURE) { + return rv; + } + + // If off-thread compile was rejected, continue with regular processing. + } + // And if it's async, move it to the loaded list. aRequest->mIsAsync really // _should_ be in a list, but the consequences if it's not are bad enough we // want to avoid trying to move it if it's not. diff --git a/dom/base/nsScriptLoader.h b/dom/base/nsScriptLoader.h index 468f50f5d5d1..b3be883f5cd9 100644 --- a/dom/base/nsScriptLoader.h +++ b/dom/base/nsScriptLoader.h @@ -470,9 +470,10 @@ private: return mEnabled && !mBlockerCount; } - nsresult AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest); + nsresult AttemptAsyncScriptCompile(nsScriptLoadRequest* aRequest); nsresult ProcessRequest(nsScriptLoadRequest* aRequest); - nsresult CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest); + nsresult CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest, + bool* oCompiledOffThread=nullptr); void FireScriptAvailable(nsresult aResult, nsScriptLoadRequest* aRequest); void FireScriptEvaluated(nsresult aResult, diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 66951d046d46..a94c934e6330 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4089,7 +4089,7 @@ JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& opt JS_PUBLIC_API(bool) JS::CanCompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length) { - static const size_t TINY_LENGTH = 1000; + static const size_t TINY_LENGTH = 5 * 1000; static const size_t HUGE_LENGTH = 100 * 1000; // These are heuristics which the caller may choose to ignore (e.g., for From b5b672c20a46f4272f5ddb83c3bb99e0914bcb2a Mon Sep 17 00:00:00 2001 From: Kannan Vijayan Date: Mon, 21 Sep 2015 19:07:01 -0400 Subject: [PATCH 076/133] Bug 1084009 - Part 2/3 - Only parse scripts off-main-thread on multicore systems. r=luke --- dom/base/nsScriptLoader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dom/base/nsScriptLoader.cpp b/dom/base/nsScriptLoader.cpp index b431fd0cb489..7120bfca3457 100644 --- a/dom/base/nsScriptLoader.cpp +++ b/dom/base/nsScriptLoader.cpp @@ -10,6 +10,7 @@ #include "nsScriptLoader.h" +#include "prsystem.h" #include "jsapi.h" #include "jsfriendapi.h" #include "xpcpublic.h" @@ -1588,7 +1589,7 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest, aRequest->mProgress = nsScriptLoadRequest::Progress_DoneLoading; // If this is currently blocking the parser, attempt to compile it off-main-thread. - if (aRequest == mParserBlockingRequest) { + if (aRequest == mParserBlockingRequest && (PR_GetNumberOfProcessors() > 1)) { nsresult rv = AttemptAsyncScriptCompile(aRequest); if (rv == NS_OK) { NS_ASSERTION(aRequest->mProgress == nsScriptLoadRequest::Progress_Compiling, From 59fbcdacd79d00e80166fdc489856ea5c075f5cb Mon Sep 17 00:00:00 2001 From: Kannan Vijayan Date: Mon, 21 Sep 2015 19:07:01 -0400 Subject: [PATCH 077/133] Bug 1084009 - Part 3/3 - Test fix to let previous patches pass. r=mikedeboer --- browser/components/uitour/test/browser_UITour_loop.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/components/uitour/test/browser_UITour_loop.js b/browser/components/uitour/test/browser_UITour_loop.js index 54b1b4c9ea66..0958f59d24d7 100644 --- a/browser/components/uitour/test/browser_UITour_loop.js +++ b/browser/components/uitour/test/browser_UITour_loop.js @@ -45,7 +45,7 @@ var tests = [ let loopDoc = document.getElementById("loop-notification-panel").children[0].contentDocument; yield waitForConditionPromise(() => { return loopDoc.readyState == 'complete'; - }, "Loop notification panel document should be fully loaded."); + }, "Loop notification panel document should be fully loaded.", 50); let gettingStartedButton = loopDoc.getElementById("fte-button"); ok(gettingStartedButton, "Getting Started button should be found"); From d1a89f48e5850efe95ee0ddba4784bfbadead003 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Mon, 21 Sep 2015 16:11:51 -0700 Subject: [PATCH 078/133] Bug 1198894: Use nsChangeHint_RepaintFrame instead of NS_STYLE_HINT_VISUAL to trigger simple repaints in nsStyleStruct.cpp CalcDifference methods. r=heycam Specifically, this makes us use nsChangeHint_RepaintFrame for changes to font decorations, border-{color,style,radius,image}, color, background-{image,color}, text-decoration-{line,color}, text-overflow --- layout/style/nsStyleStruct.cpp | 38 +++++++++++++++++++--------------- layout/style/nsStyleStruct.h | 4 ++-- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 24565688765e..44e87139759d 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -256,7 +256,7 @@ nsChangeHint nsStyleFont::CalcFontDifference(const nsFont& aFont1, const nsFont& if ((aFont1.decorations == aFont2.decorations)) { return NS_STYLE_HINT_NONE; } - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; } return NS_STYLE_HINT_REFLOW; } @@ -539,28 +539,28 @@ nsChangeHint nsStyleBorder::CalcDifference(const nsStyleBorder& aOther) const // See the explanation in nsChangeHint.h of // nsChangeHint_BorderStyleNoneChange . // Furthermore, even though we know *this* side is 0 width, just - // assume a visual hint for some other change rather than bother + // assume a repaint hint for some other change rather than bother // tracking this result through the rest of the function. if (HasVisibleStyle(ix) != aOther.HasVisibleStyle(ix)) { - return NS_CombineHint(NS_STYLE_HINT_VISUAL, + return NS_CombineHint(nsChangeHint_RepaintFrame, nsChangeHint_BorderStyleNoneChange); } } // Note that mBorderStyle stores not only the border style but also // color-related flags. Given that we've already done an mComputedBorder - // comparison, border-style differences can only lead to a VISUAL hint. So + // comparison, border-style differences can only lead to a repaint hint. So // it's OK to just compare the values directly -- if either the actual // style or the color flags differ we want to repaint. NS_FOR_CSS_SIDES(ix) { if (mBorderStyle[ix] != aOther.mBorderStyle[ix] || mBorderColor[ix] != aOther.mBorderColor[ix]) - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; } if (mBorderRadius != aOther.mBorderRadius || !mBorderColors != !aOther.mBorderColors) - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; if (IsBorderImageLoaded() || aOther.IsBorderImageLoaded()) { if (mBorderImageSource != aOther.mBorderImageSource || @@ -570,7 +570,7 @@ nsChangeHint nsStyleBorder::CalcDifference(const nsStyleBorder& aOther) const mBorderImageFill != aOther.mBorderImageFill || mBorderImageWidth != aOther.mBorderImageWidth || mBorderImageOutset != aOther.mBorderImageOutset) - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; } // Note that at this point if mBorderColors is non-null so is @@ -579,7 +579,7 @@ nsChangeHint nsStyleBorder::CalcDifference(const nsStyleBorder& aOther) const NS_FOR_CSS_SIDES(ix) { if (!nsBorderColors::Equal(mBorderColors[ix], aOther.mBorderColors[ix])) - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; } } @@ -1744,7 +1744,7 @@ nsChangeHint nsStyleColor::CalcDifference(const nsStyleColor& aOther) const { if (mColor == aOther.mColor) return NS_STYLE_HINT_NONE; - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; } // -------------------- @@ -2231,18 +2231,20 @@ nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther) if (moreLayers->mLayers[i] != lessLayers->mLayers[i]) { if ((moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element) || (lessLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element)) - return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL); + return NS_CombineHint(nsChangeHint_UpdateEffects, + nsChangeHint_RepaintFrame); hasVisualDifference = true; } } else { if (moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element) - return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL); + return NS_CombineHint(nsChangeHint_UpdateEffects, + nsChangeHint_RepaintFrame); hasVisualDifference = true; } } if (hasVisualDifference || mBackgroundColor != aOther.mBackgroundColor) - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; if (mAttachmentCount != aOther.mAttachmentCount || mClipCount != aOther.mClipCount || @@ -3343,10 +3345,12 @@ nsChangeHint nsStyleTextReset::CalcDifference(const nsStyleTextReset& aOther) co uint8_t otherLineStyle = aOther.GetDecorationStyle(); if (mTextDecorationLine != aOther.mTextDecorationLine || lineStyle != otherLineStyle) { - // Repaint for other style decoration lines because they must be in - // default overflow rect - nsChangeHint hint = NS_STYLE_HINT_VISUAL; + // Changes to our text-decoration line can impact our overflow area & + // also our descendants' overflow areas (particularly for text-frame + // descendants). So, we update those areas & trigger a repaint. + nsChangeHint hint = nsChangeHint_RepaintFrame; NS_UpdateHint(hint, nsChangeHint_UpdateSubtreeOverflow); + NS_UpdateHint(hint, nsChangeHint_SchedulePaint); return hint; } @@ -3356,11 +3360,11 @@ nsChangeHint nsStyleTextReset::CalcDifference(const nsStyleTextReset& aOther) co GetDecorationColor(decColor, isFG); aOther.GetDecorationColor(otherDecColor, otherIsFG); if (isFG != otherIsFG || (!isFG && decColor != otherDecColor)) { - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; } if (mTextOverflow != aOther.mTextOverflow) { - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; } return NS_STYLE_HINT_NONE; } diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 0fd593d32530..29e4bb132d01 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -353,7 +353,7 @@ struct nsStyleColor { nsChangeHint CalcDifference(const nsStyleColor& aOther) const; static nsChangeHint MaxDifference() { - return NS_STYLE_HINT_VISUAL; + return nsChangeHint_RepaintFrame; } static nsChangeHint DifferenceAlwaysHandledForDescendants() { // CalcDifference never returns the reflow hints that are sometimes @@ -390,7 +390,7 @@ struct nsStyleBackground { nsChangeHint CalcDifference(const nsStyleBackground& aOther) const; static nsChangeHint MaxDifference() { return NS_CombineHint(nsChangeHint_UpdateEffects, - NS_CombineHint(NS_STYLE_HINT_VISUAL, + NS_CombineHint(nsChangeHint_RepaintFrame, nsChangeHint_NeutralChange)); } static nsChangeHint DifferenceAlwaysHandledForDescendants() { From 49e6226accc39e1be29ee0fb5416e374cd72529c Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Wed, 16 Sep 2015 19:26:04 -0400 Subject: [PATCH 079/133] Bug 1014691 - Move APZ mochitests to gfx/layers/apz/test/mochitest. r=kats --HG-- rename : gfx/layers/apz/test/apz_test_native_event_utils.js => gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js rename : gfx/layers/apz/test/apz_test_utils.js => gfx/layers/apz/test/mochitest/apz_test_utils.js rename : gfx/layers/apz/test/chrome.ini => gfx/layers/apz/test/mochitest/chrome.ini rename : gfx/layers/apz/test/helper_basic_pan.html => gfx/layers/apz/test/mochitest/helper_basic_pan.html rename : gfx/layers/apz/test/helper_bug1151663.html => gfx/layers/apz/test/mochitest/helper_bug1151663.html rename : gfx/layers/apz/test/helper_bug982141.html => gfx/layers/apz/test/mochitest/helper_bug982141.html rename : gfx/layers/apz/test/helper_div_pan.html => gfx/layers/apz/test/mochitest/helper_div_pan.html rename : gfx/layers/apz/test/helper_iframe1.html => gfx/layers/apz/test/mochitest/helper_iframe1.html rename : gfx/layers/apz/test/helper_iframe2.html => gfx/layers/apz/test/mochitest/helper_iframe2.html rename : gfx/layers/apz/test/helper_iframe_pan.html => gfx/layers/apz/test/mochitest/helper_iframe_pan.html rename : gfx/layers/apz/test/helper_subframe_style.css => gfx/layers/apz/test/mochitest/helper_subframe_style.css rename : gfx/layers/apz/test/mochitest.ini => gfx/layers/apz/test/mochitest/mochitest.ini rename : gfx/layers/apz/test/test_basic_pan.html => gfx/layers/apz/test/mochitest/test_basic_pan.html rename : gfx/layers/apz/test/test_bug1151663.html => gfx/layers/apz/test/mochitest/test_bug1151663.html rename : gfx/layers/apz/test/test_bug1151667.html => gfx/layers/apz/test/mochitest/test_bug1151667.html rename : gfx/layers/apz/test/test_bug982141.html => gfx/layers/apz/test/mochitest/test_bug982141.html rename : gfx/layers/apz/test/test_layerization.html => gfx/layers/apz/test/mochitest/test_layerization.html rename : gfx/layers/apz/test/test_scroll_inactive_flattened_frame.html => gfx/layers/apz/test/mochitest/test_scroll_inactive_flattened_frame.html rename : gfx/layers/apz/test/test_smoothness.html => gfx/layers/apz/test/mochitest/test_smoothness.html rename : gfx/layers/apz/test/test_wheel_scroll.html => gfx/layers/apz/test/mochitest/test_wheel_scroll.html rename : gfx/layers/apz/test/test_wheel_transactions.html => gfx/layers/apz/test/mochitest/test_wheel_transactions.html extra : source : da98c4962d299e488ff456a35ec642708f6c8c49 --- .../apz/test/{ => mochitest}/apz_test_native_event_utils.js | 0 gfx/layers/apz/test/{ => mochitest}/apz_test_utils.js | 0 gfx/layers/apz/test/{ => mochitest}/chrome.ini | 0 gfx/layers/apz/test/{ => mochitest}/helper_basic_pan.html | 0 gfx/layers/apz/test/{ => mochitest}/helper_bug1151663.html | 0 gfx/layers/apz/test/{ => mochitest}/helper_bug982141.html | 0 gfx/layers/apz/test/{ => mochitest}/helper_div_pan.html | 0 gfx/layers/apz/test/{ => mochitest}/helper_iframe1.html | 0 gfx/layers/apz/test/{ => mochitest}/helper_iframe2.html | 0 gfx/layers/apz/test/{ => mochitest}/helper_iframe_pan.html | 0 gfx/layers/apz/test/{ => mochitest}/helper_subframe_style.css | 0 gfx/layers/apz/test/{ => mochitest}/mochitest.ini | 0 gfx/layers/apz/test/{ => mochitest}/test_basic_pan.html | 0 gfx/layers/apz/test/{ => mochitest}/test_bug1151663.html | 0 gfx/layers/apz/test/{ => mochitest}/test_bug1151667.html | 0 gfx/layers/apz/test/{ => mochitest}/test_bug982141.html | 0 gfx/layers/apz/test/{ => mochitest}/test_layerization.html | 0 .../{ => mochitest}/test_scroll_inactive_flattened_frame.html | 0 gfx/layers/apz/test/{ => mochitest}/test_smoothness.html | 0 gfx/layers/apz/test/{ => mochitest}/test_wheel_scroll.html | 0 .../apz/test/{ => mochitest}/test_wheel_transactions.html | 0 gfx/layers/moz.build | 4 ++-- 22 files changed, 2 insertions(+), 2 deletions(-) rename gfx/layers/apz/test/{ => mochitest}/apz_test_native_event_utils.js (100%) rename gfx/layers/apz/test/{ => mochitest}/apz_test_utils.js (100%) rename gfx/layers/apz/test/{ => mochitest}/chrome.ini (100%) rename gfx/layers/apz/test/{ => mochitest}/helper_basic_pan.html (100%) rename gfx/layers/apz/test/{ => mochitest}/helper_bug1151663.html (100%) rename gfx/layers/apz/test/{ => mochitest}/helper_bug982141.html (100%) rename gfx/layers/apz/test/{ => mochitest}/helper_div_pan.html (100%) rename gfx/layers/apz/test/{ => mochitest}/helper_iframe1.html (100%) rename gfx/layers/apz/test/{ => mochitest}/helper_iframe2.html (100%) rename gfx/layers/apz/test/{ => mochitest}/helper_iframe_pan.html (100%) rename gfx/layers/apz/test/{ => mochitest}/helper_subframe_style.css (100%) rename gfx/layers/apz/test/{ => mochitest}/mochitest.ini (100%) rename gfx/layers/apz/test/{ => mochitest}/test_basic_pan.html (100%) rename gfx/layers/apz/test/{ => mochitest}/test_bug1151663.html (100%) rename gfx/layers/apz/test/{ => mochitest}/test_bug1151667.html (100%) rename gfx/layers/apz/test/{ => mochitest}/test_bug982141.html (100%) rename gfx/layers/apz/test/{ => mochitest}/test_layerization.html (100%) rename gfx/layers/apz/test/{ => mochitest}/test_scroll_inactive_flattened_frame.html (100%) rename gfx/layers/apz/test/{ => mochitest}/test_smoothness.html (100%) rename gfx/layers/apz/test/{ => mochitest}/test_wheel_scroll.html (100%) rename gfx/layers/apz/test/{ => mochitest}/test_wheel_transactions.html (100%) diff --git a/gfx/layers/apz/test/apz_test_native_event_utils.js b/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js similarity index 100% rename from gfx/layers/apz/test/apz_test_native_event_utils.js rename to gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js diff --git a/gfx/layers/apz/test/apz_test_utils.js b/gfx/layers/apz/test/mochitest/apz_test_utils.js similarity index 100% rename from gfx/layers/apz/test/apz_test_utils.js rename to gfx/layers/apz/test/mochitest/apz_test_utils.js diff --git a/gfx/layers/apz/test/chrome.ini b/gfx/layers/apz/test/mochitest/chrome.ini similarity index 100% rename from gfx/layers/apz/test/chrome.ini rename to gfx/layers/apz/test/mochitest/chrome.ini diff --git a/gfx/layers/apz/test/helper_basic_pan.html b/gfx/layers/apz/test/mochitest/helper_basic_pan.html similarity index 100% rename from gfx/layers/apz/test/helper_basic_pan.html rename to gfx/layers/apz/test/mochitest/helper_basic_pan.html diff --git a/gfx/layers/apz/test/helper_bug1151663.html b/gfx/layers/apz/test/mochitest/helper_bug1151663.html similarity index 100% rename from gfx/layers/apz/test/helper_bug1151663.html rename to gfx/layers/apz/test/mochitest/helper_bug1151663.html diff --git a/gfx/layers/apz/test/helper_bug982141.html b/gfx/layers/apz/test/mochitest/helper_bug982141.html similarity index 100% rename from gfx/layers/apz/test/helper_bug982141.html rename to gfx/layers/apz/test/mochitest/helper_bug982141.html diff --git a/gfx/layers/apz/test/helper_div_pan.html b/gfx/layers/apz/test/mochitest/helper_div_pan.html similarity index 100% rename from gfx/layers/apz/test/helper_div_pan.html rename to gfx/layers/apz/test/mochitest/helper_div_pan.html diff --git a/gfx/layers/apz/test/helper_iframe1.html b/gfx/layers/apz/test/mochitest/helper_iframe1.html similarity index 100% rename from gfx/layers/apz/test/helper_iframe1.html rename to gfx/layers/apz/test/mochitest/helper_iframe1.html diff --git a/gfx/layers/apz/test/helper_iframe2.html b/gfx/layers/apz/test/mochitest/helper_iframe2.html similarity index 100% rename from gfx/layers/apz/test/helper_iframe2.html rename to gfx/layers/apz/test/mochitest/helper_iframe2.html diff --git a/gfx/layers/apz/test/helper_iframe_pan.html b/gfx/layers/apz/test/mochitest/helper_iframe_pan.html similarity index 100% rename from gfx/layers/apz/test/helper_iframe_pan.html rename to gfx/layers/apz/test/mochitest/helper_iframe_pan.html diff --git a/gfx/layers/apz/test/helper_subframe_style.css b/gfx/layers/apz/test/mochitest/helper_subframe_style.css similarity index 100% rename from gfx/layers/apz/test/helper_subframe_style.css rename to gfx/layers/apz/test/mochitest/helper_subframe_style.css diff --git a/gfx/layers/apz/test/mochitest.ini b/gfx/layers/apz/test/mochitest/mochitest.ini similarity index 100% rename from gfx/layers/apz/test/mochitest.ini rename to gfx/layers/apz/test/mochitest/mochitest.ini diff --git a/gfx/layers/apz/test/test_basic_pan.html b/gfx/layers/apz/test/mochitest/test_basic_pan.html similarity index 100% rename from gfx/layers/apz/test/test_basic_pan.html rename to gfx/layers/apz/test/mochitest/test_basic_pan.html diff --git a/gfx/layers/apz/test/test_bug1151663.html b/gfx/layers/apz/test/mochitest/test_bug1151663.html similarity index 100% rename from gfx/layers/apz/test/test_bug1151663.html rename to gfx/layers/apz/test/mochitest/test_bug1151663.html diff --git a/gfx/layers/apz/test/test_bug1151667.html b/gfx/layers/apz/test/mochitest/test_bug1151667.html similarity index 100% rename from gfx/layers/apz/test/test_bug1151667.html rename to gfx/layers/apz/test/mochitest/test_bug1151667.html diff --git a/gfx/layers/apz/test/test_bug982141.html b/gfx/layers/apz/test/mochitest/test_bug982141.html similarity index 100% rename from gfx/layers/apz/test/test_bug982141.html rename to gfx/layers/apz/test/mochitest/test_bug982141.html diff --git a/gfx/layers/apz/test/test_layerization.html b/gfx/layers/apz/test/mochitest/test_layerization.html similarity index 100% rename from gfx/layers/apz/test/test_layerization.html rename to gfx/layers/apz/test/mochitest/test_layerization.html diff --git a/gfx/layers/apz/test/test_scroll_inactive_flattened_frame.html b/gfx/layers/apz/test/mochitest/test_scroll_inactive_flattened_frame.html similarity index 100% rename from gfx/layers/apz/test/test_scroll_inactive_flattened_frame.html rename to gfx/layers/apz/test/mochitest/test_scroll_inactive_flattened_frame.html diff --git a/gfx/layers/apz/test/test_smoothness.html b/gfx/layers/apz/test/mochitest/test_smoothness.html similarity index 100% rename from gfx/layers/apz/test/test_smoothness.html rename to gfx/layers/apz/test/mochitest/test_smoothness.html diff --git a/gfx/layers/apz/test/test_wheel_scroll.html b/gfx/layers/apz/test/mochitest/test_wheel_scroll.html similarity index 100% rename from gfx/layers/apz/test/test_wheel_scroll.html rename to gfx/layers/apz/test/mochitest/test_wheel_scroll.html diff --git a/gfx/layers/apz/test/test_wheel_transactions.html b/gfx/layers/apz/test/mochitest/test_wheel_transactions.html similarity index 100% rename from gfx/layers/apz/test/test_wheel_transactions.html rename to gfx/layers/apz/test/mochitest/test_wheel_transactions.html diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index 3864836c29ca..dd58022327c7 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -406,8 +406,8 @@ CXXFLAGS += [ ] ] -MOCHITEST_MANIFESTS += ['apz/test/mochitest.ini'] -MOCHITEST_CHROME_MANIFESTS += ['apz/test/chrome.ini'] +MOCHITEST_MANIFESTS += ['apz/test/mochitest/mochitest.ini'] +MOCHITEST_CHROME_MANIFESTS += ['apz/test/mochitest/chrome.ini'] CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS'] CXXFLAGS += CONFIG['TK_CFLAGS'] From 7918cf6631cea5043a9f5b7ee12583ec6cb1d565 Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Wed, 16 Sep 2015 19:45:14 -0400 Subject: [PATCH 080/133] Bug 1014691 - Fix an include-what-you-use error in TestCompositor.cpp. r=kats --HG-- extra : source : 561ac57efc474b5e7c4cad3c55ef24edb7c955b6 --- gfx/tests/gtest/TestCompositor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/gfx/tests/gtest/TestCompositor.cpp b/gfx/tests/gtest/TestCompositor.cpp index 93961a0c9781..37d0ea1747ee 100644 --- a/gfx/tests/gtest/TestCompositor.cpp +++ b/gfx/tests/gtest/TestCompositor.cpp @@ -3,6 +3,7 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ +#include "gfxPrefs.h" #include "gfxUtils.h" #include "gtest/gtest.h" #include "TestLayers.h" From 0f6812acd56439235e6e9d24f6f18a701bfdc3c6 Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Fri, 18 Sep 2015 13:19:05 -0400 Subject: [PATCH 081/133] Bug 1014691 - Move TestAsyncPanZoomController.cpp to gfx/layers/apz/test/gtest. r=kats,glandium --HG-- rename : gfx/tests/gtest/TestAsyncPanZoomController.cpp => gfx/layers/apz/test/gtest/TestAsyncPanZoomController.cpp extra : source : 18f51acd98206483573be0fcf636e6fcc76e89b0 --- .../gtest/TestAsyncPanZoomController.cpp | 0 gfx/layers/apz/test/gtest/moz.build | 21 +++++++++++++++++++ gfx/layers/moz.build | 3 +++ gfx/moz.build | 3 --- gfx/tests/gtest/moz.build | 1 - 5 files changed, 24 insertions(+), 4 deletions(-) rename gfx/{tests => layers/apz/test}/gtest/TestAsyncPanZoomController.cpp (100%) create mode 100644 gfx/layers/apz/test/gtest/moz.build diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/layers/apz/test/gtest/TestAsyncPanZoomController.cpp similarity index 100% rename from gfx/tests/gtest/TestAsyncPanZoomController.cpp rename to gfx/layers/apz/test/gtest/TestAsyncPanZoomController.cpp diff --git a/gfx/layers/apz/test/gtest/moz.build b/gfx/layers/apz/test/gtest/moz.build new file mode 100644 index 000000000000..4a1bc8d64f81 --- /dev/null +++ b/gfx/layers/apz/test/gtest/moz.build @@ -0,0 +1,21 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +UNIFIED_SOURCES += [ + 'TestAsyncPanZoomController.cpp', +] + +include('/ipc/chromium/chromium-config.mozbuild') + +LOCAL_INCLUDES += [ + '/gfx/2d', + '/gfx/layers', + '/gfx/tests/gtest' # for TestLayers.h, which is shared with the gfx gtests +] + +FINAL_LIBRARY = 'xul-gtest' + +CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS'] diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index dd58022327c7..5ce9a5863b88 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -406,6 +406,9 @@ CXXFLAGS += [ ] ] +if CONFIG['ENABLE_TESTS']: + DIRS += ['apz/test/gtest'] + MOCHITEST_MANIFESTS += ['apz/test/mochitest/mochitest.ini'] MOCHITEST_CHROME_MANIFESTS += ['apz/test/mochitest/chrome.ini'] diff --git a/gfx/moz.build b/gfx/moz.build index d5e33270335d..2ed70f83a8fb 100644 --- a/gfx/moz.build +++ b/gfx/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/. -with Files('tests/gtest/TestAsyncPanZoomController.cpp'): - BUG_COMPONENT = ('Core', 'Panning and Zooming') - if CONFIG['MOZ_TREE_CAIRO']: DIRS += ['cairo'] diff --git a/gfx/tests/gtest/moz.build b/gfx/tests/gtest/moz.build index cc1a716d1d1b..cda7439695d6 100644 --- a/gfx/tests/gtest/moz.build +++ b/gfx/tests/gtest/moz.build @@ -8,7 +8,6 @@ UNIFIED_SOURCES += [ 'gfxSurfaceRefCountTest.cpp', # Disabled on suspicion of causing bug 904227 #'gfxWordCacheTest.cpp', - 'TestAsyncPanZoomController.cpp', 'TestBufferRotation.cpp', 'TestColorNames.cpp', 'TestCompositor.cpp', From ce4f8b079b78283a9eed6a8823774d2a796ac293 Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Wed, 16 Sep 2015 19:49:59 -0400 Subject: [PATCH 082/133] Bug 1014691 - Get TestAsyncPanZoomController to compile in its new location. r=kats --HG-- extra : source : aa30dbad3f9ff5a2cf7f847ec2ea381d4c9ea5d9 --- gfx/layers/apz/test/gtest/TestAsyncPanZoomController.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gfx/layers/apz/test/gtest/TestAsyncPanZoomController.cpp b/gfx/layers/apz/test/gtest/TestAsyncPanZoomController.cpp index 4fe9480fae13..258e47d0644c 100644 --- a/gfx/layers/apz/test/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/layers/apz/test/gtest/TestAsyncPanZoomController.cpp @@ -947,8 +947,8 @@ TEST_F(APZCBasicTester, Overzoom) { EXPECT_EQ(0.8f, fm.GetZoom().ToScaleFactor().scale); // bug 936721 - PGO builds introduce rounding error so // use a fuzzy match instead - EXPECT_LT(abs(fm.GetScrollOffset().x), 1e-5); - EXPECT_LT(abs(fm.GetScrollOffset().y), 1e-5); + EXPECT_LT(std::abs(fm.GetScrollOffset().x), 1e-5); + EXPECT_LT(std::abs(fm.GetScrollOffset().y), 1e-5); } TEST_F(APZCBasicTester, SimpleTransform) { From 27eb9671a75cbbc5853b4c03dfd865ba72ffea36 Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Fri, 18 Sep 2015 13:19:55 -0400 Subject: [PATCH 083/133] Bug 1014691 - Move APZ reftests to apz/test/reftest. r=kats --HG-- rename : gfx/layers/apz/reftests/async-scrollbar-1-h-ref.html => gfx/layers/apz/test/reftest/async-scrollbar-1-h-ref.html rename : gfx/layers/apz/reftests/async-scrollbar-1-h-rtl-ref.html => gfx/layers/apz/test/reftest/async-scrollbar-1-h-rtl-ref.html rename : gfx/layers/apz/reftests/async-scrollbar-1-h-rtl.html => gfx/layers/apz/test/reftest/async-scrollbar-1-h-rtl.html rename : gfx/layers/apz/reftests/async-scrollbar-1-h.html => gfx/layers/apz/test/reftest/async-scrollbar-1-h.html rename : gfx/layers/apz/reftests/async-scrollbar-1-v-ref.html => gfx/layers/apz/test/reftest/async-scrollbar-1-v-ref.html rename : gfx/layers/apz/reftests/async-scrollbar-1-v-rtl-ref.html => gfx/layers/apz/test/reftest/async-scrollbar-1-v-rtl-ref.html rename : gfx/layers/apz/reftests/async-scrollbar-1-v-rtl.html => gfx/layers/apz/test/reftest/async-scrollbar-1-v-rtl.html rename : gfx/layers/apz/reftests/async-scrollbar-1-v.html => gfx/layers/apz/test/reftest/async-scrollbar-1-v.html rename : gfx/layers/apz/reftests/async-scrollbar-1-vh-ref.html => gfx/layers/apz/test/reftest/async-scrollbar-1-vh-ref.html rename : gfx/layers/apz/reftests/async-scrollbar-1-vh-rtl-ref.html => gfx/layers/apz/test/reftest/async-scrollbar-1-vh-rtl-ref.html rename : gfx/layers/apz/reftests/async-scrollbar-1-vh-rtl.html => gfx/layers/apz/test/reftest/async-scrollbar-1-vh-rtl.html rename : gfx/layers/apz/reftests/async-scrollbar-1-vh.html => gfx/layers/apz/test/reftest/async-scrollbar-1-vh.html rename : gfx/layers/apz/reftests/async-scrollbar-zoom-1-ref.html => gfx/layers/apz/test/reftest/async-scrollbar-zoom-1-ref.html rename : gfx/layers/apz/reftests/async-scrollbar-zoom-1.html => gfx/layers/apz/test/reftest/async-scrollbar-zoom-1.html rename : gfx/layers/apz/reftests/async-scrollbar-zoom-2-ref.html => gfx/layers/apz/test/reftest/async-scrollbar-zoom-2-ref.html rename : gfx/layers/apz/reftests/async-scrollbar-zoom-2.html => gfx/layers/apz/test/reftest/async-scrollbar-zoom-2.html rename : gfx/layers/apz/reftests/reftest.list => gfx/layers/apz/test/reftest/reftest.list extra : source : f811b4e8a7c7b1f4cdcc79b76ee1c32116e4925d --- .../apz/{reftests => test/reftest}/async-scrollbar-1-h-ref.html | 0 .../{reftests => test/reftest}/async-scrollbar-1-h-rtl-ref.html | 0 .../apz/{reftests => test/reftest}/async-scrollbar-1-h-rtl.html | 0 .../apz/{reftests => test/reftest}/async-scrollbar-1-h.html | 0 .../apz/{reftests => test/reftest}/async-scrollbar-1-v-ref.html | 0 .../{reftests => test/reftest}/async-scrollbar-1-v-rtl-ref.html | 0 .../apz/{reftests => test/reftest}/async-scrollbar-1-v-rtl.html | 0 .../apz/{reftests => test/reftest}/async-scrollbar-1-v.html | 0 .../{reftests => test/reftest}/async-scrollbar-1-vh-ref.html | 0 .../reftest}/async-scrollbar-1-vh-rtl-ref.html | 0 .../{reftests => test/reftest}/async-scrollbar-1-vh-rtl.html | 0 .../apz/{reftests => test/reftest}/async-scrollbar-1-vh.html | 0 .../{reftests => test/reftest}/async-scrollbar-zoom-1-ref.html | 0 .../apz/{reftests => test/reftest}/async-scrollbar-zoom-1.html | 0 .../{reftests => test/reftest}/async-scrollbar-zoom-2-ref.html | 0 .../apz/{reftests => test/reftest}/async-scrollbar-zoom-2.html | 0 gfx/layers/apz/{reftests => test/reftest}/reftest.list | 0 layout/reftests/reftest.list | 2 +- 18 files changed, 1 insertion(+), 1 deletion(-) rename gfx/layers/apz/{reftests => test/reftest}/async-scrollbar-1-h-ref.html (100%) rename gfx/layers/apz/{reftests => test/reftest}/async-scrollbar-1-h-rtl-ref.html (100%) rename gfx/layers/apz/{reftests => test/reftest}/async-scrollbar-1-h-rtl.html (100%) rename gfx/layers/apz/{reftests => test/reftest}/async-scrollbar-1-h.html (100%) rename gfx/layers/apz/{reftests => test/reftest}/async-scrollbar-1-v-ref.html (100%) rename gfx/layers/apz/{reftests => test/reftest}/async-scrollbar-1-v-rtl-ref.html (100%) rename gfx/layers/apz/{reftests => test/reftest}/async-scrollbar-1-v-rtl.html (100%) rename gfx/layers/apz/{reftests => test/reftest}/async-scrollbar-1-v.html (100%) rename gfx/layers/apz/{reftests => test/reftest}/async-scrollbar-1-vh-ref.html (100%) rename gfx/layers/apz/{reftests => test/reftest}/async-scrollbar-1-vh-rtl-ref.html (100%) rename gfx/layers/apz/{reftests => test/reftest}/async-scrollbar-1-vh-rtl.html (100%) rename gfx/layers/apz/{reftests => test/reftest}/async-scrollbar-1-vh.html (100%) rename gfx/layers/apz/{reftests => test/reftest}/async-scrollbar-zoom-1-ref.html (100%) rename gfx/layers/apz/{reftests => test/reftest}/async-scrollbar-zoom-1.html (100%) rename gfx/layers/apz/{reftests => test/reftest}/async-scrollbar-zoom-2-ref.html (100%) rename gfx/layers/apz/{reftests => test/reftest}/async-scrollbar-zoom-2.html (100%) rename gfx/layers/apz/{reftests => test/reftest}/reftest.list (100%) diff --git a/gfx/layers/apz/reftests/async-scrollbar-1-h-ref.html b/gfx/layers/apz/test/reftest/async-scrollbar-1-h-ref.html similarity index 100% rename from gfx/layers/apz/reftests/async-scrollbar-1-h-ref.html rename to gfx/layers/apz/test/reftest/async-scrollbar-1-h-ref.html diff --git a/gfx/layers/apz/reftests/async-scrollbar-1-h-rtl-ref.html b/gfx/layers/apz/test/reftest/async-scrollbar-1-h-rtl-ref.html similarity index 100% rename from gfx/layers/apz/reftests/async-scrollbar-1-h-rtl-ref.html rename to gfx/layers/apz/test/reftest/async-scrollbar-1-h-rtl-ref.html diff --git a/gfx/layers/apz/reftests/async-scrollbar-1-h-rtl.html b/gfx/layers/apz/test/reftest/async-scrollbar-1-h-rtl.html similarity index 100% rename from gfx/layers/apz/reftests/async-scrollbar-1-h-rtl.html rename to gfx/layers/apz/test/reftest/async-scrollbar-1-h-rtl.html diff --git a/gfx/layers/apz/reftests/async-scrollbar-1-h.html b/gfx/layers/apz/test/reftest/async-scrollbar-1-h.html similarity index 100% rename from gfx/layers/apz/reftests/async-scrollbar-1-h.html rename to gfx/layers/apz/test/reftest/async-scrollbar-1-h.html diff --git a/gfx/layers/apz/reftests/async-scrollbar-1-v-ref.html b/gfx/layers/apz/test/reftest/async-scrollbar-1-v-ref.html similarity index 100% rename from gfx/layers/apz/reftests/async-scrollbar-1-v-ref.html rename to gfx/layers/apz/test/reftest/async-scrollbar-1-v-ref.html diff --git a/gfx/layers/apz/reftests/async-scrollbar-1-v-rtl-ref.html b/gfx/layers/apz/test/reftest/async-scrollbar-1-v-rtl-ref.html similarity index 100% rename from gfx/layers/apz/reftests/async-scrollbar-1-v-rtl-ref.html rename to gfx/layers/apz/test/reftest/async-scrollbar-1-v-rtl-ref.html diff --git a/gfx/layers/apz/reftests/async-scrollbar-1-v-rtl.html b/gfx/layers/apz/test/reftest/async-scrollbar-1-v-rtl.html similarity index 100% rename from gfx/layers/apz/reftests/async-scrollbar-1-v-rtl.html rename to gfx/layers/apz/test/reftest/async-scrollbar-1-v-rtl.html diff --git a/gfx/layers/apz/reftests/async-scrollbar-1-v.html b/gfx/layers/apz/test/reftest/async-scrollbar-1-v.html similarity index 100% rename from gfx/layers/apz/reftests/async-scrollbar-1-v.html rename to gfx/layers/apz/test/reftest/async-scrollbar-1-v.html diff --git a/gfx/layers/apz/reftests/async-scrollbar-1-vh-ref.html b/gfx/layers/apz/test/reftest/async-scrollbar-1-vh-ref.html similarity index 100% rename from gfx/layers/apz/reftests/async-scrollbar-1-vh-ref.html rename to gfx/layers/apz/test/reftest/async-scrollbar-1-vh-ref.html diff --git a/gfx/layers/apz/reftests/async-scrollbar-1-vh-rtl-ref.html b/gfx/layers/apz/test/reftest/async-scrollbar-1-vh-rtl-ref.html similarity index 100% rename from gfx/layers/apz/reftests/async-scrollbar-1-vh-rtl-ref.html rename to gfx/layers/apz/test/reftest/async-scrollbar-1-vh-rtl-ref.html diff --git a/gfx/layers/apz/reftests/async-scrollbar-1-vh-rtl.html b/gfx/layers/apz/test/reftest/async-scrollbar-1-vh-rtl.html similarity index 100% rename from gfx/layers/apz/reftests/async-scrollbar-1-vh-rtl.html rename to gfx/layers/apz/test/reftest/async-scrollbar-1-vh-rtl.html diff --git a/gfx/layers/apz/reftests/async-scrollbar-1-vh.html b/gfx/layers/apz/test/reftest/async-scrollbar-1-vh.html similarity index 100% rename from gfx/layers/apz/reftests/async-scrollbar-1-vh.html rename to gfx/layers/apz/test/reftest/async-scrollbar-1-vh.html diff --git a/gfx/layers/apz/reftests/async-scrollbar-zoom-1-ref.html b/gfx/layers/apz/test/reftest/async-scrollbar-zoom-1-ref.html similarity index 100% rename from gfx/layers/apz/reftests/async-scrollbar-zoom-1-ref.html rename to gfx/layers/apz/test/reftest/async-scrollbar-zoom-1-ref.html diff --git a/gfx/layers/apz/reftests/async-scrollbar-zoom-1.html b/gfx/layers/apz/test/reftest/async-scrollbar-zoom-1.html similarity index 100% rename from gfx/layers/apz/reftests/async-scrollbar-zoom-1.html rename to gfx/layers/apz/test/reftest/async-scrollbar-zoom-1.html diff --git a/gfx/layers/apz/reftests/async-scrollbar-zoom-2-ref.html b/gfx/layers/apz/test/reftest/async-scrollbar-zoom-2-ref.html similarity index 100% rename from gfx/layers/apz/reftests/async-scrollbar-zoom-2-ref.html rename to gfx/layers/apz/test/reftest/async-scrollbar-zoom-2-ref.html diff --git a/gfx/layers/apz/reftests/async-scrollbar-zoom-2.html b/gfx/layers/apz/test/reftest/async-scrollbar-zoom-2.html similarity index 100% rename from gfx/layers/apz/reftests/async-scrollbar-zoom-2.html rename to gfx/layers/apz/test/reftest/async-scrollbar-zoom-2.html diff --git a/gfx/layers/apz/reftests/reftest.list b/gfx/layers/apz/test/reftest/reftest.list similarity index 100% rename from gfx/layers/apz/reftests/reftest.list rename to gfx/layers/apz/test/reftest/reftest.list diff --git a/layout/reftests/reftest.list b/layout/reftests/reftest.list index a4b9df5ee3e1..eca7e0c590c1 100644 --- a/layout/reftests/reftest.list +++ b/layout/reftests/reftest.list @@ -390,4 +390,4 @@ include invalidation/reftest.list include ../../dom/encoding/test/reftest/reftest.list # APZ/async positioning tests -include ../../gfx/layers/apz/reftests/reftest.list +include ../../gfx/layers/apz/test/reftest/reftest.list From 0318c5f13743300e26f6449303ae31cbf653b2ab Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Mon, 21 Sep 2015 16:36:40 -0700 Subject: [PATCH 084/133] Bug 1087488: Remove some SPROP macro usages in Omnijar.cpp, to avoid triggering -Wtautological-compare clang warning. r=glandium --- xpcom/build/Omnijar.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xpcom/build/Omnijar.cpp b/xpcom/build/Omnijar.cpp index baceef32c512..d3a1783ec500 100644 --- a/xpcom/build/Omnijar.cpp +++ b/xpcom/build/Omnijar.cpp @@ -60,9 +60,9 @@ Omnijar::InitOne(nsIFile* aPath, Type aType) if ((aType == APP) && (!sPath[GRE])) { nsCOMPtr greDir, appDir; bool equals; - nsDirectoryService::gService->Get(SPROP(GRE), NS_GET_IID(nsIFile), + nsDirectoryService::gService->Get(sProp[GRE], NS_GET_IID(nsIFile), getter_AddRefs(greDir)); - nsDirectoryService::gService->Get(SPROP(APP), NS_GET_IID(nsIFile), + nsDirectoryService::gService->Get(sProp[APP], NS_GET_IID(nsIFile), getter_AddRefs(appDir)); if (NS_SUCCEEDED(greDir->Equals(appDir, &equals)) && equals) { sIsUnified = true; From 7e9bfa19a5d3dd6c5fd09d215288b82a5b2e5c36 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 9 Sep 2015 08:52:39 +1200 Subject: [PATCH 085/133] bug 1205540 don't send more null chunks than necessary to AnalyserNode r=padenot --HG-- extra : rebase_source : c1e6755ee91911f64a95a88abf469276be83f000 --- dom/media/webaudio/AnalyserNode.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/dom/media/webaudio/AnalyserNode.cpp b/dom/media/webaudio/AnalyserNode.cpp index cf8ce8c47836..35d6c9b35161 100644 --- a/dom/media/webaudio/AnalyserNode.cpp +++ b/dom/media/webaudio/AnalyserNode.cpp @@ -65,6 +65,19 @@ public: { *aOutput = aInput; + if (aInput.IsNull()) { + // If AnalyserNode::mChunks has only null chunks, then there is no need + // to send further null chunks. + if (mChunksToProcess == 0) { + return; + } + + --mChunksToProcess; + } else { + // This many null chunks will be required to empty AnalyserNode::mChunks. + mChunksToProcess = CHUNK_COUNT; + } + nsRefPtr transfer = new TransferBuffer(aStream, aInput.AsAudioChunk()); NS_DispatchToMainThread(transfer); @@ -74,6 +87,8 @@ public: { return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); } + + size_t mChunksToProcess = 0; }; AnalyserNode::AnalyserNode(AudioContext* aContext) From 57f288f403609777fa0c2baa213eb300e3d8bdb4 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 9 Sep 2015 08:54:03 +1200 Subject: [PATCH 086/133] bug 1205540 provide querying whether engines need to continue processing even without input r=padenot --HG-- extra : rebase_source : 08dfd9685c49b93a9ca113434f62d92de26f58e7 --- dom/media/webaudio/AnalyserNode.cpp | 5 +++++ dom/media/webaudio/AudioBufferSourceNode.cpp | 6 ++++++ dom/media/webaudio/AudioDestinationNode.cpp | 18 ++++++++++++++++++ dom/media/webaudio/AudioNodeEngine.h | 6 ++++++ dom/media/webaudio/BiquadFilterNode.cpp | 5 +++++ dom/media/webaudio/ConvolverNode.cpp | 5 +++++ dom/media/webaudio/DelayNode.cpp | 5 +++++ dom/media/webaudio/OscillatorNode.cpp | 6 ++++++ dom/media/webaudio/PannerNode.cpp | 5 +++++ dom/media/webaudio/ScriptProcessorNode.cpp | 8 ++++++++ 10 files changed, 69 insertions(+) diff --git a/dom/media/webaudio/AnalyserNode.cpp b/dom/media/webaudio/AnalyserNode.cpp index 35d6c9b35161..0027ce3a78ad 100644 --- a/dom/media/webaudio/AnalyserNode.cpp +++ b/dom/media/webaudio/AnalyserNode.cpp @@ -83,6 +83,11 @@ public: NS_DispatchToMainThread(transfer); } + virtual bool IsActive() const override + { + return mChunksToProcess != 0; + } + virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override { return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); diff --git a/dom/media/webaudio/AudioBufferSourceNode.cpp b/dom/media/webaudio/AudioBufferSourceNode.cpp index 0d165058dd5f..6ce49abd4f8b 100644 --- a/dom/media/webaudio/AudioBufferSourceNode.cpp +++ b/dom/media/webaudio/AudioBufferSourceNode.cpp @@ -508,6 +508,12 @@ public: } } + virtual bool IsActive() const override + { + // Whether buffer has been set and start() has been called. + return mBufferSampleRate != 0; + } + virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override { // Not owned: diff --git a/dom/media/webaudio/AudioDestinationNode.cpp b/dom/media/webaudio/AudioDestinationNode.cpp index 16071cb8b5c2..6b0326bea7d0 100644 --- a/dom/media/webaudio/AudioDestinationNode.cpp +++ b/dom/media/webaudio/AudioDestinationNode.cpp @@ -112,6 +112,14 @@ public: } } + virtual bool IsActive() const override + { + // Keep processing to track stream time, which is used for all timelines + // associated with the same AudioContext. + return true; + } + + class OnCompleteTask final : public nsRunnable { public: @@ -255,6 +263,16 @@ public: } } + virtual bool IsActive() const override + { + // Keep processing to track stream time, which is used for all timelines + // associated with the same AudioContext. If there are no other engines + // for the AudioContext, then this could return false to suspend the + // stream, but the stream is blocked anyway through + // AudioDestinationNode::SetIsOnlyNodeForContext(). + return true; + } + virtual void SetDoubleParameter(uint32_t aIndex, double aParam) override { if (aIndex == VOLUME) { diff --git a/dom/media/webaudio/AudioNodeEngine.h b/dom/media/webaudio/AudioNodeEngine.h index c3ae9dbd1367..f00f045dacd0 100644 --- a/dom/media/webaudio/AudioNodeEngine.h +++ b/dom/media/webaudio/AudioNodeEngine.h @@ -346,6 +346,12 @@ public: OutputChunks& aOutput, bool* aFinished); + // IsActive() returns true if the engine needs to continue processing an + // unfinished stream even when it has silent or no input connections. This + // includes tail-times and when sources have been scheduled to start. If + // returning false, then the stream can be suspended. + virtual bool IsActive() const { return false; } + bool HasNode() const { MOZ_ASSERT(NS_IsMainThread()); diff --git a/dom/media/webaudio/BiquadFilterNode.cpp b/dom/media/webaudio/BiquadFilterNode.cpp index ab4ce6455996..c657b7bff2bb 100644 --- a/dom/media/webaudio/BiquadFilterNode.cpp +++ b/dom/media/webaudio/BiquadFilterNode.cpp @@ -211,6 +211,11 @@ public: } } + virtual bool IsActive() const override + { + return !mBiquads.IsEmpty(); + } + virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override { // Not owned: diff --git a/dom/media/webaudio/ConvolverNode.cpp b/dom/media/webaudio/ConvolverNode.cpp index 9dcdcecb5655..d54fe97380ba 100644 --- a/dom/media/webaudio/ConvolverNode.cpp +++ b/dom/media/webaudio/ConvolverNode.cpp @@ -154,6 +154,11 @@ public: mReverb->process(&input, aOutput, WEBAUDIO_BLOCK_SIZE); } + virtual bool IsActive() const override + { + return mLeftOverData != INT32_MIN; + } + virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override { size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf); diff --git a/dom/media/webaudio/DelayNode.cpp b/dom/media/webaudio/DelayNode.cpp index 10afd3445f72..18d61ca33290 100644 --- a/dom/media/webaudio/DelayNode.cpp +++ b/dom/media/webaudio/DelayNode.cpp @@ -161,6 +161,11 @@ public: mHaveProducedBeforeInput = true; } + virtual bool IsActive() const override + { + return mLeftOverData != INT32_MIN; + } + virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override { size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf); diff --git a/dom/media/webaudio/OscillatorNode.cpp b/dom/media/webaudio/OscillatorNode.cpp index bd516b89ee30..1a18e0ddce0d 100644 --- a/dom/media/webaudio/OscillatorNode.cpp +++ b/dom/media/webaudio/OscillatorNode.cpp @@ -330,6 +330,12 @@ public: } + virtual bool IsActive() const override + { + // start() has been called. + return mStart != -1; + } + virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override { size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf); diff --git a/dom/media/webaudio/PannerNode.cpp b/dom/media/webaudio/PannerNode.cpp index 842258ab48f2..40a7a572dd97 100644 --- a/dom/media/webaudio/PannerNode.cpp +++ b/dom/media/webaudio/PannerNode.cpp @@ -172,6 +172,11 @@ public: (this->*mPanningModelFunction)(aInput, aOutput); } + virtual bool IsActive() const override + { + return mLeftOverData != INT_MIN; + } + void ComputeAzimuthAndElevation(float& aAzimuth, float& aElevation); float ComputeConeGain(); // Compute how much the distance contributes to the gain reduction. diff --git a/dom/media/webaudio/ScriptProcessorNode.cpp b/dom/media/webaudio/ScriptProcessorNode.cpp index 17a944ece018..587475ccd211 100644 --- a/dom/media/webaudio/ScriptProcessorNode.cpp +++ b/dom/media/webaudio/ScriptProcessorNode.cpp @@ -333,6 +333,14 @@ public: } } + virtual bool IsActive() const override + { + // Could return false when !mIsConnected after all output chunks produced + // by main thread events calling + // SharedBuffers::FinishProducingOutputBuffer() have been processed. + return true; + } + virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override { // Not owned: From b8a08a30f955552c17c083fc216a1aec9c7dff70 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Wed, 9 Sep 2015 14:19:05 +1200 Subject: [PATCH 087/133] bug 1205540 make source stream available during RemoveInput r=padenot --HG-- extra : rebase_source : 9f228fc8f2e6bc173dc3f7917c34f4b066f38209 --- dom/media/MediaStreamGraph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/media/MediaStreamGraph.cpp b/dom/media/MediaStreamGraph.cpp index 8b00606c674b..70329e8d6107 100644 --- a/dom/media/MediaStreamGraph.cpp +++ b/dom/media/MediaStreamGraph.cpp @@ -2365,8 +2365,8 @@ MediaInputPort::Disconnect() return; mSource->RemoveConsumer(this); - mSource = nullptr; mDest->RemoveInput(this); + mSource = nullptr; mDest = nullptr; GraphImpl()->SetStreamOrderDirty(); From 2a0fb73346f82c09f5b5fdb5f98388301038331c Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Fri, 18 Sep 2015 00:00:17 +1200 Subject: [PATCH 088/133] bug 1205540 mark BufferSource finished only when producing silent output block r=padenot This allows simpler processing of the finished state to mark the node as an inactive input of any downstream nodes. Otherwise the input could not be considered inactive until after downstream nodes have finished processing, but ProcessInput() may not be called again on finished streams. AudioBufferSourceNode now behaves the same as OscillatorNode and similarly to nodes that release a playing ref. --HG-- extra : rebase_source : 1268ca8f561fee2a43ba17f5fe3abc804486a50c --- dom/media/webaudio/AudioBufferSourceNode.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/dom/media/webaudio/AudioBufferSourceNode.cpp b/dom/media/webaudio/AudioBufferSourceNode.cpp index 6ce49abd4f8b..709a96d31b2e 100644 --- a/dom/media/webaudio/AudioBufferSourceNode.cpp +++ b/dom/media/webaudio/AudioBufferSourceNode.cpp @@ -466,12 +466,21 @@ public: return; } + StreamTime streamPosition = aStream->GetCurrentPosition(); + // We've finished if we've gone past mStop, or if we're past mDuration when + // looping is disabled. + if (streamPosition >= mStop || + (!mLoop && mBufferPosition >= mBufferEnd && !mRemainingResamplerTail)) { + *aFinished = true; + aOutput->SetNull(WEBAUDIO_BLOCK_SIZE); + return; + } + uint32_t channels = mBuffer ? mBuffer->GetChannels() : 0; UpdateSampleRateIfNeeded(channels); uint32_t written = 0; - StreamTime streamPosition = aStream->GetCurrentPosition(); while (written < WEBAUDIO_BLOCK_SIZE) { if (mStop != STREAM_TIME_MAX && streamPosition >= mStop) { @@ -499,13 +508,6 @@ public: } } } - - // We've finished if we've gone past mStop, or if we're past mDuration when - // looping is disabled. - if (streamPosition >= mStop || - (!mLoop && mBufferPosition >= mBufferEnd && !mRemainingResamplerTail)) { - *aFinished = true; - } } virtual bool IsActive() const override From 82019c145c69fdb973f8e03e2385d35ffc2680d8 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Mon, 21 Sep 2015 11:37:55 +1200 Subject: [PATCH 089/133] bug 1205540 initialize mBufferFormat when constructing silent block r=padenot This makes an AudioBlock valid for code testing mBufferFormat without IsNull(), without the need for explicit SetNull(). This is useful so that setting AudioNodeStream::mLastChunks each iteration is not required for inactive nodes. --HG-- extra : rebase_source : 171b7339bfe91e15b070f03bd5e0b784b58a217a --- dom/media/webaudio/AudioBlock.h | 1 + 1 file changed, 1 insertion(+) diff --git a/dom/media/webaudio/AudioBlock.h b/dom/media/webaudio/AudioBlock.h index 5d0d9e17aad0..c9a5bb400983 100644 --- a/dom/media/webaudio/AudioBlock.h +++ b/dom/media/webaudio/AudioBlock.h @@ -23,6 +23,7 @@ class AudioBlock : private AudioChunk public: AudioBlock() { mDuration = WEBAUDIO_BLOCK_SIZE; + mBufferFormat = AUDIO_FORMAT_SILENCE; } // No effort is made in constructors to ensure that mBufferIsDownstreamRef // is set because the block is expected to be a temporary and so the From 026a99369a6e76379506d3a607f0384169c174d6 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Fri, 18 Sep 2015 00:03:00 +1200 Subject: [PATCH 090/133] bug 1205540 account for active inputs and skip processing when streams are inactive r=padenot --HG-- extra : rebase_source : 20eca7c13b9757fc9c79ee414a7b4c2c8da26be2 --- dom/media/webaudio/AnalyserNode.cpp | 10 +- dom/media/webaudio/AudioBufferSourceNode.cpp | 6 +- dom/media/webaudio/AudioNodeEngine.h | 6 +- dom/media/webaudio/AudioNodeStream.cpp | 98 +++++++++++++++++++- dom/media/webaudio/AudioNodeStream.h | 25 +++++ dom/media/webaudio/BiquadFilterNode.cpp | 1 + dom/media/webaudio/ConvolverNode.cpp | 1 + dom/media/webaudio/DelayNode.cpp | 4 +- dom/media/webaudio/OscillatorNode.cpp | 5 +- dom/media/webaudio/PannerNode.cpp | 3 +- 10 files changed, 148 insertions(+), 11 deletions(-) diff --git a/dom/media/webaudio/AnalyserNode.cpp b/dom/media/webaudio/AnalyserNode.cpp index 0027ce3a78ad..d0af68431477 100644 --- a/dom/media/webaudio/AnalyserNode.cpp +++ b/dom/media/webaudio/AnalyserNode.cpp @@ -68,7 +68,11 @@ public: if (aInput.IsNull()) { // If AnalyserNode::mChunks has only null chunks, then there is no need // to send further null chunks. - if (mChunksToProcess == 0) { + if (mChunksToProcess <= 0) { + if (mChunksToProcess != INT32_MIN) { + mChunksToProcess = INT32_MIN; + aStream->CheckForInactive(); + } return; } @@ -85,7 +89,7 @@ public: virtual bool IsActive() const override { - return mChunksToProcess != 0; + return mChunksToProcess != INT32_MIN; } virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override @@ -93,7 +97,7 @@ public: return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); } - size_t mChunksToProcess = 0; + int32_t mChunksToProcess = INT32_MIN; }; AnalyserNode::AnalyserNode(AudioContext* aContext) diff --git a/dom/media/webaudio/AudioBufferSourceNode.cpp b/dom/media/webaudio/AudioBufferSourceNode.cpp index 709a96d31b2e..359335585acc 100644 --- a/dom/media/webaudio/AudioBufferSourceNode.cpp +++ b/dom/media/webaudio/AudioBufferSourceNode.cpp @@ -111,7 +111,11 @@ public: virtual void SetInt32Parameter(uint32_t aIndex, int32_t aParam) override { switch (aIndex) { - case AudioBufferSourceNode::SAMPLE_RATE: mBufferSampleRate = aParam; break; + case AudioBufferSourceNode::SAMPLE_RATE: + MOZ_ASSERT(aParam > 0); + mBufferSampleRate = aParam; + mSource->SetActive(); + break; case AudioBufferSourceNode::BUFFERSTART: MOZ_ASSERT(aParam >= 0); if (mBufferPosition == 0) { diff --git a/dom/media/webaudio/AudioNodeEngine.h b/dom/media/webaudio/AudioNodeEngine.h index f00f045dacd0..c40773d7b1d5 100644 --- a/dom/media/webaudio/AudioNodeEngine.h +++ b/dom/media/webaudio/AudioNodeEngine.h @@ -309,8 +309,10 @@ public: * aInput is guaranteed to have float sample format (if it has samples at all) * and to have been resampled to the sampling rate for the stream, and to have * exactly WEBAUDIO_BLOCK_SIZE samples. - * *aFinished is set to false by the caller. If the callee sets it to true, - * we'll finish the stream and not call this again. + * *aFinished is set to false by the caller. The callee must not set this to + * true unless silent output is produced. If set to true, we'll finish the + * stream, consider this input inactive on any downstream nodes, and not + * call this again. */ virtual void ProcessBlock(AudioNodeStream* aStream, const AudioBlock& aInput, diff --git a/dom/media/webaudio/AudioNodeStream.cpp b/dom/media/webaudio/AudioNodeStream.cpp index 1255e945814f..38311919ce61 100644 --- a/dom/media/webaudio/AudioNodeStream.cpp +++ b/dom/media/webaudio/AudioNodeStream.cpp @@ -34,6 +34,7 @@ AudioNodeStream::AudioNodeStream(AudioNodeEngine* aEngine, mSampleRate(aSampleRate), mFlags(aFlags), mNumberOfInputChannels(2), + mIsActive(aEngine->IsActive()), mMarkAsFinishedAfterThisBlock(false), mAudioParamStream(false), mPassThrough(false) @@ -49,6 +50,7 @@ AudioNodeStream::AudioNodeStream(AudioNodeEngine* aEngine, AudioNodeStream::~AudioNodeStream() { + MOZ_ASSERT(mActiveInputCount == 0); MOZ_COUNT_DTOR(AudioNodeStream); } @@ -520,7 +522,14 @@ AudioNodeStream::ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) uint16_t outputCount = mLastChunks.Length(); MOZ_ASSERT(outputCount == std::max(uint16_t(1), mEngine->OutputCount())); - if (mFinished || InMutedCycle()) { + if (!mIsActive) { + // mLastChunks are already null. +#ifdef DEBUG + for (const auto& chunk : mLastChunks) { + MOZ_ASSERT(chunk.IsNull()); + } +#endif + } else if (InMutedCycle()) { mInputChunks.Clear(); for (uint16_t i = 0; i < outputCount; ++i) { mLastChunks[i].SetNull(WEBAUDIO_BLOCK_SIZE); @@ -549,6 +558,7 @@ AudioNodeStream::ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) } if (finished) { mMarkAsFinishedAfterThisBlock = true; + CheckForInactive(); } if (mDisabledTrackIDs.Contains(static_cast(AUDIO_TRACK))) { @@ -579,7 +589,7 @@ AudioNodeStream::ProduceOutputBeforeInput(GraphTime aFrom) MOZ_ASSERT(!InMutedCycle(), "DelayNodes should break cycles"); MOZ_ASSERT(mLastChunks.Length() == 1); - if (mFinished) { + if (!mIsActive) { mLastChunks[0].SetNull(WEBAUDIO_BLOCK_SIZE); } else { mEngine->ProduceBlockBeforeInput(&mLastChunks[0]); @@ -684,4 +694,88 @@ AudioNodeStream::DestinationTimeFromTicks(AudioNodeStream* aDestination, return StreamTimeToSeconds(destinationTime); } +void +AudioNodeStream::AddInput(MediaInputPort* aPort) +{ + ProcessedMediaStream::AddInput(aPort); + AudioNodeStream* ns = aPort->GetSource()->AsAudioNodeStream(); + // Streams that are not AudioNodeStreams are considered active. + if (!ns || (ns->mIsActive && !ns->IsAudioParamStream())) { + IncrementActiveInputCount(); + } +} +void +AudioNodeStream::RemoveInput(MediaInputPort* aPort) +{ + ProcessedMediaStream::RemoveInput(aPort); + AudioNodeStream* ns = aPort->GetSource()->AsAudioNodeStream(); + // Streams that are not AudioNodeStreams are considered active. + if (!ns || (ns->mIsActive && !ns->IsAudioParamStream())) { + DecrementActiveInputCount(); + } +} + +void +AudioNodeStream::SetActive() +{ + if (mIsActive || mMarkAsFinishedAfterThisBlock) { + return; + } + + mIsActive = true; + if (IsAudioParamStream()) { + // Consumers merely influence stream order. + // They do not read from the stream. + return; + } + + for (const auto& consumer : mConsumers) { + AudioNodeStream* ns = consumer->GetDestination()->AsAudioNodeStream(); + if (ns) { + ns->IncrementActiveInputCount(); + } + } +} + +void +AudioNodeStream::CheckForInactive() +{ + if (((mActiveInputCount > 0 || mEngine->IsActive()) && + !mMarkAsFinishedAfterThisBlock) || + !mIsActive) { + return; + } + + mIsActive = false; + mInputChunks.Clear(); // not required for foreseeable future + for (auto& chunk : mLastChunks) { + chunk.SetNull(WEBAUDIO_BLOCK_SIZE); + } + if (IsAudioParamStream()) { + return; + } + + for (const auto& consumer : mConsumers) { + AudioNodeStream* ns = consumer->GetDestination()->AsAudioNodeStream(); + if (ns) { + ns->DecrementActiveInputCount(); + } + } +} + +void +AudioNodeStream::IncrementActiveInputCount() +{ + ++mActiveInputCount; + SetActive(); +} + +void +AudioNodeStream::DecrementActiveInputCount() +{ + MOZ_ASSERT(mActiveInputCount > 0); + --mActiveInputCount; + CheckForInactive(); +} + } // namespace mozilla diff --git a/dom/media/webaudio/AudioNodeStream.h b/dom/media/webaudio/AudioNodeStream.h index 042cbd92b4d0..838d4e81913a 100644 --- a/dom/media/webaudio/AudioNodeStream.h +++ b/dom/media/webaudio/AudioNodeStream.h @@ -106,6 +106,8 @@ public: } virtual AudioNodeStream* AsAudioNodeStream() override { return this; } + virtual void AddInput(MediaInputPort* aPort) override; + virtual void RemoveInput(MediaInputPort* aPort) override; // Graph thread only void SetStreamTimeParameterImpl(uint32_t aIndex, MediaStream* aRelativeToStream, @@ -165,6 +167,22 @@ public: void SizeOfAudioNodesIncludingThis(MallocSizeOf aMallocSizeOf, AudioNodeSizes& aUsage) const; + /* + * SetActive() is called when either an active input is added or the engine + * for a source node transitions from inactive to active. This is not + * called from engines for processing nodes because they only become active + * when there are active input streams, in which case this stream is already + * active. + */ + void SetActive(); + /* + * CheckForInactive() is called when the engine transitions from active to + * inactive, or an active input is removed, or the stream finishes. If the + * stream is now inactive, then mInputChunks will be cleared and mLastChunks + * will be set to null. ProcessBlock() will not be called on the engine + * again until SetActive() is called. + */ + void CheckForInactive(); protected: virtual void DestroyImpl() override; @@ -180,6 +198,8 @@ protected: uint32_t ComputedNumberOfChannels(uint32_t aInputChannelCount); void ObtainInputBlock(AudioBlock& aTmpChunk, uint32_t aPortIndex); + void IncrementActiveInputCount(); + void DecrementActiveInputCount(); // The engine that will generate output for this node. nsAutoPtr mEngine; @@ -192,11 +212,16 @@ protected: const TrackRate mSampleRate; // Whether this is an internal or external stream const Flags mFlags; + // The number of input streams that may provide non-silent input. + uint32_t mActiveInputCount = 0; // The number of input channels that this stream requires. 0 means don't care. uint32_t mNumberOfInputChannels; // The mixing modes ChannelCountMode mChannelCountMode; ChannelInterpretation mChannelInterpretation; + // Streams are considered active if the stream has not finished and either + // the engine is active or there are active input streams. + bool mIsActive; // Whether the stream should be marked as finished as soon // as the current time range has been computed block by block. bool mMarkAsFinishedAfterThisBlock; diff --git a/dom/media/webaudio/BiquadFilterNode.cpp b/dom/media/webaudio/BiquadFilterNode.cpp index c657b7bff2bb..96740bc1b7fa 100644 --- a/dom/media/webaudio/BiquadFilterNode.cpp +++ b/dom/media/webaudio/BiquadFilterNode.cpp @@ -155,6 +155,7 @@ public: if (!hasTail) { if (!mBiquads.IsEmpty()) { mBiquads.Clear(); + aStream->CheckForInactive(); nsRefPtr refchanged = new PlayingRefChangeHandler(aStream, PlayingRefChangeHandler::RELEASE); diff --git a/dom/media/webaudio/ConvolverNode.cpp b/dom/media/webaudio/ConvolverNode.cpp index d54fe97380ba..b96141cebde7 100644 --- a/dom/media/webaudio/ConvolverNode.cpp +++ b/dom/media/webaudio/ConvolverNode.cpp @@ -120,6 +120,7 @@ public: } else { if (mLeftOverData != INT32_MIN) { mLeftOverData = INT32_MIN; + aStream->CheckForInactive(); nsRefPtr refchanged = new PlayingRefChanged(aStream, PlayingRefChanged::RELEASE); aStream->Graph()-> diff --git a/dom/media/webaudio/DelayNode.cpp b/dom/media/webaudio/DelayNode.cpp index 18d61ca33290..4194325ffcca 100644 --- a/dom/media/webaudio/DelayNode.cpp +++ b/dom/media/webaudio/DelayNode.cpp @@ -96,6 +96,8 @@ public: } else { if (mLeftOverData != INT32_MIN) { mLeftOverData = INT32_MIN; + aStream->CheckForInactive(); + // Delete our buffered data now we no longer need it mBuffer.Reset(); @@ -104,7 +106,7 @@ public: aStream->Graph()-> DispatchToMainThreadAfterStreamStateUpdate(refchanged.forget()); } - *aOutput = aInput; + aOutput->SetNull(WEBAUDIO_BLOCK_SIZE); return; } diff --git a/dom/media/webaudio/OscillatorNode.cpp b/dom/media/webaudio/OscillatorNode.cpp index 1a18e0ddce0d..fe8a4c35d760 100644 --- a/dom/media/webaudio/OscillatorNode.cpp +++ b/dom/media/webaudio/OscillatorNode.cpp @@ -81,7 +81,10 @@ public: virtual void SetStreamTimeParameter(uint32_t aIndex, StreamTime aParam) override { switch (aIndex) { - case START: mStart = aParam; break; + case START: + mStart = aParam; + mSource->SetActive(); + break; case STOP: mStop = aParam; break; default: NS_ERROR("Bad OscillatorNodeEngine StreamTimeParameter"); diff --git a/dom/media/webaudio/PannerNode.cpp b/dom/media/webaudio/PannerNode.cpp index 40a7a572dd97..b68d0108c783 100644 --- a/dom/media/webaudio/PannerNode.cpp +++ b/dom/media/webaudio/PannerNode.cpp @@ -149,6 +149,7 @@ public: } else { if (mLeftOverData != INT_MIN) { mLeftOverData = INT_MIN; + aStream->CheckForInactive(); mHRTFPanner->reset(); nsRefPtr refchanged = @@ -156,7 +157,7 @@ public: aStream->Graph()-> DispatchToMainThreadAfterStreamStateUpdate(refchanged.forget()); } - *aOutput = aInput; + aOutput->SetNull(WEBAUDIO_BLOCK_SIZE); return; } } else if (mPanningModelFunction == &PannerNodeEngine::HRTFPanningFunction) { From a15b59d7f858b355bb3ab6c4d26403ef136c3aca Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Mon, 21 Sep 2015 14:21:07 -0700 Subject: [PATCH 091/133] Bug 1206817 - Take ownership of error reporting in the component loader. r=bz --- js/xpconnect/loader/mozJSComponentLoader.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index 8da370b72b88..112d3e6923ec 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -348,6 +348,7 @@ mozJSComponentLoader::LoadModule(FileLocation& aFile) dom::AutoJSAPI jsapi; jsapi.Init(); + jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); nsAutoPtr entry(new ModuleEntry(cx)); @@ -628,6 +629,7 @@ mozJSComponentLoader::ObjectForLocation(ComponentLoaderInfo& aInfo, dom::AutoJSAPI jsapi; jsapi.Init(); + jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); bool realFile = false; @@ -957,6 +959,7 @@ mozJSComponentLoader::UnloadModules() dom::AutoJSAPI jsapi; jsapi.Init(); + jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); RootedObject global(cx, mLoaderGlobal->GetJSObject()); if (global) { @@ -1170,6 +1173,7 @@ mozJSComponentLoader::ImportInto(const nsACString& aLocation, // not an AutoEntryScript. dom::AutoJSAPI jsapi; jsapi.Init(); + jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); JSAutoCompartment ac(cx, mod->obj); From cb3685d2fb264004fc006bab1ac130494fc19ae9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 21 Sep 2015 17:13:51 -0700 Subject: [PATCH 092/133] Bug 1205941 - Make TimerFirings logging output post-processible with fix_linux_stack.py. r=glandium. --- xpcom/threads/nsTimerImpl.cpp | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/xpcom/threads/nsTimerImpl.cpp b/xpcom/threads/nsTimerImpl.cpp index d1b72194b678..35189f396a9c 100644 --- a/xpcom/threads/nsTimerImpl.cpp +++ b/xpcom/threads/nsTimerImpl.cpp @@ -12,6 +12,7 @@ #include "pratom.h" #include "GeckoProfiler.h" #include "mozilla/Atomics.h" +#include "mozilla/IntegerPrintfMacros.h" #include "mozilla/Logging.h" #ifdef MOZ_NUWA_PROCESS #include "ipc/Nuwa.h" @@ -62,8 +63,10 @@ GetTimerLog() // InitWithNamedFuncCallback()) then that explicit name will be shown. // // - Otherwise, if we are on a platform that supports function name lookup -// (currently only Mac) then the looked-up name will be shown with a -// "[from dladdr]" annotation. +// (Mac or Linux) then the looked-up name will be shown with a +// "[from dladdr]" annotation. On Mac the looked-up name will be immediately +// useful. On Linux it'll need post-processing with +// tools/rb/fix_linux_stack.py. // // - Otherwise, no name will be printed. If many timers hit this case then // you'll need to re-run the workload on a Mac to find out which timers they @@ -574,7 +577,11 @@ nsTimerImpl::Fire() } } -#if defined(XP_MACOSX) +#if defined(XP_MACOSX) || (defined(XP_LINUX) && !defined(ANDROID)) +#define USE_DLADDR 1 +#endif + +#ifdef USE_DLADDR #include #include #endif @@ -609,16 +616,15 @@ nsTimerImpl::LogFiring(CallbackType aCallbackType, CallbackUnion aCallback) } else { MOZ_ASSERT(mName.is()); -#if defined(XP_MACOSX) +#ifdef USE_DLADDR annotation = "[from dladdr] "; Dl_info info; - if (dladdr(reinterpret_cast(aCallback.c), &info) == 0) { + void* addr = reinterpret_cast(aCallback.c); + if (dladdr(addr, &info) == 0) { name = "???[dladdr: failed]"; - } else if (!info.dli_sname) { - name = "???[dladdr: no matching symbol]"; - } else { + } else if (info.dli_sname) { int status; name = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status); if (status == 0) { @@ -635,9 +641,19 @@ nsTimerImpl::LogFiring(CallbackType aCallbackType, CallbackUnion aCallback) } else { name = "???[__cxa_demangle: unexpected status value]"; } + + } else if (info.dli_fname) { + // The "#0: " prefix is necessary for fix_linux_stack.py to interpret + // this string as something to convert. + snprintf(buf, buflen, "#0: ???[%s +0x%" PRIxPTR "]\n", + info.dli_fname, uintptr_t(addr) - uintptr_t(info.dli_fbase)); + name = buf; + + } else { + name = "???[dladdr: no symbol or shared object obtained]"; } #else - name = "???[dladdr: unavailable/doesn't work on this platform]"; + name = "???[dladdr is unimplemented or doesn't work well on this OS]"; #endif } From 4cfc10cfeed511347e22485749179d568b94d6a9 Mon Sep 17 00:00:00 2001 From: Sotaro Ikeda Date: Mon, 21 Sep 2015 17:22:06 -0700 Subject: [PATCH 093/133] Bug 1206174 - Improve code readability of FMRadioService r=alwu --- dom/fmradio/FMRadio.cpp | 19 ++- dom/fmradio/FMRadioService.cpp | 285 ++++++++++++++------------------- dom/fmradio/FMRadioService.h | 4 + 3 files changed, 136 insertions(+), 172 deletions(-) diff --git a/dom/fmradio/FMRadio.cpp b/dom/fmradio/FMRadio.cpp index 9a35851e561a..489946ae6acf 100644 --- a/dom/fmradio/FMRadio.cpp +++ b/dom/fmradio/FMRadio.cpp @@ -27,7 +27,6 @@ // If the pref is true, the antanna will be always available. #define DOM_FM_ANTENNA_INTERNAL_PREF "dom.fmradio.antenna.internal" -using namespace mozilla::hal; using mozilla::Preferences; BEGIN_FMRADIO_NAMESPACE @@ -106,7 +105,7 @@ private: NS_IMPL_ISUPPORTS_INHERITED0(FMRadioRequest, DOMRequest) FMRadio::FMRadio() - : mHeadphoneState(SWITCH_STATE_OFF) + : mHeadphoneState(hal::SWITCH_STATE_OFF) , mRdsGroupMask(0) , mAudioChannelAgentEnabled(false) , mHasInternalAntenna(false) @@ -131,8 +130,8 @@ FMRadio::Init(nsPIDOMWindow *aWindow) if (mHasInternalAntenna) { LOG("We have an internal antenna."); } else { - mHeadphoneState = GetCurrentSwitchState(SWITCH_HEADPHONES); - RegisterSwitchObserver(SWITCH_HEADPHONES, this); + mHeadphoneState = hal::GetCurrentSwitchState(hal::SWITCH_HEADPHONES); + hal::RegisterSwitchObserver(hal::SWITCH_HEADPHONES, this); } nsCOMPtr audioChannelAgent = @@ -155,7 +154,7 @@ FMRadio::Shutdown() IFMRadioService::Singleton()->RemoveObserver(this); if (!mHasInternalAntenna) { - UnregisterSwitchObserver(SWITCH_HEADPHONES, this); + hal::UnregisterSwitchObserver(hal::SWITCH_HEADPHONES, this); } mIsShutdown = true; @@ -168,7 +167,7 @@ FMRadio::WrapObject(JSContext* aCx, JS::Handle aGivenProto) } void -FMRadio::Notify(const SwitchEvent& aEvent) +FMRadio::Notify(const hal::SwitchEvent& aEvent) { MOZ_ASSERT(!mHasInternalAntenna); @@ -241,8 +240,8 @@ FMRadio::RdsEnabled() bool FMRadio::AntennaAvailable() const { - return mHasInternalAntenna ? true : (mHeadphoneState != SWITCH_STATE_OFF) && - (mHeadphoneState != SWITCH_STATE_UNKNOWN); + return mHasInternalAntenna ? true : (mHeadphoneState != hal::SWITCH_STATE_OFF) && + (mHeadphoneState != hal::SWITCH_STATE_UNKNOWN); } Nullable @@ -387,7 +386,7 @@ FMRadio::SeekUp() } nsRefPtr r = new FMRadioRequest(win, this); - IFMRadioService::Singleton()->Seek(FM_RADIO_SEEK_DIRECTION_UP, r); + IFMRadioService::Singleton()->Seek(hal::FM_RADIO_SEEK_DIRECTION_UP, r); return r.forget(); } @@ -401,7 +400,7 @@ FMRadio::SeekDown() } nsRefPtr r = new FMRadioRequest(win, this); - IFMRadioService::Singleton()->Seek(FM_RADIO_SEEK_DIRECTION_DOWN, r); + IFMRadioService::Singleton()->Seek(hal::FM_RADIO_SEEK_DIRECTION_DOWN, r); return r.forget(); } diff --git a/dom/fmradio/FMRadioService.cpp b/dom/fmradio/FMRadioService.cpp index 072c53048440..1afb5fa3a8bd 100644 --- a/dom/fmradio/FMRadioService.cpp +++ b/dom/fmradio/FMRadioService.cpp @@ -33,7 +33,6 @@ #define DOM_PARSED_RDS_GROUPS ((0x2 << 30) | (0x3 << 4) | (0x3 << 0)) -using namespace mozilla::hal; using mozilla::Preferences; BEGIN_FMRADIO_NAMESPACE @@ -78,9 +77,9 @@ FMRadioService::FMRadioService() memset(mTempRadiotext, 0, sizeof(mTempRadiotext)); // Read power state and frequency from Hal. - mEnabled = IsFMRadioOn(); + mEnabled = hal::IsFMRadioOn(); if (mEnabled) { - mPendingFrequencyInKHz = GetFMRadioFrequency(); + mPendingFrequencyInKHz = hal::GetFMRadioFrequency(); SetState(Enabled); } @@ -133,54 +132,34 @@ FMRadioService::FMRadioService() NS_WARNING("Failed to add settings change observer!"); } - RegisterFMRadioObserver(this); - RegisterFMRadioRDSObserver(this); + hal::RegisterFMRadioObserver(this); + hal::RegisterFMRadioRDSObserver(this); } FMRadioService::~FMRadioService() { - UnregisterFMRadioRDSObserver(this); - UnregisterFMRadioObserver(this); + hal::UnregisterFMRadioRDSObserver(this); + hal::UnregisterFMRadioObserver(this); } -class EnableRunnable final : public nsRunnable +void +FMRadioService::EnableFMRadio() { -public: - EnableRunnable(uint32_t aUpperLimit, uint32_t aLowerLimit, uint32_t aSpaceType, uint32_t aPreemphasis) - : mUpperLimit(aUpperLimit) - , mLowerLimit(aLowerLimit) - , mSpaceType(aSpaceType) - , mPreemphasis(aPreemphasis) - { + hal::FMRadioSettings info; + info.upperLimit() = mUpperBoundInKHz; + info.lowerLimit() = mLowerBoundInKHz; + info.spaceType() = mChannelWidthInKHz; + info.preEmphasis() = mPreemphasis; + + hal::EnableFMRadio(info); + + if (!mTuneThread) { + // hal::FMRadioSeek and hal::SetFMRadioFrequency run on this thread. These + // call ioctls that can stall the main thread, so we run them here. + mTuneThread = new LazyIdleThread( + TUNE_THREAD_TIMEOUT_MS, NS_LITERAL_CSTRING("FM Tuning")); } - - NS_IMETHOD Run() - { - FMRadioSettings info; - info.upperLimit() = mUpperLimit; - info.lowerLimit() = mLowerLimit; - info.spaceType() = mSpaceType; - info.preEmphasis() = mPreemphasis; - - EnableFMRadio(info); - - FMRadioService* fmRadioService = FMRadioService::Singleton(); - if (!fmRadioService->mTuneThread) { - // SeekRunnable and SetFrequencyRunnable run on this thread. These - // call ioctls that can stall the main thread, so we run them here. - fmRadioService->mTuneThread = new LazyIdleThread( - TUNE_THREAD_TIMEOUT_MS, NS_LITERAL_CSTRING("FM Tuning")); - } - - return NS_OK; - } - -private: - uint32_t mUpperLimit; - uint32_t mLowerLimit; - uint32_t mSpaceType; - uint32_t mPreemphasis; -}; +} /** * Read the airplane-mode setting, if the airplane-mode is not enabled, we @@ -197,9 +176,9 @@ public: NS_IMETHOD Handle(const nsAString& aName, JS::Handle aResult) { - FMRadioService* fmRadioService = FMRadioService::Singleton(); + nsRefPtr fmRadioService = FMRadioService::Singleton(); MOZ_ASSERT(mPendingRequest == fmRadioService->mPendingRequest); - + fmRadioService->mHasReadAirplaneModeSetting = true; if (!aResult.isBoolean()) { @@ -211,12 +190,11 @@ public: fmRadioService->mAirplaneModeEnabled = aResult.toBoolean(); if (!fmRadioService->mAirplaneModeEnabled) { - EnableRunnable* runnable = - new EnableRunnable(fmRadioService->mUpperBoundInKHz, - fmRadioService->mLowerBoundInKHz, - fmRadioService->mChannelWidthInKHz, - fmRadioService->mPreemphasis); - NS_DispatchToMainThread(runnable); + NS_DispatchToMainThread(NS_NewRunnableFunction( + [fmRadioService] () -> void { + fmRadioService->EnableFMRadio(); + } + )); } else { // Airplane mode is enabled, set the state back to Disabled. fmRadioService->TransitionState(ErrorResponse( @@ -247,80 +225,29 @@ private: NS_IMPL_ISUPPORTS(ReadAirplaneModeSettingTask, nsISettingsServiceCallback) -class DisableRunnable final : public nsRunnable +void +FMRadioService::DisableFMRadio() { -public: - DisableRunnable() { } + if (mTuneThread) { + mTuneThread->Shutdown(); + mTuneThread = nullptr; + } + // Fix Bug 796733. DisableFMRadio should be called before + // SetFmRadioAudioEnabled to prevent the annoying beep sound. + hal::DisableFMRadio(); + EnableAudio(false); +}; - NS_IMETHOD Run() - { - FMRadioService* fmRadioService = FMRadioService::Singleton(); - if (fmRadioService->mTuneThread) { - fmRadioService->mTuneThread->Shutdown(); - fmRadioService->mTuneThread = nullptr; +void +FMRadioService::DispatchFMRadioEventToMainThread(enum FMRadioEventType aType) +{ + nsRefPtr self = this; + NS_DispatchToMainThread(NS_NewRunnableFunction( + [self, aType] () -> void { + self->NotifyFMRadioEvent(aType); } - // Fix Bug 796733. DisableFMRadio should be called before - // SetFmRadioAudioEnabled to prevent the annoying beep sound. - DisableFMRadio(); - fmRadioService->EnableAudio(false); - - return NS_OK; - } -}; - -class SetFrequencyRunnable final : public nsRunnable -{ -public: - SetFrequencyRunnable(int32_t aFrequency) - : mFrequency(aFrequency) { } - - NS_IMETHOD Run() - { - SetFMRadioFrequency(mFrequency); - return NS_OK; - } - -private: - int32_t mFrequency; -}; - -class SeekRunnable final : public nsRunnable -{ -public: - SeekRunnable(FMRadioSeekDirection aDirection) : mDirection(aDirection) { } - - NS_IMETHOD Run() - { - switch (mDirection) { - case FM_RADIO_SEEK_DIRECTION_UP: - case FM_RADIO_SEEK_DIRECTION_DOWN: - FMRadioSeek(mDirection); - break; - default: - MOZ_CRASH(); - } - - return NS_OK; - } - -private: - FMRadioSeekDirection mDirection; -}; - -class NotifyRunnable final : public nsRunnable -{ -public: - NotifyRunnable(FMRadioEventType aType) : mType(aType) { } - - NS_IMETHOD Run() - { - FMRadioService::Singleton()->NotifyFMRadioEvent(mType); - return NS_OK; - } - -private: - FMRadioEventType mType; -}; + )); +} void FMRadioService::TransitionState(const FMRadioResponseType& aResponse, @@ -357,7 +284,7 @@ FMRadioService::RemoveObserver(FMRadioEventObserver* aObserver) if (mObserverList.Length() == 0) { // Turning off the FM radio HW because observer list is empty. - if (IsFMRadioOn()) { + if (hal::IsFMRadioOn()) { DoDisable(); } } @@ -416,7 +343,7 @@ bool FMRadioService::IsEnabled() const { MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); - return IsFMRadioOn(); + return hal::IsFMRadioOn(); } bool @@ -431,7 +358,7 @@ FMRadioService::GetFrequency() const { MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); if (IsEnabled()) { - int32_t frequencyInKHz = GetFMRadioFrequency(); + int32_t frequencyInKHz = hal::GetFMRadioFrequency(); return frequencyInKHz / 1000.0; } @@ -583,10 +510,12 @@ FMRadioService::Enable(double aFrequencyInMHz, return; } - NS_DispatchToMainThread(new EnableRunnable(mUpperBoundInKHz, - mLowerBoundInKHz, - mChannelWidthInKHz, - mPreemphasis)); + nsRefPtr self = this; + NS_DispatchToMainThread(NS_NewRunnableFunction( + [self] () -> void { + self->EnableFMRadio(); + } + )); } void @@ -665,8 +594,13 @@ FMRadioService::DoDisable() // console.log("We will catch disabled event "); // }; // we need to call hal::DisableFMRadio() asynchronously. Same reason for - // EnableRunnable and SetFrequencyRunnable. - NS_DispatchToMainThread(new DisableRunnable()); + // EnableFMRadio and hal::SetFMRadioFrequency. + nsRefPtr self = this; + NS_DispatchToMainThread(NS_NewRunnableFunction( + [self] () -> void { + self->DisableFMRadio(); + } + )); } void @@ -693,7 +627,7 @@ FMRadioService::SetFrequency(double aFrequencyInMHz, NS_DispatchToMainThread(aReplyRunnable); return; case Seeking: - CancelFMRadioSeek(); + hal::CancelFMRadioSeek(); TransitionState(ErrorResponse( NS_LITERAL_STRING("Seek action is cancelled")), Enabled); break; @@ -710,15 +644,19 @@ FMRadioService::SetFrequency(double aFrequencyInMHz, return; } - mTuneThread->Dispatch(new SetFrequencyRunnable(roundedFrequency), - nsIThread::DISPATCH_NORMAL); + mTuneThread->Dispatch( + NS_NewRunnableFunction( + [roundedFrequency] () -> void { + hal::SetFMRadioFrequency(roundedFrequency); + } + ), nsIThread::DISPATCH_NORMAL); aReplyRunnable->SetReply(SuccessResponse()); NS_DispatchToMainThread(aReplyRunnable); } void -FMRadioService::Seek(FMRadioSeekDirection aDirection, +FMRadioService::Seek(hal::FMRadioSeekDirection aDirection, FMRadioReplyRunnable* aReplyRunnable) { MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); @@ -752,7 +690,19 @@ FMRadioService::Seek(FMRadioSeekDirection aDirection, SetState(Seeking); mPendingRequest = aReplyRunnable; - mTuneThread->Dispatch(new SeekRunnable(aDirection), nsIThread::DISPATCH_NORMAL); + mTuneThread->Dispatch( + NS_NewRunnableFunction( + [aDirection] () -> void { + switch (aDirection) { + case hal::FM_RADIO_SEEK_DIRECTION_UP: + case hal::FM_RADIO_SEEK_DIRECTION_DOWN: + hal::FMRadioSeek(aDirection); + break; + default: + MOZ_CRASH(); + } + } + ), nsIThread::DISPATCH_NORMAL); } void @@ -770,7 +720,7 @@ FMRadioService::CancelSeek(FMRadioReplyRunnable* aReplyRunnable) } // Cancel the seek immediately to prevent it from completing. - CancelFMRadioSeek(); + hal::CancelFMRadioSeek(); TransitionState( ErrorResponse(NS_LITERAL_STRING("Seek action is cancelled")), Enabled); @@ -783,7 +733,7 @@ void FMRadioService::SetRDSGroupMask(uint32_t aRDSGroupMask) { mRDSGroupMask = aRDSGroupMask; - if (IsFMRadioOn() && mRDSEnabled) { + if (hal::IsFMRadioOn() && mRDSEnabled) { DebugOnly enabled = hal::EnableRDS(mRDSGroupMask | DOM_PARSED_RDS_GROUPS); MOZ_ASSERT(enabled); } @@ -795,7 +745,7 @@ FMRadioService::EnableRDS(FMRadioReplyRunnable* aReplyRunnable) MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); MOZ_ASSERT(aReplyRunnable); - if (IsFMRadioOn()) { + if (hal::IsFMRadioOn()) { if (!hal::EnableRDS(mRDSGroupMask | DOM_PARSED_RDS_GROUPS)) { aReplyRunnable->SetReply( ErrorResponse(NS_LITERAL_STRING("Could not enable RDS"))); @@ -808,7 +758,8 @@ FMRadioService::EnableRDS(FMRadioReplyRunnable* aReplyRunnable) aReplyRunnable->SetReply(SuccessResponse()); NS_DispatchToMainThread(aReplyRunnable); - NS_DispatchToMainThread(new NotifyRunnable(RDSEnabledChanged)); + + DispatchFMRadioEventToMainThread(RDSEnabledChanged); } void @@ -817,7 +768,7 @@ FMRadioService::DisableRDS(FMRadioReplyRunnable* aReplyRunnable) MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); MOZ_ASSERT(aReplyRunnable); - if (IsFMRadioOn()) { + if (hal::IsFMRadioOn()) { hal::DisableRDS(); } @@ -826,7 +777,8 @@ FMRadioService::DisableRDS(FMRadioReplyRunnable* aReplyRunnable) if (mRDSEnabled) { mRDSEnabled = false; - NS_DispatchToMainThread(new NotifyRunnable(RDSEnabledChanged)); + + DispatchFMRadioEventToMainThread(RDSEnabledChanged); } } @@ -873,11 +825,11 @@ FMRadioService::NotifyFMRadioEvent(FMRadioEventType aType) } void -FMRadioService::Notify(const FMRadioOperationInformation& aInfo) +FMRadioService::Notify(const hal::FMRadioOperationInformation& aInfo) { switch (aInfo.operation()) { - case FM_RADIO_OPERATION_ENABLE: - MOZ_ASSERT(IsFMRadioOn()); + case hal::FM_RADIO_OPERATION_ENABLE: + MOZ_ASSERT(hal::IsFMRadioOn()); MOZ_ASSERT(mState == Disabling || mState == Enabling); // If we're disabling, disable the radio right now. @@ -891,7 +843,7 @@ FMRadioService::Notify(const FMRadioOperationInformation& aInfo) // To make sure the FM app will get the right frequency after the FM // radio is enabled, we have to set the frequency first. - SetFMRadioFrequency(mPendingFrequencyInKHz); + hal::SetFMRadioFrequency(mPendingFrequencyInKHz); // Bug 949855: enable audio after the FM radio HW is enabled, to make sure // 'hw.fm.isAnalog' could be detected as |true| during first time launch. @@ -902,7 +854,7 @@ FMRadioService::Notify(const FMRadioOperationInformation& aInfo) // Update the current frequency without sending the`FrequencyChanged` // event, to make sure the FM app will get the right frequency when the // `EnabledChange` event is sent. - mPendingFrequencyInKHz = GetFMRadioFrequency(); + mPendingFrequencyInKHz = hal::GetFMRadioFrequency(); UpdatePowerState(); // The frequency was changed from '0' to some meaningful number, so we @@ -916,7 +868,7 @@ FMRadioService::Notify(const FMRadioOperationInformation& aInfo) } } break; - case FM_RADIO_OPERATION_DISABLE: + case hal::FM_RADIO_OPERATION_DISABLE: MOZ_ASSERT(mState == Disabling); mPISet = false; @@ -926,7 +878,7 @@ FMRadioService::Notify(const FMRadioOperationInformation& aInfo) TransitionState(SuccessResponse(), Disabled); UpdatePowerState(); break; - case FM_RADIO_OPERATION_SEEK: + case hal::FM_RADIO_OPERATION_SEEK: // Seek action might be cancelled by SetFrequency(), we need to check if // the current state is Seeking. @@ -936,7 +888,7 @@ FMRadioService::Notify(const FMRadioOperationInformation& aInfo) UpdateFrequency(); break; - case FM_RADIO_OPERATION_TUNE: + case hal::FM_RADIO_OPERATION_TUNE: UpdateFrequency(); break; default: @@ -1014,7 +966,7 @@ static const uint16_t sRDSToUnicodeMap[256] = { }; void -FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup) +FMRadioService::Notify(const hal::FMRadioRDSGroup& aRDSGroup) { uint16_t blocks[4]; blocks[0] = aRDSGroup.blockA(); @@ -1035,7 +987,8 @@ FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup) memset(mTempRadiotext, 0, sizeof(mTempRadiotext)); } mPISet = true; - NS_DispatchToMainThread(new NotifyRunnable(PIChanged)); + + DispatchFMRadioEventToMainThread(PIChanged); } mLastPI = blocks[0]; @@ -1044,7 +997,8 @@ FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup) if ((mPTY != pty && pty == mLastPTY) || !mPTYSet) { mPTY = pty; mPTYSet = true; - NS_DispatchToMainThread(new NotifyRunnable(PTYChanged)); + + DispatchFMRadioEventToMainThread(PTYChanged); } mLastPTY = pty; @@ -1075,7 +1029,8 @@ FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup) MutexAutoLock lock(mRDSLock); mPSNameSet = true; memcpy(mPSName, mTempPSName, sizeof(mTempPSName)); - NS_DispatchToMainThread(new NotifyRunnable(PSChanged)); + + DispatchFMRadioEventToMainThread(PSChanged); } break; } @@ -1089,7 +1044,8 @@ FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup) mRadiotextAB = textAB; MutexAutoLock lock(mRDSLock); memset(mRadiotext, 0, sizeof(mRadiotext)); - NS_DispatchToMainThread(new NotifyRunnable(RadiotextChanged)); + + DispatchFMRadioEventToMainThread(RadiotextChanged); } // mRadiotextState is a bitmask that lets us ensure all segments @@ -1129,7 +1085,8 @@ FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup) MutexAutoLock lock(mRDSLock); mRadiotextSet = true; memcpy(mRadiotext, mTempRadiotext, sizeof(mTempRadiotext)); - NS_DispatchToMainThread(new NotifyRunnable(RadiotextChanged)); + + DispatchFMRadioEventToMainThread(RadiotextChanged); break; } case 5: // 2b Radiotext @@ -1142,7 +1099,8 @@ FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup) mRadiotextAB = textAB; MutexAutoLock lock(mRDSLock); memset(mRadiotext, 0, sizeof(mRadiotext)); - NS_DispatchToMainThread(new NotifyRunnable(RadiotextChanged)); + + DispatchFMRadioEventToMainThread(RadiotextChanged); } if (!segmentAddr) { @@ -1177,7 +1135,8 @@ FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup) MutexAutoLock lock(mRDSLock); mRadiotextSet = true; memcpy(mRadiotext, mTempRadiotext, sizeof(mTempRadiotext)); - NS_DispatchToMainThread(new NotifyRunnable(RadiotextChanged)); + + DispatchFMRadioEventToMainThread(RadiotextChanged); break; } case 31: // 15b Fast Tuning and Switching @@ -1187,7 +1146,8 @@ FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup) break; } mPTY = pty; - NS_DispatchToMainThread(new NotifyRunnable(PTYChanged)); + + DispatchFMRadioEventToMainThread(PTYChanged); break; } } @@ -1209,13 +1169,14 @@ FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup) MutexAutoLock lock(mRDSLock); mRDSGroup = newgroup; mRDSGroupSet = true; - NS_DispatchToMainThread(new NotifyRunnable(NewRDSGroup)); + + DispatchFMRadioEventToMainThread(NewRDSGroup); } void FMRadioService::UpdatePowerState() { - bool enabled = IsFMRadioOn(); + bool enabled = hal::IsFMRadioOn(); if (enabled != mEnabled) { mEnabled = enabled; NotifyFMRadioEvent(EnabledChanged); @@ -1225,7 +1186,7 @@ FMRadioService::UpdatePowerState() void FMRadioService::UpdateFrequency() { - int32_t frequency = GetFMRadioFrequency(); + int32_t frequency = hal::GetFMRadioFrequency(); if (mPendingFrequencyInKHz != frequency) { mPendingFrequencyInKHz = frequency; NotifyFMRadioEvent(FrequencyChanged); diff --git a/dom/fmradio/FMRadioService.h b/dom/fmradio/FMRadioService.h index bc01d46ef2f1..2a753eddac10 100644 --- a/dom/fmradio/FMRadioService.h +++ b/dom/fmradio/FMRadioService.h @@ -196,6 +196,10 @@ public: /* FMRadioRDSObserver */ void Notify(const hal::FMRadioRDSGroup& aRDSGroup) override; + void EnableFMRadio(); + void DisableFMRadio(); + void DispatchFMRadioEventToMainThread(enum FMRadioEventType aType); + NS_DECL_NSIOBSERVER protected: From 18eb6f5805b9cf5d52b02cfc6d6db574cddf043b Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Mon, 21 Sep 2015 17:37:29 -0700 Subject: [PATCH 094/133] Backed out changeset f7cbf3aa76fc (bug 1099103) for test_input_number_l10n.html failures --- dom/html/test/forms/test_input_number_data.js | 5 -- .../test/forms/test_input_number_l10n.html | 13 ---- .../forms/test_input_number_validation.html | 15 ----- layout/forms/nsNumberControlFrame.cpp | 64 ++++++++++--------- 4 files changed, 35 insertions(+), 62 deletions(-) diff --git a/dom/html/test/forms/test_input_number_data.js b/dom/html/test/forms/test_input_number_data.js index a1b34b4a0e28..e17f452fee19 100644 --- a/dom/html/test/forms/test_input_number_data.js +++ b/dom/html/test/forms/test_input_number_data.js @@ -30,8 +30,3 @@ var tests = [ inputWithoutGrouping: "123456.78", value: 123456.78 }, ]; - -var invalidTests = [ - { desc: "Invalid German", langTag: "de", input: "12.34" } -]; - diff --git a/dom/html/test/forms/test_input_number_l10n.html b/dom/html/test/forms/test_input_number_l10n.html index 4d46f7a80371..db1ad0995ef4 100644 --- a/dom/html/test/forms/test_input_number_l10n.html +++ b/dom/html/test/forms/test_input_number_l10n.html @@ -49,24 +49,11 @@ function runTest(test) { "') localization without grouping separator"); } -function runInvalidInputTest(test) { - elem.lang = test.langTag; - elem.value = 0; - elem.focus(); - elem.select(); - sendString(test.input); - is(elem.value, "", "Test " + test.desc + " ('" + test.langTag + - "') with invalid input: " + test.input); -} - function startTests() { elem = document.getElementById("input"); for (var test of tests) { runTest(test, elem); } - for (var test of invalidTests) { - runInvalidInputTest(test, elem); - } } diff --git a/dom/html/test/forms/test_input_number_validation.html b/dom/html/test/forms/test_input_number_validation.html index 336e47788abd..8b8af2b7f278 100644 --- a/dom/html/test/forms/test_input_number_validation.html +++ b/dom/html/test/forms/test_input_number_validation.html @@ -57,26 +57,11 @@ function runTest(test) { checkIsInvalid(elem, `${desc} without grouping separator`); } -function runInvalidInputTest(test) { - elem.lang = test.langTag; - - gInvalid = false; // reset - var desc = `${test.desc} (lang='${test.langTag}', id='${elem.id}')`; - elem.value = 0; - elem.focus(); - elem.select(); - sendString(test.input); - checkIsInvalid(elem, `${desc} with invalid input`); -} - function startTests() { elem = document.getElementById("input"); for (var test of tests) { runTest(test); } - for (var test of invalidTests) { - runInvalidInputTest(test); - } elem = document.getElementById("requiredinput"); for (var test of tests) { runTest(test); diff --git a/layout/forms/nsNumberControlFrame.cpp b/layout/forms/nsNumberControlFrame.cpp index 78d8b5737db7..d95bdda86103 100644 --- a/layout/forms/nsNumberControlFrame.cpp +++ b/layout/forms/nsNumberControlFrame.cpp @@ -776,40 +776,46 @@ nsNumberControlFrame::GetValueOfAnonTextControl(nsAString& aValue) // // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#floating-point-numbers // - // This is necessary to allow the number that we return to be parsed by - // functions like HTMLInputElement::StringToDecimal (the HTML-5-conforming - // parsing function) which don't know how to handle numbers that are - // formatted differently (for example, with non-ASCII digits, with grouping - // separator characters or with a decimal separator character other than - // '.'). - + // so that it can be parsed by functions like HTMLInputElement:: + // StringToDecimal (the HTML-5-conforming parsing function) which don't know + // how to handle numbers that are formatted differently (for example, with + // non-ASCII digits, with grouping separator characters or with a decimal + // separator character other than '.'). + // + // We need to be careful to avoid normalizing numbers that are already + // formatted for a locale that matches the format of HTML 5's "valid + // floating-point number" and have no grouping separator characters. (In + // other words we want to return the number as specified by the user, not the + // de-localized serialization, since the latter will normalize the value.) + // For example, if the user's locale is English and the user types in "2e2" + // then inputElement.value should be "2e2" and not "100". This is because + // content (and tests) expect us to avoid "normalizing" the number that the + // user types in if it's not necessary in order to make sure it conforms to + // HTML 5's "valid floating-point number" format. + // + // Note that we also need to be careful when trying to avoid normalization. + // For example, just because "1.234" _looks_ like a valid floating-point + // number according to the spec does not mean that it should be returned + // as-is. If the user's locale is German, then this represents the value + // 1234, not 1.234, so it still needs to be de-localized. Alternatively, if + // the user's locale is English and they type in "1,234" we _do_ need to + // normalize the number to "1234" because HTML 5's valid floating-point + // number format does not allow the ',' grouping separator. We can detect all + // the cases where we need to convert by seeing if the locale-specific + // parsing function understands the user input to mean the same thing as the + // HTML-5-conforming parsing function. If so, then we should return the value + // as-is to avoid normalization. Otherwise, we return the de-localized + // serialization. ICUUtils::LanguageTagIterForContent langTagIter(mContent); double value = ICUUtils::ParseNumber(aValue, langTagIter); - if (!IsFinite(value)) { + if (IsFinite(value) && + value != HTMLInputElement::StringToDecimal(aValue).toDouble()) { aValue.Truncate(); - return; + aValue.AppendFloat(value); } - if (value == HTMLInputElement::StringToDecimal(aValue).toDouble()) { - // We want to preserve the formatting of the number as typed in by the user - // whenever possible. Since the localized serialization parses to the same - // number as the de-localized serialization, we can do that. This helps - // prevent normalization of input such as "2e2" (which would otherwise be - // converted to "200"). Content relies on this. - // - // Typically we will only get here for locales in which numbers are - // formatted in the same way as they are for HTML5's "valid floating-point - // number" format. - return; - } - // We can't preserve the formatting, otherwise functions such as - // HTMLInputElement::StringToDecimal would incorrectly process the number - // input by the user. For example, "12.345" with lang=de de-localizes as - // 12345, but HTMLInputElement::StringToDecimal would mistakenly parse it as - // 12.345. Another example would be "12,345" with lang=de which de-localizes - // as 12.345, but HTMLInputElement::StringToDecimal would parse it to NaN. - aValue.Truncate(); - aValue.AppendFloat(value); #endif + // else, we return whatever FromContent put into aValue (the number as typed + // in by the user) } bool From f947a303a82c7ad5359b884f8bbf3082ed1c5e62 Mon Sep 17 00:00:00 2001 From: Sotaro Ikeda Date: Mon, 21 Sep 2015 17:43:41 -0700 Subject: [PATCH 095/133] Bug 1206212 - Remove AUDIO_STREAM_FM after KK r=alwu --- dom/system/gonk/AudioManager.cpp | 13 ++++++++++++- dom/system/gonk/android_audio/AudioSystem.h | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/dom/system/gonk/AudioManager.cpp b/dom/system/gonk/AudioManager.cpp index 314d838e7924..1e52e3777489 100644 --- a/dom/system/gonk/AudioManager.cpp +++ b/dom/system/gonk/AudioManager.cpp @@ -77,7 +77,9 @@ static const uint32_t sMaxStreamVolumeTbl[AUDIO_STREAM_CNT] = { 15, // enforced audible 15, // DTMF 15, // TTS +#if ANDROID_VERSION < 19 15, // FM +#endif }; // Use a half value of each volume category as the default volume. @@ -794,12 +796,16 @@ AudioManager::SetFmRadioAudioEnabled(bool aFmRadioAudioEnabled) aFmRadioAudioEnabled ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE : AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, ""); UpdateHeadsetConnectionState(GetCurrentSwitchState(SWITCH_HEADPHONES)); + // AUDIO_STREAM_FM is not used on recent gonk. + // AUDIO_STREAM_MUSIC is used for FM radio volume control. +#if ANDROID_VERSION < 19 // sync volume with music after powering on fm radio if (aFmRadioAudioEnabled) { uint32_t volIndex = mCurrentStreamVolumeTbl[AUDIO_STREAM_MUSIC]; SetStreamVolumeIndex(AUDIO_STREAM_FM, volIndex); mCurrentStreamVolumeTbl[AUDIO_STREAM_FM] = volIndex; } +#endif return NS_OK; } @@ -819,6 +825,9 @@ AudioManager::SetVolumeByCategory(uint32_t aCategory, uint32_t aIndex) nsresult status; switch (static_cast(aCategory)) { case VOLUME_MEDIA: + // AUDIO_STREAM_FM is not used on recent gonk. + // AUDIO_STREAM_MUSIC is used for FM radio volume control. +#if ANDROID_VERSION < 19 // sync FMRadio's volume with content channel. if (IsDeviceOn(AUDIO_DEVICE_OUT_FM)) { status = SetStreamVolumeIndex(AUDIO_STREAM_FM, aIndex); @@ -826,6 +835,7 @@ AudioManager::SetVolumeByCategory(uint32_t aCategory, uint32_t aIndex) return status; } } +#endif status = SetStreamVolumeIndex(AUDIO_STREAM_MUSIC, aIndex); break; case VOLUME_NOTIFICATION: @@ -1005,6 +1015,7 @@ AudioManager::SetStreamVolumeIndex(int32_t aStream, uint32_t aIndex) { aIndex); return status ? NS_ERROR_FAILURE : NS_OK; #else +#if ANDROID_VERSION < 19 if (aStream == AUDIO_STREAM_FM) { status = AudioSystem::setStreamVolumeIndex( static_cast(aStream), @@ -1012,7 +1023,7 @@ AudioManager::SetStreamVolumeIndex(int32_t aStream, uint32_t aIndex) { AUDIO_DEVICE_OUT_FM); return status ? NS_ERROR_FAILURE : NS_OK; } - +#endif if (mPresentProfile == DEVICE_PRIMARY) { status = AudioSystem::setStreamVolumeIndex( static_cast(aStream), diff --git a/dom/system/gonk/android_audio/AudioSystem.h b/dom/system/gonk/android_audio/AudioSystem.h index 2a6fc925d129..86cbb16da0ef 100644 --- a/dom/system/gonk/android_audio/AudioSystem.h +++ b/dom/system/gonk/android_audio/AudioSystem.h @@ -74,7 +74,9 @@ typedef enum { AUDIO_STREAM_ENFORCED_AUDIBLE = 7, /* Sounds that cannot be muted by user and must be routed to speaker */ AUDIO_STREAM_DTMF = 8, AUDIO_STREAM_TTS = 9, +#if ANDROID_VERSION < 19 AUDIO_STREAM_FM = 10, +#endif AUDIO_STREAM_CNT, AUDIO_STREAM_MAX = AUDIO_STREAM_CNT - 1, From 5d40efa578ee1c0b08009de6c325639d9267a04e Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Mon, 21 Sep 2015 17:10:37 -0400 Subject: [PATCH 096/133] Bug 1206894 - Enable asynchronous dispatching of fetch events; r=jdm This refactoring patch separates the preparation of the fetch event object from its dispatching, so that consumers would be able to dispatch the event asynchronously. --- docshell/base/nsDocShell.cpp | 57 ++++++++++++++++++- dom/workers/ServiceWorkerManager.cpp | 40 ++++++++----- dom/workers/ServiceWorkerManager.h | 15 +++-- modules/libjar/InterceptedJARChannel.cpp | 9 ++- .../base/nsINetworkInterceptController.idl | 22 ++++++- netwerk/protocol/http/HttpChannelParent.cpp | 47 ++++++++++++++- netwerk/protocol/http/HttpChannelParent.h | 3 + netwerk/protocol/http/InterceptedChannel.cpp | 9 ++- 8 files changed, 174 insertions(+), 28 deletions(-) diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 4373cc944caf..c91baf32c752 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -13922,8 +13922,55 @@ nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNavigate, return NS_OK; } +namespace { + +class FetchEventDispatcher final : public nsIFetchEventDispatcher +{ +public: + FetchEventDispatcher(nsIInterceptedChannel* aChannel, + nsIRunnable* aContinueRunnable) + : mChannel(aChannel) + , mContinueRunnable(aContinueRunnable) + { + } + + NS_DECL_ISUPPORTS + NS_DECL_NSIFETCHEVENTDISPATCHER + +private: + ~FetchEventDispatcher() + { + } + + nsCOMPtr mChannel; + nsCOMPtr mContinueRunnable; +}; + +NS_IMPL_ISUPPORTS(FetchEventDispatcher, nsIFetchEventDispatcher) + NS_IMETHODIMP -nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel) +FetchEventDispatcher::Dispatch() +{ + nsRefPtr swm = ServiceWorkerManager::GetInstance(); + if (!swm) { + mChannel->Cancel(NS_ERROR_INTERCEPTION_FAILED); + return NS_OK; + } + + ErrorResult error; + swm->DispatchPreparedFetchEvent(mChannel, mContinueRunnable, error); + if (NS_WARN_IF(error.Failed())) { + return error.StealNSResult(); + } + + return NS_OK; +} + +} + +NS_IMETHODIMP +nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel, + nsIFetchEventDispatcher** aFetchDispatcher) { nsRefPtr swm = ServiceWorkerManager::GetInstance(); if (!swm) { @@ -13949,11 +13996,17 @@ nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel) OriginAttributes attrs(GetAppId(), GetIsInBrowserElement()); ErrorResult error; - swm->DispatchFetchEvent(attrs, doc, aChannel, isReload, error); + nsCOMPtr runnable = + swm->PrepareFetchEvent(attrs, doc, aChannel, isReload, error); if (NS_WARN_IF(error.Failed())) { return error.StealNSResult(); } + MOZ_ASSERT(runnable); + nsRefPtr dispatcher = + new FetchEventDispatcher(aChannel, runnable); + dispatcher.forget(aFetchDispatcher); + return NS_OK; } diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp index 23742b68edbc..50e6f6c5fd09 100644 --- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -3982,20 +3982,22 @@ public: NS_IMPL_ISUPPORTS_INHERITED(FetchEventRunnable, WorkerRunnable, nsIHttpHeaderVisitor) -void -ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttributes, - nsIDocument* aDoc, - nsIInterceptedChannel* aChannel, - bool aIsReload, - ErrorResult& aRv) +already_AddRefed +ServiceWorkerManager::PrepareFetchEvent(const OriginAttributes& aOriginAttributes, + nsIDocument* aDoc, + nsIInterceptedChannel* aChannel, + bool aIsReload, + ErrorResult& aRv) { MOZ_ASSERT(aChannel); + MOZ_ASSERT(NS_IsMainThread()); + nsCOMPtr serviceWorker; bool isNavigation = false; aRv = aChannel->GetIsNavigation(&isNavigation); if (NS_WARN_IF(aRv.Failed())) { - return; + return nullptr; } // if the ServiceWorker script fails to load for some reason, just resume @@ -4014,13 +4016,13 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut nsCOMPtr internalChannel; aRv = aChannel->GetChannel(getter_AddRefs(internalChannel)); if (NS_WARN_IF(aRv.Failed())) { - return; + return nullptr; } nsCOMPtr uri; aRv = internalChannel->GetURI(getter_AddRefs(uri)); if (NS_WARN_IF(aRv.Failed())) { - return; + return nullptr; } nsRefPtr registration = @@ -4028,7 +4030,7 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut if (!registration) { NS_WARNING("No registration found when dispatching the fetch event"); aRv.Throw(NS_ERROR_FAILURE); - return; + return nullptr; } // This should only happen if IsAvailable() returned true. @@ -4043,7 +4045,7 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut } if (NS_WARN_IF(aRv.Failed())) { - return; + return nullptr; } nsMainThreadPtrHandle handle( @@ -4058,6 +4060,18 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut serviceWorkerHandle, clientInfo, aIsReload); + return continueRunnable.forget(); +} + +void +ServiceWorkerManager::DispatchPreparedFetchEvent(nsIInterceptedChannel* aChannel, + nsIRunnable* aPreparedRunnable, + ErrorResult& aRv) +{ + MOZ_ASSERT(aChannel); + MOZ_ASSERT(aPreparedRunnable); + MOZ_ASSERT(NS_IsMainThread()); + nsCOMPtr innerChannel; aRv = aChannel->GetChannel(getter_AddRefs(innerChannel)); if (NS_WARN_IF(aRv.Failed())) { @@ -4068,13 +4082,13 @@ ServiceWorkerManager::DispatchFetchEvent(const OriginAttributes& aOriginAttribut // If there is no upload stream, then continue immediately if (!uploadChannel) { - MOZ_ALWAYS_TRUE(NS_SUCCEEDED(continueRunnable->Run())); + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aPreparedRunnable->Run())); return; } // Otherwise, ensure the upload stream can be cloned directly. This may // require some async copying, so provide a callback. - aRv = uploadChannel->EnsureUploadStreamIsCloneable(continueRunnable); + aRv = uploadChannel->EnsureUploadStreamIsCloneable(aPreparedRunnable); } bool diff --git a/dom/workers/ServiceWorkerManager.h b/dom/workers/ServiceWorkerManager.h index c2de794eaf63..b60fdd4906b4 100644 --- a/dom/workers/ServiceWorkerManager.h +++ b/dom/workers/ServiceWorkerManager.h @@ -315,12 +315,17 @@ public: bool IsControlled(nsIDocument* aDocument, ErrorResult& aRv); + already_AddRefed + PrepareFetchEvent(const OriginAttributes& aOriginAttributes, + nsIDocument* aDoc, + nsIInterceptedChannel* aChannel, + bool aIsReload, + ErrorResult& aRv); + void - DispatchFetchEvent(const OriginAttributes& aOriginAttributes, - nsIDocument* aDoc, - nsIInterceptedChannel* aChannel, - bool aIsReload, - ErrorResult& aRv); + DispatchPreparedFetchEvent(nsIInterceptedChannel* aChannel, + nsIRunnable* aPreparedRunnable, + ErrorResult& aRv); void SoftUpdate(nsIPrincipal* aPrincipal, diff --git a/modules/libjar/InterceptedJARChannel.cpp b/modules/libjar/InterceptedJARChannel.cpp index ef2cdb7568e4..b6619f668672 100644 --- a/modules/libjar/InterceptedJARChannel.cpp +++ b/modules/libjar/InterceptedJARChannel.cpp @@ -122,7 +122,14 @@ InterceptedJARChannel::NotifyController() 0, UINT32_MAX, true, true); NS_ENSURE_SUCCESS_VOID(rv); - rv = mController->ChannelIntercepted(this); + nsCOMPtr dispatcher; + rv = mController->ChannelIntercepted(this, getter_AddRefs(dispatcher)); + if (NS_WARN_IF(NS_FAILED(rv))) { + rv = ResetInterception(); + NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), + "Failed to resume intercepted network request"); + } + rv = dispatcher->Dispatch(); if (NS_WARN_IF(NS_FAILED(rv))) { rv = ResetInterception(); NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), diff --git a/netwerk/base/nsINetworkInterceptController.idl b/netwerk/base/nsINetworkInterceptController.idl index a5f41b96f336..74d61573c5a9 100644 --- a/netwerk/base/nsINetworkInterceptController.idl +++ b/netwerk/base/nsINetworkInterceptController.idl @@ -26,7 +26,7 @@ class ChannelInfo; * which do not implement nsIChannel. */ -[scriptable, uuid(1062c96a-d73c-4ad5-beb7-6e803e414973)] +[scriptable, uuid(40851f73-f799-4a22-a69b-05e0371ee373)] interface nsIInterceptedChannel : nsISupports { /** @@ -83,13 +83,29 @@ interface nsIInterceptedChannel : nsISupports void setChannelInfo(in ChannelInfo channelInfo); }; +/** + * Interface to allow consumers to dispatch the fetch event asynchronously. + * Consumers get access to this interface by calling channelIntercepted(), + * and they can choose to either dispatch() immediately or do that at some + * later time. + */ + +[scriptable, uuid(799504e4-36f8-4ab5-b9d2-53f0c0c40c04)] +interface nsIFetchEventDispatcher : nsISupports +{ + /** + * Actually dispatches the fetch event to the service worker. + */ + void dispatch(); +}; + /** * Interface to allow consumers to attach themselves to a channel's * notification callbacks/loadgroup and determine if a given channel * request should be intercepted before any network request is initiated. */ -[scriptable, uuid(69150b77-b561-43a2-bfba-7301dd5a35d0)] +[scriptable, uuid(0a7aa192-0520-4995-88a3-225ed1a0930d)] interface nsINetworkInterceptController : nsISupports { /** @@ -107,5 +123,5 @@ interface nsINetworkInterceptController : nsISupports * * @param aChannel the controlling interface for a channel that has been intercepted */ - void channelIntercepted(in nsIInterceptedChannel aChannel); + nsIFetchEventDispatcher channelIntercepted(in nsIInterceptedChannel aChannel); }; diff --git a/netwerk/protocol/http/HttpChannelParent.cpp b/netwerk/protocol/http/HttpChannelParent.cpp index 011b889ed9bf..319a15229ea6 100644 --- a/netwerk/protocol/http/HttpChannelParent.cpp +++ b/netwerk/protocol/http/HttpChannelParent.cpp @@ -200,12 +200,54 @@ public: } }; +class ResponseSynthesizer final : public nsIFetchEventDispatcher +{ +public: + ResponseSynthesizer(nsIInterceptedChannel* aChannel, + HttpChannelParent* aParentChannel) + : mChannel(aChannel) + , mParentChannel(aParentChannel) + { + } + + NS_DECL_ISUPPORTS + NS_DECL_NSIFETCHEVENTDISPATCHER + +private: + ~ResponseSynthesizer() + { + } + + nsCOMPtr mChannel; + nsRefPtr mParentChannel; +}; + +NS_IMPL_ISUPPORTS(ResponseSynthesizer, nsIFetchEventDispatcher) + NS_IMETHODIMP -HttpChannelParent::ChannelIntercepted(nsIInterceptedChannel* aChannel) +ResponseSynthesizer::Dispatch() +{ + mParentChannel->SynthesizeResponse(mChannel); + + return NS_OK; +} + +NS_IMETHODIMP +HttpChannelParent::ChannelIntercepted(nsIInterceptedChannel* aChannel, + nsIFetchEventDispatcher** aDispatcher) +{ + nsRefPtr dispatcher = + new ResponseSynthesizer(aChannel, this); + dispatcher.forget(aDispatcher); + return NS_OK; +} + +void +HttpChannelParent::SynthesizeResponse(nsIInterceptedChannel* aChannel) { if (mShouldSuspendIntercept) { mInterceptedChannel = aChannel; - return NS_OK; + return; } aChannel->SynthesizeStatus(mSynthesizedResponseHead->Status(), @@ -217,7 +259,6 @@ HttpChannelParent::ChannelIntercepted(nsIInterceptedChannel* aChannel) NS_DispatchToCurrentThread(event); mSynthesizedResponseHead = nullptr; - return NS_OK; } //----------------------------------------------------------------------------- diff --git a/netwerk/protocol/http/HttpChannelParent.h b/netwerk/protocol/http/HttpChannelParent.h index bfa007679fb3..d91b8d72332b 100644 --- a/netwerk/protocol/http/HttpChannelParent.h +++ b/netwerk/protocol/http/HttpChannelParent.h @@ -170,9 +170,12 @@ private: void DivertOnStopRequest(const nsresult& statusCode); void DivertComplete(); + void SynthesizeResponse(nsIInterceptedChannel* aChannel); + friend class DivertDataAvailableEvent; friend class DivertStopRequestEvent; friend class DivertCompleteEvent; + friend class ResponseSynthesizer; nsRefPtr mChannel; nsCOMPtr mCacheEntry; diff --git a/netwerk/protocol/http/InterceptedChannel.cpp b/netwerk/protocol/http/InterceptedChannel.cpp index 9a7918e2d467..e29028e05505 100644 --- a/netwerk/protocol/http/InterceptedChannel.cpp +++ b/netwerk/protocol/http/InterceptedChannel.cpp @@ -59,7 +59,14 @@ InterceptedChannelBase::EnsureSynthesizedResponse() void InterceptedChannelBase::DoNotifyController() { - nsresult rv = mController->ChannelIntercepted(this); + nsCOMPtr dispatcher; + nsresult rv = mController->ChannelIntercepted(this, + getter_AddRefs(dispatcher)); + if (NS_WARN_IF(NS_FAILED(rv))) { + rv = ResetInterception(); + NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to resume intercepted network request"); + } + rv = dispatcher->Dispatch(); if (NS_WARN_IF(NS_FAILED(rv))) { rv = ResetInterception(); NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to resume intercepted network request"); From 8e1b61b7aa2b0d0a0185e4538340ee30b281b315 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Mon, 10 Aug 2015 14:57:15 -0700 Subject: [PATCH 097/133] Bug 1192989 - Simplify handling by ifdefing in all.js. - r=kamidphish --- dom/canvas/WebGLContextExtensions.cpp | 12 +------- .../nonchrome_webgl_debug_renderer_info.html | 18 ++++-------- .../test_webgl_debug_renderer_info.html | 16 +++++++++-- .../test_renderer_strings.html | 28 +++++++++++-------- modules/libpref/init/all.js | 9 +++++- 5 files changed, 44 insertions(+), 39 deletions(-) diff --git a/dom/canvas/WebGLContextExtensions.cpp b/dom/canvas/WebGLContextExtensions.cpp index c620e6beefe0..79040e1a4111 100644 --- a/dom/canvas/WebGLContextExtensions.cpp +++ b/dom/canvas/WebGLContextExtensions.cpp @@ -161,18 +161,8 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt5); case WebGLExtensionID::WEBGL_debug_renderer_info: - { - bool isEnabled = true; + return Preferences::GetBool("webgl.enable-debug-renderer-info", false); -#ifdef RELEASE_BUILD - // Keep this disabled on Release and Beta for now. (see bug 1171228) - isEnabled = false; -#endif - if (Preferences::GetBool("webgl.disable-debug-renderer-info", false)) - isEnabled = false; - - return isEnabled; - } case WebGLExtensionID::WEBGL_depth_texture: // WEBGL_depth_texture supports DEPTH_STENCIL textures if (!gl->IsSupported(gl::GLFeature::packed_depth_stencil)) diff --git a/dom/canvas/test/chrome/nonchrome_webgl_debug_renderer_info.html b/dom/canvas/test/chrome/nonchrome_webgl_debug_renderer_info.html index 3af79906ee6e..1e31e2b03c68 100644 --- a/dom/canvas/test/chrome/nonchrome_webgl_debug_renderer_info.html +++ b/dom/canvas/test/chrome/nonchrome_webgl_debug_renderer_info.html @@ -2,11 +2,6 @@ diff --git a/dom/tests/mochitest/general/storagePermissionsUtils.js b/dom/tests/mochitest/general/storagePermissionsUtils.js index d161a598520a..4d1609d9f49f 100644 --- a/dom/tests/mochitest/general/storagePermissionsUtils.js +++ b/dom/tests/mochitest/general/storagePermissionsUtils.js @@ -62,44 +62,49 @@ function runWorker(url) { }); } -function chromePower() { +function chromePower(allowed, blockSessionStorage) { + + // localStorage is affected by storage policy. try { SpecialPowers.wrap(window).localStorage.getItem("X"); - ok(true, "getting localStorage didn't throw"); + ok(allowed, "getting localStorage from chrome didn't throw"); } catch (e) { - ok(false, "getting localStorage should not throw"); + ok(!allowed, "getting localStorage from chrome threw"); } + + // sessionStorage is not. See bug 1183968. try { SpecialPowers.wrap(window).sessionStorage.getItem("X"); - ok(true, "getting sessionStorage didn't throw"); + ok(!blockSessionStorage, "getting sessionStorage from chrome didn't throw"); } catch (e) { - ok(false, "getting sessionStorage should not throw"); + ok(blockSessionStorage, "getting sessionStorage from chrome threw"); } + // indexedDB is affected by storage policy. try { SpecialPowers.wrap(window).indexedDB; - ok(true, "getting indexedDB didn't throw"); + ok(allowed, "getting indexedDB from chrome didn't throw"); } catch (e) { - ok(false, "getting indexedDB should not throw"); + ok(!allowed, "getting indexedDB from chrome threw"); } + // Same with caches, along with the additional https-only requirement. try { + var shouldResolve = allowed && location.protocol == "https:"; var promise = SpecialPowers.wrap(window).caches.keys(); - ok(true, "getting caches didn't throw"); - + ok(true, "getting caches from chrome should never throw"); return new Promise((resolve, reject) => { promise.then(function() { - ok(location.protocol == "https:", "The promise was not rejected"); + ok(shouldResolve, "The promise was resolved for chrome"); resolve(); }, function(e) { - ok(location.protocol != "https:", "The promise should not have been rejected: " + e); + ok(!shouldResolve, "The promise was rejected for chrome: " + e); resolve(); }); }); } catch (e) { - ok(false, "getting caches should not have thrown"); - return Promise.resolve(); + ok(false, "getting caches from chrome threw"); } } diff --git a/dom/tests/mochitest/general/test_storagePermissionsAccept.html b/dom/tests/mochitest/general/test_storagePermissionsAccept.html index bbe34e9a0e72..10bd43594c20 100644 --- a/dom/tests/mochitest/general/test_storagePermissionsAccept.html +++ b/dom/tests/mochitest/general/test_storagePermissionsAccept.html @@ -20,7 +20,7 @@ task(function* () { // Same origin iframes should be allowed, unless they redirect to a URI with the null principal yield runIFrame("frameStorageAllowed.html"); yield runIFrame("frameStorageNullprincipal.sjs"); - yield runIFrame("frameStorageChrome.html"); + yield runIFrame("frameStorageChrome.html?allowed=yes"); // Sandboxed iframes should have the null principal, and thus can't access storage document.querySelector('iframe').setAttribute('sandbox', 'allow-scripts'); @@ -31,7 +31,7 @@ task(function* () { // Thirdparty iframes should be allowed, unless they redirect to a URI with the null principal yield runIFrame(thirdparty + "frameStorageAllowed.html"); yield runIFrame(thirdparty + "frameStorageNullprincipal.sjs"); - yield runIFrame(thirdparty + "frameStorageChrome.html"); + yield runIFrame(thirdparty + "frameStorageChrome.html?allowed=yes"); // Workers should be able to access storage yield runWorker("workerStorageAllowed.js"); diff --git a/dom/tests/mochitest/general/test_storagePermissionsLimitForeign.html b/dom/tests/mochitest/general/test_storagePermissionsLimitForeign.html index fa18b47e4adb..36a7523164aa 100644 --- a/dom/tests/mochitest/general/test_storagePermissionsLimitForeign.html +++ b/dom/tests/mochitest/general/test_storagePermissionsLimitForeign.html @@ -17,10 +17,12 @@ task(function* () { // We should be able to access storage yield storageAllowed(); - // Same origin iframes should be prevented, unless they have chrome privileges + // Same origin iframes should be allowed. yield runIFrame("frameStorageAllowed.html"); + yield runIFrame("frameStorageChrome.html?allowed=yes"); + + // Null principal iframes should not. yield runIFrame("frameStorageNullprincipal.sjs"); - yield runIFrame("frameStorageChrome.html"); // Sandboxed iframes should have the null principal, and thus can't access storage document.querySelector('iframe').setAttribute('sandbox', 'allow-scripts'); @@ -28,10 +30,10 @@ task(function* () { yield runIFrame("frameStorageNullprincipal.sjs"); document.querySelector('iframe').removeAttribute('sandbox'); - // Thirdparty iframes should be blocked, unless they have chrome privileges + // Thirdparty iframes should be blocked, even when accessed from chrome over Xrays. yield runIFrame(thirdparty + "frameStoragePrevented.html#thirdparty"); yield runIFrame(thirdparty + "frameStorageNullprincipal.sjs"); - yield runIFrame(thirdparty + "frameStorageChrome.html"); + yield runIFrame(thirdparty + "frameStorageChrome.html?allowed=no"); // Workers should be unable to access storage yield runWorker("workerStorageAllowed.js"); diff --git a/dom/tests/mochitest/general/test_storagePermissionsReject.html b/dom/tests/mochitest/general/test_storagePermissionsReject.html index 28495cdbb83e..2a93f4d07d6f 100644 --- a/dom/tests/mochitest/general/test_storagePermissionsReject.html +++ b/dom/tests/mochitest/general/test_storagePermissionsReject.html @@ -17,10 +17,10 @@ task(function* () { // We should be unable to access storage yield storagePrevented(); - // Same origin iframes should be prevented, unless they have chrome privileges + // Same origin iframes should be blocked. yield runIFrame("frameStoragePrevented.html"); yield runIFrame("frameStorageNullprincipal.sjs"); - yield runIFrame("frameStorageChrome.html"); + yield runIFrame("frameStorageChrome.html?allowed=no&blockSessionStorage=yes"); // Sandboxed iframes should have the null principal, and thus can't access storage document.querySelector('iframe').setAttribute('sandbox', 'allow-scripts'); @@ -28,9 +28,10 @@ task(function* () { yield runIFrame("frameStorageNullprincipal.sjs"); document.querySelector('iframe').removeAttribute('sandbox'); - // thirdparty iframes should be blocked, unless they have chrome privileges + // thirdparty iframes should be blocked. yield runIFrame(thirdparty + "frameStoragePrevented.html"); yield runIFrame(thirdparty + "frameStorageNullprincipal.sjs"); + yield runIFrame(thirdparty + "frameStorageChrome.html?allowed=no&blockSessionStorage=yes"); // Workers should be unable to access storage yield runWorker("workerStoragePrevented.js"); diff --git a/dom/tests/mochitest/general/test_storagePermissionsRejectForeign.html b/dom/tests/mochitest/general/test_storagePermissionsRejectForeign.html index 7088d89d2f33..5ff3fc63ff75 100644 --- a/dom/tests/mochitest/general/test_storagePermissionsRejectForeign.html +++ b/dom/tests/mochitest/general/test_storagePermissionsRejectForeign.html @@ -20,7 +20,7 @@ task(function* () { // Same origin iframes should be allowed, unless they redirect to a URI with the null principal yield runIFrame("frameStorageAllowed.html"); yield runIFrame("frameStorageNullprincipal.sjs"); - yield runIFrame("frameStorageChrome.html"); + yield runIFrame("frameStorageChrome.html?allowed=yes"); // Sandboxed iframes should have the null principal, and thus can't access storage document.querySelector('iframe').setAttribute('sandbox', 'allow-scripts'); @@ -28,10 +28,10 @@ task(function* () { yield runIFrame("frameStorageNullprincipal.sjs"); document.querySelector('iframe').removeAttribute('sandbox'); - // thirdparty iframes should be blocked, unless they have chrome privileges + // thirdparty iframes should be blocked. yield runIFrame(thirdparty + "frameStoragePrevented.html#thirdparty"); yield runIFrame(thirdparty + "frameStorageNullprincipal.sjs"); - yield runIFrame(thirdparty + "frameStorageChrome.html"); + yield runIFrame(thirdparty + "frameStorageChrome.html?allowed=no"); // Workers should be able to access storage yield runWorker("workerStorageAllowed.js");