diff --git a/build.gradle b/build.gradle index d39a6c271bab..70eed4215840 100644 --- a/build.gradle +++ b/build.gradle @@ -67,10 +67,6 @@ if ('multi' == System.env.AB_CD) { // dependency chain to fail, since multi isn't a real locale. To avoid // this, if Gradle is invoked with AB_CD=multi, we don't invoke Make at all. task generateCodeAndResources() -} else if (System.env.IS_LANGUAGE_REPACK == '1') { - // Single-locale l10n repacks set `IS_LANGUAGE_REPACK=1` and handle resource - // and code generation themselves. - task generateCodeAndResources() } else { task generateCodeAndResources(type:Exec) { workingDir "${topobjdir}" diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index b6e43de999b7..4abfde1e7b75 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -1486,11 +1486,9 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTM NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioTrackList) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVideoTrackList) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeys) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIncomingMediaKeys) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectedVideoStreamTrack) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingPlayPromises) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSeekDOMPromise) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSetMediaKeysDOMPromise) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLElement) @@ -1517,11 +1515,9 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLE NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioTrackList) NS_IMPL_CYCLE_COLLECTION_UNLINK(mVideoTrackList) NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaKeys) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mIncomingMediaKeys) NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelectedVideoStreamTrack) NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingPlayPromises) NS_IMPL_CYCLE_COLLECTION_UNLINK(mSeekDOMPromise) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mSetMediaKeysDOMPromise) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(HTMLMediaElement) @@ -1727,7 +1723,6 @@ void HTMLMediaElement::ShutdownDecoder() { RemoveMediaElementFromURITable(); NS_ASSERTION(mDecoder, "Must have decoder to shut down"); - mSetCDMRequest.DisconnectIfExists(); mWaitingForKeyListener.DisconnectIfExists(); if (mMediaSource) { mMediaSource->CompletePendingTransactions(); @@ -3991,7 +3986,6 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed& aNo mPlaybackRate(1.0), mPreservesPitch(true), mPlayed(new TimeRanges(ToSupports(OwnerDoc()))), - mAttachingMediaKey(false), mCurrentPlayRangeStart(-1.0), mLoadedDataFired(false), mAutoplaying(true), @@ -7022,180 +7016,6 @@ HTMLMediaElement::ContainsRestrictedContent() return GetMediaKeys() != nullptr; } -void -HTMLMediaElement::SetCDMProxyFailure(const MediaResult& aResult) -{ - LOG(LogLevel::Debug, ("%s", __func__)); - MOZ_ASSERT(mSetMediaKeysDOMPromise); - - ResetSetMediaKeysTempVariables(); - - mSetMediaKeysDOMPromise->MaybeReject(aResult.Code(), aResult.Message()); -} - -void -HTMLMediaElement::RemoveMediaKeys() -{ - LOG(LogLevel::Debug, ("%s", __func__)); - // 5.2.3 Stop using the CDM instance represented by the mediaKeys attribute - // to decrypt media data and remove the association with the media element. - mMediaKeys->Unbind(); - mMediaKeys = nullptr; -} - -bool -HTMLMediaElement::TryRemoveMediaKeysAssociation() -{ - MOZ_ASSERT(mMediaKeys); - LOG(LogLevel::Debug, ("%s", __func__)); - // 5.2.1 If the user agent or CDM do not support removing the association, - // let this object's attaching media keys value be false and reject promise - // with a new DOMException whose name is NotSupportedError. - // 5.2.2 If the association cannot currently be removed, let this object's - // attaching media keys value be false and reject promise with a new - // DOMException whose name is InvalidStateError. - if (mDecoder) { - RefPtr self = this; - mDecoder->SetCDMProxy(nullptr) - ->Then(mAbstractMainThread, - __func__, - [self]() { - self->mSetCDMRequest.Complete(); - - self->RemoveMediaKeys(); - if (self->AttachNewMediaKeys()) { - // No incoming MediaKeys object or MediaDecoder is not created yet. - self->MakeAssociationWithCDMResolved(); - } - }, - [self](const MediaResult& aResult) { - self->mSetCDMRequest.Complete(); - // 5.2.4 If the preceding step failed, let this object's attaching media - // keys value be false and reject promise with a new DOMException whose - // name is the appropriate error name. - self->SetCDMProxyFailure(aResult); - }) - ->Track(mSetCDMRequest); - return false; - } - - RemoveMediaKeys(); - return true; -} - -bool -HTMLMediaElement::DetachExistingMediaKeys() -{ - LOG(LogLevel::Debug, ("%s", __func__)); - MOZ_ASSERT(mSetMediaKeysDOMPromise); - // 5.1 If mediaKeys is not null, CDM instance represented by mediaKeys is - // already in use by another media element, and the user agent is unable - // to use it with this element, let this object's attaching media keys - // value be false and reject promise with a new DOMException whose name - // is QuotaExceededError. - if (mIncomingMediaKeys && mIncomingMediaKeys->IsBoundToMediaElement()) { - SetCDMProxyFailure(MediaResult( - NS_ERROR_DOM_QUOTA_EXCEEDED_ERR, - "MediaKeys object is already bound to another HTMLMediaElement")); - return false; - } - - // 5.2 If the mediaKeys attribute is not null, run the following steps: - if (mMediaKeys) { - return TryRemoveMediaKeysAssociation(); - } - return true; -} - -void -HTMLMediaElement::MakeAssociationWithCDMResolved() -{ - LOG(LogLevel::Debug, ("%s", __func__)); - MOZ_ASSERT(mSetMediaKeysDOMPromise); - - // 5.4 Set the mediaKeys attribute to mediaKeys. - mMediaKeys = mIncomingMediaKeys; - // 5.5 Let this object's attaching media keys value be false. - ResetSetMediaKeysTempVariables(); - // 5.6 Resolve promise. - mSetMediaKeysDOMPromise->MaybeResolveWithUndefined(); - mSetMediaKeysDOMPromise = nullptr; -} - -bool -HTMLMediaElement::TryMakeAssociationWithCDM(CDMProxy* aProxy) -{ - LOG(LogLevel::Debug, ("%s", __func__)); - MOZ_ASSERT(aProxy); - - // 5.3.3 Queue a task to run the "Attempt to Resume Playback If Necessary" - // algorithm on the media element. - // Note: Setting the CDMProxy on the MediaDecoder will unblock playback. - if (mDecoder) { - // CDMProxy is set asynchronously in MediaFormatReader, once it's done, - // HTMLMediaElement should resolve or reject the DOM promise. - RefPtr self = this; - mDecoder->SetCDMProxy(aProxy) - ->Then(mAbstractMainThread, - __func__, - [self]() { - self->mSetCDMRequest.Complete(); - self->MakeAssociationWithCDMResolved(); - }, - [self](const MediaResult& aResult) { - self->mSetCDMRequest.Complete(); - self->SetCDMProxyFailure(aResult); - }) - ->Track(mSetCDMRequest); - return false; - } - return true; -} - -bool -HTMLMediaElement::AttachNewMediaKeys() -{ - LOG(LogLevel::Debug, - ("%s incoming MediaKeys(%p)", __func__, mIncomingMediaKeys.get())); - MOZ_ASSERT(mSetMediaKeysDOMPromise); - - // 5.3. If mediaKeys is not null, run the following steps: - if (mIncomingMediaKeys) { - auto cdmProxy = mIncomingMediaKeys->GetCDMProxy(); - if (!cdmProxy) { - SetCDMProxyFailure(MediaResult( - NS_ERROR_DOM_INVALID_STATE_ERR, - "CDM crashed before binding MediaKeys object to HTMLMediaElement")); - return false; - } - - // 5.3.1 Associate the CDM instance represented by mediaKeys with the - // media element for decrypting media data. - if (NS_FAILED(mIncomingMediaKeys->Bind(this))) { - // 5.3.2 If the preceding step failed, run the following steps: - - // 5.3.2.1 Set the mediaKeys attribute to null. - mMediaKeys = nullptr; - // 5.3.2.2 Let this object's attaching media keys value be false. - // 5.3.2.3 Reject promise with a new DOMException whose name is - // the appropriate error name. - SetCDMProxyFailure( - MediaResult(NS_ERROR_DOM_INVALID_STATE_ERR, - "Failed to bind MediaKeys object to HTMLMediaElement")); - return false; - } - return TryMakeAssociationWithCDM(cdmProxy); - } - return true; -} - -void -HTMLMediaElement::ResetSetMediaKeysTempVariables() -{ - mAttachingMediaKey = false; - mIncomingMediaKeys = nullptr; -} - already_AddRefed HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys, ErrorResult& aRv) @@ -7227,31 +7047,89 @@ HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys, return promise.forget(); } + // Note: Our attaching code is synchronous, so we can skip the following steps. + // 2. If this object's attaching media keys value is true, return a // promise rejected with a new DOMException whose name is InvalidStateError. - if (mAttachingMediaKey) { - promise->MaybeReject( - NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("A MediaKeys object is in attaching operation.")); - return promise.forget(); - } - // 3. Let this object's attaching media keys value be true. - mAttachingMediaKey = true; - mIncomingMediaKeys = aMediaKeys; - // 4. Let promise be a new promise. - mSetMediaKeysDOMPromise = promise; - // 5. Run the following steps in parallel: - // 5.1 & 5.2 & 5.3 - if (!DetachExistingMediaKeys() || !AttachNewMediaKeys()) { + // 5.1 If mediaKeys is not null, CDM instance represented by mediaKeys is + // already in use by another media element, and the user agent is unable + // to use it with this element, let this object's attaching media keys + // value be false and reject promise with a new DOMException whose name + // is QuotaExceededError. + if (aMediaKeys && aMediaKeys->IsBoundToMediaElement()) { + promise->MaybeReject(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR, + NS_LITERAL_CSTRING("MediaKeys object is already bound to another HTMLMediaElement")); return promise.forget(); } - // 5.4, 5.5, 5.6 - MakeAssociationWithCDMResolved(); + // 5.2 If the mediaKeys attribute is not null, run the following steps: + if (mMediaKeys) { + // 5.2.1 If the user agent or CDM do not support removing the association, + // let this object's attaching media keys value be false and reject promise + // with a new DOMException whose name is NotSupportedError. + + // 5.2.2 If the association cannot currently be removed, let this object's + // attaching media keys value be false and reject promise with a new + // DOMException whose name is InvalidStateError. + if (mDecoder) { + // We don't support swapping out the MediaKeys once we've started to + // setup the playback pipeline. Note this also means we don't need to worry + // about handling disassociating the MediaKeys from the MediaDecoder. + promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, + NS_LITERAL_CSTRING("Can't change MediaKeys on HTMLMediaElement after load has started")); + return promise.forget(); + } + + // 5.2.3 Stop using the CDM instance represented by the mediaKeys attribute + // to decrypt media data and remove the association with the media element. + mMediaKeys->Unbind(); + mMediaKeys = nullptr; + + // 5.2.4 If the preceding step failed, let this object's attaching media + // keys value be false and reject promise with a new DOMException whose + // name is the appropriate error name. + } + + // 5.3. If mediaKeys is not null, run the following steps: + if (aMediaKeys) { + if (!aMediaKeys->GetCDMProxy()) { + promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, + NS_LITERAL_CSTRING("CDM crashed before binding MediaKeys object to HTMLMediaElement")); + return promise.forget(); + } + + // 5.3.1 Associate the CDM instance represented by mediaKeys with the + // media element for decrypting media data. + if (NS_FAILED(aMediaKeys->Bind(this))) { + // 5.3.2 If the preceding step failed, run the following steps: + // 5.3.2.1 Set the mediaKeys attribute to null. + mMediaKeys = nullptr; + // 5.3.2.2 Let this object's attaching media keys value be false. + // 5.3.2.3 Reject promise with a new DOMException whose name is + // the appropriate error name. + promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, + NS_LITERAL_CSTRING("Failed to bind MediaKeys object to HTMLMediaElement")); + return promise.forget(); + } + // 5.3.3 Queue a task to run the "Attempt to Resume Playback If Necessary" + // algorithm on the media element. + // Note: Setting the CDMProxy on the MediaDecoder will unblock playback. + if (mDecoder) { + mDecoder->SetCDMProxy(aMediaKeys->GetCDMProxy()); + } + } + + // 5.4 Set the mediaKeys attribute to mediaKeys. + mMediaKeys = aMediaKeys; + + // 5.5 Let this object's attaching media keys value be false. + + // 5.6 Resolve promise. + promise->MaybeResolveWithUndefined(); // 6. Return promise. return promise.forget(); diff --git a/dom/html/HTMLMediaElement.h b/dom/html/HTMLMediaElement.h index 5a9a1b196f6b..f0eee1e59b2a 100644 --- a/dom/html/HTMLMediaElement.h +++ b/dom/html/HTMLMediaElement.h @@ -12,7 +12,6 @@ #include "MediaEventSource.h" #include "SeekTarget.h" #include "MediaDecoderOwner.h" -#include "MediaPromiseDefs.h" #include "nsCycleCollectionParticipant.h" #include "nsIObserver.h" #include "mozilla/CORSMode.h" @@ -1333,15 +1332,6 @@ protected: const nsAttrValueOrString& aValue, bool aNotify) override; - bool DetachExistingMediaKeys(); - bool TryRemoveMediaKeysAssociation(); - void RemoveMediaKeys(); - bool AttachNewMediaKeys(); - bool TryMakeAssociationWithCDM(CDMProxy* aProxy); - void MakeAssociationWithCDMResolved(); - void SetCDMProxyFailure(const MediaResult& aResult); - void ResetSetMediaKeysTempVariables(); - // The current decoder. Load() has been called on this decoder. // At most one of mDecoder and mSrcStream can be non-null. RefPtr mDecoder; @@ -1544,12 +1534,6 @@ protected: // Encrypted Media Extension media keys. RefPtr mMediaKeys; - RefPtr mIncomingMediaKeys; - // The dom promise is used for HTMLMediaElement::SetMediaKeys. - RefPtr mSetMediaKeysDOMPromise; - // Used to indicate if the MediaKeys attaching operation is on-going or not. - bool mAttachingMediaKey; - MozPromiseRequestHolder mSetCDMRequest; // Stores the time at the start of the current 'played' range. double mCurrentPlayRangeStart; diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp index 372fccee243d..f5a42c6ff954 100644 --- a/dom/media/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -1423,15 +1423,18 @@ MediaDecoder::CanPlayThrough() return val; } -RefPtr +void MediaDecoder::SetCDMProxy(CDMProxy* aProxy) { MOZ_ASSERT(NS_IsMainThread()); - return InvokeAsync>(mReader->OwnerThread(), - mReader.get(), - __func__, - &MediaFormatReader::SetCDMProxy, - aProxy); + RefPtr proxy = aProxy; + RefPtr reader = mReader; + nsCOMPtr r = NS_NewRunnableFunction( + "MediaFormatReader::SetCDMProxy", + [reader, proxy]() { + reader->SetCDMProxy(proxy); + }); + mReader->OwnerThread()->Dispatch(r.forget()); } bool diff --git a/dom/media/MediaDecoder.h b/dom/media/MediaDecoder.h index 8030ea5bb9b7..fbdc0a22d620 100644 --- a/dom/media/MediaDecoder.h +++ b/dom/media/MediaDecoder.h @@ -12,7 +12,6 @@ #include "MediaDecoderOwner.h" #include "MediaEventSource.h" #include "MediaMetadataManager.h" -#include "MediaPromiseDefs.h" #include "MediaResource.h" #include "MediaStatistics.h" #include "MediaStreamGraph.h" @@ -356,7 +355,7 @@ private: return mAbstractMainThread; } - RefPtr SetCDMProxy(CDMProxy* aProxy); + void SetCDMProxy(CDMProxy* aProxy); void EnsureTelemetryReported(); diff --git a/dom/media/MediaFormatReader.cpp b/dom/media/MediaFormatReader.cpp index 10bee6876221..082580daf1ad 100644 --- a/dom/media/MediaFormatReader.cpp +++ b/dom/media/MediaFormatReader.cpp @@ -1228,10 +1228,6 @@ MediaFormatReader::Shutdown() mMetadataPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__); mSeekPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__); mSkipRequest.DisconnectIfExists(); - mSetCDMPromise.RejectIfExists( - MediaResult(NS_ERROR_DOM_INVALID_STATE_ERR, - "MediaFormatReader is shutting down"), - __func__); if (mAudio.HasPromise()) { mAudio.RejectPromise(NS_ERROR_DOM_MEDIA_CANCELED, __func__); @@ -1322,101 +1318,23 @@ MediaFormatReader::Init() return NS_OK; } -bool -MediaFormatReader::ResolveSetCDMPromiseIfDone(TrackType aTrack) -{ - // When a CDM proxy is set, MFR would shutdown the existing MediaDataDecoder - // and would create new one for specific track in the next Update. - MOZ_ASSERT(OnTaskQueue()); - - if (mSetCDMPromise.IsEmpty()) { - return true; - } - - MOZ_ASSERT(mCDMProxy); - if (mSetCDMForTracks.contains(aTrack)) { - mSetCDMForTracks -= aTrack; - } - - if (mSetCDMForTracks.isEmpty()) { - LOGV("%s : Done ", __func__); - mSetCDMPromise.Resolve(/* aIgnored = */ true, __func__); - ScheduleUpdate(TrackInfo::kAudioTrack); - ScheduleUpdate(TrackInfo::kVideoTrack); - return true; - } - LOGV("%s : %s track is ready.", __func__, TrackTypeToStr(aTrack)); - return false; -} - void -MediaFormatReader::PrepareToSetCDMForTrack(TrackType aTrack) -{ - MOZ_ASSERT(OnTaskQueue()); - LOGV("%s : %s", __func__, TrackTypeToStr(aTrack)); - - mSetCDMForTracks += aTrack; - if (mCDMProxy) { - // An old cdm proxy exists, so detaching old cdm proxy by shutting down - // MediaDataDecoder. - ShutdownDecoder(aTrack); - } - ScheduleUpdate(aTrack); -} - -bool -MediaFormatReader::IsDecoderWaitingForCDM(TrackType aTrack) -{ - MOZ_ASSERT(OnTaskQueue()); - return IsEncrypted() && mSetCDMForTracks.contains(aTrack) && !mCDMProxy; -} - -RefPtr MediaFormatReader::SetCDMProxy(CDMProxy* aProxy) { - MOZ_ASSERT(OnTaskQueue()); - LOGV("SetCDMProxy (%p)", aProxy); - - if (mShutdown) { - return SetCDMPromise::CreateAndReject( - MediaResult(NS_ERROR_DOM_INVALID_STATE_ERR, - "MediaFormatReader is shutting down"), - __func__); - } - - mSetCDMPromise.RejectIfExists( - MediaResult(NS_ERROR_DOM_INVALID_STATE_ERR, - "Another new CDM proxy is being set."), - __func__); - - // Shutdown all decoders as switching CDM proxy indicates that it's - // inappropriate for the existing decoders to continue decoding via the old - // CDM proxy. - if (HasAudio()) { - PrepareToSetCDMForTrack(TrackInfo::kAudioTrack); - } - if (HasVideo()) { - PrepareToSetCDMForTrack(TrackInfo::kVideoTrack); - } - - mCDMProxy = aProxy; - - if (IsEncrypted() && !mCDMProxy) { - // Release old PDMFactory which contains an EMEDecoderModule. - mPlatform = nullptr; - } - - if (!mInitDone || mSetCDMForTracks.isEmpty() || !mCDMProxy) { - // 1) MFR is not initialized yet or - // 2) Demuxer is initialized without active audio and video or - // 3) A null cdm proxy is set - // the promise can be resolved directly. - mSetCDMForTracks.clear(); - return SetCDMPromise::CreateAndResolve(/* aIgnored = */ true, __func__); - } - - RefPtr p = mSetCDMPromise.Ensure(__func__); - return p; + RefPtr proxy = aProxy; + RefPtr self = this; + nsCOMPtr r = + NS_NewRunnableFunction("MediaFormatReader::SetCDMProxy", [=]() { + MOZ_ASSERT(self->OnTaskQueue()); + self->mCDMProxy = proxy; + if (HasAudio()) { + self->ScheduleUpdate(TrackInfo::kAudioTrack); + } + if (HasVideo()) { + self->ScheduleUpdate(TrackInfo::kVideoTrack); + } + }); + OwnerThread()->Dispatch(r.forget()); } bool @@ -2473,13 +2391,6 @@ MediaFormatReader::Update(TrackType aTrack) LOG("Rejecting %s promise: WAITING_FOR_DATA due to waiting for key", TrackTypeToStr(aTrack)); decoder.RejectPromise(NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA, __func__); - } else if (IsDecoderWaitingForCDM(aTrack)) { - // Rejecting the promise could lead to entering buffering state for MDSM, - // once a qualified(with the same key system and sessions created by the - // same InitData) new cdm proxy is set, decoding can be resumed. - LOG("Rejecting %s promise: WAITING_FOR_DATA due to waiting for CDM", - TrackTypeToStr(aTrack)); - decoder.RejectPromise(NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA, __func__); } } @@ -2537,7 +2448,7 @@ MediaFormatReader::Update(TrackType aTrack) LOGV("Update(%s) ni=%d no=%d in:%" PRIu64 " out:%" PRIu64 " qs=%u decoding:%d flushing:%d desc:%s pending:%u waiting:%d eos:%d " - "ds:%d sid:%u waitcdm:%d", + "ds:%d sid:%u", TrackTypeToStr(aTrack), needInput, needOutput, @@ -2551,10 +2462,9 @@ MediaFormatReader::Update(TrackType aTrack) decoder.mWaitingForData, decoder.mDemuxEOS, int32_t(decoder.mDrainState), - decoder.mLastStreamSourceID, - IsDecoderWaitingForCDM(aTrack)); + decoder.mLastStreamSourceID); - if (IsWaitingOnCDMResource() || !ResolveSetCDMPromiseIfDone(aTrack)) { + if (IsWaitingOnCDMResource()) { // If the content is encrypted, MFR won't start to create decoder until // CDMProxy is set. return; @@ -2564,9 +2474,7 @@ MediaFormatReader::Update(TrackType aTrack) (!decoder.mTimeThreshold || decoder.mTimeThreshold.ref().mWaiting)) || (decoder.mWaitingForKey && decoder.mDecodeRequest.Exists())) { // Nothing more we can do at present. - LOGV("Still waiting for data or key. data(%d)/key(%d)", - decoder.mWaitingForData, - decoder.mWaitingForKey); + LOGV("Still waiting for data or key."); return; } diff --git a/dom/media/MediaFormatReader.h b/dom/media/MediaFormatReader.h index 9446aea75d5b..822b22cf3c0e 100644 --- a/dom/media/MediaFormatReader.h +++ b/dom/media/MediaFormatReader.h @@ -18,7 +18,6 @@ #include "MediaDataDemuxer.h" #include "MediaMetadataManager.h" #include "MediaPrefs.h" -#include "MediaPromiseDefs.h" #include "nsAutoPtr.h" #include "PDMFactory.h" #include "SeekTarget.h" @@ -92,6 +91,7 @@ class MediaFormatReader final static const bool IsExclusive = true; typedef TrackInfo::TrackType TrackType; typedef MozPromise NotifyDataArrivedPromise; + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaFormatReader) public: @@ -194,7 +194,7 @@ public: // cases like MSE. bool UseBufferingHeuristics() const { return mTrackDemuxersMayBlock; } - RefPtr SetCDMProxy(CDMProxy* aProxy); + void SetCDMProxy(CDMProxy* aProxy); // Returns a string describing the state of the decoder data. // Used for debugging purposes. @@ -792,12 +792,6 @@ private: // Used in bug 1393399 for telemetry. const MediaDecoderOwnerID mMediaDecoderOwnerID; - - bool ResolveSetCDMPromiseIfDone(TrackType aTrack); - void PrepareToSetCDMForTrack(TrackType aTrack); - MozPromiseHolder mSetCDMPromise; - TrackSet mSetCDMForTracks{}; - bool IsDecoderWaitingForCDM(TrackType aTrack); }; } // namespace mozilla diff --git a/dom/media/MediaPromiseDefs.h b/dom/media/MediaPromiseDefs.h deleted file mode 100644 index 59654923b832..000000000000 --- a/dom/media/MediaPromiseDefs.h +++ /dev/null @@ -1,19 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* 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/. */ -#ifndef MediaPromiseDefs_h_ -#define MediaPromiseDefs_h_ - -#include "MediaResult.h" -#include "mozilla/MozPromise.h" - -namespace mozilla { - -using SetCDMPromise = - MozPromise; - -} // namespace mozilla - -#endif diff --git a/dom/media/moz.build b/dom/media/moz.build index b61e9df35c4c..551067a6b5e0 100644 --- a/dom/media/moz.build +++ b/dom/media/moz.build @@ -121,7 +121,6 @@ EXPORTS += [ 'MediaMetadataManager.h', 'MediaMIMETypes.h', 'MediaPrefs.h', - 'MediaPromiseDefs.h', 'MediaQueue.h', 'MediaRecorder.h', 'MediaResource.h', diff --git a/dom/media/platforms/wmf/DXVA2Manager.cpp b/dom/media/platforms/wmf/DXVA2Manager.cpp index 112aa40cfb38..575d4d8b1717 100644 --- a/dom/media/platforms/wmf/DXVA2Manager.cpp +++ b/dom/media/platforms/wmf/DXVA2Manager.cpp @@ -929,7 +929,7 @@ D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample, NS_ENSURE_TRUE(client, E_FAIL); RefPtr mutex; - HRESULT hr; + HRESULT hr = S_OK; RefPtr texture = image->GetTexture(); texture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex)); @@ -987,7 +987,9 @@ D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample, // It appears some race-condition may allow us to arrive here even when mSyncObject // is null. It's better to avoid that crash. client->SyncWithObject(mSyncObject); - mSyncObject->Synchronize(); + if (!mSyncObject->Synchronize(true)) { + return DXGI_ERROR_DEVICE_RESET; + } } image.forget(aOutImage); diff --git a/dom/media/platforms/wmf/WMFMediaDataDecoder.cpp b/dom/media/platforms/wmf/WMFMediaDataDecoder.cpp index 65ec9598ae14..405bd467bc09 100644 --- a/dom/media/platforms/wmf/WMFMediaDataDecoder.cpp +++ b/dom/media/platforms/wmf/WMFMediaDataDecoder.cpp @@ -115,6 +115,10 @@ WMFMediaDataDecoder::ProcessError(HRESULT aError, const char* aReason) SendTelemetry(aError); mRecordedError = true; } + + //TODO: For the error DXGI_ERROR_DEVICE_RESET, we could return + // NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER to get the latest device. Maybe retry + // up to 3 times. return DecodePromise::CreateAndReject( MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR, RESULT_DETAIL("%s:%x", aReason, aError)), @@ -127,7 +131,10 @@ WMFMediaDataDecoder::ProcessDecode(MediaRawData* aSample) DecodedData results; HRESULT hr = mMFTManager->Input(aSample); if (hr == MF_E_NOTACCEPTING) { - ProcessOutput(results); + hr = ProcessOutput(results); + if (FAILED(hr)) { + return ProcessError(hr, "MFTManager::Output(1)"); + } hr = mMFTManager->Input(aSample); } @@ -143,7 +150,7 @@ WMFMediaDataDecoder::ProcessDecode(MediaRawData* aSample) if (SUCCEEDED(hr) || hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { return DecodePromise::CreateAndResolve(Move(results), __func__); } - return ProcessError(hr, "MFTManager::Output"); + return ProcessError(hr, "MFTManager::Output(2)"); } HRESULT diff --git a/dom/media/test/bipbop_225w_175kbps.mp4^headers^ b/dom/media/test/bipbop_225w_175kbps.mp4^headers^ deleted file mode 100644 index 4030ea1d3ddb..000000000000 --- a/dom/media/test/bipbop_225w_175kbps.mp4^headers^ +++ /dev/null @@ -1 +0,0 @@ -Cache-Control: no-store diff --git a/dom/media/test/crashtests/crashtests.list b/dom/media/test/crashtests/crashtests.list index 5f2d363bb92f..3fde1fdb2387 100644 --- a/dom/media/test/crashtests/crashtests.list +++ b/dom/media/test/crashtests/crashtests.list @@ -108,6 +108,6 @@ load oscillator-ended-1.html load oscillator-ended-2.html skip-if(Android&&AndroidVersion=='22') load video-replay-after-audio-end.html # bug 1315125, bug 1358876 # This needs to run at the end to avoid leaking busted state into other tests. -load 691096-1.html +skip-if(Android) load 691096-1.html # Bug 1365451 load 1236639.html test-pref(media.navigator.permission.disabled,true) load 1388372.html diff --git a/dom/media/test/mochitest.ini b/dom/media/test/mochitest.ini index a505b97e1864..3fb833716700 100644 --- a/dom/media/test/mochitest.ini +++ b/dom/media/test/mochitest.ini @@ -74,8 +74,6 @@ support-files = bipbop-cenc-videoinit.mp4^headers^ bipbop-cenc-video-10s.mp4 bipbop-cenc-video-10s.mp4^headers^ - bipbop_225w_175kbps.mp4 - bipbop_225w_175kbps.mp4^headers^ bipbop_225w_175kbps-cenc-audio-key1-1.m4s bipbop_225w_175kbps-cenc-audio-key1-1.m4s^headers^ bipbop_225w_175kbps-cenc-audio-key1-2.m4s @@ -760,8 +758,6 @@ skip-if = toolkit == 'android' # bug 1149374 skip-if = toolkit == 'android' # bug 1149374 [test_eme_detach_media_keys.html] skip-if = toolkit == 'android' # bug 1149374 -[test_eme_detach_reattach_same_mediakeys_during_playback.html] -skip-if = toolkit == 'android' # bug 1149374 [test_eme_initDataTypes.html] skip-if = toolkit == 'android' # bug 1149374 [test_eme_missing_pssh.html] @@ -787,8 +783,6 @@ skip-if = toolkit == 'android' # bug 1149374 [test_eme_stream_capture_blocked_case3.html] tags=msg capturestream skip-if = toolkit == 'android' # bug 1149374 -[test_eme_unsetMediaKeys_then_capture.html] -skip-if = toolkit == 'android' # bug 1149374 [test_eme_waitingforkey.html] skip-if = toolkit == 'android' # bug 1149374 [test_empty_resource.html] @@ -849,6 +843,7 @@ tags=msg skip-if = android_version == '17' # android(bug 1232305) tags=msg [test_mediarecorder_record_addtracked_stream.html] +skip-if = toolkit == 'android' # Bug 1408241 tags=msg capturestream [test_mediarecorder_record_audiocontext.html] skip-if = android_version == '17' # android(bug 1232305) diff --git a/dom/media/test/test_eme_detach_reattach_same_mediakeys_during_playback.html b/dom/media/test/test_eme_detach_reattach_same_mediakeys_during_playback.html deleted file mode 100644 index 89b14d96ff02..000000000000 --- a/dom/media/test/test_eme_detach_reattach_same_mediakeys_during_playback.html +++ /dev/null @@ -1,144 +0,0 @@ - - - - Test Encrypted Media Extensions - - - - - - -
-
-
-
- - diff --git a/dom/media/test/test_eme_unsetMediaKeys_then_capture.html b/dom/media/test/test_eme_unsetMediaKeys_then_capture.html deleted file mode 100644 index 1cb1614f311b..000000000000 --- a/dom/media/test/test_eme_unsetMediaKeys_then_capture.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - Test Encrypted Media Extensions - - - - - - -
-
-
- - diff --git a/gfx/layers/SyncObject.h b/gfx/layers/SyncObject.h index e7c454570a72..874b30f75445 100644 --- a/gfx/layers/SyncObject.h +++ b/gfx/layers/SyncObject.h @@ -28,14 +28,15 @@ public: static already_AddRefed CreateSyncObjectHost( #ifdef XP_WIN - ID3D11Device* aDevice = nullptr + ID3D11Device* aDevice = nullptr #endif - ); + ); virtual bool Init() = 0; virtual SyncHandle GetSyncHandle() = 0; + // Return false for failed synchronization. virtual bool Synchronize() = 0; protected: @@ -50,9 +51,9 @@ public: static already_AddRefed CreateSyncObjectClient(SyncHandle aHandle #ifdef XP_WIN - , ID3D11Device* aDevice = nullptr + , ID3D11Device* aDevice = nullptr #endif - ); + ); enum class SyncType { D3D11, @@ -60,7 +61,8 @@ public: virtual SyncType GetSyncType() = 0; - virtual void Synchronize() = 0; + // Return false for failed synchronization. + virtual bool Synchronize(bool aFallible = false) = 0; virtual bool IsSyncObjectValid() = 0; diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index ad95eeeb1104..407f589723e5 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -1697,7 +1697,7 @@ SyncObjectD3D11Client::SyncObjectD3D11Client(SyncHandle aSyncHandle, ID3D11Devic } bool -SyncObjectD3D11Client::Init() +SyncObjectD3D11Client::Init(bool aFallible) { if (mKeyedMutex) { return true; @@ -1709,7 +1709,7 @@ SyncObjectD3D11Client::Init() (void**)(ID3D11Texture2D**)getter_AddRefs(mSyncTexture)); if (FAILED(hr) || !mSyncTexture) { gfxCriticalNote << "Failed to OpenSharedResource for SyncObjectD3D11: " << hexa(hr); - if (ShouldDevCrashOnSyncInitFailure()) { + if (!aFallible && ShouldDevCrashOnSyncInitFailure()) { gfxDevCrash(LogReason::D3D11FinalizeFrame) << "Without device reset: " << hexa(hr); } return false; @@ -1719,8 +1719,13 @@ SyncObjectD3D11Client::Init() if (FAILED(hr) || !mKeyedMutex) { // Leave both the critical error and MOZ_CRASH for now; the critical error lets // us "save" the hr value. We will probably eventually replace this with gfxDevCrash. - gfxCriticalError() << "Failed to get KeyedMutex (2): " << hexa(hr); - MOZ_CRASH("GFX: Cannot get D3D11 KeyedMutex"); + if (!aFallible) { + gfxCriticalError() << "Failed to get KeyedMutex (2): " << hexa(hr); + MOZ_CRASH("GFX: Cannot get D3D11 KeyedMutex"); + } else { + gfxCriticalNote << "Failed to get KeyedMutex (3): " << hexa(hr); + } + return false; } return true; @@ -1747,8 +1752,8 @@ SyncObjectD3D11Client::IsSyncObjectValid() // into our sync object and only use a lock for this sync object. // This way, we don't have to sync every texture we send to the compositor. // We only have to do this once per transaction. -void -SyncObjectD3D11Client::Synchronize() +bool +SyncObjectD3D11Client::Synchronize(bool aFallible) { // Since this can be called from either the Paint or Main thread. // We don't want this to race since we initialize the sync texture here @@ -1756,10 +1761,10 @@ SyncObjectD3D11Client::Synchronize() MutexAutoLock syncLock(mSyncLock); if (!mSyncedTextures.size()) { - return; + return true; } - if (!Init()) { - return; + if (!Init(aFallible)) { + return false; } HRESULT hr; @@ -1768,9 +1773,14 @@ SyncObjectD3D11Client::Synchronize() if (hr == WAIT_TIMEOUT) { if (DeviceManagerDx::Get()->HasDeviceReset()) { gfxWarning() << "AcquireSync timed out because of device reset."; - return; + return false; } - gfxDevCrash(LogReason::D3D11SyncLock) << "Timeout on the D3D11 sync lock"; + if (aFallible) { + gfxWarning() << "Timeout on the D3D11 sync lock."; + } else { + gfxDevCrash(LogReason::D3D11SyncLock) << "Timeout on the D3D11 sync lock."; + } + return false; } D3D11_BOX box; @@ -1782,13 +1792,13 @@ SyncObjectD3D11Client::Synchronize() if (dev == DeviceManagerDx::Get()->GetContentDevice()) { if (DeviceManagerDx::Get()->HasDeviceReset()) { - return; + return false; } } if (dev != mDevice) { gfxWarning() << "Attempt to sync texture from invalid device."; - return; + return false; } RefPtr ctx; @@ -1799,6 +1809,8 @@ SyncObjectD3D11Client::Synchronize() } mSyncedTextures.clear(); + + return true; } uint32_t diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h index 035e52fdc0d8..2858268ec833 100644 --- a/gfx/layers/d3d11/TextureD3D11.h +++ b/gfx/layers/d3d11/TextureD3D11.h @@ -478,7 +478,7 @@ class SyncObjectD3D11Client : public SyncObjectClient public: explicit SyncObjectD3D11Client(SyncHandle aSyncHandle, ID3D11Device* aDevice); - virtual void Synchronize() override; + virtual bool Synchronize(bool aFallible) override; virtual bool IsSyncObjectValid() override; @@ -487,7 +487,7 @@ public: void RegisterTexture(ID3D11Texture2D* aTexture); private: - bool Init(); + bool Init(bool aFallible); SyncHandle mSyncHandle; RefPtr mDevice; diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 4d19f5269228..e9f404f84e11 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -1210,10 +1210,11 @@ class GCRuntime AtomMarkingRuntime atomMarking; private: - // When empty, chunks reside in the emptyChunks pool and are re-used as - // needed or eventually expired if not re-used. The emptyChunks pool gets - // refilled from the background allocation task heuristically so that empty - // chunks should always available for immediate allocation without syscalls. + // When chunks are empty, they reside in the emptyChunks pool and are + // re-used as needed or eventually expired if not re-used. The emptyChunks + // pool gets refilled from the background allocation task heuristically so + // that empty chunks should always be available for immediate allocation + // without syscalls. GCLockData emptyChunks_; // Chunks which have had some, but not all, of their arenas allocated live diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp index 1ea06efde9b1..6132c8accb68 100644 --- a/js/src/gc/Nursery.cpp +++ b/js/src/gc/Nursery.cpp @@ -116,7 +116,8 @@ js::Nursery::Nursery(JSRuntime* rt) , currentStartPosition_(0) , currentEnd_(0) , currentChunk_(0) - , maxNurseryChunks_(0) + , maxChunkCount_(0) + , chunkCountLimit_(0) , previousPromotionRate_(0) , profileThreshold_(0) , enableProfiling_(false) @@ -140,15 +141,18 @@ js::Nursery::init(uint32_t maxNurseryBytes, AutoLockGCBgAlloc& lock) return false; /* maxNurseryBytes parameter is rounded down to a multiple of chunk size. */ - maxNurseryChunks_ = maxNurseryBytes >> ChunkShift; + chunkCountLimit_ = maxNurseryBytes >> ChunkShift; /* If no chunks are specified then the nursery is permanently disabled. */ - if (maxNurseryChunks_ == 0) + if (chunkCountLimit_ == 0) return true; - updateNumChunksLocked(1, lock); - if (numChunks() == 0) + maxChunkCount_ = 1; + if (!allocateNextChunk(0, lock)) { + maxChunkCount_ = 0; return false; + } + /* After this point the Nursery has been enabled */ setCurrentChunk(0); setStartPosition(); @@ -192,12 +196,17 @@ js::Nursery::enable() { MOZ_ASSERT(isEmpty()); MOZ_ASSERT(!runtime()->gc.isVerifyPreBarriersEnabled()); - if (isEnabled() || !maxChunks()) + if (isEnabled() || !chunkCountLimit()) return; - updateNumChunks(1); - if (numChunks() == 0) - return; + { + AutoLockGCBgAlloc lock(runtime()); + maxChunkCount_ = 1; + if (!allocateNextChunk(0, lock)) { + maxChunkCount_ = 0; + return; + } + } setCurrentChunk(0); setStartPosition(); @@ -215,8 +224,12 @@ js::Nursery::disable() MOZ_ASSERT(isEmpty()); if (!isEnabled()) return; - updateNumChunks(0); + + freeChunksFrom(0); + maxChunkCount_ = 0; + currentEnd_ = 0; + runtime()->gc.storeBuffer().disable(); } @@ -237,7 +250,7 @@ js::Nursery::isEmpty() const void js::Nursery::enterZealMode() { if (isEnabled()) - updateNumChunks(maxNurseryChunks_); + maxChunkCount_ = chunkCountLimit(); } void @@ -303,9 +316,19 @@ js::Nursery::allocate(size_t size) #endif if (currentEnd() < position() + size) { - if (currentChunk_ + 1 == numChunks()) + unsigned chunkno = currentChunk_ + 1; + MOZ_ASSERT(chunkno <= chunkCountLimit()); + MOZ_ASSERT(chunkno <= maxChunkCount()); + MOZ_ASSERT(chunkno <= allocatedChunkCount()); + if (chunkno == maxChunkCount()) return nullptr; - setCurrentChunk(currentChunk_ + 1); + if (MOZ_UNLIKELY(chunkno == allocatedChunkCount())) { + AutoLockGCBgAlloc lock(runtime()); + if (!allocateNextChunk(chunkno, lock)) + return nullptr; + MOZ_ASSERT(chunkno < allocatedChunkCount()); + } + setCurrentChunk(chunkno); } void* thing = (void*)position(); @@ -524,6 +547,7 @@ js::Nursery::renderProfileJSON(JSONPrinter& json) const json.property("bytes_used", previousGC.nurseryUsedBytes); json.property("cur_capacity", previousGC.nurseryCapacity); json.property("new_capacity", spaceToEnd()); + json.property("lazy_capacity", allocatedChunkCount() * ChunkSize); json.beginObjectProperty("phase_times"); @@ -686,7 +710,7 @@ js::Nursery::collect(JS::gcreason::Reason reason) // Disable the nursery if the user changed the configuration setting. The // nursery can only be re-enabled by resetting the configurationa and // restarting firefox. - if (maxNurseryChunks_ == 0) + if (chunkCountLimit_ == 0) disable(); endProfile(ProfileKey::Total); @@ -709,7 +733,7 @@ js::Nursery::collect(JS::gcreason::Reason reason) fprintf(stderr, "MinorGC: %20s %5.1f%% %4u ", JS::gcreason::ExplainReason(reason), promotionRate * 100, - numChunks()); + maxChunkCount()); printProfileDurations(profileDurations_); if (reportTenurings_) { @@ -914,18 +938,18 @@ js::Nursery::clear() { #ifdef JS_GC_ZEAL /* Poison the nursery contents so touching a freed object will crash. */ - for (unsigned i = 0; i < numChunks(); i++) + for (unsigned i = 0; i < allocatedChunkCount(); i++) chunk(i).poisonAndInit(runtime(), JS_SWEPT_NURSERY_PATTERN); if (runtime()->hasZealMode(ZealMode::GenerationalGC)) { /* Only reset the alloc point when we are close to the end. */ - if (currentChunk_ + 1 == numChunks()) + if (currentChunk_ + 1 == maxChunkCount()) setCurrentChunk(0); } else #endif { #ifdef JS_CRASH_DIAGNOSTICS - for (unsigned i = 0; i < numChunks(); ++i) + for (unsigned i = 0; i < allocatedChunkCount(); ++i) chunk(i).poisonAndInit(runtime(), JS_SWEPT_NURSERY_PATTERN); #endif setCurrentChunk(0); @@ -938,7 +962,7 @@ js::Nursery::clear() size_t js::Nursery::spaceToEnd() const { - unsigned lastChunk = numChunks() - 1; + unsigned lastChunk = maxChunkCount() - 1; MOZ_ASSERT(lastChunk >= currentStartChunk_); MOZ_ASSERT(currentStartPosition_ - chunk(currentStartChunk_).start() <= NurseryChunkUsableSize); @@ -946,7 +970,7 @@ js::Nursery::spaceToEnd() const size_t bytes = (chunk(currentStartChunk_).end() - currentStartPosition_) + ((lastChunk - currentStartChunk_) * NurseryChunkUsableSize); - MOZ_ASSERT(bytes <= numChunks() * NurseryChunkUsableSize); + MOZ_ASSERT(bytes <= maxChunkCount() * NurseryChunkUsableSize); return bytes; } @@ -954,14 +978,40 @@ js::Nursery::spaceToEnd() const MOZ_ALWAYS_INLINE void js::Nursery::setCurrentChunk(unsigned chunkno) { - MOZ_ASSERT(chunkno < maxChunks()); - MOZ_ASSERT(chunkno < numChunks()); + MOZ_ASSERT(chunkno < chunkCountLimit()); + MOZ_ASSERT(chunkno < allocatedChunkCount()); currentChunk_ = chunkno; position_ = chunk(chunkno).start(); currentEnd_ = chunk(chunkno).end(); chunk(chunkno).poisonAndInit(runtime(), JS_FRESH_NURSERY_PATTERN); } +bool +js::Nursery::allocateNextChunk(const unsigned chunkno, + AutoLockGCBgAlloc& lock) +{ + const unsigned priorCount = allocatedChunkCount(); + const unsigned newCount = priorCount + 1; + + MOZ_ASSERT((chunkno == currentChunk_ + 1) || (chunkno == 0 && allocatedChunkCount() == 0)); + MOZ_ASSERT(chunkno == allocatedChunkCount()); + MOZ_ASSERT(chunkno < chunkCountLimit()); + MOZ_ASSERT(chunkno < maxChunkCount()); + + if (!chunks_.resize(newCount)) + return false; + + Chunk* newChunk; + newChunk = runtime()->gc.getOrAllocChunk(lock); + if (!newChunk) { + chunks_.shrinkTo(priorCount); + return false; + } + + chunks_[chunkno] = NurseryChunk::fromChunk(newChunk); + return true; +} + MOZ_ALWAYS_INLINE void js::Nursery::setStartPosition() { @@ -998,23 +1048,25 @@ js::Nursery::maybeResizeNursery(JS::gcreason::Reason reason) float(previousGC.tenuredBytes) / float(previousGC.nurseryCapacity); newMaxNurseryChunks = runtime()->gc.tunables.gcMaxNurseryBytes() >> ChunkShift; - if (newMaxNurseryChunks != maxNurseryChunks_) { - maxNurseryChunks_ = newMaxNurseryChunks; + if (newMaxNurseryChunks != chunkCountLimit_) { + chunkCountLimit_ = newMaxNurseryChunks; /* The configured maximum nursery size is changing */ - const int extraChunks = numChunks() - newMaxNurseryChunks; - if (extraChunks > 0) { + if (maxChunkCount() > newMaxNurseryChunks) { /* We need to shrink the nursery */ - shrinkAllocableSpace(extraChunks); + shrinkAllocableSpace(newMaxNurseryChunks); previousPromotionRate_ = promotionRate; return; } } - if (promotionRate > GrowThreshold) + if (promotionRate > GrowThreshold) { + // The GC nursery is an optimization and so if we fail to allocate + // nursery chunks we do not report an error. growAllocableSpace(); - else if (promotionRate < ShrinkThreshold && previousPromotionRate_ < ShrinkThreshold) - shrinkAllocableSpace(1); + } else if (promotionRate < ShrinkThreshold && previousPromotionRate_ < ShrinkThreshold) { + shrinkAllocableSpace(maxChunkCount() - 1); + } previousPromotionRate_ = promotionRate; } @@ -1022,72 +1074,46 @@ js::Nursery::maybeResizeNursery(JS::gcreason::Reason reason) void js::Nursery::growAllocableSpace() { - updateNumChunks(Min(numChunks() * 2, maxNurseryChunks_)); + maxChunkCount_ = Min(maxChunkCount() * 2, chunkCountLimit()); } void -js::Nursery::shrinkAllocableSpace(unsigned removeNumChunks) +js::Nursery::freeChunksFrom(unsigned firstFreeChunk) +{ + MOZ_ASSERT(firstFreeChunk < chunks_.length()); + { + AutoLockGC lock(runtime()); + for (unsigned i = firstFreeChunk; i < chunks_.length(); i++) + runtime()->gc.recycleChunk(chunk(i).toChunk(runtime()), lock); + } + chunks_.shrinkTo(firstFreeChunk); +} + +void +js::Nursery::shrinkAllocableSpace(unsigned newCount) { #ifdef JS_GC_ZEAL if (runtime()->hasZealMode(ZealMode::GenerationalGC)) return; #endif - updateNumChunks(Max(numChunks() - removeNumChunks, 1u)); + + // Don't shrink the nursery to zero (use Nursery::disable() instead) and + // don't attempt to shrink it to the same size. + if ((newCount == 0) || (newCount == maxChunkCount())) + return; + + MOZ_ASSERT(newCount < maxChunkCount()); + + if (newCount < allocatedChunkCount()) + freeChunksFrom(newCount); + + maxChunkCount_ = newCount; } void js::Nursery::minimizeAllocableSpace() { -#ifdef JS_GC_ZEAL - if (runtime()->hasZealMode(ZealMode::GenerationalGC)) - return; -#endif - updateNumChunks(1); -} - -void -js::Nursery::updateNumChunks(unsigned newCount) -{ - if (numChunks() != newCount) { - AutoLockGCBgAlloc lock(runtime()); - updateNumChunksLocked(newCount, lock); - } -} - -void -js::Nursery::updateNumChunksLocked(unsigned newCount, - AutoLockGCBgAlloc& lock) -{ - // The GC nursery is an optimization and so if we fail to allocate nursery - // chunks we do not report an error. - - MOZ_ASSERT(newCount <= maxChunks()); - - unsigned priorCount = numChunks(); - MOZ_ASSERT(priorCount != newCount); - - if (newCount < priorCount) { - // Shrink the nursery and free unused chunks. - for (unsigned i = newCount; i < priorCount; i++) - runtime()->gc.recycleChunk(chunk(i).toChunk(runtime()), lock); - chunks_.shrinkTo(newCount); - return; - } - - // Grow the nursery and allocate new chunks. - if (!chunks_.resize(newCount)) - return; - - for (unsigned i = priorCount; i < newCount; i++) { - auto newChunk = runtime()->gc.getOrAllocChunk(lock); - if (!newChunk) { - chunks_.shrinkTo(i); - return; - } - - chunks_[i] = NurseryChunk::fromChunk(newChunk); - chunk(i).poisonAndInit(runtime(), JS_FRESH_NURSERY_PATTERN); - } + shrinkAllocableSpace(1); } bool diff --git a/js/src/gc/Nursery.h b/js/src/gc/Nursery.h index 0af23e62254d..d52d60e8628f 100644 --- a/js/src/gc/Nursery.h +++ b/js/src/gc/Nursery.h @@ -141,15 +141,22 @@ class Nursery MOZ_MUST_USE bool init(uint32_t maxNurseryBytes, AutoLockGCBgAlloc& lock); - unsigned maxChunks() const { return maxNurseryChunks_; } - unsigned numChunks() const { return chunks_.length(); } + unsigned chunkCountLimit() const { return chunkCountLimit_; } - bool exists() const { return maxChunks() != 0; } - size_t nurserySize() const { return maxChunks() << ChunkShift; } + // Number of allocated (ready to use) chunks. + unsigned allocatedChunkCount() const { return chunks_.length(); } + + // Total number of chunks and the capacity of the nursery. Chunks will be + // lazilly allocated and added to the chunks array up to this limit, after + // that the nursery must be collected, this limit may be raised during + // collection. + unsigned maxChunkCount() const { return maxChunkCount_; } + + bool exists() const { return chunkCountLimit() != 0; } void enable(); void disable(); - bool isEnabled() const { return numChunks() != 0; } + bool isEnabled() const { return maxChunkCount() != 0; } /* Return true if no allocations have been made since the last collection. */ bool isEmpty() const; @@ -234,7 +241,7 @@ class Nursery MOZ_MUST_USE bool queueDictionaryModeObjectToSweep(NativeObject* obj); size_t sizeOfHeapCommitted() const { - return numChunks() * gc::ChunkSize; + return allocatedChunkCount() * gc::ChunkSize; } size_t sizeOfMallocedBuffers(mozilla::MallocSizeOf mallocSizeOf) const { if (!mallocedBuffers.initialized()) @@ -253,7 +260,7 @@ class Nursery MOZ_ALWAYS_INLINE size_t freeSpace() const { MOZ_ASSERT(currentEnd_ - position_ <= NurseryChunkUsableSize); return (currentEnd_ - position_) + - (numChunks() - currentChunk_ - 1) * NurseryChunkUsableSize; + (maxChunkCount() - currentChunk_ - 1) * NurseryChunkUsableSize; } #ifdef JS_GC_ZEAL @@ -311,8 +318,18 @@ class Nursery /* The index of the chunk that is currently being allocated from. */ unsigned currentChunk_; - /* Maximum number of chunks to allocate for the nursery. */ - unsigned maxNurseryChunks_; + /* + * The nursery may grow the chunks_ vector up to this size without a + * collection. This allows the nursery to grow lazilly. This limit may + * change during maybeResizeNursery() each collection. + */ + unsigned maxChunkCount_; + + /* + * This limit is fixed by configuration. It represents the maximum size + * the nursery is permitted to tune itself to in maybeResizeNursery(); + */ + unsigned chunkCountLimit_; /* Promotion rate for the previous minor collection. */ float previousPromotionRate_; @@ -419,8 +436,6 @@ class Nursery Canary* lastCanary_; #endif - NurseryChunk* allocChunk(); - NurseryChunk& chunk(unsigned index) const { return *chunks_[index]; } @@ -428,9 +443,12 @@ class Nursery void setCurrentChunk(unsigned chunkno); void setStartPosition(); - void updateNumChunks(unsigned newCount); - void updateNumChunksLocked(unsigned newCount, - AutoLockGCBgAlloc& lock); + /* + * Allocate the next chunk, or the first chunk for initialization. + * Callers will probably want to call setCurrentChunk(0) next. + */ + MOZ_MUST_USE bool allocateNextChunk(unsigned chunkno, + AutoLockGCBgAlloc& lock); MOZ_ALWAYS_INLINE uintptr_t currentEnd() const; @@ -483,9 +501,13 @@ class Nursery /* Change the allocable space provided by the nursery. */ void maybeResizeNursery(JS::gcreason::Reason reason); void growAllocableSpace(); - void shrinkAllocableSpace(unsigned removeNumChunks); + void shrinkAllocableSpace(unsigned newCount); void minimizeAllocableSpace(); + // Free the chunks starting at firstFreeChunk until the end of the chunks + // vector. Shrinks the vector but does not update maxChunkCount(). + void freeChunksFrom(unsigned firstFreeChunk); + /* Profile recording and printing. */ void maybeClearProfileDurations(); void startProfile(ProfileKey key); diff --git a/mobile/android/config/mozconfigs/android-aarch64/l10n-nightly b/mobile/android/config/mozconfigs/android-aarch64/l10n-nightly index 0d2c0b4b7527..35d9ca226329 100644 --- a/mobile/android/config/mozconfigs/android-aarch64/l10n-nightly +++ b/mobile/android/config/mozconfigs/android-aarch64/l10n-nightly @@ -2,21 +2,39 @@ NO_NDK=1 . "$topsrcdir/mobile/android/config/mozconfigs/common" -. "$topsrcdir/mobile/android/config/mozconfigs/android-aarch64/nightly" - # L10n ac_add_options --with-l10n-base=../../l10n-central -# Don't autoclobber l10n, as this can lead to missing binaries and broken builds -# Bug 1283438 -mk_add_options AUTOCLOBBER= - . "$topsrcdir/build/mozconfig.no-compile" # Global options ac_add_options --disable-tests +# Android +ac_add_options --with-android-min-sdk=21 +ac_add_options --target=aarch64-linux-android + ac_add_options --enable-updater ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} +export MOZILLA_OFFICIAL=1 + +ac_add_options --with-branding=mobile/android/branding/nightly + +ac_add_options --disable-stdcxx-compat + +# Don't autoclobber l10n, as this can lead to missing binaries and broken builds +# Bug 1283438 +mk_add_options AUTOCLOBBER= + +# Disable Keyfile Loading (and checks) since l10n doesn't need these keys +# This overrides the settings in the common android mozconfig +ac_add_options --without-mozilla-api-keyfile +ac_add_options --without-google-api-keyfile +ac_add_options --without-adjust-sdk-keyfile +ac_add_options --without-leanplum-sdk-keyfile +ac_add_options --without-pocket-api-keyfile +# Similarly explicitly disable install tracking for l10n, we'll inherit from en-US +export MOZ_INSTALL_TRACKING= + . "$topsrcdir/mobile/android/config/mozconfigs/common.override" diff --git a/mobile/android/config/mozconfigs/android-api-16/l10n-nightly b/mobile/android/config/mozconfigs/android-api-16/l10n-nightly index bdd0bb41acfa..4144dfa19daf 100644 --- a/mobile/android/config/mozconfigs/android-api-16/l10n-nightly +++ b/mobile/android/config/mozconfigs/android-api-16/l10n-nightly @@ -2,21 +2,44 @@ NO_NDK=1 . "$topsrcdir/mobile/android/config/mozconfigs/common" -. "$topsrcdir/mobile/android/config/mozconfigs/android-api-16/nightly" - # L10n ac_add_options --with-l10n-base=../../l10n-central -# Don't autoclobber l10n, as this can lead to missing binaries and broken builds -# Bug 1283438 -mk_add_options AUTOCLOBBER= - . "$topsrcdir/build/mozconfig.no-compile" # Global options ac_add_options --disable-tests +# Android +# Warning: Before increasing the with-android-min-sdk value, please note several places in and out +# of tree have to be changed. Otherwise, places like Treeherder or archive.mozilla.org will +# advertise a bad API level. This may confuse people. As an example, please look at bug 1384482. +# If you think you can't handle the whole set of changes, please reach out to the Release +# Engineering team. +ac_add_options --with-android-min-sdk=16 +ac_add_options --target=arm-linux-androideabi + ac_add_options --enable-updater ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} +export MOZILLA_OFFICIAL=1 + +ac_add_options --with-branding=mobile/android/branding/nightly + +ac_add_options --disable-stdcxx-compat + +# Don't autoclobber l10n, as this can lead to missing binaries and broken builds +# Bug 1283438 +mk_add_options AUTOCLOBBER= + +# Disable Keyfile Loading (and checks) since l10n doesn't need these keys +# This overrides the settings in the common android mozconfig +ac_add_options --without-mozilla-api-keyfile +ac_add_options --without-google-api-keyfile +ac_add_options --without-adjust-sdk-keyfile +ac_add_options --without-leanplum-sdk-keyfile +ac_add_options --without-pocket-api-keyfile +# Similarly explicitly disable install tracking for l10n, we'll inherit from en-US +export MOZ_INSTALL_TRACKING= + . "$topsrcdir/mobile/android/config/mozconfigs/common.override" diff --git a/mobile/android/config/mozconfigs/android-x86/l10n-nightly b/mobile/android/config/mozconfigs/android-x86/l10n-nightly index c4cac7ceb010..118d3407ceca 100644 --- a/mobile/android/config/mozconfigs/android-x86/l10n-nightly +++ b/mobile/android/config/mozconfigs/android-x86/l10n-nightly @@ -2,21 +2,34 @@ NO_NDK=1 . "$topsrcdir/mobile/android/config/mozconfigs/common" -. "$topsrcdir/mobile/android/config/mozconfigs/android-x86/nightly" - # L10n ac_add_options --with-l10n-base=../../l10n-central -# Don't autoclobber l10n, as this can lead to missing binaries and broken builds -# Bug 1283438 -mk_add_options AUTOCLOBBER= - . "$topsrcdir/build/mozconfig.no-compile" # Global options ac_add_options --disable-tests +# Android +# Warning: Before increasing the with-android-min-sdk value, please note several places in and out +# of tree have to be changed. Otherwise, places like Treeherder or archive.mozilla.org will +# advertise a bad API level. This may confuse people. As an example, please look at bug 1384482. +# If you think you can't handle the whole set of changes, please reach out to the Release +# Engineering team. +ac_add_options --target=i386-linux-android +ac_add_options --with-android-min-sdk=16 + ac_add_options --enable-updater ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL} +export MOZILLA_OFFICIAL=1 + +ac_add_options --with-branding=mobile/android/branding/nightly + +ac_add_options --disable-stdcxx-compat + +# Don't autoclobber l10n, as this can lead to missing binaries and broken builds +# Bug 1283438 +mk_add_options AUTOCLOBBER= + . "$topsrcdir/mobile/android/config/mozconfigs/common.override" diff --git a/mobile/android/geckoview/build.gradle b/mobile/android/geckoview/build.gradle index ee0281423fd4..3a39c41014e0 100644 --- a/mobile/android/geckoview/build.gradle +++ b/mobile/android/geckoview/build.gradle @@ -55,8 +55,7 @@ android { // TODO: ensure these fields always agree with mobile/android/geckoview/BuildConfig.java.in, // either by diffing the processed files or by generating the output from a single source. buildConfigField 'String', "GRE_MILESTONE", "\"${mozconfig.substs.GRE_MILESTONE}\"" - // This should really come from the included binaries, but that's not easy. - buildConfigField 'String', "MOZ_APP_ABI", mozconfig.substs['COMPILE_ENVIRONMENT'] ? "\"${ mozconfig.substs.TARGET_XPCOM_ABI}\"" : '"arm-eabi-gcc3"'; + buildConfigField 'String', "MOZ_APP_ABI", "\"${mozconfig.substs.TARGET_XPCOM_ABI}\""; buildConfigField 'String', "MOZ_APP_BASENAME", "\"${mozconfig.substs.MOZ_APP_BASENAME}\""; // For the benefit of future archaeologists: diff --git a/mobile/android/gradle/with_gecko_binaries.gradle b/mobile/android/gradle/with_gecko_binaries.gradle index 9b8bc53074f1..5b067f3d96cc 100644 --- a/mobile/android/gradle/with_gecko_binaries.gradle +++ b/mobile/android/gradle/with_gecko_binaries.gradle @@ -152,32 +152,25 @@ ext.configureVariantWithJNIWrappers = { variant, module -> // suggest that it is. It certainly doesn't hurt. def prepareDependenciesTask = tasks.getByName("prepare${variant.name.capitalize()}Dependencies") - def wrapperTask - if (System.env.IS_LANGUAGE_REPACK == '1') { - // Single-locale l10n repacks set `IS_LANGUAGE_REPACK=1` and don't - // really have a build environment. - wrapperTask = task("generateJNIWrappersFor${module}${variant.name.capitalize()}") - } else { - wrapperTask = task("generateJNIWrappersFor${module}${variant.name.capitalize()}", type: JavaExec) { - classpath "${topobjdir}/build/annotationProcessors/annotationProcessors.jar" - - // Configure the classpath at evaluation-time, not at - // configuration-time: see above comment. - doFirst { - classpath variant.javaCompile.classpath - // Include android.jar. - classpath variant.javaCompile.options.bootClasspath - } - - main = 'org.mozilla.gecko.annotationProcessors.AnnotationProcessor' - args module - args jarTask.outputs.files.iterator().next() - - workingDir "${topobjdir}/mobile/android/base" - - dependsOn jarTask - dependsOn prepareDependenciesTask + def wrapperTask = task("generateJNIWrappersFor${module}${variant.name.capitalize()}", type: JavaExec) { + classpath "${topobjdir}/build/annotationProcessors/annotationProcessors.jar" + + // Configure the classpath at evaluation-time, not at + // configuration-time: see above comment. + doFirst { + classpath variant.javaCompile.classpath + // Include android.jar. + classpath variant.javaCompile.options.bootClasspath } + + main = 'org.mozilla.gecko.annotationProcessors.AnnotationProcessor' + args module + args jarTask.outputs.files.iterator().next() + + workingDir "${topobjdir}/mobile/android/base" + + dependsOn jarTask + dependsOn prepareDependenciesTask } if (module == 'Generated') { diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp index b203a2722b6a..1c8520d04c10 100644 --- a/modules/libpref/Preferences.cpp +++ b/modules/libpref/Preferences.cpp @@ -3263,7 +3263,7 @@ class ValueObserver final : public nsIObserver , public ValueObserverHashKey { - ~ValueObserver() { Preferences::RemoveObserver(this, mPrefName.get()); } + ~ValueObserver() = default; public: NS_DECL_ISUPPORTS @@ -4681,8 +4681,7 @@ pref_InitInitialObjects() if (!strcmp(NS_STRINGIFY(MOZ_UPDATE_CHANNEL), "nightly") || !strcmp(NS_STRINGIFY(MOZ_UPDATE_CHANNEL), "aurora") || - !strcmp(NS_STRINGIFY(MOZ_UPDATE_CHANNEL), "beta") || - developerBuild) { + !strcmp(NS_STRINGIFY(MOZ_UPDATE_CHANNEL), "beta") || developerBuild) { PREF_SetBoolPref(kTelemetryPref, true, true); } else { PREF_SetBoolPref(kTelemetryPref, false, true); @@ -4951,13 +4950,13 @@ NotifyObserver(const char* aPref, void* aClosure) } static void -RegisterPriorityCallback(PrefChangedFunc aCallback, - const char* aPref, - void* aClosure) +RegisterCallbackHelper(PrefChangedFunc aCallback, + const char* aPref, + void* aClosure, + Preferences::MatchKind aMatchKind, + bool aIsPriority) { - MOZ_ASSERT(Preferences::IsServiceAvailable()); - - ValueObserverHashKey hashKey(aPref, aCallback, Preferences::ExactMatch); + ValueObserverHashKey hashKey(aPref, aCallback, aMatchKind); RefPtr observer; gObserverTable->Get(&hashKey, getter_AddRefs(observer)); if (observer) { @@ -4965,15 +4964,27 @@ RegisterPriorityCallback(PrefChangedFunc aCallback, return; } - observer = new ValueObserver(aPref, aCallback, Preferences::ExactMatch); + observer = new ValueObserver(aPref, aCallback, aMatchKind); observer->AppendClosure(aClosure); - PREF_RegisterCallback(aPref, - NotifyObserver, - static_cast(observer), - /* isPriority */ true); + PREF_RegisterCallback( + aPref, NotifyObserver, static_cast(observer), aIsPriority); gObserverTable->Put(observer, observer); } +// RegisterVarCacheCallback uses high priority callbacks to ensure that cache +// observers are called prior to ordinary pref observers. Doing this ensures +// that ordinary observers will never get stale values from cache variables. +static void +RegisterVarCacheCallback(PrefChangedFunc aCallback, + const char* aPref, + void* aClosure) +{ + MOZ_ASSERT(Preferences::IsServiceAvailable()); + + RegisterCallbackHelper( + aCallback, aPref, aClosure, Preferences::ExactMatch, /* isPriority */ true); +} + /* static */ nsresult Preferences::RegisterCallback(PrefChangedFunc aCallback, const char* aPref, @@ -4983,20 +4994,8 @@ Preferences::RegisterCallback(PrefChangedFunc aCallback, MOZ_ASSERT(aCallback); NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE); - ValueObserverHashKey hashKey(aPref, aCallback, aMatchKind); - RefPtr observer; - gObserverTable->Get(&hashKey, getter_AddRefs(observer)); - if (observer) { - observer->AppendClosure(aClosure); - return NS_OK; - } - - observer = new ValueObserver(aPref, aCallback, aMatchKind); - observer->AppendClosure(aClosure); - nsresult rv = AddStrongObserver(observer, aPref); - NS_ENSURE_SUCCESS(rv, rv); - - gObserverTable->Put(observer, observer); + RegisterCallbackHelper( + aCallback, aPref, aClosure, aMatchKind, /* isPriority */ false); return NS_OK; } @@ -5037,15 +5036,14 @@ Preferences::UnregisterCallback(PrefChangedFunc aCallback, observer->RemoveClosure(aClosure); if (observer->HasNoClosures()) { // Delete the callback since its list of closures is empty. + MOZ_ALWAYS_SUCCEEDS( + PREF_UnregisterCallback(aPref, NotifyObserver, observer)); + gObserverTable->Remove(observer); } return NS_OK; } -// We insert cache observers using RegisterPriorityCallback to ensure they are -// called prior to ordinary pref observers. Doing this ensures that ordinary -// observers will never get stale values from cache variables. - static void BoolVarChanged(const char* aPref, void* aClosure) { @@ -5076,7 +5074,7 @@ Preferences::AddBoolVarCache(bool* aCache, const char* aPref, bool aDefault) data->mCacheLocation = aCache; data->mDefaultValueBool = aDefault; CacheDataAppendElement(data); - RegisterPriorityCallback(BoolVarChanged, aPref, data); + RegisterVarCacheCallback(BoolVarChanged, aPref, data); return NS_OK; } @@ -5103,7 +5101,7 @@ Preferences::AddIntVarCache(int32_t* aCache, data->mCacheLocation = aCache; data->mDefaultValueInt = aDefault; CacheDataAppendElement(data); - RegisterPriorityCallback(IntVarChanged, aPref, data); + RegisterVarCacheCallback(IntVarChanged, aPref, data); return NS_OK; } @@ -5130,7 +5128,7 @@ Preferences::AddUintVarCache(uint32_t* aCache, data->mCacheLocation = aCache; data->mDefaultValueUint = aDefault; CacheDataAppendElement(data); - RegisterPriorityCallback(UintVarChanged, aPref, data); + RegisterVarCacheCallback(UintVarChanged, aPref, data); return NS_OK; } @@ -5159,7 +5157,7 @@ Preferences::AddAtomicUintVarCache(Atomic* aCache, data->mCacheLocation = aCache; data->mDefaultValueUint = aDefault; CacheDataAppendElement(data); - RegisterPriorityCallback(AtomicUintVarChanged, aPref, data); + RegisterVarCacheCallback(AtomicUintVarChanged, aPref, data); return NS_OK; } @@ -5192,7 +5190,7 @@ Preferences::AddFloatVarCache(float* aCache, const char* aPref, float aDefault) data->mCacheLocation = aCache; data->mDefaultValueFloat = aDefault; CacheDataAppendElement(data); - RegisterPriorityCallback(FloatVarChanged, aPref, data); + RegisterVarCacheCallback(FloatVarChanged, aPref, data); return NS_OK; } diff --git a/netwerk/cookie/nsCookieService.cpp b/netwerk/cookie/nsCookieService.cpp index 0502905355a7..5142ad24e5c9 100644 --- a/netwerk/cookie/nsCookieService.cpp +++ b/netwerk/cookie/nsCookieService.cpp @@ -1338,6 +1338,8 @@ nsCookieService::TryInitDB(bool aRecreateDB) // No more upgrades. Update the schema version. rv = mDefaultDBState->syncConn->SetSchemaVersion(COOKIES_SCHEMA_VERSION); NS_ENSURE_SUCCESS(rv, RESULT_RETRY); + + Telemetry::Accumulate(Telemetry::MOZ_SQLITE_COOKIES_OLD_SCHEMA, dbSchemaVersion); MOZ_FALLTHROUGH; case COOKIES_SCHEMA_VERSION: @@ -1429,6 +1431,7 @@ nsCookieService::TryInitDB(bool aRecreateDB) gCookieService->ImportCookies(oldCookieFile); oldCookieFile->Remove(false); gCookieService->mDBState = initialState; + Telemetry::Accumulate(Telemetry::MOZ_SQLITE_COOKIES_OLD_SCHEMA, 0); }); NS_DispatchToMainThread(runnable); diff --git a/taskcluster/ci/l10n/kind.yml b/taskcluster/ci/l10n/kind.yml index 482c15d36484..a2304fdb525b 100644 --- a/taskcluster/ci/l10n/kind.yml +++ b/taskcluster/ci/l10n/kind.yml @@ -46,10 +46,6 @@ job-template: android-api-16-l10n: in-tree: android-build win.*: null - secrets: - by-build-platform: - default: false - android-api-16-l10n: true toolchains: by-build-platform: default: [] @@ -114,8 +110,7 @@ job-template: actions: by-build-platform: default: [clone-locales list-locales setup repack summary] - android-api-16-l10n: [get-secrets - clone-locales list-locales setup repack + android-api-16-l10n: [clone-locales list-locales setup repack upload-repacks summary] script: by-build-platform: diff --git a/taskcluster/ci/nightly-l10n/kind.yml b/taskcluster/ci/nightly-l10n/kind.yml index 0d04fdda8ed8..f8688f3f6adb 100644 --- a/taskcluster/ci/nightly-l10n/kind.yml +++ b/taskcluster/ci/nightly-l10n/kind.yml @@ -49,10 +49,6 @@ job-template: android-api-16-nightly: in-tree: android-build win.*: null - secrets: - by-build-platform: - default: false - android-api-16-nightly: true toolchains: by-build-platform: default: [] @@ -175,8 +171,7 @@ job-template: by-build-platform: default: ['clone-locales', 'list-locales', 'setup', 'repack', 'submit-to-balrog', 'summary'] - android-api-16-nightly: ['get-secrets', - 'clone-locales', 'list-locales', 'setup', 'repack', + android-api-16-nightly: ['clone-locales', 'list-locales', 'setup', 'repack', 'upload-repacks', 'submit-to-balrog', 'summary'] script: by-build-platform: diff --git a/taskcluster/taskgraph/transforms/l10n.py b/taskcluster/taskgraph/transforms/l10n.py index 75fbe83b49cc..42e9fc781175 100644 --- a/taskcluster/taskgraph/transforms/l10n.py +++ b/taskcluster/taskgraph/transforms/l10n.py @@ -107,13 +107,6 @@ l10n_description_schema = Schema({ Optional('toolchains'): _by_platform([basestring]), - # The set of secret names to which the task has access; these are prefixed - # with `project/releng/gecko/{treeherder.kind}/level-{level}/`. Setting - # this will enable any worker features required and set the task's scopes - # appropriately. `true` here means ['*'], all secrets. Not supported on - # Windows - Required('secrets', default=False): _by_platform(Any(bool, [basestring])), - # Information for treeherder Required('treeherder'): { # Platform to display the task on in treeherder @@ -258,7 +251,6 @@ def handle_keyed_by(config, jobs): "description", "run-time", "docker-image", - "secrets", "toolchains", "tooltool", "env", @@ -393,7 +385,6 @@ def make_job_description(config, jobs): 'script': job['mozharness']['script'], 'actions': job['mozharness']['actions'], 'options': job['mozharness']['options'], - 'secrets': job['secrets'], }, 'attributes': job['attributes'], 'treeherder': { diff --git a/testing/mozharness/configs/single_locale/tc_android-api-16.py b/testing/mozharness/configs/single_locale/tc_android-api-16.py index a551b13bb5cd..509754d0fe9e 100644 --- a/testing/mozharness/configs/single_locale/tc_android-api-16.py +++ b/testing/mozharness/configs/single_locale/tc_android-api-16.py @@ -15,37 +15,4 @@ config = { }, "mozilla_dir": "src/", "simple_name_move": True, - 'secret_files': [ - {'filename': '/builds/gapi.data', - 'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/gapi.data', - 'min_scm_level': 1}, - {'filename': '/builds/mozilla-fennec-geoloc-api.key', - 'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/mozilla-fennec-geoloc-api.key', - 'min_scm_level': 2, 'default': 'try-build-has-no-secrets'}, - {'filename': '/builds/adjust-sdk.token', - 'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/adjust-sdk.token', - 'min_scm_level': 2, 'default': 'try-build-has-no-secrets'}, - {'filename': '/builds/adjust-sdk-beta.token', - 'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/adjust-sdk-beta.token', - 'min_scm_level': 2, 'default': 'try-build-has-no-secrets'}, - {'filename': '/builds/leanplum-sdk-release.token', - 'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/leanplum-sdk-release.token', - 'min_scm_level': 2, 'default': 'try-build-has-no-secrets'}, - {'filename': '/builds/leanplum-sdk-beta.token', - 'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/leanplum-sdk-beta.token', - 'min_scm_level': 2, 'default': 'try-build-has-no-secrets'}, - {'filename': '/builds/leanplum-sdk-nightly.token', - 'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/leanplum-sdk-nightly.token', - 'min_scm_level': 2, 'default': 'try-build-has-no-secrets'}, - {'filename': '/builds/pocket-api-release.token', - 'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/pocket-api-release.token', - 'min_scm_level': 2, 'default': 'try-build-has-no-secrets'}, - {'filename': '/builds/pocket-api-beta.token', - 'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/pocket-api-beta.token', - 'min_scm_level': 2, 'default': 'try-build-has-no-secrets'}, - {'filename': '/builds/pocket-api-nightly.token', - 'secret_name': 'project/releng/gecko/build/level-%(scm-level)s/pocket-api-nightly.token', - 'min_scm_level': 2, 'default': 'try-build-has-no-secrets'}, - - ], } diff --git a/testing/mozharness/scripts/mobile_l10n.py b/testing/mozharness/scripts/mobile_l10n.py index bc3fb748f992..10bda50a8793 100755 --- a/testing/mozharness/scripts/mobile_l10n.py +++ b/testing/mozharness/scripts/mobile_l10n.py @@ -38,7 +38,6 @@ from mozharness.mozilla.tooltool import TooltoolMixin from mozharness.base.vcs.vcsbase import MercurialScript from mozharness.mozilla.l10n.locales import LocalesMixin from mozharness.mozilla.mock import MockMixin -from mozharness.mozilla.secrets import SecretsMixin from mozharness.mozilla.updates.balrog import BalrogMixin from mozharness.base.python import VirtualenvMixin from mozharness.mozilla.taskcluster_helper import Taskcluster @@ -48,7 +47,7 @@ from mozharness.mozilla.taskcluster_helper import Taskcluster class MobileSingleLocale(MockMixin, LocalesMixin, ReleaseMixin, MobileSigningMixin, TransferMixin, TooltoolMixin, BuildbotMixin, PurgeMixin, MercurialScript, BalrogMixin, - VirtualenvMixin, SecretsMixin): + VirtualenvMixin): config_options = [[ ['--locale', ], {"action": "extend", @@ -125,7 +124,6 @@ class MobileSingleLocale(MockMixin, LocalesMixin, ReleaseMixin, def __init__(self, require_config_file=True): buildscript_kwargs = { 'all_actions': [ - "get-secrets", "clobber", "pull", "clone-locales", @@ -187,20 +185,6 @@ class MobileSingleLocale(MockMixin, LocalesMixin, ReleaseMixin, if 'MOZ_SIGNING_SERVERS' in os.environ: repack_env['MOZ_SIGN_CMD'] = \ subprocess.list2cmdline(self.query_moz_sign_cmd(formats=['jar'])) - - if self.query_is_nightly() or self.query_is_nightly_promotion(): - if self.query_is_nightly(): - # Nightly promotion needs to set update_channel but not do all - # the 'IS_NIGHTLY' automation parts, like uploading symbols - # (for now). - repack_env["IS_NIGHTLY"] = "yes" - # In branch_specifics.py we might set update_channel explicitly. - if c.get('update_channel'): - repack_env["MOZ_UPDATE_CHANNEL"] = c['update_channel'] - else: # Let's just give the generic channel based on branch. - repack_env["MOZ_UPDATE_CHANNEL"] = \ - "nightly-%s" % (c['branch'],) - self.repack_env = repack_env return self.repack_env diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index f0e0db8a4b53..0cec3d613fba 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -4426,6 +4426,15 @@ "n_buckets": 10, "description": "Time spent on SQLite read() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, + "MOZ_SQLITE_COOKIES_OLD_SCHEMA": { + "record_in_processes": ["main"], + "expires_in_version": "62", + "kind": "enumerated", + "n_values": 10, + "bug_numbers": [1412218], + "alert_emails": ["necko@mozilla.com", "junior@mozilla.com"], + "description": "Old schema version of the cookie database. 0 for having legacy cookies.txt." + }, "MOZ_SQLITE_COOKIES_BLOCK_MAIN_THREAD_MS": { "record_in_processes": ["main"], "expires_in_version": "never", diff --git a/toolkit/mozapps/installer/upload-files-APK.mk b/toolkit/mozapps/installer/upload-files-APK.mk index 10279a8ae828..9bc3fc49cb4b 100644 --- a/toolkit/mozapps/installer/upload-files-APK.mk +++ b/toolkit/mozapps/installer/upload-files-APK.mk @@ -94,7 +94,6 @@ repackage_fennec = \ $(UNPACKAGE) \ $(GECKO_APP_AP_PATH)/gecko-nodeps.ap_ \ --omnijar $(MOZ_PKG_DIR)/$(OMNIJAR_NAME) \ - --classes-dex $(GECKO_APP_AP_PATH)/classes.dex \ --output $(PACKAGE:.apk=-unsigned-unaligned.apk) && \ $(call RELEASE_SIGN_ANDROID_APK,$(PACKAGE:.apk=-unsigned-unaligned.apk),$(PACKAGE))